Import libarchive 3.4.0
This commit is contained in:
parent
236588358a
commit
fcf02ec8c5
|
@ -23,6 +23,13 @@ the actual statements in the files are controlling.
|
|||
* The following source files are in the public domain:
|
||||
libarchive/archive_getdate.c
|
||||
|
||||
* The following source files are triple-licensed with the ability to choose
|
||||
from CC0 1.0 Universal, OpenSSL or Apache 2.0 licenses:
|
||||
libarchive/archive_blake2.h
|
||||
libarchive/archive_blake2_impl.h
|
||||
libarchive/archive_blake2s_ref.c
|
||||
libarchive/archive_blake2sp_ref.c
|
||||
|
||||
* The build files---including Makefiles, configure scripts,
|
||||
and auxiliary scripts used as part of the compile process---have
|
||||
widely varying licensing terms. Please check individual files before
|
||||
|
@ -34,7 +41,7 @@ do use the license below. The varying licensing of the build scripts
|
|||
seems to be an unavoidable mess.
|
||||
|
||||
|
||||
Copyright (c) 2003-2009 <author(s)>
|
||||
Copyright (c) 2003-2018 <author(s)>
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
|
|
@ -1,3 +1,31 @@
|
|||
Jun 11, 2019: libarchive 3.4.0 released
|
||||
|
||||
May 18, 2019: Fixes for reading Android APK and JAR archives
|
||||
|
||||
Apr 16, 2019: Support for non-recursive list and extract
|
||||
|
||||
Apr 14, 2019: New tar option: --exclude-vcs
|
||||
|
||||
Mar 27, 2019: Support for file and directory symlinks on Windows
|
||||
|
||||
Mar 12, 2019: Important fixes for storing file attributes and flags
|
||||
|
||||
Jan 20, 2019: Support for xz, lzma, ppmd8 and bzip2 decompression in ZIP files
|
||||
|
||||
Oct 06, 2018: RAR 5.0 reader
|
||||
|
||||
Sep 03, 2018: libarchive 3.3.3 released
|
||||
|
||||
Jul 19, 2018: Avoid super-linear slowdown on malformed mtree files
|
||||
|
||||
Jan 27, 2018: Many fixes for building with Visual Studio
|
||||
|
||||
Oct 19, 2017: NO_OVERWRITE doesn't change existing directory attributes
|
||||
|
||||
Aug 12, 2017: New support for Zstandard read and write filters
|
||||
|
||||
Jul 09, 2017: libarchive 3.3.2 released
|
||||
|
||||
Mar 16, 2017: NFSv4 ACL support for Linux (librichacl)
|
||||
|
||||
Feb 26, 2017: libarchive 3.3.1 released
|
||||
|
|
|
@ -78,16 +78,16 @@ Currently, the library automatically detects and reads the following fomats:
|
|||
* POSIX pax interchange format
|
||||
* POSIX octet-oriented cpio
|
||||
* SVR4 ASCII cpio
|
||||
* POSIX octet-oriented cpio
|
||||
* Binary cpio (big-endian or little-endian)
|
||||
* ISO9660 CD-ROM images (with optional Rockridge or Joliet extensions)
|
||||
* ZIP archives (with uncompressed or "deflate" compressed entries, including support for encrypted Zip archives)
|
||||
* ZIPX archives (with support for bzip2, ppmd8, lzma and xz compressed entries)
|
||||
* GNU and BSD 'ar' archives
|
||||
* 'mtree' format
|
||||
* 7-Zip archives
|
||||
* Microsoft CAB format
|
||||
* LHA and LZH archives
|
||||
* RAR archives (with some limitations due to RAR's proprietary status)
|
||||
* RAR and RAR 5.0 archives (with some limitations due to RAR's proprietary status)
|
||||
* XAR archives
|
||||
|
||||
The library also detects and handles any of the following before evaluating the archive:
|
||||
|
@ -99,6 +99,7 @@ The library also detects and handles any of the following before evaluating the
|
|||
* lzma, lzip, and xz compression
|
||||
* lz4 compression
|
||||
* lzop compression
|
||||
* zstandard compression
|
||||
|
||||
The library can create archives in any of the following formats:
|
||||
* POSIX ustar
|
||||
|
@ -125,6 +126,7 @@ When creating archives, the result can be filtered with any of the following:
|
|||
* lzma, lzip, and xz compression
|
||||
* lz4 compression
|
||||
* lzop compression
|
||||
* zstandard compression
|
||||
|
||||
## Notes about the Library Design
|
||||
|
||||
|
@ -159,7 +161,7 @@ questions we are asked about libarchive:
|
|||
|
||||
* On read, compression and format are always detected automatically.
|
||||
|
||||
* The same API is used for all formats; in particular, it's very
|
||||
* The same API is used for all formats; it should be very
|
||||
easy for software using libarchive to transparently handle
|
||||
any of libarchive's archiving formats.
|
||||
|
||||
|
|
|
@ -61,7 +61,7 @@ usage(FILE *stream, int eval)
|
|||
static void
|
||||
version(void)
|
||||
{
|
||||
printf("bsdcat %s - %s\n",
|
||||
printf("bsdcat %s - %s \n",
|
||||
BSDCAT_VERSION_STRING,
|
||||
archive_version_details());
|
||||
exit(0);
|
||||
|
@ -70,6 +70,12 @@ version(void)
|
|||
void
|
||||
bsdcat_next(void)
|
||||
{
|
||||
if (a != NULL) {
|
||||
if (archive_read_close(a) != ARCHIVE_OK)
|
||||
bsdcat_print_error();
|
||||
archive_read_free(a);
|
||||
}
|
||||
|
||||
a = archive_read_new();
|
||||
archive_read_support_filter_all(a);
|
||||
archive_read_support_format_empty(a);
|
||||
|
@ -100,8 +106,10 @@ bsdcat_read_to_stdout(const char* filename)
|
|||
;
|
||||
else if (archive_read_data_into_fd(a, 1) != ARCHIVE_OK)
|
||||
bsdcat_print_error();
|
||||
if (archive_read_free(a) != ARCHIVE_OK)
|
||||
if (archive_read_close(a) != ARCHIVE_OK)
|
||||
bsdcat_print_error();
|
||||
archive_read_free(a);
|
||||
a = NULL;
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -135,15 +143,14 @@ main(int argc, char **argv)
|
|||
if (*bsdcat->argv == NULL) {
|
||||
bsdcat_current_path = "<stdin>";
|
||||
bsdcat_read_to_stdout(NULL);
|
||||
} else
|
||||
} else {
|
||||
while (*bsdcat->argv) {
|
||||
bsdcat_current_path = *bsdcat->argv++;
|
||||
bsdcat_read_to_stdout(bsdcat_current_path);
|
||||
bsdcat_next();
|
||||
}
|
||||
|
||||
if (a != NULL)
|
||||
archive_read_free(a);
|
||||
archive_read_free(a); /* Help valgrind & friends */
|
||||
}
|
||||
|
||||
exit(exit_status);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
DEFINE_TEST(test_0)
|
||||
DEFINE_TEST(test_empty_gz)
|
||||
DEFINE_TEST(test_empty_lz4)
|
||||
DEFINE_TEST(test_empty_xz)
|
||||
DEFINE_TEST(test_empty_zstd)
|
||||
DEFINE_TEST(test_error)
|
||||
DEFINE_TEST(test_error_mixed)
|
||||
DEFINE_TEST(test_expand_bz2)
|
||||
DEFINE_TEST(test_expand_gz)
|
||||
DEFINE_TEST(test_expand_lz4)
|
||||
DEFINE_TEST(test_expand_mixed)
|
||||
DEFINE_TEST(test_expand_plain)
|
||||
DEFINE_TEST(test_expand_xz)
|
||||
DEFINE_TEST(test_expand_Z)
|
||||
DEFINE_TEST(test_expand_zstd)
|
||||
DEFINE_TEST(test_help)
|
||||
DEFINE_TEST(test_stdin)
|
||||
DEFINE_TEST(test_version)
|
|
@ -0,0 +1,4 @@
|
|||
begin 644 test_empty.zst
|
||||
-*+4O_010`0``F>G840``
|
||||
`
|
||||
end
|
|
@ -0,0 +1,41 @@
|
|||
/*-
|
||||
* Copyright (c) 2017 Sean Purcell
|
||||
* 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_zstd)
|
||||
{
|
||||
const char *reffile = "test_empty.zst";
|
||||
int f;
|
||||
|
||||
extract_reference_file(reffile);
|
||||
f = systemf("%s %s >test.out 2>test.err", testprog, reffile);
|
||||
if (f == 0 || canZstd()) {
|
||||
assertEqualInt(0, f);
|
||||
assertEmptyFile("test.out");
|
||||
assertEmptyFile("test.err");
|
||||
} else {
|
||||
skipping("It seems zstd is not supported on this platform");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
begin 644 test_expand.zst
|
||||
J*+4O_010Z0``8V]N=&5N=',@;V8@=&5S=%]E>'!A;F0N>G-T+@J;23#F
|
||||
`
|
||||
end
|
|
@ -0,0 +1,41 @@
|
|||
/*-
|
||||
* Copyright (c) 2017 Sean Purcell
|
||||
* 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_zstd)
|
||||
{
|
||||
const char *reffile = "test_expand.zst";
|
||||
int f;
|
||||
|
||||
extract_reference_file(reffile);
|
||||
f = systemf("%s %s >test.out 2>test.err", testprog, reffile);
|
||||
if (f == 0 || canZstd()) {
|
||||
assertEqualInt(0, f);
|
||||
assertTextFileContents("contents of test_expand.zst.\n", "test.out");
|
||||
assertEmptyFile("test.err");
|
||||
} else {
|
||||
skipping("It seems zstd is not supported on this platform");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/*-
|
||||
* Copyright (c) 2017 Sean Purcell
|
||||
* 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"
|
||||
|
||||
#if !defined(_WIN32) || defined(__CYGWIN__)
|
||||
#define DEV_NULL "/dev/null"
|
||||
#else
|
||||
#define DEV_NULL "NUL"
|
||||
#endif
|
||||
|
||||
DEFINE_TEST(test_stdin)
|
||||
{
|
||||
int f;
|
||||
|
||||
f = systemf("%s <%s >test.out 2>test.err", testprog, DEV_NULL);
|
||||
assertEqualInt(0, f);
|
||||
assertEmptyFile("test.out");
|
||||
assertEmptyFile("test.err");
|
||||
}
|
||||
|
|
@ -187,6 +187,11 @@ In input mode, this option is ignored.
|
|||
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 zstd
|
||||
(o mode only)
|
||||
Compress the archive with zstd-compatible compression before writing it.
|
||||
In input mode, this option is ignored; zstd compression is recognized
|
||||
automatically on input.
|
||||
.It Fl Fl lzma
|
||||
(o mode only)
|
||||
Compress the file with lzma-compatible compression before writing it.
|
||||
|
|
|
@ -92,6 +92,7 @@ static const struct option {
|
|||
{ "verbose", 0, 'v' },
|
||||
{ "version", 0, OPTION_VERSION },
|
||||
{ "xz", 0, 'J' },
|
||||
{ "zstd", 0, OPTION_ZSTD },
|
||||
{ NULL, 0, 0 }
|
||||
};
|
||||
|
||||
|
|
|
@ -134,8 +134,9 @@ main(int argc, char *argv[])
|
|||
struct cpio _cpio; /* Allocated on stack. */
|
||||
struct cpio *cpio;
|
||||
const char *errmsg;
|
||||
char *tptr;
|
||||
int uid, gid;
|
||||
int opt;
|
||||
int opt, t;
|
||||
|
||||
cpio = &_cpio;
|
||||
memset(cpio, 0, sizeof(*cpio));
|
||||
|
@ -204,9 +205,15 @@ main(int argc, char *argv[])
|
|||
cpio->add_filter = opt;
|
||||
break;
|
||||
case 'C': /* NetBSD/OpenBSD */
|
||||
cpio->bytes_per_block = atoi(cpio->argument);
|
||||
if (cpio->bytes_per_block <= 0)
|
||||
lafe_errc(1, 0, "Invalid blocksize %s", cpio->argument);
|
||||
errno = 0;
|
||||
tptr = NULL;
|
||||
t = (int)strtol(cpio->argument, &tptr, 10);
|
||||
if (errno || t <= 0 || *(cpio->argument) == '\0' ||
|
||||
tptr == NULL || *tptr != '\0') {
|
||||
lafe_errc(1, 0, "Invalid blocksize: %s",
|
||||
cpio->argument);
|
||||
}
|
||||
cpio->bytes_per_block = t;
|
||||
break;
|
||||
case 'c': /* POSIX 1997 */
|
||||
cpio->format = "odc";
|
||||
|
@ -269,6 +276,7 @@ main(int argc, char *argv[])
|
|||
case OPTION_LZ4:
|
||||
case OPTION_LZMA: /* GNU tar, others */
|
||||
case OPTION_LZOP: /* GNU tar, others */
|
||||
case OPTION_ZSTD:
|
||||
cpio->compress = opt;
|
||||
break;
|
||||
case 'm': /* POSIX 1997 */
|
||||
|
@ -498,7 +506,7 @@ long_help(void)
|
|||
static void
|
||||
version(void)
|
||||
{
|
||||
fprintf(stdout,"bsdcpio %s - %s\n",
|
||||
fprintf(stdout,"bsdcpio %s - %s \n",
|
||||
BSDCPIO_VERSION_STRING,
|
||||
archive_version_details());
|
||||
exit(0);
|
||||
|
@ -546,6 +554,9 @@ mode_out(struct cpio *cpio)
|
|||
case OPTION_LZOP:
|
||||
r = archive_write_add_filter_lzop(cpio->archive);
|
||||
break;
|
||||
case OPTION_ZSTD:
|
||||
r = archive_write_add_filter_zstd(cpio->archive);
|
||||
break;
|
||||
case 'j': case 'y':
|
||||
r = archive_write_add_filter_bzip2(cpio->archive);
|
||||
break;
|
||||
|
@ -628,6 +639,7 @@ mode_out(struct cpio *cpio)
|
|||
blocks == 1 ? "block" : "blocks");
|
||||
}
|
||||
archive_write_free(cpio->archive);
|
||||
archive_entry_linkresolver_free(cpio->linkresolver);
|
||||
}
|
||||
|
||||
static const char *
|
||||
|
@ -743,8 +755,10 @@ file_to_archive(struct cpio *cpio, const char *srcpath)
|
|||
}
|
||||
if (cpio->option_rename)
|
||||
destpath = cpio_rename(destpath);
|
||||
if (destpath == NULL)
|
||||
if (destpath == NULL) {
|
||||
archive_entry_free(entry);
|
||||
return (0);
|
||||
}
|
||||
archive_entry_copy_pathname(entry, destpath);
|
||||
|
||||
/*
|
||||
|
@ -1194,12 +1208,15 @@ mode_pass(struct cpio *cpio, const char *destdir)
|
|||
struct lafe_line_reader *lr;
|
||||
const char *p;
|
||||
int r;
|
||||
size_t destdir_len;
|
||||
|
||||
/* Ensure target dir has a trailing '/' to simplify path surgery. */
|
||||
cpio->destdir = malloc(strlen(destdir) + 8);
|
||||
strcpy(cpio->destdir, destdir);
|
||||
if (destdir[strlen(destdir) - 1] != '/')
|
||||
strcat(cpio->destdir, "/");
|
||||
destdir_len = strlen(destdir);
|
||||
cpio->destdir = malloc(destdir_len + 8);
|
||||
memcpy(cpio->destdir, destdir, destdir_len);
|
||||
if (destdir_len == 0 || destdir[destdir_len - 1] != '/')
|
||||
cpio->destdir[destdir_len++] = '/';
|
||||
cpio->destdir[destdir_len++] = '\0';
|
||||
|
||||
cpio->archive = archive_write_disk_new();
|
||||
if (cpio->archive == NULL)
|
||||
|
@ -1240,6 +1257,7 @@ mode_pass(struct cpio *cpio, const char *destdir)
|
|||
}
|
||||
|
||||
archive_write_free(cpio->archive);
|
||||
free(cpio->pass_destpath);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -111,7 +111,8 @@ enum {
|
|||
OPTION_PRESERVE_OWNER,
|
||||
OPTION_QUIET,
|
||||
OPTION_UUENCODE,
|
||||
OPTION_VERSION
|
||||
OPTION_VERSION,
|
||||
OPTION_ZSTD,
|
||||
};
|
||||
|
||||
int cpio_getopt(struct cpio *cpio);
|
||||
|
|
|
@ -1,27 +1,48 @@
|
|||
DEFINE_TEST(test_0)
|
||||
DEFINE_TEST(test_basic)
|
||||
DEFINE_TEST(test_cmdline)
|
||||
DEFINE_TEST(test_extract_cpio_bz2)
|
||||
DEFINE_TEST(test_extract_cpio_grz)
|
||||
DEFINE_TEST(test_extract_cpio_gz)
|
||||
DEFINE_TEST(test_extract_cpio_lrz)
|
||||
DEFINE_TEST(test_extract_cpio_lz4)
|
||||
DEFINE_TEST(test_extract_cpio_lz)
|
||||
DEFINE_TEST(test_extract_cpio_lzma)
|
||||
DEFINE_TEST(test_extract_cpio_lzo)
|
||||
DEFINE_TEST(test_extract_cpio_xz)
|
||||
DEFINE_TEST(test_extract_cpio_Z)
|
||||
DEFINE_TEST(test_extract_cpio_zstd)
|
||||
DEFINE_TEST(test_format_newc)
|
||||
DEFINE_TEST(test_gcpio_compat)
|
||||
DEFINE_TEST(test_option_B_upper)
|
||||
DEFINE_TEST(test_option_C_upper)
|
||||
DEFINE_TEST(test_option_J_upper)
|
||||
DEFINE_TEST(test_option_L_upper)
|
||||
DEFINE_TEST(test_option_Z_upper)
|
||||
DEFINE_TEST(test_missing_file)
|
||||
DEFINE_TEST(test_option_0)
|
||||
DEFINE_TEST(test_option_a)
|
||||
DEFINE_TEST(test_option_b64encode)
|
||||
DEFINE_TEST(test_option_B_upper)
|
||||
DEFINE_TEST(test_option_c)
|
||||
DEFINE_TEST(test_option_C_upper)
|
||||
DEFINE_TEST(test_option_d)
|
||||
DEFINE_TEST(test_option_f)
|
||||
DEFINE_TEST(test_option_grzip)
|
||||
DEFINE_TEST(test_option_help)
|
||||
DEFINE_TEST(test_option_J_upper)
|
||||
DEFINE_TEST(test_option_l)
|
||||
DEFINE_TEST(test_option_lrzip)
|
||||
DEFINE_TEST(test_option_L_upper)
|
||||
DEFINE_TEST(test_option_lz4)
|
||||
DEFINE_TEST(test_option_lzma)
|
||||
DEFINE_TEST(test_option_lzop)
|
||||
DEFINE_TEST(test_option_m)
|
||||
DEFINE_TEST(test_option_passphrase)
|
||||
DEFINE_TEST(test_option_t)
|
||||
DEFINE_TEST(test_option_u)
|
||||
DEFINE_TEST(test_option_uuencode)
|
||||
DEFINE_TEST(test_option_version)
|
||||
DEFINE_TEST(test_option_xz)
|
||||
DEFINE_TEST(test_option_y)
|
||||
DEFINE_TEST(test_option_z)
|
||||
DEFINE_TEST(test_option_zstd)
|
||||
DEFINE_TEST(test_option_Z_upper)
|
||||
DEFINE_TEST(test_owner_parse)
|
||||
DEFINE_TEST(test_passthrough_dotdot)
|
||||
DEFINE_TEST(test_passthrough_reverse)
|
||||
DEFINE_TEST(test_pathmatch)
|
||||
|
|
|
@ -46,7 +46,7 @@ verify_files(const char *msg)
|
|||
|
||||
/* Symlink */
|
||||
if (canSymlink())
|
||||
assertIsSymlink("symlink", "file");
|
||||
assertIsSymlink("symlink", "file", 0);
|
||||
|
||||
/* Another file with 1 link and different permissions. */
|
||||
failure(msg);
|
||||
|
@ -144,49 +144,79 @@ DEFINE_TEST(test_basic)
|
|||
/* File with 10 bytes content. */
|
||||
assertMakeFile("file", 0644, "1234567890");
|
||||
fprintf(filelist, "file\n");
|
||||
if (is_LargeInode("file"))
|
||||
if (is_LargeInode("file")) {
|
||||
strncat(result,
|
||||
"bsdcpio: file: large inode number truncated: "
|
||||
"Numerical result out of range\n",
|
||||
"bsdcpio: file: large inode number truncated: ",
|
||||
sizeof(result) - strlen(result) -1);
|
||||
strncat(result,
|
||||
strerror(ERANGE),
|
||||
sizeof(result) - strlen(result) -1);
|
||||
strncat(result,
|
||||
"\n",
|
||||
sizeof(result) - strlen(result) -1);
|
||||
}
|
||||
|
||||
/* hardlink to above file. */
|
||||
assertMakeHardlink("linkfile", "file");
|
||||
fprintf(filelist, "linkfile\n");
|
||||
if (is_LargeInode("linkfile"))
|
||||
if (is_LargeInode("linkfile")) {
|
||||
strncat(result,
|
||||
"bsdcpio: linkfile: large inode number truncated: "
|
||||
"Numerical result out of range\n",
|
||||
"bsdcpio: linkfile: large inode number truncated: ",
|
||||
sizeof(result) - strlen(result) -1);
|
||||
strncat(result,
|
||||
strerror(ERANGE),
|
||||
sizeof(result) - strlen(result) -1);
|
||||
strncat(result,
|
||||
"\n",
|
||||
sizeof(result) - strlen(result) -1);
|
||||
}
|
||||
|
||||
/* Symlink to above file. */
|
||||
if (canSymlink()) {
|
||||
assertMakeSymlink("symlink", "file");
|
||||
assertMakeSymlink("symlink", "file", 0);
|
||||
fprintf(filelist, "symlink\n");
|
||||
if (is_LargeInode("symlink"))
|
||||
if (is_LargeInode("symlink")) {
|
||||
strncat(result,
|
||||
"bsdcpio: symlink: large inode number truncated: "
|
||||
"Numerical result out of range\n",
|
||||
"bsdcpio: symlink: large inode number truncated: ",
|
||||
sizeof(result) - strlen(result) -1);
|
||||
strncat(result,
|
||||
strerror(ERANGE),
|
||||
sizeof(result) - strlen(result) -1);
|
||||
strncat(result,
|
||||
"\n",
|
||||
sizeof(result) - strlen(result) -1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Another file with different permissions. */
|
||||
assertMakeFile("file2", 0777, "1234567890");
|
||||
fprintf(filelist, "file2\n");
|
||||
if (is_LargeInode("file2"))
|
||||
if (is_LargeInode("file2")) {
|
||||
strncat(result,
|
||||
"bsdcpio: file2: large inode number truncated: "
|
||||
"Numerical result out of range\n",
|
||||
"bsdcpio: file2: large inode number truncated: ",
|
||||
sizeof(result) - strlen(result) -1);
|
||||
strncat(result,
|
||||
strerror(ERANGE),
|
||||
sizeof(result) - strlen(result) -1);
|
||||
strncat(result,
|
||||
"\n",
|
||||
sizeof(result) - strlen(result) -1);
|
||||
}
|
||||
|
||||
/* Directory. */
|
||||
assertMakeDir("dir", 0775);
|
||||
fprintf(filelist, "dir\n");
|
||||
if (is_LargeInode("dir"))
|
||||
if (is_LargeInode("dir")) {
|
||||
strncat(result,
|
||||
"bsdcpio: dir: large inode number truncated: "
|
||||
"Numerical result out of range\n",
|
||||
"bsdcpio: dir: large inode number truncated: ",
|
||||
sizeof(result) - strlen(result) -1);
|
||||
strncat(result,
|
||||
strerror(ERANGE),
|
||||
sizeof(result) - strlen(result) -1);
|
||||
strncat(result,
|
||||
"\n",
|
||||
sizeof(result) - strlen(result) -1);
|
||||
}
|
||||
strncat(result, "2 blocks\n", sizeof(result) - strlen(result) -1);
|
||||
|
||||
/* All done. */
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
begin 644 test_extract.cpio.zst
|
||||
M*+4O_01090,`,@41%X")&@#'G6T\K16_MR)#=DK)5:.1,2J0HY2"!(1!`!7R
|
||||
M$(UB`2"*D41;J2UF&)<0!Y7X'TU<%W.\W^R]GO-WW^OO^QX0`%P<]30-!#U`
|
||||
?!KD!`#XP,_`U4`HT3+RF:#!7Y\V@R)5"7P"^;WEUK@``
|
||||
`
|
||||
end
|
|
@ -0,0 +1,48 @@
|
|||
/*-
|
||||
* Copyright (c) 2017 Sean Purcell
|
||||
* 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_zstd)
|
||||
{
|
||||
const char *reffile = "test_extract.cpio.zst";
|
||||
int f;
|
||||
|
||||
extract_reference_file(reffile);
|
||||
f = systemf("%s -it < %s >test.out 2>test.err", testprog, reffile);
|
||||
if (f == 0 || canZstd()) {
|
||||
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 zstd is not supported on this platform");
|
||||
}
|
||||
}
|
|
@ -114,7 +114,7 @@ DEFINE_TEST(test_format_newc)
|
|||
|
||||
/* "symlink" */
|
||||
if (canSymlink()) {
|
||||
assertMakeSymlink("symlink", "file1");
|
||||
assertMakeSymlink("symlink", "file1", 0);
|
||||
fprintf(list, "symlink\n");
|
||||
}
|
||||
|
||||
|
@ -124,26 +124,42 @@ DEFINE_TEST(test_format_newc)
|
|||
|
||||
/* Setup result message. */
|
||||
memset(result, 0, sizeof(result));
|
||||
if (is_LargeInode("file1"))
|
||||
if (is_LargeInode("file1")) {
|
||||
strncat(result,
|
||||
"bsdcpio: file1: large inode number truncated: "
|
||||
"Numerical result out of range\n",
|
||||
"bsdcpio: file1: large inode number truncated: ",
|
||||
sizeof(result) - strlen(result) -1);
|
||||
if (canSymlink() && is_LargeInode("symlink"))
|
||||
strncat(result, strerror(ERANGE),
|
||||
sizeof(result) - strlen(result) -1);
|
||||
strncat(result, "\n",
|
||||
sizeof(result) - strlen(result) -1);
|
||||
}
|
||||
if (canSymlink() && is_LargeInode("symlink")) {
|
||||
strncat(result,
|
||||
"bsdcpio: symlink: large inode number truncated: "
|
||||
"Numerical result out of range\n",
|
||||
"bsdcpio: symlink: large inode number truncated: ",
|
||||
sizeof(result) - strlen(result) -1);
|
||||
if (is_LargeInode("dir"))
|
||||
strncat(result, strerror(ERANGE),
|
||||
sizeof(result) - strlen(result) -1);
|
||||
strncat(result, "\n",
|
||||
sizeof(result) - strlen(result) -1);
|
||||
}
|
||||
if (is_LargeInode("dir")) {
|
||||
strncat(result,
|
||||
"bsdcpio: dir: large inode number truncated: "
|
||||
"Numerical result out of range\n",
|
||||
"bsdcpio: dir: large inode number truncated: ",
|
||||
sizeof(result) - strlen(result) -1);
|
||||
if (is_LargeInode("hardlink"))
|
||||
strncat(result, strerror(ERANGE),
|
||||
sizeof(result) - strlen(result) -1);
|
||||
strncat(result, "\n",
|
||||
sizeof(result) - strlen(result) -1);
|
||||
}
|
||||
if (is_LargeInode("hardlink")) {
|
||||
strncat(result,
|
||||
"bsdcpio: hardlink: large inode number truncated: "
|
||||
"Numerical result out of range\n",
|
||||
"bsdcpio: hardlink: large inode number truncated: ",
|
||||
sizeof(result) - strlen(result) -1);
|
||||
strncat(result, strerror(ERANGE),
|
||||
sizeof(result) - strlen(result) -1);
|
||||
strncat(result, "\n",
|
||||
sizeof(result) - strlen(result) -1);
|
||||
}
|
||||
|
||||
/* Record some facts about what we just created: */
|
||||
now = time(NULL); /* They were all created w/in last two seconds. */
|
||||
|
@ -217,7 +233,12 @@ DEFINE_TEST(test_format_newc)
|
|||
assert(is_hex(e, 110));
|
||||
assertEqualMem(e + 0, "070701", 6); /* Magic */
|
||||
assert(is_hex(e + 6, 8)); /* ino */
|
||||
#if defined(_WIN32) && !defined(CYGWIN)
|
||||
/* Mode: Group members bits and others bits do not work. */
|
||||
assertEqualInt(0xa180, from_hex(e + 14, 8) & 0xffc0);
|
||||
#else
|
||||
assertEqualInt(0xa1ff, from_hex(e + 14, 8)); /* Mode */
|
||||
#endif
|
||||
assertEqualInt(from_hex(e + 22, 8), uid); /* uid */
|
||||
assertEqualInt(gid, from_hex(e + 30, 8)); /* gid */
|
||||
assertEqualMem(e + 38, "00000001", 8); /* nlink */
|
||||
|
|
|
@ -71,7 +71,7 @@ unpack_test(const char *from, const char *options, const char *se)
|
|||
|
||||
/* Symlink */
|
||||
if (canSymlink())
|
||||
assertIsSymlink("symlink", "file");
|
||||
assertIsSymlink("symlink", "file", 0);
|
||||
|
||||
/* dir */
|
||||
assertIsDir("dir", 0775);
|
||||
|
|
|
@ -30,8 +30,10 @@ __FBSDID("$FreeBSD: src/usr.bin/cpio/test/test_option_L.c,v 1.2 2008/08/24 06:21
|
|||
* tests won't run on Windows. */
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
#define CAT "type"
|
||||
#define SEP "\\"
|
||||
#else
|
||||
#define CAT "cat"
|
||||
#define SEP "/"
|
||||
#endif
|
||||
|
||||
DEFINE_TEST(test_option_L_upper)
|
||||
|
@ -51,7 +53,7 @@ DEFINE_TEST(test_option_L_upper)
|
|||
fprintf(filelist, "file\n");
|
||||
|
||||
/* Symlink to above file. */
|
||||
assertMakeSymlink("symlink", "file");
|
||||
assertMakeSymlink("symlink", "file", 0);
|
||||
fprintf(filelist, "symlink\n");
|
||||
|
||||
fclose(filelist);
|
||||
|
@ -61,7 +63,7 @@ DEFINE_TEST(test_option_L_upper)
|
|||
assertTextFileContents("1 block\n", "copy.err");
|
||||
|
||||
failure("Regular -p without -L should preserve symlinks.");
|
||||
assertIsSymlink("copy/symlink", NULL);
|
||||
assertIsSymlink("copy/symlink", NULL, 0);
|
||||
|
||||
r = systemf(CAT " filelist | %s -pd -L copy-L >copy-L.out 2>copy-L.err", testprog);
|
||||
assertEqualInt(r, 0);
|
||||
|
@ -77,13 +79,14 @@ DEFINE_TEST(test_option_L_upper)
|
|||
|
||||
assertMakeDir("unpack", 0755);
|
||||
assertChdir("unpack");
|
||||
r = systemf(CAT " ../archive.out | %s -i >unpack.out 2>unpack.err", testprog);
|
||||
r = systemf(CAT " .." SEP "archive.out | %s -i >unpack.out 2>unpack.err", testprog);
|
||||
|
||||
failure("Error invoking %s -i", testprog);
|
||||
assertEqualInt(r, 0);
|
||||
assertTextFileContents("1 block\n", "unpack.err");
|
||||
assertChdir("..");
|
||||
|
||||
assertIsSymlink("unpack/symlink", NULL);
|
||||
assertIsSymlink("unpack/symlink", NULL, 0);
|
||||
|
||||
r = systemf(CAT " filelist | %s -oL >archive-L.out 2>archive-L.err", testprog);
|
||||
failure("Error invoking %s -oL", testprog);
|
||||
|
@ -92,7 +95,8 @@ DEFINE_TEST(test_option_L_upper)
|
|||
|
||||
assertMakeDir("unpack-L", 0755);
|
||||
assertChdir("unpack-L");
|
||||
r = systemf(CAT " ../archive-L.out | %s -i >unpack-L.out 2>unpack-L.err", testprog);
|
||||
r = systemf(CAT " .." SEP "archive-L.out | %s -i >unpack-L.out 2>unpack-L.err", testprog);
|
||||
|
||||
failure("Error invoking %s -i < archive-L.out", testprog);
|
||||
assertEqualInt(r, 0);
|
||||
assertTextFileContents("1 block\n", "unpack-L.err");
|
||||
|
|
|
@ -43,17 +43,18 @@ DEFINE_TEST(test_option_Z_upper)
|
|||
if (strstr(p, "compression not available") != NULL) {
|
||||
skipping("This version of bsdcpio was compiled "
|
||||
"without compress support");
|
||||
free(p);
|
||||
return;
|
||||
}
|
||||
failure("-Z option is broken");
|
||||
assertEqualInt(r, 0);
|
||||
goto done;
|
||||
free(p);
|
||||
return;
|
||||
}
|
||||
free(p);
|
||||
/* Check that the archive file has a compress signature. */
|
||||
p = slurpfile(&s, "archive.out");
|
||||
assert(s > 2);
|
||||
assertEqualMem(p, "\x1f\x9d", 2);
|
||||
done:
|
||||
free(p);
|
||||
}
|
||||
|
|
|
@ -71,8 +71,13 @@ test_create(void)
|
|||
* #ifdef this section out. Most of the test below is
|
||||
* still valid. */
|
||||
memset(×, 0, sizeof(times));
|
||||
#if defined(_WIN32) && !defined(CYGWIN)
|
||||
times.actime = 86400;
|
||||
times.modtime = 86400;
|
||||
#else
|
||||
times.actime = 1;
|
||||
times.modtime = 3;
|
||||
#endif
|
||||
assertEqualInt(0, utime(files[i].name, ×));
|
||||
|
||||
/* Record whatever atime the file ended up with. */
|
||||
|
@ -96,7 +101,8 @@ DEFINE_TEST(test_option_a)
|
|||
test_create();
|
||||
|
||||
/* Sanity check; verify that atimes really do get modified. */
|
||||
assert((p = slurpfile(NULL, "f0")) != NULL);
|
||||
p = slurpfile(NULL, "f0");
|
||||
assert(p != NULL);
|
||||
free(p);
|
||||
assertEqualInt(0, stat("f0", &st));
|
||||
if (st.st_atime == files[0].atime_sec) {
|
||||
|
|
|
@ -42,6 +42,7 @@ DEFINE_TEST(test_option_b64encode)
|
|||
p = slurpfile(&s, "archive.out");
|
||||
assert(s > 2);
|
||||
assertEqualMem(p, "begin-base64 644", 16);
|
||||
free(p);
|
||||
|
||||
/* Archive it with uuencode only. */
|
||||
assertEqualInt(0,
|
||||
|
@ -51,4 +52,5 @@ DEFINE_TEST(test_option_b64encode)
|
|||
p = slurpfile(&s, "archive.out");
|
||||
assert(s > 2);
|
||||
assertEqualMem(p, "begin-base64 644", 16);
|
||||
free(p);
|
||||
}
|
||||
|
|
|
@ -85,7 +85,7 @@ DEFINE_TEST(test_option_c)
|
|||
|
||||
/* "symlink" */
|
||||
if (canSymlink()) {
|
||||
assertMakeSymlink("symlink", "file");
|
||||
assertMakeSymlink("symlink", "file", 0);
|
||||
fprintf(filelist, "symlink\n");
|
||||
}
|
||||
|
||||
|
|
|
@ -44,9 +44,10 @@ DEFINE_TEST(test_option_grzip)
|
|||
systemf("echo f | %s -o --grzip >archive.out 2>archive.err",
|
||||
testprog));
|
||||
p = slurpfile(&s, "archive.err");
|
||||
p[s] = '\0';
|
||||
free(p);
|
||||
/* Check that the archive file has an grzip signature. */
|
||||
p = slurpfile(&s, "archive.out");
|
||||
assert(s > 2);
|
||||
assertEqualMem(p, "GRZipII\x00\x02\x04:)", 12);
|
||||
free(p);
|
||||
}
|
||||
|
|
|
@ -44,9 +44,10 @@ DEFINE_TEST(test_option_lrzip)
|
|||
systemf("echo f | %s -o --lrzip >archive.out 2>archive.err",
|
||||
testprog));
|
||||
p = slurpfile(&s, "archive.err");
|
||||
p[s] = '\0';
|
||||
free(p);
|
||||
/* Check that the archive file has an lzma signature. */
|
||||
p = slurpfile(&s, "archive.out");
|
||||
assert(s > 2);
|
||||
assertEqualMem(p, "LRZI\x00", 5);
|
||||
free(p);
|
||||
}
|
||||
|
|
|
@ -43,6 +43,7 @@ DEFINE_TEST(test_option_lz4)
|
|||
if (strstr(p, "compression not available") != NULL) {
|
||||
skipping("This version of bsdcpio was compiled "
|
||||
"without lz4 support");
|
||||
free(p);
|
||||
return;
|
||||
}
|
||||
/* POSIX permits different handling of the spawnp
|
||||
|
@ -52,6 +53,7 @@ DEFINE_TEST(test_option_lz4)
|
|||
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.");
|
||||
free(p);
|
||||
return;
|
||||
}
|
||||
/* Some systems successfully spawn the new process,
|
||||
|
@ -61,6 +63,7 @@ DEFINE_TEST(test_option_lz4)
|
|||
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.");
|
||||
free(p);
|
||||
return;
|
||||
}
|
||||
/* On some systems the error won't be detected until closing
|
||||
|
@ -68,14 +71,18 @@ DEFINE_TEST(test_option_lz4)
|
|||
if (strstr(p, "Error closing") != NULL && !canLz4()) {
|
||||
skipping("This version of bsdcpio uses an external lz4 program "
|
||||
"but no such program is available on this system.");
|
||||
free(p);
|
||||
return;
|
||||
}
|
||||
failure("--lz4 option is broken: %s", p);
|
||||
free(p);
|
||||
assertEqualInt(r, 0);
|
||||
return;
|
||||
}
|
||||
free(p);
|
||||
/* Check that the archive file has an lz4 signature. */
|
||||
p = slurpfile(&s, "archive.out");
|
||||
assert(s > 2);
|
||||
assertEqualMem(p, "\x04\x22\x4d\x18", 4);
|
||||
free(p);
|
||||
}
|
||||
|
|
|
@ -43,14 +43,18 @@ DEFINE_TEST(test_option_lzma)
|
|||
if (strstr(p, "compression not available") != NULL) {
|
||||
skipping("This version of bsdcpio was compiled "
|
||||
"without lzma support");
|
||||
free(p);
|
||||
return;
|
||||
}
|
||||
failure("--lzma option is broken");
|
||||
assertEqualInt(r, 0);
|
||||
free(p);
|
||||
return;
|
||||
}
|
||||
free(p);
|
||||
/* Check that the archive file has an lzma signature. */
|
||||
p = slurpfile(&s, "archive.out");
|
||||
assert(s > 2);
|
||||
assertEqualMem(p, "\x5d\00\00", 3);
|
||||
free(p);
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ DEFINE_TEST(test_option_lzop)
|
|||
r = systemf("echo f | %s -o --lzop >archive.out 2>archive.err",
|
||||
testprog);
|
||||
p = slurpfile(&s, "archive.err");
|
||||
p[s] = '\0';
|
||||
free(p);
|
||||
if (r != 0) {
|
||||
if (!canLzop()) {
|
||||
skipping("lzop is not supported on this platform");
|
||||
|
@ -53,4 +53,5 @@ DEFINE_TEST(test_option_lzop)
|
|||
p = slurpfile(&s, "archive.out");
|
||||
assert(s > 2);
|
||||
assertEqualMem(p, "\x89\x4c\x5a\x4f\x00\x0d\x0a\x1a\x0a", 9);
|
||||
free(p);
|
||||
}
|
||||
|
|
|
@ -88,11 +88,11 @@ DEFINE_TEST(test_option_t)
|
|||
setlocale(LC_ALL, "");
|
||||
#endif
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
strftime(date2, sizeof(date), "%b %d %Y", localtime(&mtime));
|
||||
_snprintf(date, sizeof(date)-1, "%12s file", date2);
|
||||
strftime(date2, sizeof(date2)-1, "%b %d %Y", localtime(&mtime));
|
||||
_snprintf(date, sizeof(date)-1, "%12.12s file", date2);
|
||||
#else
|
||||
strftime(date2, sizeof(date), "%b %e %Y", localtime(&mtime));
|
||||
snprintf(date, sizeof(date)-1, "%12s file", date2);
|
||||
strftime(date2, sizeof(date2)-1, "%b %e %Y", localtime(&mtime));
|
||||
snprintf(date, sizeof(date)-1, "%12.12s file", date2);
|
||||
#endif
|
||||
assertEqualMem(p + 42, date, strlen(date));
|
||||
free(p);
|
||||
|
|
|
@ -42,6 +42,7 @@ DEFINE_TEST(test_option_uuencode)
|
|||
p = slurpfile(&s, "archive.out");
|
||||
assert(s > 2);
|
||||
assertEqualMem(p, "begin 644", 9);
|
||||
free(p);
|
||||
|
||||
/* Archive it with uuencode only. */
|
||||
assertEqualInt(0,
|
||||
|
@ -51,4 +52,5 @@ DEFINE_TEST(test_option_uuencode)
|
|||
p = slurpfile(&s, "archive.out");
|
||||
assert(s > 2);
|
||||
assertEqualMem(p, "begin 644", 9);
|
||||
free(p);
|
||||
}
|
||||
|
|
|
@ -44,14 +44,18 @@ DEFINE_TEST(test_option_xz)
|
|||
if (strstr(p, "compression not available") != NULL) {
|
||||
skipping("This version of bsdcpio was compiled "
|
||||
"without xz support");
|
||||
free(p);
|
||||
return;
|
||||
}
|
||||
free(p);
|
||||
failure("--xz option is broken");
|
||||
assertEqualInt(r, 0);
|
||||
return;
|
||||
}
|
||||
free(p);
|
||||
/* Check that the archive file has an xz signature. */
|
||||
p = slurpfile(&s, "archive.out");
|
||||
assert(s > 2);
|
||||
assertEqualMem(p, "\xFD\x37\x7A\x58\x5A\x00", 6);
|
||||
free(p);
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ DEFINE_TEST(test_option_y)
|
|||
r = systemf("echo f | %s -oy >archive.out 2>archive.err",
|
||||
testprog);
|
||||
p = slurpfile(&s, "archive.err");
|
||||
p[s] = '\0';
|
||||
free(p);
|
||||
if (r != 0) {
|
||||
if (!canBzip2()) {
|
||||
skipping("bzip2 is not supported on this platform");
|
||||
|
@ -46,14 +46,12 @@ DEFINE_TEST(test_option_y)
|
|||
}
|
||||
failure("-y option is broken");
|
||||
assertEqualInt(r, 0);
|
||||
goto done;
|
||||
return;
|
||||
}
|
||||
assertTextFileContents("1 block\n", "archive.err");
|
||||
/* Check that the archive file has a bzip2 signature. */
|
||||
free(p);
|
||||
p = slurpfile(&s, "archive.out");
|
||||
assert(s > 2);
|
||||
assertEqualMem(p, "BZh9", 4);
|
||||
done:
|
||||
free(p);
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ DEFINE_TEST(test_option_z)
|
|||
r = systemf("echo f | %s -oz >archive.out 2>archive.err",
|
||||
testprog);
|
||||
p = slurpfile(&s, "archive.err");
|
||||
p[s] = '\0';
|
||||
free(p);
|
||||
if (r != 0) {
|
||||
if (!canGzip()) {
|
||||
skipping("gzip is not supported on this platform");
|
||||
|
@ -52,4 +52,5 @@ DEFINE_TEST(test_option_z)
|
|||
p = slurpfile(&s, "archive.out");
|
||||
assert(s > 4);
|
||||
assertEqualMem(p, "\x1f\x8b\x08\x00", 4);
|
||||
free(p);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
/*-
|
||||
* Copyright (c) 2017 Sean Purcell
|
||||
* 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_zstd)
|
||||
{
|
||||
char *p;
|
||||
int r;
|
||||
size_t s;
|
||||
|
||||
/* Create a file. */
|
||||
assertMakeFile("f", 0644, "a");
|
||||
|
||||
/* Archive it with zstd compression. */
|
||||
r = systemf("echo f | %s -o --zstd >archive.out 2>archive.err",
|
||||
testprog);
|
||||
p = slurpfile(&s, "archive.err");
|
||||
p[s] = '\0';
|
||||
if (r != 0) {
|
||||
if (strstr(p, "Unsupported compression") != NULL) {
|
||||
skipping("This version of bsdcpio was compiled "
|
||||
"without zstd support");
|
||||
goto done;
|
||||
}
|
||||
/* 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 && !canZstd()) {
|
||||
skipping("This version of bsdcpio uses an external zstd program "
|
||||
"but no such program is available on this system.");
|
||||
goto done;
|
||||
}
|
||||
/* 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 && !canZstd()) {
|
||||
skipping("This version of bsdcpio uses an external zstd program "
|
||||
"but no such program is available on this system.");
|
||||
goto done;
|
||||
}
|
||||
/* On some systems the error won't be detected until closing
|
||||
time, by a 127 exit error returned by waitpid. */
|
||||
if (strstr(p, "Error closing") != NULL && !canZstd()) {
|
||||
skipping("This version of bsdcpio uses an external zstd program "
|
||||
"but no such program is available on this system.");
|
||||
return;
|
||||
}
|
||||
failure("--zstd option is broken: %s", p);
|
||||
assertEqualInt(r, 0);
|
||||
goto done;
|
||||
}
|
||||
free(p);
|
||||
/* Check that the archive file has an zstd signature. */
|
||||
p = slurpfile(&s, "archive.out");
|
||||
assert(s > 2);
|
||||
assertEqualMem(p, "\x28\xb5\x2f\xfd", 4);
|
||||
|
||||
done:
|
||||
free(p);
|
||||
}
|
|
@ -36,7 +36,7 @@
|
|||
* assert that ARCHIVE_VERSION_NUMBER >= 2012108.
|
||||
*/
|
||||
/* Note: Compiler will complain if this does not match archive_entry.h! */
|
||||
#define ARCHIVE_VERSION_NUMBER 3003002
|
||||
#define ARCHIVE_VERSION_NUMBER 3004000
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <stddef.h> /* for wchar_t */
|
||||
|
@ -155,7 +155,7 @@ __LA_DECL int archive_version_number(void);
|
|||
/*
|
||||
* Textual name/version of the library, useful for version displays.
|
||||
*/
|
||||
#define ARCHIVE_VERSION_ONLY_STRING "3.3.2dev"
|
||||
#define ARCHIVE_VERSION_ONLY_STRING "3.4.0"
|
||||
#define ARCHIVE_VERSION_STRING "libarchive " ARCHIVE_VERSION_ONLY_STRING
|
||||
__LA_DECL const char * archive_version_string(void);
|
||||
|
||||
|
@ -177,6 +177,7 @@ __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);
|
||||
__LA_DECL const char * archive_libzstd_version(void);
|
||||
|
||||
/* Declare our basic types. */
|
||||
struct archive;
|
||||
|
@ -276,6 +277,7 @@ typedef const char *archive_passphrase_callback(struct archive *,
|
|||
#define ARCHIVE_FILTER_LZOP 11
|
||||
#define ARCHIVE_FILTER_GRZIP 12
|
||||
#define ARCHIVE_FILTER_LZ4 13
|
||||
#define ARCHIVE_FILTER_ZSTD 14
|
||||
|
||||
#if ARCHIVE_VERSION_NUMBER < 4000000
|
||||
#define ARCHIVE_COMPRESSION_NONE ARCHIVE_FILTER_NONE
|
||||
|
@ -338,6 +340,7 @@ typedef const char *archive_passphrase_callback(struct archive *,
|
|||
#define ARCHIVE_FORMAT_RAR 0xD0000
|
||||
#define ARCHIVE_FORMAT_7ZIP 0xE0000
|
||||
#define ARCHIVE_FORMAT_WARC 0xF0000
|
||||
#define ARCHIVE_FORMAT_RAR_V5 0x100000
|
||||
|
||||
/*
|
||||
* Codes returned by archive_read_format_capabilities().
|
||||
|
@ -433,6 +436,7 @@ __LA_DECL int archive_read_support_filter_program_signature
|
|||
__LA_DECL int archive_read_support_filter_rpm(struct archive *);
|
||||
__LA_DECL int archive_read_support_filter_uu(struct archive *);
|
||||
__LA_DECL int archive_read_support_filter_xz(struct archive *);
|
||||
__LA_DECL int archive_read_support_filter_zstd(struct archive *);
|
||||
|
||||
__LA_DECL int archive_read_support_format_7zip(struct archive *);
|
||||
__LA_DECL int archive_read_support_format_all(struct archive *);
|
||||
|
@ -446,6 +450,7 @@ __LA_DECL int archive_read_support_format_iso9660(struct archive *);
|
|||
__LA_DECL int archive_read_support_format_lha(struct archive *);
|
||||
__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_rar5(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 *);
|
||||
|
@ -778,6 +783,7 @@ __LA_DECL int archive_write_add_filter_program(struct archive *,
|
|||
const char *cmd);
|
||||
__LA_DECL int archive_write_add_filter_uuencode(struct archive *);
|
||||
__LA_DECL int archive_write_add_filter_xz(struct archive *);
|
||||
__LA_DECL int archive_write_add_filter_zstd(struct archive *);
|
||||
|
||||
|
||||
/* A convenience function to set the format based on the code or name. */
|
||||
|
@ -1089,6 +1095,8 @@ __LA_DECL int archive_match_excluded(struct archive *,
|
|||
*/
|
||||
__LA_DECL int archive_match_path_excluded(struct archive *,
|
||||
struct archive_entry *);
|
||||
/* Control recursive inclusion of directory content when directory is included. Default on. */
|
||||
__LA_DECL int archive_match_set_inclusion_recursion(struct archive *, int);
|
||||
/* Add exclusion pathname pattern. */
|
||||
__LA_DECL int archive_match_exclude_pattern(struct archive *, const char *);
|
||||
__LA_DECL int archive_match_exclude_pattern_w(struct archive *,
|
||||
|
|
|
@ -138,14 +138,10 @@ archive_acl_clear(struct archive_acl *acl)
|
|||
free(acl->acl_head);
|
||||
acl->acl_head = ap;
|
||||
}
|
||||
if (acl->acl_text_w != NULL) {
|
||||
free(acl->acl_text_w);
|
||||
acl->acl_text_w = NULL;
|
||||
}
|
||||
if (acl->acl_text != NULL) {
|
||||
free(acl->acl_text);
|
||||
acl->acl_text = NULL;
|
||||
}
|
||||
free(acl->acl_text_w);
|
||||
acl->acl_text_w = NULL;
|
||||
free(acl->acl_text);
|
||||
acl->acl_text = NULL;
|
||||
acl->acl_p = NULL;
|
||||
acl->acl_types = 0;
|
||||
acl->acl_state = 0; /* Not counting. */
|
||||
|
@ -324,14 +320,10 @@ acl_new_entry(struct archive_acl *acl,
|
|||
return (NULL);
|
||||
}
|
||||
|
||||
if (acl->acl_text_w != NULL) {
|
||||
free(acl->acl_text_w);
|
||||
acl->acl_text_w = NULL;
|
||||
}
|
||||
if (acl->acl_text != NULL) {
|
||||
free(acl->acl_text);
|
||||
acl->acl_text = NULL;
|
||||
}
|
||||
free(acl->acl_text_w);
|
||||
acl->acl_text_w = NULL;
|
||||
free(acl->acl_text);
|
||||
acl->acl_text = NULL;
|
||||
|
||||
/*
|
||||
* If there's a matching entry already in the list, overwrite it.
|
||||
|
@ -753,8 +745,10 @@ archive_acl_to_text_w(struct archive_acl *acl, ssize_t *text_len, int flags,
|
|||
append_entry_w(&wp, prefix, ap->type, ap->tag, flags,
|
||||
wname, ap->permset, id);
|
||||
count++;
|
||||
} else if (r < 0 && errno == ENOMEM)
|
||||
} else if (r < 0 && errno == ENOMEM) {
|
||||
free(ws);
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/* Add terminating character */
|
||||
|
@ -975,8 +969,10 @@ archive_acl_to_text_l(struct archive_acl *acl, ssize_t *text_len, int flags,
|
|||
prefix = NULL;
|
||||
r = archive_mstring_get_mbs_l(
|
||||
&ap->name, &name, &len, sc);
|
||||
if (r != 0)
|
||||
if (r != 0) {
|
||||
free(s);
|
||||
return (NULL);
|
||||
}
|
||||
if (count > 0)
|
||||
*p++ = separator;
|
||||
if (name == NULL ||
|
||||
|
@ -1159,6 +1155,7 @@ archive_acl_from_text_w(struct archive_acl *acl, const wchar_t *text,
|
|||
switch (want_type) {
|
||||
case ARCHIVE_ENTRY_ACL_TYPE_POSIX1E:
|
||||
want_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
|
||||
__LA_FALLTHROUGH;
|
||||
case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
|
||||
case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
|
||||
numfields = 5;
|
||||
|
@ -1580,17 +1577,29 @@ next_field_w(const wchar_t **wp, const wchar_t **start,
|
|||
|
||||
/* Scan for the separator. */
|
||||
while (**wp != L'\0' && **wp != L',' && **wp != L':' &&
|
||||
**wp != L'\n') {
|
||||
**wp != L'\n' && **wp != L'#') {
|
||||
(*wp)++;
|
||||
}
|
||||
*sep = **wp;
|
||||
|
||||
/* Trim trailing whitespace to locate end of field. */
|
||||
*end = *wp - 1;
|
||||
while (**end == L' ' || **end == L'\t' || **end == L'\n') {
|
||||
(*end)--;
|
||||
/* Locate end of field, trim trailing whitespace if necessary */
|
||||
if (*wp == *start) {
|
||||
*end = *wp;
|
||||
} else {
|
||||
*end = *wp - 1;
|
||||
while (**end == L' ' || **end == L'\t' || **end == L'\n') {
|
||||
(*end)--;
|
||||
}
|
||||
(*end)++;
|
||||
}
|
||||
|
||||
/* Handle in-field comments */
|
||||
if (*sep == L'#') {
|
||||
while (**wp != L'\0' && **wp != L',' && **wp != L'\n') {
|
||||
(*wp)++;
|
||||
}
|
||||
*sep = **wp;
|
||||
}
|
||||
(*end)++;
|
||||
|
||||
/* Adjust scanner location. */
|
||||
if (**wp != L'\0')
|
||||
|
@ -1626,6 +1635,7 @@ archive_acl_from_text_l(struct archive_acl *acl, const char *text,
|
|||
switch (want_type) {
|
||||
case ARCHIVE_ENTRY_ACL_TYPE_POSIX1E:
|
||||
want_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
|
||||
__LA_FALLTHROUGH;
|
||||
case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
|
||||
case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
|
||||
numfields = 5;
|
||||
|
@ -1640,7 +1650,7 @@ archive_acl_from_text_l(struct archive_acl *acl, const char *text,
|
|||
ret = ARCHIVE_OK;
|
||||
types = 0;
|
||||
|
||||
while (text != NULL && *text != '\0') {
|
||||
while (text != NULL && *text != '\0') {
|
||||
/*
|
||||
* Parse the fields out of the next entry,
|
||||
* advance 'text' to start of next entry.
|
||||
|
@ -1705,6 +1715,11 @@ archive_acl_from_text_l(struct archive_acl *acl, const char *text,
|
|||
st = field[n].start + 1;
|
||||
len = field[n].end - field[n].start;
|
||||
|
||||
if (len == 0) {
|
||||
ret = ARCHIVE_WARN;
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (*s) {
|
||||
case 'u':
|
||||
if (len == 1 || (len == 4
|
||||
|
@ -2051,17 +2066,30 @@ next_field(const char **p, const char **start,
|
|||
*start = *p;
|
||||
|
||||
/* Scan for the separator. */
|
||||
while (**p != '\0' && **p != ',' && **p != ':' && **p != '\n') {
|
||||
while (**p != '\0' && **p != ',' && **p != ':' && **p != '\n' &&
|
||||
**p != '#') {
|
||||
(*p)++;
|
||||
}
|
||||
*sep = **p;
|
||||
|
||||
/* Trim trailing whitespace to locate end of field. */
|
||||
*end = *p - 1;
|
||||
while (**end == ' ' || **end == '\t' || **end == '\n') {
|
||||
(*end)--;
|
||||
/* Locate end of field, trim trailing whitespace if necessary */
|
||||
if (*p == *start) {
|
||||
*end = *p;
|
||||
} else {
|
||||
*end = *p - 1;
|
||||
while (**end == ' ' || **end == '\t' || **end == '\n') {
|
||||
(*end)--;
|
||||
}
|
||||
(*end)++;
|
||||
}
|
||||
|
||||
/* Handle in-field comments */
|
||||
if (*sep == '#') {
|
||||
while (**p != '\0' && **p != ',' && **p != '\n') {
|
||||
(*p)++;
|
||||
}
|
||||
*sep = **p;
|
||||
}
|
||||
(*end)++;
|
||||
|
||||
/* Adjust scanner location. */
|
||||
if (**p != '\0')
|
||||
|
|
|
@ -0,0 +1,194 @@
|
|||
/*
|
||||
BLAKE2 reference source code package - reference C implementations
|
||||
|
||||
Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the
|
||||
terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
|
||||
your option. The terms of these licenses can be found at:
|
||||
|
||||
- CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
|
||||
- OpenSSL license : https://www.openssl.org/source/license.html
|
||||
- Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
More information about the BLAKE2 hash function can be found at
|
||||
https://blake2.net.
|
||||
*/
|
||||
#ifndef BLAKE2_H
|
||||
#define BLAKE2_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define BLAKE2_PACKED(x) __pragma(pack(push, 1)) x __pragma(pack(pop))
|
||||
#else
|
||||
#define BLAKE2_PACKED(x) x __attribute__((packed))
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
enum blake2s_constant
|
||||
{
|
||||
BLAKE2S_BLOCKBYTES = 64,
|
||||
BLAKE2S_OUTBYTES = 32,
|
||||
BLAKE2S_KEYBYTES = 32,
|
||||
BLAKE2S_SALTBYTES = 8,
|
||||
BLAKE2S_PERSONALBYTES = 8
|
||||
};
|
||||
|
||||
enum blake2b_constant
|
||||
{
|
||||
BLAKE2B_BLOCKBYTES = 128,
|
||||
BLAKE2B_OUTBYTES = 64,
|
||||
BLAKE2B_KEYBYTES = 64,
|
||||
BLAKE2B_SALTBYTES = 16,
|
||||
BLAKE2B_PERSONALBYTES = 16
|
||||
};
|
||||
|
||||
typedef struct blake2s_state__
|
||||
{
|
||||
uint32_t h[8];
|
||||
uint32_t t[2];
|
||||
uint32_t f[2];
|
||||
uint8_t buf[BLAKE2S_BLOCKBYTES];
|
||||
size_t buflen;
|
||||
size_t outlen;
|
||||
uint8_t last_node;
|
||||
} blake2s_state;
|
||||
|
||||
typedef struct blake2b_state__
|
||||
{
|
||||
uint64_t h[8];
|
||||
uint64_t t[2];
|
||||
uint64_t f[2];
|
||||
uint8_t buf[BLAKE2B_BLOCKBYTES];
|
||||
size_t buflen;
|
||||
size_t outlen;
|
||||
uint8_t last_node;
|
||||
} blake2b_state;
|
||||
|
||||
typedef struct blake2sp_state__
|
||||
{
|
||||
blake2s_state S[8][1];
|
||||
blake2s_state R[1];
|
||||
uint8_t buf[8 * BLAKE2S_BLOCKBYTES];
|
||||
size_t buflen;
|
||||
size_t outlen;
|
||||
} blake2sp_state;
|
||||
|
||||
typedef struct blake2bp_state__
|
||||
{
|
||||
blake2b_state S[4][1];
|
||||
blake2b_state R[1];
|
||||
uint8_t buf[4 * BLAKE2B_BLOCKBYTES];
|
||||
size_t buflen;
|
||||
size_t outlen;
|
||||
} blake2bp_state;
|
||||
|
||||
BLAKE2_PACKED(struct blake2s_param__
|
||||
{
|
||||
uint8_t digest_length; /* 1 */
|
||||
uint8_t key_length; /* 2 */
|
||||
uint8_t fanout; /* 3 */
|
||||
uint8_t depth; /* 4 */
|
||||
uint32_t leaf_length; /* 8 */
|
||||
uint32_t node_offset; /* 12 */
|
||||
uint16_t xof_length; /* 14 */
|
||||
uint8_t node_depth; /* 15 */
|
||||
uint8_t inner_length; /* 16 */
|
||||
/* uint8_t reserved[0]; */
|
||||
uint8_t salt[BLAKE2S_SALTBYTES]; /* 24 */
|
||||
uint8_t personal[BLAKE2S_PERSONALBYTES]; /* 32 */
|
||||
});
|
||||
|
||||
typedef struct blake2s_param__ blake2s_param;
|
||||
|
||||
BLAKE2_PACKED(struct blake2b_param__
|
||||
{
|
||||
uint8_t digest_length; /* 1 */
|
||||
uint8_t key_length; /* 2 */
|
||||
uint8_t fanout; /* 3 */
|
||||
uint8_t depth; /* 4 */
|
||||
uint32_t leaf_length; /* 8 */
|
||||
uint32_t node_offset; /* 12 */
|
||||
uint32_t xof_length; /* 16 */
|
||||
uint8_t node_depth; /* 17 */
|
||||
uint8_t inner_length; /* 18 */
|
||||
uint8_t reserved[14]; /* 32 */
|
||||
uint8_t salt[BLAKE2B_SALTBYTES]; /* 48 */
|
||||
uint8_t personal[BLAKE2B_PERSONALBYTES]; /* 64 */
|
||||
});
|
||||
|
||||
typedef struct blake2b_param__ blake2b_param;
|
||||
|
||||
typedef struct blake2xs_state__
|
||||
{
|
||||
blake2s_state S[1];
|
||||
blake2s_param P[1];
|
||||
} blake2xs_state;
|
||||
|
||||
typedef struct blake2xb_state__
|
||||
{
|
||||
blake2b_state S[1];
|
||||
blake2b_param P[1];
|
||||
} blake2xb_state;
|
||||
|
||||
/* Padded structs result in a compile-time error */
|
||||
enum {
|
||||
BLAKE2_DUMMY_1 = 1/(sizeof(blake2s_param) == BLAKE2S_OUTBYTES),
|
||||
BLAKE2_DUMMY_2 = 1/(sizeof(blake2b_param) == BLAKE2B_OUTBYTES)
|
||||
};
|
||||
|
||||
/* Streaming API */
|
||||
int blake2s_init( blake2s_state *S, size_t outlen );
|
||||
int blake2s_init_key( blake2s_state *S, size_t outlen, const void *key, size_t keylen );
|
||||
int blake2s_init_param( blake2s_state *S, const blake2s_param *P );
|
||||
int blake2s_update( blake2s_state *S, const void *in, size_t inlen );
|
||||
int blake2s_final( blake2s_state *S, void *out, size_t outlen );
|
||||
|
||||
int blake2b_init( blake2b_state *S, size_t outlen );
|
||||
int blake2b_init_key( blake2b_state *S, size_t outlen, const void *key, size_t keylen );
|
||||
int blake2b_init_param( blake2b_state *S, const blake2b_param *P );
|
||||
int blake2b_update( blake2b_state *S, const void *in, size_t inlen );
|
||||
int blake2b_final( blake2b_state *S, void *out, size_t outlen );
|
||||
|
||||
int blake2sp_init( blake2sp_state *S, size_t outlen );
|
||||
int blake2sp_init_key( blake2sp_state *S, size_t outlen, const void *key, size_t keylen );
|
||||
int blake2sp_update( blake2sp_state *S, const void *in, size_t inlen );
|
||||
int blake2sp_final( blake2sp_state *S, void *out, size_t outlen );
|
||||
|
||||
int blake2bp_init( blake2bp_state *S, size_t outlen );
|
||||
int blake2bp_init_key( blake2bp_state *S, size_t outlen, const void *key, size_t keylen );
|
||||
int blake2bp_update( blake2bp_state *S, const void *in, size_t inlen );
|
||||
int blake2bp_final( blake2bp_state *S, void *out, size_t outlen );
|
||||
|
||||
/* Variable output length API */
|
||||
int blake2xs_init( blake2xs_state *S, const size_t outlen );
|
||||
int blake2xs_init_key( blake2xs_state *S, const size_t outlen, const void *key, size_t keylen );
|
||||
int blake2xs_update( blake2xs_state *S, const void *in, size_t inlen );
|
||||
int blake2xs_final(blake2xs_state *S, void *out, size_t outlen);
|
||||
|
||||
int blake2xb_init( blake2xb_state *S, const size_t outlen );
|
||||
int blake2xb_init_key( blake2xb_state *S, const size_t outlen, const void *key, size_t keylen );
|
||||
int blake2xb_update( blake2xb_state *S, const void *in, size_t inlen );
|
||||
int blake2xb_final(blake2xb_state *S, void *out, size_t outlen);
|
||||
|
||||
/* Simple API */
|
||||
int blake2s( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
|
||||
int blake2b( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
|
||||
|
||||
int blake2sp( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
|
||||
int blake2bp( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
|
||||
|
||||
int blake2xs( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
|
||||
int blake2xb( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
|
||||
|
||||
/* This is simply an alias for blake2b */
|
||||
int blake2( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,160 @@
|
|||
/*
|
||||
BLAKE2 reference source code package - reference C implementations
|
||||
|
||||
Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the
|
||||
terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
|
||||
your option. The terms of these licenses can be found at:
|
||||
|
||||
- CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
|
||||
- OpenSSL license : https://www.openssl.org/source/license.html
|
||||
- Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
More information about the BLAKE2 hash function can be found at
|
||||
https://blake2.net.
|
||||
*/
|
||||
#ifndef BLAKE2_IMPL_H
|
||||
#define BLAKE2_IMPL_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#if !defined(__cplusplus) && (!defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L)
|
||||
#if defined(_MSC_VER)
|
||||
#define BLAKE2_INLINE __inline
|
||||
#elif defined(__GNUC__)
|
||||
#define BLAKE2_INLINE __inline__
|
||||
#else
|
||||
#define BLAKE2_INLINE
|
||||
#endif
|
||||
#else
|
||||
#define BLAKE2_INLINE inline
|
||||
#endif
|
||||
|
||||
static BLAKE2_INLINE uint32_t load32( const void *src )
|
||||
{
|
||||
#if defined(NATIVE_LITTLE_ENDIAN)
|
||||
uint32_t w;
|
||||
memcpy(&w, src, sizeof w);
|
||||
return w;
|
||||
#else
|
||||
const uint8_t *p = ( const uint8_t * )src;
|
||||
return (( uint32_t )( p[0] ) << 0) |
|
||||
(( uint32_t )( p[1] ) << 8) |
|
||||
(( uint32_t )( p[2] ) << 16) |
|
||||
(( uint32_t )( p[3] ) << 24) ;
|
||||
#endif
|
||||
}
|
||||
|
||||
static BLAKE2_INLINE uint64_t load64( const void *src )
|
||||
{
|
||||
#if defined(NATIVE_LITTLE_ENDIAN)
|
||||
uint64_t w;
|
||||
memcpy(&w, src, sizeof w);
|
||||
return w;
|
||||
#else
|
||||
const uint8_t *p = ( const uint8_t * )src;
|
||||
return (( uint64_t )( p[0] ) << 0) |
|
||||
(( uint64_t )( p[1] ) << 8) |
|
||||
(( uint64_t )( p[2] ) << 16) |
|
||||
(( uint64_t )( p[3] ) << 24) |
|
||||
(( uint64_t )( p[4] ) << 32) |
|
||||
(( uint64_t )( p[5] ) << 40) |
|
||||
(( uint64_t )( p[6] ) << 48) |
|
||||
(( uint64_t )( p[7] ) << 56) ;
|
||||
#endif
|
||||
}
|
||||
|
||||
static BLAKE2_INLINE uint16_t load16( const void *src )
|
||||
{
|
||||
#if defined(NATIVE_LITTLE_ENDIAN)
|
||||
uint16_t w;
|
||||
memcpy(&w, src, sizeof w);
|
||||
return w;
|
||||
#else
|
||||
const uint8_t *p = ( const uint8_t * )src;
|
||||
return ( uint16_t )((( uint32_t )( p[0] ) << 0) |
|
||||
(( uint32_t )( p[1] ) << 8));
|
||||
#endif
|
||||
}
|
||||
|
||||
static BLAKE2_INLINE void store16( void *dst, uint16_t w )
|
||||
{
|
||||
#if defined(NATIVE_LITTLE_ENDIAN)
|
||||
memcpy(dst, &w, sizeof w);
|
||||
#else
|
||||
uint8_t *p = ( uint8_t * )dst;
|
||||
*p++ = ( uint8_t )w; w >>= 8;
|
||||
*p++ = ( uint8_t )w;
|
||||
#endif
|
||||
}
|
||||
|
||||
static BLAKE2_INLINE void store32( void *dst, uint32_t w )
|
||||
{
|
||||
#if defined(NATIVE_LITTLE_ENDIAN)
|
||||
memcpy(dst, &w, sizeof w);
|
||||
#else
|
||||
uint8_t *p = ( uint8_t * )dst;
|
||||
p[0] = (uint8_t)(w >> 0);
|
||||
p[1] = (uint8_t)(w >> 8);
|
||||
p[2] = (uint8_t)(w >> 16);
|
||||
p[3] = (uint8_t)(w >> 24);
|
||||
#endif
|
||||
}
|
||||
|
||||
static BLAKE2_INLINE void store64( void *dst, uint64_t w )
|
||||
{
|
||||
#if defined(NATIVE_LITTLE_ENDIAN)
|
||||
memcpy(dst, &w, sizeof w);
|
||||
#else
|
||||
uint8_t *p = ( uint8_t * )dst;
|
||||
p[0] = (uint8_t)(w >> 0);
|
||||
p[1] = (uint8_t)(w >> 8);
|
||||
p[2] = (uint8_t)(w >> 16);
|
||||
p[3] = (uint8_t)(w >> 24);
|
||||
p[4] = (uint8_t)(w >> 32);
|
||||
p[5] = (uint8_t)(w >> 40);
|
||||
p[6] = (uint8_t)(w >> 48);
|
||||
p[7] = (uint8_t)(w >> 56);
|
||||
#endif
|
||||
}
|
||||
|
||||
static BLAKE2_INLINE uint64_t load48( const void *src )
|
||||
{
|
||||
const uint8_t *p = ( const uint8_t * )src;
|
||||
return (( uint64_t )( p[0] ) << 0) |
|
||||
(( uint64_t )( p[1] ) << 8) |
|
||||
(( uint64_t )( p[2] ) << 16) |
|
||||
(( uint64_t )( p[3] ) << 24) |
|
||||
(( uint64_t )( p[4] ) << 32) |
|
||||
(( uint64_t )( p[5] ) << 40) ;
|
||||
}
|
||||
|
||||
static BLAKE2_INLINE void store48( void *dst, uint64_t w )
|
||||
{
|
||||
uint8_t *p = ( uint8_t * )dst;
|
||||
p[0] = (uint8_t)(w >> 0);
|
||||
p[1] = (uint8_t)(w >> 8);
|
||||
p[2] = (uint8_t)(w >> 16);
|
||||
p[3] = (uint8_t)(w >> 24);
|
||||
p[4] = (uint8_t)(w >> 32);
|
||||
p[5] = (uint8_t)(w >> 40);
|
||||
}
|
||||
|
||||
static BLAKE2_INLINE uint32_t rotr32( const uint32_t w, const unsigned c )
|
||||
{
|
||||
return ( w >> c ) | ( w << ( 32 - c ) );
|
||||
}
|
||||
|
||||
static BLAKE2_INLINE uint64_t rotr64( const uint64_t w, const unsigned c )
|
||||
{
|
||||
return ( w >> c ) | ( w << ( 64 - c ) );
|
||||
}
|
||||
|
||||
/* prevents compiler optimizing out memset() */
|
||||
static BLAKE2_INLINE void secure_zero_memory(void *v, size_t n)
|
||||
{
|
||||
static void *(*const volatile memset_v)(void *, int, size_t) = &memset;
|
||||
memset_v(v, 0, n);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,367 @@
|
|||
/*
|
||||
BLAKE2 reference source code package - reference C implementations
|
||||
|
||||
Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the
|
||||
terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
|
||||
your option. The terms of these licenses can be found at:
|
||||
|
||||
- CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
|
||||
- OpenSSL license : https://www.openssl.org/source/license.html
|
||||
- Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
More information about the BLAKE2 hash function can be found at
|
||||
https://blake2.net.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "archive_blake2.h"
|
||||
#include "archive_blake2_impl.h"
|
||||
|
||||
static const uint32_t blake2s_IV[8] =
|
||||
{
|
||||
0x6A09E667UL, 0xBB67AE85UL, 0x3C6EF372UL, 0xA54FF53AUL,
|
||||
0x510E527FUL, 0x9B05688CUL, 0x1F83D9ABUL, 0x5BE0CD19UL
|
||||
};
|
||||
|
||||
static const uint8_t blake2s_sigma[10][16] =
|
||||
{
|
||||
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } ,
|
||||
{ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } ,
|
||||
{ 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } ,
|
||||
{ 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } ,
|
||||
{ 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } ,
|
||||
{ 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } ,
|
||||
{ 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } ,
|
||||
{ 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } ,
|
||||
{ 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } ,
|
||||
{ 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } ,
|
||||
};
|
||||
|
||||
static void blake2s_set_lastnode( blake2s_state *S )
|
||||
{
|
||||
S->f[1] = (uint32_t)-1;
|
||||
}
|
||||
|
||||
/* Some helper functions, not necessarily useful */
|
||||
static int blake2s_is_lastblock( const blake2s_state *S )
|
||||
{
|
||||
return S->f[0] != 0;
|
||||
}
|
||||
|
||||
static void blake2s_set_lastblock( blake2s_state *S )
|
||||
{
|
||||
if( S->last_node ) blake2s_set_lastnode( S );
|
||||
|
||||
S->f[0] = (uint32_t)-1;
|
||||
}
|
||||
|
||||
static void blake2s_increment_counter( blake2s_state *S, const uint32_t inc )
|
||||
{
|
||||
S->t[0] += inc;
|
||||
S->t[1] += ( S->t[0] < inc );
|
||||
}
|
||||
|
||||
static void blake2s_init0( blake2s_state *S )
|
||||
{
|
||||
size_t i;
|
||||
memset( S, 0, sizeof( blake2s_state ) );
|
||||
|
||||
for( i = 0; i < 8; ++i ) S->h[i] = blake2s_IV[i];
|
||||
}
|
||||
|
||||
/* init2 xors IV with input parameter block */
|
||||
int blake2s_init_param( blake2s_state *S, const blake2s_param *P )
|
||||
{
|
||||
const unsigned char *p = ( const unsigned char * )( P );
|
||||
size_t i;
|
||||
|
||||
blake2s_init0( S );
|
||||
|
||||
/* IV XOR ParamBlock */
|
||||
for( i = 0; i < 8; ++i )
|
||||
S->h[i] ^= load32( &p[i * 4] );
|
||||
|
||||
S->outlen = P->digest_length;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Sequential blake2s initialization */
|
||||
int blake2s_init( blake2s_state *S, size_t outlen )
|
||||
{
|
||||
blake2s_param P[1];
|
||||
|
||||
/* Move interval verification here? */
|
||||
if ( ( !outlen ) || ( outlen > BLAKE2S_OUTBYTES ) ) return -1;
|
||||
|
||||
P->digest_length = (uint8_t)outlen;
|
||||
P->key_length = 0;
|
||||
P->fanout = 1;
|
||||
P->depth = 1;
|
||||
store32( &P->leaf_length, 0 );
|
||||
store32( &P->node_offset, 0 );
|
||||
store16( &P->xof_length, 0 );
|
||||
P->node_depth = 0;
|
||||
P->inner_length = 0;
|
||||
/* memset(P->reserved, 0, sizeof(P->reserved) ); */
|
||||
memset( P->salt, 0, sizeof( P->salt ) );
|
||||
memset( P->personal, 0, sizeof( P->personal ) );
|
||||
return blake2s_init_param( S, P );
|
||||
}
|
||||
|
||||
int blake2s_init_key( blake2s_state *S, size_t outlen, const void *key, size_t keylen )
|
||||
{
|
||||
blake2s_param P[1];
|
||||
|
||||
if ( ( !outlen ) || ( outlen > BLAKE2S_OUTBYTES ) ) return -1;
|
||||
|
||||
if ( !key || !keylen || keylen > BLAKE2S_KEYBYTES ) return -1;
|
||||
|
||||
P->digest_length = (uint8_t)outlen;
|
||||
P->key_length = (uint8_t)keylen;
|
||||
P->fanout = 1;
|
||||
P->depth = 1;
|
||||
store32( &P->leaf_length, 0 );
|
||||
store32( &P->node_offset, 0 );
|
||||
store16( &P->xof_length, 0 );
|
||||
P->node_depth = 0;
|
||||
P->inner_length = 0;
|
||||
/* memset(P->reserved, 0, sizeof(P->reserved) ); */
|
||||
memset( P->salt, 0, sizeof( P->salt ) );
|
||||
memset( P->personal, 0, sizeof( P->personal ) );
|
||||
|
||||
if( blake2s_init_param( S, P ) < 0 ) return -1;
|
||||
|
||||
{
|
||||
uint8_t block[BLAKE2S_BLOCKBYTES];
|
||||
memset( block, 0, BLAKE2S_BLOCKBYTES );
|
||||
memcpy( block, key, keylen );
|
||||
blake2s_update( S, block, BLAKE2S_BLOCKBYTES );
|
||||
secure_zero_memory( block, BLAKE2S_BLOCKBYTES ); /* Burn the key from stack */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define G(r,i,a,b,c,d) \
|
||||
do { \
|
||||
a = a + b + m[blake2s_sigma[r][2*i+0]]; \
|
||||
d = rotr32(d ^ a, 16); \
|
||||
c = c + d; \
|
||||
b = rotr32(b ^ c, 12); \
|
||||
a = a + b + m[blake2s_sigma[r][2*i+1]]; \
|
||||
d = rotr32(d ^ a, 8); \
|
||||
c = c + d; \
|
||||
b = rotr32(b ^ c, 7); \
|
||||
} while(0)
|
||||
|
||||
#define ROUND(r) \
|
||||
do { \
|
||||
G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \
|
||||
G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \
|
||||
G(r,2,v[ 2],v[ 6],v[10],v[14]); \
|
||||
G(r,3,v[ 3],v[ 7],v[11],v[15]); \
|
||||
G(r,4,v[ 0],v[ 5],v[10],v[15]); \
|
||||
G(r,5,v[ 1],v[ 6],v[11],v[12]); \
|
||||
G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \
|
||||
G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \
|
||||
} while(0)
|
||||
|
||||
static void blake2s_compress( blake2s_state *S, const uint8_t in[BLAKE2S_BLOCKBYTES] )
|
||||
{
|
||||
uint32_t m[16];
|
||||
uint32_t v[16];
|
||||
size_t i;
|
||||
|
||||
for( i = 0; i < 16; ++i ) {
|
||||
m[i] = load32( in + i * sizeof( m[i] ) );
|
||||
}
|
||||
|
||||
for( i = 0; i < 8; ++i ) {
|
||||
v[i] = S->h[i];
|
||||
}
|
||||
|
||||
v[ 8] = blake2s_IV[0];
|
||||
v[ 9] = blake2s_IV[1];
|
||||
v[10] = blake2s_IV[2];
|
||||
v[11] = blake2s_IV[3];
|
||||
v[12] = S->t[0] ^ blake2s_IV[4];
|
||||
v[13] = S->t[1] ^ blake2s_IV[5];
|
||||
v[14] = S->f[0] ^ blake2s_IV[6];
|
||||
v[15] = S->f[1] ^ blake2s_IV[7];
|
||||
|
||||
ROUND( 0 );
|
||||
ROUND( 1 );
|
||||
ROUND( 2 );
|
||||
ROUND( 3 );
|
||||
ROUND( 4 );
|
||||
ROUND( 5 );
|
||||
ROUND( 6 );
|
||||
ROUND( 7 );
|
||||
ROUND( 8 );
|
||||
ROUND( 9 );
|
||||
|
||||
for( i = 0; i < 8; ++i ) {
|
||||
S->h[i] = S->h[i] ^ v[i] ^ v[i + 8];
|
||||
}
|
||||
}
|
||||
|
||||
#undef G
|
||||
#undef ROUND
|
||||
|
||||
int blake2s_update( blake2s_state *S, const void *pin, size_t inlen )
|
||||
{
|
||||
const unsigned char * in = (const unsigned char *)pin;
|
||||
if( inlen > 0 )
|
||||
{
|
||||
size_t left = S->buflen;
|
||||
size_t fill = BLAKE2S_BLOCKBYTES - left;
|
||||
if( inlen > fill )
|
||||
{
|
||||
S->buflen = 0;
|
||||
memcpy( S->buf + left, in, fill ); /* Fill buffer */
|
||||
blake2s_increment_counter( S, BLAKE2S_BLOCKBYTES );
|
||||
blake2s_compress( S, S->buf ); /* Compress */
|
||||
in += fill; inlen -= fill;
|
||||
while(inlen > BLAKE2S_BLOCKBYTES) {
|
||||
blake2s_increment_counter(S, BLAKE2S_BLOCKBYTES);
|
||||
blake2s_compress( S, in );
|
||||
in += BLAKE2S_BLOCKBYTES;
|
||||
inlen -= BLAKE2S_BLOCKBYTES;
|
||||
}
|
||||
}
|
||||
memcpy( S->buf + S->buflen, in, inlen );
|
||||
S->buflen += inlen;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int blake2s_final( blake2s_state *S, void *out, size_t outlen )
|
||||
{
|
||||
uint8_t buffer[BLAKE2S_OUTBYTES] = {0};
|
||||
size_t i;
|
||||
|
||||
if( out == NULL || outlen < S->outlen )
|
||||
return -1;
|
||||
|
||||
if( blake2s_is_lastblock( S ) )
|
||||
return -1;
|
||||
|
||||
blake2s_increment_counter( S, ( uint32_t )S->buflen );
|
||||
blake2s_set_lastblock( S );
|
||||
memset( S->buf + S->buflen, 0, BLAKE2S_BLOCKBYTES - S->buflen ); /* Padding */
|
||||
blake2s_compress( S, S->buf );
|
||||
|
||||
for( i = 0; i < 8; ++i ) /* Output full hash to temp buffer */
|
||||
store32( buffer + sizeof( S->h[i] ) * i, S->h[i] );
|
||||
|
||||
memcpy( out, buffer, outlen );
|
||||
secure_zero_memory(buffer, sizeof(buffer));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int blake2s( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen )
|
||||
{
|
||||
blake2s_state S[1];
|
||||
|
||||
/* Verify parameters */
|
||||
if ( NULL == in && inlen > 0 ) return -1;
|
||||
|
||||
if ( NULL == out ) return -1;
|
||||
|
||||
if ( NULL == key && keylen > 0) return -1;
|
||||
|
||||
if( !outlen || outlen > BLAKE2S_OUTBYTES ) return -1;
|
||||
|
||||
if( keylen > BLAKE2S_KEYBYTES ) return -1;
|
||||
|
||||
if( keylen > 0 )
|
||||
{
|
||||
if( blake2s_init_key( S, outlen, key, keylen ) < 0 ) return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( blake2s_init( S, outlen ) < 0 ) return -1;
|
||||
}
|
||||
|
||||
blake2s_update( S, ( const uint8_t * )in, inlen );
|
||||
blake2s_final( S, out, outlen );
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(SUPERCOP)
|
||||
int crypto_hash( unsigned char *out, unsigned char *in, unsigned long long inlen )
|
||||
{
|
||||
return blake2s( out, BLAKE2S_OUTBYTES, in, inlen, NULL, 0 );
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(BLAKE2S_SELFTEST)
|
||||
#include <string.h>
|
||||
#include "blake2-kat.h"
|
||||
int main( void )
|
||||
{
|
||||
uint8_t key[BLAKE2S_KEYBYTES];
|
||||
uint8_t buf[BLAKE2_KAT_LENGTH];
|
||||
size_t i, step;
|
||||
|
||||
for( i = 0; i < BLAKE2S_KEYBYTES; ++i )
|
||||
key[i] = ( uint8_t )i;
|
||||
|
||||
for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
|
||||
buf[i] = ( uint8_t )i;
|
||||
|
||||
/* Test simple API */
|
||||
for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
|
||||
{
|
||||
uint8_t hash[BLAKE2S_OUTBYTES];
|
||||
blake2s( hash, BLAKE2S_OUTBYTES, buf, i, key, BLAKE2S_KEYBYTES );
|
||||
|
||||
if( 0 != memcmp( hash, blake2s_keyed_kat[i], BLAKE2S_OUTBYTES ) )
|
||||
{
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
/* Test streaming API */
|
||||
for(step = 1; step < BLAKE2S_BLOCKBYTES; ++step) {
|
||||
for (i = 0; i < BLAKE2_KAT_LENGTH; ++i) {
|
||||
uint8_t hash[BLAKE2S_OUTBYTES];
|
||||
blake2s_state S;
|
||||
uint8_t * p = buf;
|
||||
size_t mlen = i;
|
||||
int err = 0;
|
||||
|
||||
if( (err = blake2s_init_key(&S, BLAKE2S_OUTBYTES, key, BLAKE2S_KEYBYTES)) < 0 ) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
while (mlen >= step) {
|
||||
if ( (err = blake2s_update(&S, p, step)) < 0 ) {
|
||||
goto fail;
|
||||
}
|
||||
mlen -= step;
|
||||
p += step;
|
||||
}
|
||||
if ( (err = blake2s_update(&S, p, mlen)) < 0) {
|
||||
goto fail;
|
||||
}
|
||||
if ( (err = blake2s_final(&S, hash, BLAKE2S_OUTBYTES)) < 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (0 != memcmp(hash, blake2s_keyed_kat[i], BLAKE2S_OUTBYTES)) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
puts( "ok" );
|
||||
return 0;
|
||||
fail:
|
||||
puts("error");
|
||||
return -1;
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,359 @@
|
|||
/*
|
||||
BLAKE2 reference source code package - reference C implementations
|
||||
|
||||
Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the
|
||||
terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
|
||||
your option. The terms of these licenses can be found at:
|
||||
|
||||
- CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
|
||||
- OpenSSL license : https://www.openssl.org/source/license.html
|
||||
- Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
More information about the BLAKE2 hash function can be found at
|
||||
https://blake2.net.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#include <omp.h>
|
||||
#endif
|
||||
|
||||
#include "archive_blake2.h"
|
||||
#include "archive_blake2_impl.h"
|
||||
|
||||
#define PARALLELISM_DEGREE 8
|
||||
|
||||
/*
|
||||
blake2sp_init_param defaults to setting the expecting output length
|
||||
from the digest_length parameter block field.
|
||||
|
||||
In some cases, however, we do not want this, as the output length
|
||||
of these instances is given by inner_length instead.
|
||||
*/
|
||||
static int blake2sp_init_leaf_param( blake2s_state *S, const blake2s_param *P )
|
||||
{
|
||||
int err = blake2s_init_param(S, P);
|
||||
S->outlen = P->inner_length;
|
||||
return err;
|
||||
}
|
||||
|
||||
static int blake2sp_init_leaf( blake2s_state *S, size_t outlen, size_t keylen, uint32_t offset )
|
||||
{
|
||||
blake2s_param P[1];
|
||||
P->digest_length = (uint8_t)outlen;
|
||||
P->key_length = (uint8_t)keylen;
|
||||
P->fanout = PARALLELISM_DEGREE;
|
||||
P->depth = 2;
|
||||
store32( &P->leaf_length, 0 );
|
||||
store32( &P->node_offset, offset );
|
||||
store16( &P->xof_length, 0 );
|
||||
P->node_depth = 0;
|
||||
P->inner_length = BLAKE2S_OUTBYTES;
|
||||
memset( P->salt, 0, sizeof( P->salt ) );
|
||||
memset( P->personal, 0, sizeof( P->personal ) );
|
||||
return blake2sp_init_leaf_param( S, P );
|
||||
}
|
||||
|
||||
static int blake2sp_init_root( blake2s_state *S, size_t outlen, size_t keylen )
|
||||
{
|
||||
blake2s_param P[1];
|
||||
P->digest_length = (uint8_t)outlen;
|
||||
P->key_length = (uint8_t)keylen;
|
||||
P->fanout = PARALLELISM_DEGREE;
|
||||
P->depth = 2;
|
||||
store32( &P->leaf_length, 0 );
|
||||
store32( &P->node_offset, 0 );
|
||||
store16( &P->xof_length, 0 );
|
||||
P->node_depth = 1;
|
||||
P->inner_length = BLAKE2S_OUTBYTES;
|
||||
memset( P->salt, 0, sizeof( P->salt ) );
|
||||
memset( P->personal, 0, sizeof( P->personal ) );
|
||||
return blake2s_init_param( S, P );
|
||||
}
|
||||
|
||||
|
||||
int blake2sp_init( blake2sp_state *S, size_t outlen )
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if( !outlen || outlen > BLAKE2S_OUTBYTES ) return -1;
|
||||
|
||||
memset( S->buf, 0, sizeof( S->buf ) );
|
||||
S->buflen = 0;
|
||||
S->outlen = outlen;
|
||||
|
||||
if( blake2sp_init_root( S->R, outlen, 0 ) < 0 )
|
||||
return -1;
|
||||
|
||||
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
||||
if( blake2sp_init_leaf( S->S[i], outlen, 0, (uint32_t)i ) < 0 ) return -1;
|
||||
|
||||
S->R->last_node = 1;
|
||||
S->S[PARALLELISM_DEGREE - 1]->last_node = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int blake2sp_init_key( blake2sp_state *S, size_t outlen, const void *key, size_t keylen )
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if( !outlen || outlen > BLAKE2S_OUTBYTES ) return -1;
|
||||
|
||||
if( !key || !keylen || keylen > BLAKE2S_KEYBYTES ) return -1;
|
||||
|
||||
memset( S->buf, 0, sizeof( S->buf ) );
|
||||
S->buflen = 0;
|
||||
S->outlen = outlen;
|
||||
|
||||
if( blake2sp_init_root( S->R, outlen, keylen ) < 0 )
|
||||
return -1;
|
||||
|
||||
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
||||
if( blake2sp_init_leaf( S->S[i], outlen, keylen, (uint32_t)i ) < 0 ) return -1;
|
||||
|
||||
S->R->last_node = 1;
|
||||
S->S[PARALLELISM_DEGREE - 1]->last_node = 1;
|
||||
{
|
||||
uint8_t block[BLAKE2S_BLOCKBYTES];
|
||||
memset( block, 0, BLAKE2S_BLOCKBYTES );
|
||||
memcpy( block, key, keylen );
|
||||
|
||||
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
||||
blake2s_update( S->S[i], block, BLAKE2S_BLOCKBYTES );
|
||||
|
||||
secure_zero_memory( block, BLAKE2S_BLOCKBYTES ); /* Burn the key from stack */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int blake2sp_update( blake2sp_state *S, const void *pin, size_t inlen )
|
||||
{
|
||||
const unsigned char * in = (const unsigned char *)pin;
|
||||
size_t left = S->buflen;
|
||||
size_t fill = sizeof( S->buf ) - left;
|
||||
size_t i;
|
||||
|
||||
if( left && inlen >= fill )
|
||||
{
|
||||
memcpy( S->buf + left, in, fill );
|
||||
|
||||
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
||||
blake2s_update( S->S[i], S->buf + i * BLAKE2S_BLOCKBYTES, BLAKE2S_BLOCKBYTES );
|
||||
|
||||
in += fill;
|
||||
inlen -= fill;
|
||||
left = 0;
|
||||
}
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel shared(S), num_threads(PARALLELISM_DEGREE)
|
||||
#else
|
||||
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
||||
#endif
|
||||
{
|
||||
#if defined(_OPENMP)
|
||||
size_t i = omp_get_thread_num();
|
||||
#endif
|
||||
size_t inlen__ = inlen;
|
||||
const unsigned char *in__ = ( const unsigned char * )in;
|
||||
in__ += i * BLAKE2S_BLOCKBYTES;
|
||||
|
||||
while( inlen__ >= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES )
|
||||
{
|
||||
blake2s_update( S->S[i], in__, BLAKE2S_BLOCKBYTES );
|
||||
in__ += PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
|
||||
inlen__ -= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
|
||||
}
|
||||
}
|
||||
|
||||
in += inlen - inlen % ( PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES );
|
||||
inlen %= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
|
||||
|
||||
if( inlen > 0 )
|
||||
memcpy( S->buf + left, in, inlen );
|
||||
|
||||
S->buflen = left + inlen;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int blake2sp_final( blake2sp_state *S, void *out, size_t outlen )
|
||||
{
|
||||
uint8_t hash[PARALLELISM_DEGREE][BLAKE2S_OUTBYTES];
|
||||
size_t i;
|
||||
|
||||
if(out == NULL || outlen < S->outlen) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
||||
{
|
||||
if( S->buflen > i * BLAKE2S_BLOCKBYTES )
|
||||
{
|
||||
size_t left = S->buflen - i * BLAKE2S_BLOCKBYTES;
|
||||
|
||||
if( left > BLAKE2S_BLOCKBYTES ) left = BLAKE2S_BLOCKBYTES;
|
||||
|
||||
blake2s_update( S->S[i], S->buf + i * BLAKE2S_BLOCKBYTES, left );
|
||||
}
|
||||
|
||||
blake2s_final( S->S[i], hash[i], BLAKE2S_OUTBYTES );
|
||||
}
|
||||
|
||||
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
||||
blake2s_update( S->R, hash[i], BLAKE2S_OUTBYTES );
|
||||
|
||||
return blake2s_final( S->R, out, S->outlen );
|
||||
}
|
||||
|
||||
|
||||
int blake2sp( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen )
|
||||
{
|
||||
uint8_t hash[PARALLELISM_DEGREE][BLAKE2S_OUTBYTES];
|
||||
blake2s_state S[PARALLELISM_DEGREE][1];
|
||||
blake2s_state FS[1];
|
||||
size_t i;
|
||||
|
||||
/* Verify parameters */
|
||||
if ( NULL == in && inlen > 0 ) return -1;
|
||||
|
||||
if ( NULL == out ) return -1;
|
||||
|
||||
if ( NULL == key && keylen > 0) return -1;
|
||||
|
||||
if( !outlen || outlen > BLAKE2S_OUTBYTES ) return -1;
|
||||
|
||||
if( keylen > BLAKE2S_KEYBYTES ) return -1;
|
||||
|
||||
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
||||
if( blake2sp_init_leaf( S[i], outlen, keylen, (uint32_t)i ) < 0 ) return -1;
|
||||
|
||||
S[PARALLELISM_DEGREE - 1]->last_node = 1; /* mark last node */
|
||||
|
||||
if( keylen > 0 )
|
||||
{
|
||||
uint8_t block[BLAKE2S_BLOCKBYTES];
|
||||
memset( block, 0, BLAKE2S_BLOCKBYTES );
|
||||
memcpy( block, key, keylen );
|
||||
|
||||
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
||||
blake2s_update( S[i], block, BLAKE2S_BLOCKBYTES );
|
||||
|
||||
secure_zero_memory( block, BLAKE2S_BLOCKBYTES ); /* Burn the key from stack */
|
||||
}
|
||||
|
||||
#if defined(_OPENMP)
|
||||
#pragma omp parallel shared(S,hash), num_threads(PARALLELISM_DEGREE)
|
||||
#else
|
||||
|
||||
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
||||
#endif
|
||||
{
|
||||
#if defined(_OPENMP)
|
||||
size_t i = omp_get_thread_num();
|
||||
#endif
|
||||
size_t inlen__ = inlen;
|
||||
const unsigned char *in__ = ( const unsigned char * )in;
|
||||
in__ += i * BLAKE2S_BLOCKBYTES;
|
||||
|
||||
while( inlen__ >= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES )
|
||||
{
|
||||
blake2s_update( S[i], in__, BLAKE2S_BLOCKBYTES );
|
||||
in__ += PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
|
||||
inlen__ -= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
|
||||
}
|
||||
|
||||
if( inlen__ > i * BLAKE2S_BLOCKBYTES )
|
||||
{
|
||||
const size_t left = inlen__ - i * BLAKE2S_BLOCKBYTES;
|
||||
const size_t len = left <= BLAKE2S_BLOCKBYTES ? left : BLAKE2S_BLOCKBYTES;
|
||||
blake2s_update( S[i], in__, len );
|
||||
}
|
||||
|
||||
blake2s_final( S[i], hash[i], BLAKE2S_OUTBYTES );
|
||||
}
|
||||
|
||||
if( blake2sp_init_root( FS, outlen, keylen ) < 0 )
|
||||
return -1;
|
||||
|
||||
FS->last_node = 1;
|
||||
|
||||
for( i = 0; i < PARALLELISM_DEGREE; ++i )
|
||||
blake2s_update( FS, hash[i], BLAKE2S_OUTBYTES );
|
||||
|
||||
return blake2s_final( FS, out, outlen );
|
||||
}
|
||||
|
||||
|
||||
|
||||
#if defined(BLAKE2SP_SELFTEST)
|
||||
#include <string.h>
|
||||
#include "blake2-kat.h"
|
||||
int main( void )
|
||||
{
|
||||
uint8_t key[BLAKE2S_KEYBYTES];
|
||||
uint8_t buf[BLAKE2_KAT_LENGTH];
|
||||
size_t i, step;
|
||||
|
||||
for( i = 0; i < BLAKE2S_KEYBYTES; ++i )
|
||||
key[i] = ( uint8_t )i;
|
||||
|
||||
for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
|
||||
buf[i] = ( uint8_t )i;
|
||||
|
||||
/* Test simple API */
|
||||
for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
|
||||
{
|
||||
uint8_t hash[BLAKE2S_OUTBYTES];
|
||||
blake2sp( hash, BLAKE2S_OUTBYTES, buf, i, key, BLAKE2S_KEYBYTES );
|
||||
|
||||
if( 0 != memcmp( hash, blake2sp_keyed_kat[i], BLAKE2S_OUTBYTES ) )
|
||||
{
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
/* Test streaming API */
|
||||
for(step = 1; step < BLAKE2S_BLOCKBYTES; ++step) {
|
||||
for (i = 0; i < BLAKE2_KAT_LENGTH; ++i) {
|
||||
uint8_t hash[BLAKE2S_OUTBYTES];
|
||||
blake2sp_state S;
|
||||
uint8_t * p = buf;
|
||||
size_t mlen = i;
|
||||
int err = 0;
|
||||
|
||||
if( (err = blake2sp_init_key(&S, BLAKE2S_OUTBYTES, key, BLAKE2S_KEYBYTES)) < 0 ) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
while (mlen >= step) {
|
||||
if ( (err = blake2sp_update(&S, p, step)) < 0 ) {
|
||||
goto fail;
|
||||
}
|
||||
mlen -= step;
|
||||
p += step;
|
||||
}
|
||||
if ( (err = blake2sp_update(&S, p, mlen)) < 0) {
|
||||
goto fail;
|
||||
}
|
||||
if ( (err = blake2sp_final(&S, hash, BLAKE2S_OUTBYTES)) < 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (0 != memcmp(hash, blake2sp_keyed_kat[i], BLAKE2S_OUTBYTES)) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
puts( "ok" );
|
||||
return 0;
|
||||
fail:
|
||||
puts("error");
|
||||
return -1;
|
||||
}
|
||||
#endif
|
|
@ -100,10 +100,10 @@ get_argument(struct archive_string *as, const char *p)
|
|||
|
||||
/*
|
||||
* Set up command line arguments.
|
||||
* Returns ARChIVE_OK if everything okey.
|
||||
* Returns ARChIVE_FAILED if there is a lack of the `"' terminator or an
|
||||
* Returns ARCHIVE_OK if everything okey.
|
||||
* Returns ARCHIVE_FAILED if there is a lack of the `"' terminator or an
|
||||
* empty command line.
|
||||
* Returns ARChIVE_FATAL if no memory.
|
||||
* Returns ARCHIVE_FATAL if no memory.
|
||||
*/
|
||||
int
|
||||
__archive_cmdline_parse(struct archive_cmdline *data, const char *cmd)
|
||||
|
|
|
@ -153,7 +153,7 @@ aes_ctr_encrypt_counter(archive_crypto_ctx *ctx)
|
|||
CCCryptorStatus r;
|
||||
|
||||
r = CCCryptorReset(ref, NULL);
|
||||
if (r != kCCSuccess)
|
||||
if (r != kCCSuccess && r != kCCUnimplemented)
|
||||
return -1;
|
||||
r = CCCryptorUpdate(ref, ctx->nonce, AES_BLOCK_SIZE, ctx->encr_buf,
|
||||
AES_BLOCK_SIZE, NULL);
|
||||
|
@ -316,7 +316,14 @@ aes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, size_t key_len)
|
|||
memcpy(ctx->key, key, key_len);
|
||||
memset(ctx->nonce, 0, sizeof(ctx->nonce));
|
||||
ctx->encr_pos = AES_BLOCK_SIZE;
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
|
||||
if (!EVP_CIPHER_CTX_reset(ctx->ctx)) {
|
||||
EVP_CIPHER_CTX_free(ctx->ctx);
|
||||
ctx->ctx = NULL;
|
||||
}
|
||||
#else
|
||||
EVP_CIPHER_CTX_init(ctx->ctx);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -64,7 +64,7 @@ typedef struct {
|
|||
} archive_crypto_ctx;
|
||||
|
||||
#elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H)
|
||||
#include <Bcrypt.h>
|
||||
#include <bcrypt.h>
|
||||
|
||||
/* Common in other bcrypt implementations, but missing from VS2008. */
|
||||
#ifndef BCRYPT_SUCCESS
|
||||
|
|
|
@ -93,7 +93,9 @@ static const acl_perm_map_t acl_nfs4_flag_map[] = {
|
|||
{ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_INHERIT_ONLY},
|
||||
{ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACL_ENTRY_SUCCESSFUL_ACCESS},
|
||||
{ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACL_ENTRY_FAILED_ACCESS},
|
||||
#ifdef ACL_ENTRY_INHERITED
|
||||
{ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED}
|
||||
#endif
|
||||
};
|
||||
|
||||
static const int acl_nfs4_flag_map_size =
|
||||
|
|
|
@ -145,10 +145,8 @@ sunacl_get(int cmd, int *aclcnt, int fd, const char *path)
|
|||
cnt = facl(fd, cmd, cnt, aclp);
|
||||
}
|
||||
} else {
|
||||
if (aclp != NULL) {
|
||||
free(aclp);
|
||||
aclp = NULL;
|
||||
}
|
||||
free(aclp);
|
||||
aclp = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -168,6 +168,7 @@ archive_entry_clear(struct archive_entry *entry)
|
|||
archive_entry_xattr_clear(entry);
|
||||
archive_entry_sparse_clear(entry);
|
||||
free(entry->stat);
|
||||
entry->ae_symlink_type = AE_SYMLINK_TYPE_UNDEFINED;
|
||||
memset(entry, 0, sizeof(*entry));
|
||||
return entry;
|
||||
}
|
||||
|
@ -202,6 +203,9 @@ archive_entry_clone(struct archive_entry *entry)
|
|||
entry2->ae_set = entry->ae_set;
|
||||
archive_mstring_copy(&entry2->ae_uname, &entry->ae_uname);
|
||||
|
||||
/* Copy symlink type */
|
||||
entry2->ae_symlink_type = entry->ae_symlink_type;
|
||||
|
||||
/* Copy encryption status */
|
||||
entry2->encryption = entry->encryption;
|
||||
|
||||
|
@ -253,6 +257,7 @@ archive_entry_new2(struct archive *a)
|
|||
if (entry == NULL)
|
||||
return (NULL);
|
||||
entry->archive = a;
|
||||
entry->ae_symlink_type = AE_SYMLINK_TYPE_UNDEFINED;
|
||||
return (entry);
|
||||
}
|
||||
|
||||
|
@ -675,6 +680,12 @@ archive_entry_symlink(struct archive_entry *entry)
|
|||
return (NULL);
|
||||
}
|
||||
|
||||
int
|
||||
archive_entry_symlink_type(struct archive_entry *entry)
|
||||
{
|
||||
return (entry->ae_symlink_type);
|
||||
}
|
||||
|
||||
const char *
|
||||
archive_entry_symlink_utf8(struct archive_entry *entry)
|
||||
{
|
||||
|
@ -1245,6 +1256,12 @@ archive_entry_set_symlink(struct archive_entry *entry, const char *linkname)
|
|||
entry->ae_set &= ~AE_SET_SYMLINK;
|
||||
}
|
||||
|
||||
void
|
||||
archive_entry_set_symlink_type(struct archive_entry *entry, int type)
|
||||
{
|
||||
entry->ae_symlink_type = type;
|
||||
}
|
||||
|
||||
void
|
||||
archive_entry_set_symlink_utf8(struct archive_entry *entry, const char *linkname)
|
||||
{
|
||||
|
@ -1491,7 +1508,7 @@ archive_entry_acl_next(struct archive_entry *entry, int want_type, int *type,
|
|||
* the style of the generated ACL.
|
||||
*/
|
||||
wchar_t *
|
||||
archive_entry_acl_to_text_w(struct archive_entry *entry, ssize_t *len,
|
||||
archive_entry_acl_to_text_w(struct archive_entry *entry, la_ssize_t *len,
|
||||
int flags)
|
||||
{
|
||||
return (archive_acl_to_text_w(&entry->acl, len, flags,
|
||||
|
@ -1499,7 +1516,7 @@ archive_entry_acl_to_text_w(struct archive_entry *entry, ssize_t *len,
|
|||
}
|
||||
|
||||
char *
|
||||
archive_entry_acl_to_text(struct archive_entry *entry, ssize_t *len,
|
||||
archive_entry_acl_to_text(struct archive_entry *entry, la_ssize_t *len,
|
||||
int flags)
|
||||
{
|
||||
return (archive_acl_to_text_l(&entry->acl, len, flags, NULL));
|
||||
|
@ -1560,10 +1577,8 @@ archive_entry_acl_text_compat(int *flags)
|
|||
const wchar_t *
|
||||
archive_entry_acl_text_w(struct archive_entry *entry, int flags)
|
||||
{
|
||||
if (entry->acl.acl_text_w != NULL) {
|
||||
free(entry->acl.acl_text_w);
|
||||
entry->acl.acl_text_w = NULL;
|
||||
}
|
||||
free(entry->acl.acl_text_w);
|
||||
entry->acl.acl_text_w = NULL;
|
||||
if (archive_entry_acl_text_compat(&flags) == 0)
|
||||
entry->acl.acl_text_w = archive_acl_to_text_w(&entry->acl,
|
||||
NULL, flags, entry->archive);
|
||||
|
@ -1574,10 +1589,8 @@ archive_entry_acl_text_w(struct archive_entry *entry, int flags)
|
|||
const char *
|
||||
archive_entry_acl_text(struct archive_entry *entry, int flags)
|
||||
{
|
||||
if (entry->acl.acl_text != NULL) {
|
||||
free(entry->acl.acl_text);
|
||||
entry->acl.acl_text = NULL;
|
||||
}
|
||||
free(entry->acl.acl_text);
|
||||
entry->acl.acl_text = NULL;
|
||||
if (archive_entry_acl_text_compat(&flags) == 0)
|
||||
entry->acl.acl_text = archive_acl_to_text_l(&entry->acl, NULL,
|
||||
flags, NULL);
|
||||
|
@ -1590,10 +1603,8 @@ int
|
|||
_archive_entry_acl_text_l(struct archive_entry *entry, int flags,
|
||||
const char **acl_text, size_t *len, struct archive_string_conv *sc)
|
||||
{
|
||||
if (entry->acl.acl_text != NULL) {
|
||||
free(entry->acl.acl_text);
|
||||
entry->acl.acl_text = NULL;
|
||||
}
|
||||
free(entry->acl.acl_text);
|
||||
entry->acl.acl_text = NULL;
|
||||
|
||||
if (archive_entry_acl_text_compat(&flags) == 0)
|
||||
entry->acl.acl_text = archive_acl_to_text_l(&entry->acl,
|
||||
|
@ -1638,6 +1649,51 @@ _archive_entry_acl_text_l(struct archive_entry *entry, int flags,
|
|||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Supported file flags on FreeBSD and Mac OS:
|
||||
* sappnd,sappend SF_APPEND
|
||||
* arch,archived SF_ARCHIVED
|
||||
* schg,schange,simmutable SF_IMMUTABLE
|
||||
* sunlnk,sunlink SF_NOUNLINK (FreeBSD only)
|
||||
* uappnd,uappend UF_APPEND
|
||||
* compressed UF_COMPRESSED (Mac OS only)
|
||||
* hidden,uhidden UF_HIDDEN
|
||||
* uchg,uchange,uimmutable UF_IMMUTABLE
|
||||
* nodump UF_NODUMP
|
||||
* uunlnk,uunlink UF_NOUNLINK (FreeBSD only)
|
||||
* offline,uoffline UF_OFFLINE (FreeBSD only)
|
||||
* opaque UF_OPAQUE
|
||||
* rdonly,urdonly,readonly UF_READONLY (FreeBSD only)
|
||||
* reparse,ureparse UF_REPARSE (FreeBSD only)
|
||||
* sparse,usparse UF_SPARSE (FreeBSD only)
|
||||
* system,usystem UF_SYSTEM (FreeBSD only)
|
||||
*
|
||||
* See chflags(2) for more information
|
||||
*
|
||||
* Supported file attributes on Linux:
|
||||
* a append only FS_APPEND_FL sappnd
|
||||
* A no atime updates FS_NOATIME_FL atime
|
||||
* c compress FS_COMPR_FL compress
|
||||
* C no copy on write FS_NOCOW_FL cow
|
||||
* d no dump FS_NODUMP_FL dump
|
||||
* D synchronous directory updates FS_DIRSYNC_FL dirsync
|
||||
* i immutable FS_IMMUTABLE_FL schg
|
||||
* j data journalling FS_JOURNAL_DATA_FL journal
|
||||
* P project hierarchy FS_PROJINHERIT_FL projinherit
|
||||
* s secure deletion FS_SECRM_FL securedeletion
|
||||
* S synchronous updates FS_SYNC_FL sync
|
||||
* t no tail-merging FS_NOTAIL_FL tail
|
||||
* T top of directory hierarchy FS_TOPDIR_FL topdir
|
||||
* u undeletable FS_UNRM_FL undel
|
||||
*
|
||||
* See ioctl_iflags(2) for more information
|
||||
*
|
||||
* Equivalent file flags supported on FreeBSD / Mac OS and Linux:
|
||||
* SF_APPEND FS_APPEND_FL sappnd
|
||||
* SF_IMMUTABLE FS_IMMUTABLE_FL schg
|
||||
* UF_NODUMP FS_NODUMP_FL nodump
|
||||
*/
|
||||
|
||||
static const struct flag {
|
||||
const char *name;
|
||||
const wchar_t *wname;
|
||||
|
@ -1646,190 +1702,162 @@ static const struct flag {
|
|||
} flags[] = {
|
||||
/* Preferred (shorter) names per flag first, all prefixed by "no" */
|
||||
#ifdef SF_APPEND
|
||||
{ "nosappnd", L"nosappnd", SF_APPEND, 0 },
|
||||
{ "nosappend", L"nosappend", SF_APPEND, 0 },
|
||||
{ "nosappnd", L"nosappnd", SF_APPEND, 0},
|
||||
{ "nosappend", L"nosappend", SF_APPEND, 0},
|
||||
#endif
|
||||
#if defined(FS_APPEND_FL) /* 'a' */
|
||||
{ "nosappnd", L"nosappnd", FS_APPEND_FL, 0 },
|
||||
{ "nosappend", L"nosappend", FS_APPEND_FL, 0 },
|
||||
{ "nosappnd", L"nosappnd", FS_APPEND_FL, 0},
|
||||
{ "nosappend", L"nosappend", FS_APPEND_FL, 0},
|
||||
#elif defined(EXT2_APPEND_FL) /* 'a' */
|
||||
{ "nosappnd", L"nosappnd", EXT2_APPEND_FL, 0 },
|
||||
{ "nosappend", L"nosappend", EXT2_APPEND_FL, 0 },
|
||||
{ "nosappnd", L"nosappnd", EXT2_APPEND_FL, 0},
|
||||
{ "nosappend", L"nosappend", EXT2_APPEND_FL, 0},
|
||||
#endif
|
||||
#ifdef SF_ARCHIVED
|
||||
{ "noarch", L"noarch", SF_ARCHIVED, 0 },
|
||||
{ "noarchived", L"noarchived", SF_ARCHIVED, 0 },
|
||||
{ "noarch", L"noarch", SF_ARCHIVED, 0},
|
||||
{ "noarchived", L"noarchived", SF_ARCHIVED, 0},
|
||||
#endif
|
||||
#ifdef SF_IMMUTABLE
|
||||
{ "noschg", L"noschg", SF_IMMUTABLE, 0 },
|
||||
{ "noschange", L"noschange", SF_IMMUTABLE, 0 },
|
||||
{ "nosimmutable", L"nosimmutable", SF_IMMUTABLE, 0 },
|
||||
{ "noschg", L"noschg", SF_IMMUTABLE, 0},
|
||||
{ "noschange", L"noschange", SF_IMMUTABLE, 0},
|
||||
{ "nosimmutable", L"nosimmutable", SF_IMMUTABLE, 0},
|
||||
#endif
|
||||
#if defined(FS_IMMUTABLE_FL) /* 'i' */
|
||||
{ "noschg", L"noschg", FS_IMMUTABLE_FL, 0 },
|
||||
{ "noschange", L"noschange", FS_IMMUTABLE_FL, 0 },
|
||||
{ "nosimmutable", L"nosimmutable", FS_IMMUTABLE_FL, 0 },
|
||||
{ "noschg", L"noschg", FS_IMMUTABLE_FL, 0},
|
||||
{ "noschange", L"noschange", FS_IMMUTABLE_FL, 0},
|
||||
{ "nosimmutable", L"nosimmutable", FS_IMMUTABLE_FL, 0},
|
||||
#elif defined(EXT2_IMMUTABLE_FL) /* 'i' */
|
||||
{ "noschg", L"noschg", EXT2_IMMUTABLE_FL, 0 },
|
||||
{ "noschange", L"noschange", EXT2_IMMUTABLE_FL, 0 },
|
||||
{ "nosimmutable", L"nosimmutable", EXT2_IMMUTABLE_FL, 0 },
|
||||
{ "noschg", L"noschg", EXT2_IMMUTABLE_FL, 0},
|
||||
{ "noschange", L"noschange", EXT2_IMMUTABLE_FL, 0},
|
||||
{ "nosimmutable", L"nosimmutable", EXT2_IMMUTABLE_FL, 0},
|
||||
#endif
|
||||
#ifdef SF_NOUNLINK
|
||||
{ "nosunlnk", L"nosunlnk", SF_NOUNLINK, 0 },
|
||||
{ "nosunlink", L"nosunlink", SF_NOUNLINK, 0 },
|
||||
#endif
|
||||
#ifdef SF_SNAPSHOT
|
||||
{ "nosnapshot", L"nosnapshot", SF_SNAPSHOT, 0 },
|
||||
{ "nosunlnk", L"nosunlnk", SF_NOUNLINK, 0},
|
||||
{ "nosunlink", L"nosunlink", SF_NOUNLINK, 0},
|
||||
#endif
|
||||
#ifdef UF_APPEND
|
||||
{ "nouappnd", L"nouappnd", UF_APPEND, 0 },
|
||||
{ "nouappend", L"nouappend", UF_APPEND, 0 },
|
||||
{ "nouappnd", L"nouappnd", UF_APPEND, 0},
|
||||
{ "nouappend", L"nouappend", UF_APPEND, 0},
|
||||
#endif
|
||||
#ifdef UF_IMMUTABLE
|
||||
{ "nouchg", L"nouchg", UF_IMMUTABLE, 0 },
|
||||
{ "nouchange", L"nouchange", UF_IMMUTABLE, 0 },
|
||||
{ "nouimmutable", L"nouimmutable", UF_IMMUTABLE, 0 },
|
||||
{ "nouchg", L"nouchg", UF_IMMUTABLE, 0},
|
||||
{ "nouchange", L"nouchange", UF_IMMUTABLE, 0},
|
||||
{ "nouimmutable", L"nouimmutable", UF_IMMUTABLE, 0},
|
||||
#endif
|
||||
#ifdef UF_NODUMP
|
||||
{ "nodump", L"nodump", 0, UF_NODUMP},
|
||||
#endif
|
||||
#if defined(FS_NODUMP_FL) /* 'd' */
|
||||
{ "nodump", L"nodump", 0, FS_NODUMP_FL},
|
||||
#elif defined(EXT2_NODUMP_FL) /* 'd' */
|
||||
#elif defined(EXT2_NODUMP_FL)
|
||||
{ "nodump", L"nodump", 0, EXT2_NODUMP_FL},
|
||||
#endif
|
||||
#ifdef UF_OPAQUE
|
||||
{ "noopaque", L"noopaque", UF_OPAQUE, 0 },
|
||||
{ "noopaque", L"noopaque", UF_OPAQUE, 0},
|
||||
#endif
|
||||
#ifdef UF_NOUNLINK
|
||||
{ "nouunlnk", L"nouunlnk", UF_NOUNLINK, 0 },
|
||||
{ "nouunlink", L"nouunlink", UF_NOUNLINK, 0 },
|
||||
{ "nouunlnk", L"nouunlnk", UF_NOUNLINK, 0},
|
||||
{ "nouunlink", L"nouunlink", UF_NOUNLINK, 0},
|
||||
#endif
|
||||
#ifdef UF_COMPRESSED
|
||||
{ "nocompressed",L"nocompressed", UF_COMPRESSED, 0 },
|
||||
/* Mac OS */
|
||||
{ "nocompressed", L"nocompressed", UF_COMPRESSED, 0},
|
||||
#endif
|
||||
#ifdef UF_HIDDEN
|
||||
{ "nohidden", L"nohidden", UF_HIDDEN, 0 },
|
||||
{ "nohidden", L"nohidden", UF_HIDDEN, 0},
|
||||
{ "nouhidden", L"nouhidden", UF_HIDDEN, 0},
|
||||
#endif
|
||||
#if defined(FS_UNRM_FL)
|
||||
{ "nouunlink", L"nouunlink", FS_UNRM_FL, 0},
|
||||
#ifdef FILE_ATTRIBUTE_HIDDEN
|
||||
{ "nohidden", L"nohidden", FILE_ATTRIBUTE_HIDDEN, 0},
|
||||
{ "nouhidden", L"nouhidden", FILE_ATTRIBUTE_HIDDEN, 0},
|
||||
#endif
|
||||
#ifdef UF_OFFLINE
|
||||
{ "nooffline", L"nooffline", UF_OFFLINE, 0},
|
||||
{ "nouoffline", L"nouoffline", UF_OFFLINE, 0},
|
||||
#endif
|
||||
#ifdef UF_READONLY
|
||||
{ "nordonly", L"nordonly", UF_READONLY, 0},
|
||||
{ "nourdonly", L"nourdonly", UF_READONLY, 0},
|
||||
{ "noreadonly", L"noreadonly", UF_READONLY, 0},
|
||||
#endif
|
||||
#ifdef FILE_ATTRIBUTE_READONLY
|
||||
{ "nordonly", L"nordonly", FILE_ATTRIBUTE_READONLY, 0},
|
||||
{ "nourdonly", L"nourdonly", FILE_ATTRIBUTE_READONLY, 0},
|
||||
{ "noreadonly", L"noreadonly", FILE_ATTRIBUTE_READONLY, 0},
|
||||
#endif
|
||||
#ifdef UF_SPARSE
|
||||
{ "nosparse", L"nosparse", UF_SPARSE, 0},
|
||||
{ "nousparse", L"nousparse", UF_SPARSE, 0},
|
||||
#endif
|
||||
#ifdef UF_REPARSE
|
||||
{ "noreparse", L"noreparse", UF_REPARSE, 0},
|
||||
{ "noureparse", L"noureparse", UF_REPARSE, 0},
|
||||
#endif
|
||||
#ifdef UF_SYSTEM
|
||||
{ "nosystem", L"nosystem", UF_SYSTEM, 0},
|
||||
{ "nousystem", L"nousystem", UF_SYSTEM, 0},
|
||||
#endif
|
||||
#ifdef FILE_ATTRIBUTE_SYSTEM
|
||||
{ "nosystem", L"nosystem", FILE_ATTRIBUTE_SYSTEM, 0},
|
||||
{ "nousystem", L"nousystem", FILE_ATTRIBUTE_SYSTEM, 0},
|
||||
#endif
|
||||
#if defined(FS_UNRM_FL) /* 'u' */
|
||||
{ "noundel", L"noundel", FS_UNRM_FL, 0},
|
||||
#elif defined(EXT2_UNRM_FL)
|
||||
{ "nouunlink", L"nouunlink", EXT2_UNRM_FL, 0},
|
||||
{ "noundel", L"noundel", EXT2_UNRM_FL, 0},
|
||||
#endif
|
||||
|
||||
#if defined(FS_BTREE_FL)
|
||||
{ "nobtree", L"nobtree", FS_BTREE_FL, 0 },
|
||||
#elif defined(EXT2_BTREE_FL)
|
||||
{ "nobtree", L"nobtree", EXT2_BTREE_FL, 0 },
|
||||
#if defined(FS_COMPR_FL) /* 'c' */
|
||||
{ "nocompress", L"nocompress", FS_COMPR_FL, 0},
|
||||
#elif defined(EXT2_COMPR_FL)
|
||||
{ "nocompress", L"nocompress", EXT2_COMPR_FL, 0},
|
||||
#endif
|
||||
|
||||
#if defined(FS_ECOMPR_FL)
|
||||
{ "nocomperr", L"nocomperr", FS_ECOMPR_FL, 0 },
|
||||
#elif defined(EXT2_ECOMPR_FL)
|
||||
{ "nocomperr", L"nocomperr", EXT2_ECOMPR_FL, 0 },
|
||||
#if defined(FS_NOATIME_FL) /* 'A' */
|
||||
{ "noatime", L"noatime", 0, FS_NOATIME_FL},
|
||||
#elif defined(EXT2_NOATIME_FL)
|
||||
{ "noatime", L"noatime", 0, EXT2_NOATIME_FL},
|
||||
#endif
|
||||
|
||||
#if defined(FS_COMPR_FL) /* 'c' */
|
||||
{ "nocompress", L"nocompress", FS_COMPR_FL, 0 },
|
||||
#elif defined(EXT2_COMPR_FL) /* 'c' */
|
||||
{ "nocompress", L"nocompress", EXT2_COMPR_FL, 0 },
|
||||
#endif
|
||||
|
||||
#if defined(FS_NOATIME_FL) /* 'A' */
|
||||
{ "noatime", L"noatime", 0, FS_NOATIME_FL},
|
||||
#elif defined(EXT2_NOATIME_FL) /* 'A' */
|
||||
{ "noatime", L"noatime", 0, EXT2_NOATIME_FL},
|
||||
#endif
|
||||
|
||||
#if defined(FS_DIRTY_FL)
|
||||
{ "nocompdirty",L"nocompdirty", FS_DIRTY_FL, 0},
|
||||
#elif defined(EXT2_DIRTY_FL)
|
||||
{ "nocompdirty",L"nocompdirty", EXT2_DIRTY_FL, 0},
|
||||
#endif
|
||||
|
||||
#if defined(FS_COMPRBLK_FL)
|
||||
#if defined(FS_NOCOMPR_FL)
|
||||
{ "nocomprblk", L"nocomprblk", FS_COMPRBLK_FL, FS_NOCOMPR_FL},
|
||||
#else
|
||||
{ "nocomprblk", L"nocomprblk", FS_COMPRBLK_FL, 0},
|
||||
#endif
|
||||
#elif defined(EXT2_COMPRBLK_FL)
|
||||
#if defined(EXT2_NOCOMPR_FL)
|
||||
{ "nocomprblk", L"nocomprblk", EXT2_COMPRBLK_FL, EXT2_NOCOMPR_FL},
|
||||
#else
|
||||
{ "nocomprblk", L"nocomprblk", EXT2_COMPRBLK_FL, 0},
|
||||
#endif
|
||||
#endif
|
||||
#if defined(FS_DIRSYNC_FL)
|
||||
{ "nodirsync", L"nodirsync", FS_DIRSYNC_FL, 0},
|
||||
#if defined(FS_DIRSYNC_FL) /* 'D' */
|
||||
{ "nodirsync", L"nodirsync", FS_DIRSYNC_FL, 0},
|
||||
#elif defined(EXT2_DIRSYNC_FL)
|
||||
{ "nodirsync", L"nodirsync", EXT2_DIRSYNC_FL, 0},
|
||||
{ "nodirsync", L"nodirsync", EXT2_DIRSYNC_FL, 0},
|
||||
#endif
|
||||
#if defined(FS_INDEX_FL)
|
||||
{ "nohashidx", L"nohashidx", FS_INDEX_FL, 0},
|
||||
#elif defined(EXT2_INDEX_FL)
|
||||
{ "nohashidx", L"nohashidx", EXT2_INDEX_FL, 0},
|
||||
#endif
|
||||
#if defined(FS_IMAGIC_FL)
|
||||
{ "noimagic", L"noimagic", FS_IMAGIC_FL, 0},
|
||||
#elif defined(EXT2_IMAGIC_FL)
|
||||
{ "noimagic", L"noimagic", EXT2_IMAGIC_FL, 0},
|
||||
#endif
|
||||
#if defined(FS_JOURNAL_DATA_FL)
|
||||
{ "nojournal", L"nojournal", FS_JOURNAL_DATA_FL, 0},
|
||||
#if defined(FS_JOURNAL_DATA_FL) /* 'j' */
|
||||
{ "nojournal-data",L"nojournal-data", FS_JOURNAL_DATA_FL, 0},
|
||||
{ "nojournal", L"nojournal", FS_JOURNAL_DATA_FL, 0},
|
||||
#elif defined(EXT3_JOURNAL_DATA_FL)
|
||||
{ "nojournal", L"nojournal", EXT3_JOURNAL_DATA_FL, 0},
|
||||
{ "nojournal-data",L"nojournal-data", EXT3_JOURNAL_DATA_FL, 0},
|
||||
{ "nojournal", L"nojournal", EXT3_JOURNAL_DATA_FL, 0},
|
||||
#endif
|
||||
#if defined(FS_SECRM_FL)
|
||||
{ "nosecuredeletion",L"nosecuredeletion",FS_SECRM_FL, 0},
|
||||
#if defined(FS_SECRM_FL) /* 's' */
|
||||
{ "nosecdel", L"nosecdel", FS_SECRM_FL, 0},
|
||||
{ "nosecuredeletion",L"nosecuredeletion",FS_SECRM_FL, 0},
|
||||
#elif defined(EXT2_SECRM_FL)
|
||||
{ "nosecuredeletion",L"nosecuredeletion",EXT2_SECRM_FL, 0},
|
||||
{ "nosecdel", L"nosecdel", EXT2_SECRM_FL, 0},
|
||||
{ "nosecuredeletion",L"nosecuredeletion",EXT2_SECRM_FL, 0},
|
||||
#endif
|
||||
#if defined(FS_SYNC_FL)
|
||||
{ "nosync", L"nosync", FS_SYNC_FL, 0},
|
||||
#if defined(FS_SYNC_FL) /* 'S' */
|
||||
{ "nosync", L"nosync", FS_SYNC_FL, 0},
|
||||
#elif defined(EXT2_SYNC_FL)
|
||||
{ "nosync", L"nosync", EXT2_SYNC_FL, 0},
|
||||
{ "nosync", L"nosync", EXT2_SYNC_FL, 0},
|
||||
#endif
|
||||
#if defined(FS_NOTAIL_FL)
|
||||
{ "notail", L"notail", 0, FS_NOTAIL_FL},
|
||||
#if defined(FS_NOTAIL_FL) /* 't' */
|
||||
{ "notail", L"notail", 0, FS_NOTAIL_FL},
|
||||
#elif defined(EXT2_NOTAIL_FL)
|
||||
{ "notail", L"notail", 0, EXT2_NOTAIL_FL},
|
||||
{ "notail", L"notail", 0, EXT2_NOTAIL_FL},
|
||||
#endif
|
||||
#if defined(FS_TOPDIR_FL)
|
||||
{ "notopdir", L"notopdir", FS_TOPDIR_FL, 0},
|
||||
#if defined(FS_TOPDIR_FL) /* 'T' */
|
||||
{ "notopdir", L"notopdir", FS_TOPDIR_FL, 0},
|
||||
#elif defined(EXT2_TOPDIR_FL)
|
||||
{ "notopdir", L"notopdir", EXT2_TOPDIR_FL, 0},
|
||||
{ "notopdir", L"notopdir", EXT2_TOPDIR_FL, 0},
|
||||
#endif
|
||||
#ifdef FS_ENCRYPT_FL
|
||||
{ "noencrypt", L"noencrypt", FS_ENCRYPT_FL, 0},
|
||||
#ifdef FS_NOCOW_FL /* 'C' */
|
||||
{ "nocow", L"nocow", 0, FS_NOCOW_FL},
|
||||
#endif
|
||||
#ifdef FS_HUGE_FILE_FL
|
||||
{ "nohugefile", L"nohugefile", FS_HUGE_FILE_FL, 0},
|
||||
#ifdef FS_PROJINHERIT_FL /* 'P' */
|
||||
{ "noprojinherit",L"noprojinherit", FS_PROJINHERIT_FL, 0},
|
||||
#endif
|
||||
#ifdef FS_EXTENT_FL
|
||||
{ "noextent", L"noextent", FS_EXTENT_FL, 0},
|
||||
#endif
|
||||
#ifdef FS_EA_INODE_FL
|
||||
{ "noeainode", L"noeainode", FS_EA_INODE_FL, 0},
|
||||
#endif
|
||||
#ifdef FS_EOFBLOCKS_FL
|
||||
{ "noeofblocks",L"noeofblocks", FS_EOFBLOCKS_FL, 0},
|
||||
#endif
|
||||
#ifdef FS_NOCOW_FL
|
||||
{ "nocow", L"nocow", FS_NOCOW_FL, 0},
|
||||
#endif
|
||||
#ifdef FS_INLINE_DATA_FL
|
||||
{ "noinlinedata",L"noinlinedata", FS_INLINE_DATA_FL, 0},
|
||||
#endif
|
||||
#ifdef FS_PROJINHERIT_FL
|
||||
{ "noprojinherit",L"noprojinherit", FS_PROJINHERIT_FL, 0},
|
||||
#endif
|
||||
#if defined(FS_RESERVED_FL)
|
||||
{ "noreserved", L"noreserved", FS_RESERVED_FL, 0},
|
||||
#elif defined(EXT2_RESERVED_FL)
|
||||
{ "noreserved", L"noreserved", EXT2_RESERVED_FL, 0},
|
||||
#endif
|
||||
{ NULL, NULL, 0, 0 }
|
||||
{ NULL, NULL, 0, 0}
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
#define ARCHIVE_ENTRY_H_INCLUDED
|
||||
|
||||
/* Note: Compiler will complain if this does not match archive.h! */
|
||||
#define ARCHIVE_VERSION_NUMBER 3003002
|
||||
#define ARCHIVE_VERSION_NUMBER 3004000
|
||||
|
||||
/*
|
||||
* Note: archive_entry.h is for use outside of libarchive; the
|
||||
|
@ -42,6 +42,7 @@
|
|||
|
||||
#include <sys/types.h>
|
||||
#include <stddef.h> /* for wchar_t */
|
||||
#include <stdint.h>
|
||||
#include <time.h>
|
||||
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
|
@ -189,6 +190,13 @@ struct archive_entry;
|
|||
#define AE_IFDIR ((__LA_MODE_T)0040000)
|
||||
#define AE_IFIFO ((__LA_MODE_T)0010000)
|
||||
|
||||
/*
|
||||
* Symlink types
|
||||
*/
|
||||
#define AE_SYMLINK_TYPE_UNDEFINED 0
|
||||
#define AE_SYMLINK_TYPE_FILE 1
|
||||
#define AE_SYMLINK_TYPE_DIRECTORY 2
|
||||
|
||||
/*
|
||||
* Basic object manipulation
|
||||
*/
|
||||
|
@ -274,6 +282,7 @@ __LA_DECL int archive_entry_size_is_set(struct archive_entry *);
|
|||
__LA_DECL const char *archive_entry_strmode(struct archive_entry *);
|
||||
__LA_DECL const char *archive_entry_symlink(struct archive_entry *);
|
||||
__LA_DECL const char *archive_entry_symlink_utf8(struct archive_entry *);
|
||||
__LA_DECL int archive_entry_symlink_type(struct archive_entry *);
|
||||
__LA_DECL const wchar_t *archive_entry_symlink_w(struct archive_entry *);
|
||||
__LA_DECL la_int64_t archive_entry_uid(struct archive_entry *);
|
||||
__LA_DECL const char *archive_entry_uname(struct archive_entry *);
|
||||
|
@ -349,6 +358,7 @@ __LA_DECL void archive_entry_unset_size(struct archive_entry *);
|
|||
__LA_DECL void archive_entry_copy_sourcepath(struct archive_entry *, const char *);
|
||||
__LA_DECL void archive_entry_copy_sourcepath_w(struct archive_entry *, const wchar_t *);
|
||||
__LA_DECL void archive_entry_set_symlink(struct archive_entry *, const char *);
|
||||
__LA_DECL void archive_entry_set_symlink_type(struct archive_entry *, int);
|
||||
__LA_DECL void archive_entry_set_symlink_utf8(struct archive_entry *, const char *);
|
||||
__LA_DECL void archive_entry_copy_symlink(struct archive_entry *, const char *);
|
||||
__LA_DECL void archive_entry_copy_symlink_w(struct archive_entry *, const wchar_t *);
|
||||
|
@ -691,7 +701,6 @@ __LA_DECL void archive_entry_linkify(struct archive_entry_linkresolver *,
|
|||
struct archive_entry **, struct archive_entry **);
|
||||
__LA_DECL struct archive_entry *archive_entry_partial_links(
|
||||
struct archive_entry_linkresolver *res, unsigned int *links);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
.\" Copyright (c) 2019 Martin Matuska
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd April 15, 2019
|
||||
.Dt ARCHIVE_ENTRY_MISC 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm archive_entry_symlink_type ,
|
||||
.Nm archive_entry_set_symlink_type
|
||||
.Nd miscellaneous functions for manipulating properties of archive_entry.
|
||||
.Sh LIBRARY
|
||||
Streaming Archive Library (libarchive, -larchive)
|
||||
.Sh SYNOPSIS
|
||||
.In archive_entry.h
|
||||
.Ft int
|
||||
.Fn archive_entry_symlink_type "struct archive_entry *a"
|
||||
.Ft void
|
||||
.Fn archive_entry_set_symlink_type "struct archive_entry *a" "int"
|
||||
.Sh DESCRIPTION
|
||||
The function
|
||||
.Fn archive_entry_symlink_type
|
||||
returns and the function
|
||||
.Fn archive_entry_set_symlink_type
|
||||
sets the type of the symbolic link stored in an archive entry. These functions
|
||||
have special meaning on operating systems that support multiple symbolic link
|
||||
types (e.g. Microsoft Windows).
|
||||
.Pp
|
||||
Supported values are:
|
||||
.Bl -tag -width "AE_SYMLINK_TYPE_DIRECTORY" -compact
|
||||
.It AE_SYMLINK_TYPE_UNDEFINED
|
||||
Symbolic link target type is not defined (default on unix systems)
|
||||
.It AE_SYMLINK_TYPE_FILE
|
||||
Symbolic link points to a file
|
||||
.It AE_SYMLINK_TYPE_DIRECTORY
|
||||
Symbolic link points to a directory
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr archive_entry 3 ,
|
||||
.Xr archive_entry_paths 3 ,
|
||||
.Xr archive_entry_stat 3 ,
|
||||
.Xr libarchive 3
|
|
@ -176,6 +176,9 @@ struct archive_entry {
|
|||
|
||||
/* Miscellaneous. */
|
||||
char strmode[12];
|
||||
|
||||
/* Symlink type support */
|
||||
int ae_symlink_type;
|
||||
};
|
||||
|
||||
#endif /* ARCHIVE_ENTRY_PRIVATE_H_INCLUDED */
|
||||
|
|
|
@ -51,7 +51,7 @@ archive_entry_sparse_clear(struct archive_entry *entry)
|
|||
|
||||
void
|
||||
archive_entry_sparse_add_entry(struct archive_entry *entry,
|
||||
int64_t offset, int64_t length)
|
||||
la_int64_t offset, la_int64_t length)
|
||||
{
|
||||
struct ae_sparse *sp;
|
||||
|
||||
|
@ -135,7 +135,7 @@ archive_entry_sparse_reset(struct archive_entry * entry)
|
|||
|
||||
int
|
||||
archive_entry_sparse_next(struct archive_entry * entry,
|
||||
int64_t *offset, int64_t *length)
|
||||
la_int64_t *offset, la_int64_t *length)
|
||||
{
|
||||
if (entry->sparse_p) {
|
||||
*offset = entry->sparse_p->offset;
|
||||
|
|
|
@ -83,6 +83,7 @@ __hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx)
|
|||
static int
|
||||
__hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len)
|
||||
{
|
||||
#pragma GCC diagnostic ignored "-Wcast-qual"
|
||||
BCRYPT_ALG_HANDLE hAlg;
|
||||
BCRYPT_HASH_HANDLE hHash;
|
||||
DWORD hash_len;
|
||||
|
|
|
@ -93,6 +93,9 @@ struct archive_match {
|
|||
/* exclusion/inclusion set flag. */
|
||||
int setflag;
|
||||
|
||||
/* Recursively include directory content? */
|
||||
int recursive_include;
|
||||
|
||||
/*
|
||||
* Matching filename patterns.
|
||||
*/
|
||||
|
@ -223,6 +226,7 @@ archive_match_new(void)
|
|||
return (NULL);
|
||||
a->archive.magic = ARCHIVE_MATCH_MAGIC;
|
||||
a->archive.state = ARCHIVE_STATE_NEW;
|
||||
a->recursive_include = 1;
|
||||
match_list_init(&(a->inclusions));
|
||||
match_list_init(&(a->exclusions));
|
||||
__archive_rb_tree_init(&(a->exclusion_tree), &rb_ops_mbs);
|
||||
|
@ -470,6 +474,28 @@ archive_match_path_excluded(struct archive *_a,
|
|||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* When recursive inclusion of directory content is enabled,
|
||||
* an inclusion pattern that matches a directory will also
|
||||
* include everything beneath that directory. Enabled by default.
|
||||
*
|
||||
* For compatibility with GNU tar, exclusion patterns always
|
||||
* match if a subset of the full patch matches (i.e., they are
|
||||
* are not rooted at the beginning of the path) and thus there
|
||||
* is no corresponding non-recursive exclusion mode.
|
||||
*/
|
||||
int
|
||||
archive_match_set_inclusion_recursion(struct archive *_a, int enabled)
|
||||
{
|
||||
struct archive_match *a;
|
||||
|
||||
archive_check_magic(_a, ARCHIVE_MATCH_MAGIC,
|
||||
ARCHIVE_STATE_NEW, "archive_match_set_inclusion_recursion");
|
||||
a = (struct archive_match *)_a;
|
||||
a->recursive_include = enabled;
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Utility functions to get statistic information for inclusion patterns.
|
||||
*/
|
||||
|
@ -781,7 +807,10 @@ static int
|
|||
match_path_inclusion(struct archive_match *a, struct match *m,
|
||||
int mbs, const void *pn)
|
||||
{
|
||||
int flag = PATHMATCH_NO_ANCHOR_END;
|
||||
/* Recursive operation requires only a prefix match. */
|
||||
int flag = a->recursive_include ?
|
||||
PATHMATCH_NO_ANCHOR_END :
|
||||
0;
|
||||
int r;
|
||||
|
||||
if (mbs) {
|
||||
|
@ -1232,7 +1261,7 @@ set_timefilter_pathname_mbs(struct archive_match *a, int timetype,
|
|||
archive_set_error(&(a->archive), EINVAL, "pathname is empty");
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
if (stat(path, &st) != 0) {
|
||||
if (la_stat(path, &st) != 0) {
|
||||
archive_set_error(&(a->archive), errno, "Failed to stat()");
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
|
@ -1582,7 +1611,7 @@ time_excluded(struct archive_match *a, struct archive_entry *entry)
|
|||
*/
|
||||
|
||||
int
|
||||
archive_match_include_uid(struct archive *_a, int64_t uid)
|
||||
archive_match_include_uid(struct archive *_a, la_int64_t uid)
|
||||
{
|
||||
struct archive_match *a;
|
||||
|
||||
|
@ -1593,7 +1622,7 @@ archive_match_include_uid(struct archive *_a, int64_t uid)
|
|||
}
|
||||
|
||||
int
|
||||
archive_match_include_gid(struct archive *_a, int64_t gid)
|
||||
archive_match_include_gid(struct archive *_a, la_int64_t gid)
|
||||
{
|
||||
struct archive_match *a;
|
||||
|
||||
|
|
|
@ -28,7 +28,8 @@
|
|||
#include <openssl/hmac.h>
|
||||
#include <openssl/opensslv.h>
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
|
||||
(defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20700000L)
|
||||
#include <stdlib.h> /* malloc, free */
|
||||
#include <string.h> /* memset */
|
||||
static inline HMAC_CTX *HMAC_CTX_new(void)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: archive_pack_dev.c,v 1.1.1.1 2017/04/20 12:55:35 joerg Exp $ */
|
||||
/* $NetBSD: archive_pack_dev.c,v 1.1.1.2 2019/07/24 13:50:22 joerg Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998, 2001 The NetBSD Foundation, Inc.
|
||||
|
@ -37,7 +37,7 @@
|
|||
#include <sys/cdefs.h>
|
||||
#endif
|
||||
#if !defined(lint)
|
||||
__RCSID("$NetBSD: archive_pack_dev.c,v 1.1.1.1 2017/04/20 12:55:35 joerg Exp $");
|
||||
__RCSID("$NetBSD: archive_pack_dev.c,v 1.1.1.2 2019/07/24 13:50:22 joerg Exp $");
|
||||
#endif /* not lint */
|
||||
|
||||
#ifdef HAVE_LIMITS_H
|
||||
|
@ -57,6 +57,12 @@ __RCSID("$NetBSD: archive_pack_dev.c,v 1.1.1.1 2017/04/20 12:55:35 joerg Exp $")
|
|||
#ifdef HAVE_SYS_STAT_H
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_SYSMACROS_H
|
||||
#include <sys/sysmacros.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_MKDEV_H
|
||||
#include <sys/mkdev.h>
|
||||
#endif
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
|
|
@ -52,12 +52,25 @@
|
|||
#error Oops: No config.h and no pre-built configuration in archive_platform.h.
|
||||
#endif
|
||||
|
||||
/* On macOS check for some symbols based on the deployment target version. */
|
||||
#if defined(__APPLE__)
|
||||
# undef HAVE_FUTIMENS
|
||||
# undef HAVE_UTIMENSAT
|
||||
# include <AvailabilityMacros.h>
|
||||
# if MAC_OS_X_VERSION_MIN_REQUIRED >= 101300
|
||||
# define HAVE_FUTIMENS 1
|
||||
# define HAVE_UTIMENSAT 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* It should be possible to get rid of this by extending the feature-test
|
||||
* macros to cover Windows API functions, probably along with non-trivial
|
||||
* refactoring of code to find structures that sit more cleanly on top of
|
||||
* either Windows or Posix APIs. */
|
||||
#if (defined(__WIN32__) || defined(_WIN32) || defined(__WIN32)) && !defined(__CYGWIN__)
|
||||
#include "archive_windows.h"
|
||||
#else
|
||||
#define la_stat(path,stref) stat(path,stref)
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -180,4 +193,10 @@
|
|||
#define ARCHIVE_ERRNO_MISC (-1)
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && (__GNUC__ >= 7)
|
||||
#define __LA_FALLTHROUGH __attribute__((fallthrough))
|
||||
#else
|
||||
#define __LA_FALLTHROUGH
|
||||
#endif
|
||||
|
||||
#endif /* !ARCHIVE_PLATFORM_H_INCLUDED */
|
||||
|
|
|
@ -115,14 +115,14 @@ static void Ppmd7_Construct(CPpmd7 *p)
|
|||
memset(p->HB2Flag + 0x40, 8, 0x100 - 0x40);
|
||||
}
|
||||
|
||||
static void Ppmd7_Free(CPpmd7 *p, ISzAlloc *alloc)
|
||||
static void Ppmd7_Free(CPpmd7 *p)
|
||||
{
|
||||
alloc->Free(alloc, p->Base);
|
||||
free(p->Base);
|
||||
p->Size = 0;
|
||||
p->Base = 0;
|
||||
}
|
||||
|
||||
static Bool Ppmd7_Alloc(CPpmd7 *p, UInt32 size, ISzAlloc *alloc)
|
||||
static Bool Ppmd7_Alloc(CPpmd7 *p, UInt32 size)
|
||||
{
|
||||
if (p->Base == 0 || p->Size != size)
|
||||
{
|
||||
|
@ -131,14 +131,14 @@ static Bool Ppmd7_Alloc(CPpmd7 *p, UInt32 size, ISzAlloc *alloc)
|
|||
if (size < UNIT_SIZE) {
|
||||
return False;
|
||||
}
|
||||
Ppmd7_Free(p, alloc);
|
||||
Ppmd7_Free(p);
|
||||
p->AlignOffset =
|
||||
#ifdef PPMD_32BIT
|
||||
(4 - size) & 3;
|
||||
#else
|
||||
4 - (size & 3);
|
||||
#endif
|
||||
if ((p->Base = (Byte *)alloc->Alloc(alloc, p->AlignOffset + size
|
||||
if ((p->Base = (Byte *)malloc(p->AlignOffset + size
|
||||
#ifndef PPMD_32BIT
|
||||
+ UNIT_SIZE
|
||||
#endif
|
||||
|
|
|
@ -95,8 +95,8 @@ typedef struct
|
|||
{
|
||||
/* Base Functions */
|
||||
void (*Ppmd7_Construct)(CPpmd7 *p);
|
||||
Bool (*Ppmd7_Alloc)(CPpmd7 *p, UInt32 size, ISzAlloc *alloc);
|
||||
void (*Ppmd7_Free)(CPpmd7 *p, ISzAlloc *alloc);
|
||||
Bool (*Ppmd7_Alloc)(CPpmd7 *p, UInt32 size);
|
||||
void (*Ppmd7_Free)(CPpmd7 *p);
|
||||
void (*Ppmd7_Init)(CPpmd7 *p, unsigned maxOrder);
|
||||
#define Ppmd7_WasAllocated(p) ((p)->Base != NULL)
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,148 @@
|
|||
/* Ppmd8.h -- PPMdI codec
|
||||
2011-01-27 : Igor Pavlov : Public domain
|
||||
This code is based on:
|
||||
PPMd var.I (2002): Dmitry Shkarin : Public domain
|
||||
Carryless rangecoder (1999): Dmitry Subbotin : Public domain */
|
||||
|
||||
#ifndef __PPMD8_H
|
||||
#define __PPMD8_H
|
||||
|
||||
#include "archive_ppmd_private.h"
|
||||
|
||||
#define PPMD8_MIN_ORDER 2
|
||||
#define PPMD8_MAX_ORDER 16
|
||||
|
||||
struct CPpmd8_Context_;
|
||||
|
||||
typedef
|
||||
#ifdef PPMD_32BIT
|
||||
struct CPpmd8_Context_ *
|
||||
#else
|
||||
UInt32
|
||||
#endif
|
||||
CPpmd8_Context_Ref;
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
typedef struct CPpmd8_Context_
|
||||
{
|
||||
Byte NumStats;
|
||||
Byte Flags;
|
||||
UInt16 SummFreq;
|
||||
CPpmd_State_Ref Stats;
|
||||
CPpmd8_Context_Ref Suffix;
|
||||
} CPpmd8_Context;
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
#define Ppmd8Context_OneState(p) ((CPpmd_State *)&(p)->SummFreq)
|
||||
|
||||
/* The BUG in Shkarin's code for FREEZE mode was fixed, but that fixed
|
||||
code is not compatible with original code for some files compressed
|
||||
in FREEZE mode. So we disable FREEZE mode support. */
|
||||
|
||||
enum
|
||||
{
|
||||
PPMD8_RESTORE_METHOD_RESTART,
|
||||
PPMD8_RESTORE_METHOD_CUT_OFF
|
||||
#ifdef PPMD8_FREEZE_SUPPORT
|
||||
, PPMD8_RESTORE_METHOD_FREEZE
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CPpmd8_Context *MinContext, *MaxContext;
|
||||
CPpmd_State *FoundState;
|
||||
unsigned OrderFall, InitEsc, PrevSuccess, MaxOrder;
|
||||
Int32 RunLength, InitRL; /* must be 32-bit at least */
|
||||
|
||||
UInt32 Size;
|
||||
UInt32 GlueCount;
|
||||
Byte *Base, *LoUnit, *HiUnit, *Text, *UnitsStart;
|
||||
UInt32 AlignOffset;
|
||||
unsigned RestoreMethod;
|
||||
|
||||
/* Range Coder */
|
||||
UInt32 Range;
|
||||
UInt32 Code;
|
||||
UInt32 Low;
|
||||
union
|
||||
{
|
||||
IByteIn *In;
|
||||
IByteOut *Out;
|
||||
} Stream;
|
||||
|
||||
Byte Indx2Units[PPMD_NUM_INDEXES];
|
||||
Byte Units2Indx[128];
|
||||
CPpmd_Void_Ref FreeList[PPMD_NUM_INDEXES];
|
||||
UInt32 Stamps[PPMD_NUM_INDEXES];
|
||||
|
||||
Byte NS2BSIndx[256], NS2Indx[260];
|
||||
CPpmd_See DummySee, See[24][32];
|
||||
UInt16 BinSumm[25][64];
|
||||
} CPpmd8;
|
||||
|
||||
void Ppmd8_Construct(CPpmd8 *p);
|
||||
Bool Ppmd8_Alloc(CPpmd8 *p, UInt32 size);
|
||||
void Ppmd8_Free(CPpmd8 *p);
|
||||
void Ppmd8_Init(CPpmd8 *p, unsigned maxOrder, unsigned restoreMethod);
|
||||
#define Ppmd8_WasAllocated(p) ((p)->Base != NULL)
|
||||
|
||||
|
||||
/* ---------- Internal Functions ---------- */
|
||||
|
||||
extern const Byte PPMD8_kExpEscape[16];
|
||||
|
||||
#ifdef PPMD_32BIT
|
||||
#define Ppmd8_GetPtr(p, ptr) (ptr)
|
||||
#define Ppmd8_GetContext(p, ptr) (ptr)
|
||||
#define Ppmd8_GetStats(p, ctx) ((ctx)->Stats)
|
||||
#else
|
||||
#define Ppmd8_GetPtr(p, offs) ((void *)((p)->Base + (offs)))
|
||||
#define Ppmd8_GetContext(p, offs) ((CPpmd8_Context *)Ppmd8_GetPtr((p), (offs)))
|
||||
#define Ppmd8_GetStats(p, ctx) ((CPpmd_State *)Ppmd8_GetPtr((p), ((ctx)->Stats)))
|
||||
#endif
|
||||
|
||||
void Ppmd8_Update1(CPpmd8 *p);
|
||||
void Ppmd8_Update1_0(CPpmd8 *p);
|
||||
void Ppmd8_Update2(CPpmd8 *p);
|
||||
void Ppmd8_UpdateBin(CPpmd8 *p);
|
||||
|
||||
#define Ppmd8_GetBinSumm(p) \
|
||||
&p->BinSumm[p->NS2Indx[Ppmd8Context_OneState(p->MinContext)->Freq - 1]][ \
|
||||
p->NS2BSIndx[Ppmd8_GetContext(p, p->MinContext->Suffix)->NumStats] + \
|
||||
p->PrevSuccess + p->MinContext->Flags + ((p->RunLength >> 26) & 0x20)]
|
||||
|
||||
CPpmd_See *Ppmd8_MakeEscFreq(CPpmd8 *p, unsigned numMasked, UInt32 *scale);
|
||||
|
||||
|
||||
/* ---------- Decode ---------- */
|
||||
|
||||
Bool Ppmd8_RangeDec_Init(CPpmd8 *p);
|
||||
#define Ppmd8_RangeDec_IsFinishedOK(p) ((p)->Code == 0)
|
||||
int Ppmd8_DecodeSymbol(CPpmd8 *p); /* returns: -1 as EndMarker, -2 as DataError */
|
||||
|
||||
/* ---------- Encode ---------- */
|
||||
|
||||
#define Ppmd8_RangeEnc_Init(p) { (p)->Low = 0; (p)->Range = 0xFFFFFFFF; }
|
||||
void Ppmd8_RangeEnc_FlushData(CPpmd8 *p);
|
||||
void Ppmd8_EncodeSymbol(CPpmd8 *p, int symbol); /* symbol = -1 means EndMarker */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* Base Functions */
|
||||
void (*Ppmd8_Construct)(CPpmd8 *p);
|
||||
Bool (*Ppmd8_Alloc)(CPpmd8 *p, UInt32 size);
|
||||
void (*Ppmd8_Free)(CPpmd8 *p);
|
||||
void (*Ppmd8_Init)(CPpmd8 *p, unsigned max_order, unsigned restore_method);
|
||||
#define Ppmd7_WasAllocated(p) ((p)->Base != NULL)
|
||||
|
||||
/* Decode Functions */
|
||||
int (*Ppmd8_RangeDec_Init)(CPpmd8 *p);
|
||||
int (*Ppmd8_DecodeSymbol)(CPpmd8 *p);
|
||||
} IPpmd8;
|
||||
|
||||
extern const IPpmd8 __archive_ppmd8_functions;
|
||||
|
||||
#endif
|
|
@ -69,13 +69,6 @@ typedef struct
|
|||
void (*Write)(void *p, Byte b);
|
||||
} IByteOut;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void *(*Alloc)(void *p, size_t size);
|
||||
void (*Free)(void *p, void *address); /* address can be 0 */
|
||||
} ISzAlloc;
|
||||
|
||||
/*** End defined in Types.h ***/
|
||||
/*** Begin defined in CpuArch.h ***/
|
||||
|
||||
|
|
|
@ -120,7 +120,8 @@ archive_read_new(void)
|
|||
* Record the do-not-extract-to file. This belongs in archive_read_extract.c.
|
||||
*/
|
||||
void
|
||||
archive_read_extract_set_skip_file(struct archive *_a, int64_t d, int64_t i)
|
||||
archive_read_extract_set_skip_file(struct archive *_a, la_int64_t d,
|
||||
la_int64_t i)
|
||||
{
|
||||
struct archive_read *a = (struct archive_read *)_a;
|
||||
|
||||
|
@ -610,6 +611,15 @@ choose_filters(struct archive_read *a)
|
|||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
int
|
||||
__archive_read_header(struct archive_read *a, struct archive_entry *entry)
|
||||
{
|
||||
if (a->filter->read_header)
|
||||
return a->filter->read_header(a->filter, entry);
|
||||
else
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Read header of next entry.
|
||||
*/
|
||||
|
@ -747,7 +757,7 @@ choose_format(struct archive_read *a)
|
|||
* Return the file offset (within the uncompressed data stream) where
|
||||
* the last header started.
|
||||
*/
|
||||
int64_t
|
||||
la_int64_t
|
||||
archive_read_header_position(struct archive *_a)
|
||||
{
|
||||
struct archive_read *a = (struct archive_read *)_a;
|
||||
|
@ -820,7 +830,7 @@ archive_read_format_capabilities(struct archive *_a)
|
|||
* DO NOT intermingle calls to this function and archive_read_data_block
|
||||
* to read a single entry body.
|
||||
*/
|
||||
ssize_t
|
||||
la_ssize_t
|
||||
archive_read_data(struct archive *_a, void *buff, size_t s)
|
||||
{
|
||||
struct archive *a = (struct archive *)_a;
|
||||
|
@ -881,7 +891,8 @@ archive_read_data(struct archive *_a, void *buff, size_t s)
|
|||
len = a->read_data_remaining;
|
||||
if (len > s)
|
||||
len = s;
|
||||
memcpy(dest, a->read_data_block, len);
|
||||
if (len)
|
||||
memcpy(dest, a->read_data_block, len);
|
||||
s -= len;
|
||||
a->read_data_block += len;
|
||||
a->read_data_remaining -= len;
|
||||
|
@ -942,7 +953,7 @@ archive_read_data_skip(struct archive *_a)
|
|||
return (r);
|
||||
}
|
||||
|
||||
int64_t
|
||||
la_int64_t
|
||||
archive_seek_data(struct archive *_a, int64_t offset, int whence)
|
||||
{
|
||||
struct archive_read *a = (struct archive_read *)_a;
|
||||
|
@ -1625,7 +1636,8 @@ __archive_read_filter_seek(struct archive_read_filter *filter, int64_t offset,
|
|||
switch (whence) {
|
||||
case SEEK_CUR:
|
||||
/* Adjust the offset and use SEEK_SET instead */
|
||||
offset += filter->position;
|
||||
offset += filter->position;
|
||||
__LA_FALLTHROUGH;
|
||||
case SEEK_SET:
|
||||
cursor = 0;
|
||||
while (1)
|
||||
|
|
|
@ -89,6 +89,10 @@ archive_read_append_filter(struct archive *_a, int code)
|
|||
strcpy(str, "lz4");
|
||||
r1 = archive_read_support_filter_lz4(_a);
|
||||
break;
|
||||
case ARCHIVE_FILTER_ZSTD:
|
||||
strcpy(str, "zstd");
|
||||
r1 = archive_read_support_filter_zstd(_a);
|
||||
break;
|
||||
case ARCHIVE_FILTER_LZIP:
|
||||
strcpy(str, "lzip");
|
||||
r1 = archive_read_support_filter_lzip(_a);
|
||||
|
|
|
@ -127,7 +127,7 @@ archive_read_disk_entry_setup_acls(struct archive_read_disk *a,
|
|||
/*
|
||||
* Enter working directory and return working pathname of archive_entry.
|
||||
* If a pointer to an integer is provided and its value is below zero
|
||||
* open a file descriptor on this pahtname.
|
||||
* open a file descriptor on this pathname.
|
||||
*/
|
||||
const char *
|
||||
archive_read_disk_entry_setup_path(struct archive_read_disk *a,
|
||||
|
@ -163,6 +163,9 @@ archive_read_disk_entry_from_file(struct archive *_a,
|
|||
int initial_fd = fd;
|
||||
int r, r1;
|
||||
|
||||
archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC, ARCHIVE_STATE_ANY,
|
||||
"archive_read_disk_entry_from_file");
|
||||
|
||||
archive_clear_error(_a);
|
||||
path = archive_entry_sourcepath(entry);
|
||||
if (path == NULL)
|
||||
|
@ -188,7 +191,7 @@ archive_read_disk_entry_from_file(struct archive *_a,
|
|||
}
|
||||
} else
|
||||
#endif
|
||||
if (stat(path, &s) != 0) {
|
||||
if (la_stat(path, &s) != 0) {
|
||||
archive_set_error(&a->archive, errno,
|
||||
"Can't stat %s", path);
|
||||
return (ARCHIVE_FAILED);
|
||||
|
@ -928,11 +931,10 @@ setup_sparse(struct archive_read_disk *a,
|
|||
return (ARCHIVE_OK);
|
||||
|
||||
/* Does filesystem support the reporting of hole ? */
|
||||
if (*fd < 0) {
|
||||
if (*fd < 0)
|
||||
path = archive_read_disk_entry_setup_path(a, entry, fd);
|
||||
if (path == NULL)
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
else
|
||||
path = NULL;
|
||||
|
||||
if (*fd >= 0) {
|
||||
#ifdef _PC_MIN_HOLE_SIZE
|
||||
|
@ -943,6 +945,8 @@ setup_sparse(struct archive_read_disk *a,
|
|||
if (initial_off != 0)
|
||||
lseek(*fd, 0, SEEK_SET);
|
||||
} else {
|
||||
if (path == NULL)
|
||||
return (ARCHIVE_FAILED);
|
||||
#ifdef _PC_MIN_HOLE_SIZE
|
||||
if (pathconf(path, _PC_MIN_HOLE_SIZE) <= 0)
|
||||
return (ARCHIVE_OK);
|
||||
|
|
|
@ -387,7 +387,7 @@ archive_read_disk_vtable(void)
|
|||
}
|
||||
|
||||
const char *
|
||||
archive_read_disk_gname(struct archive *_a, int64_t gid)
|
||||
archive_read_disk_gname(struct archive *_a, la_int64_t gid)
|
||||
{
|
||||
struct archive_read_disk *a = (struct archive_read_disk *)_a;
|
||||
if (ARCHIVE_OK != __archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
|
||||
|
@ -399,7 +399,7 @@ archive_read_disk_gname(struct archive *_a, int64_t gid)
|
|||
}
|
||||
|
||||
const char *
|
||||
archive_read_disk_uname(struct archive *_a, int64_t uid)
|
||||
archive_read_disk_uname(struct archive *_a, la_int64_t uid)
|
||||
{
|
||||
struct archive_read_disk *a = (struct archive_read_disk *)_a;
|
||||
if (ARCHIVE_OK != __archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
|
||||
|
@ -413,7 +413,7 @@ archive_read_disk_uname(struct archive *_a, int64_t uid)
|
|||
int
|
||||
archive_read_disk_set_gname_lookup(struct archive *_a,
|
||||
void *private_data,
|
||||
const char * (*lookup_gname)(void *private, int64_t gid),
|
||||
const char * (*lookup_gname)(void *private, la_int64_t gid),
|
||||
void (*cleanup_gname)(void *private))
|
||||
{
|
||||
struct archive_read_disk *a = (struct archive_read_disk *)_a;
|
||||
|
@ -432,7 +432,7 @@ archive_read_disk_set_gname_lookup(struct archive *_a,
|
|||
int
|
||||
archive_read_disk_set_uname_lookup(struct archive *_a,
|
||||
void *private_data,
|
||||
const char * (*lookup_uname)(void *private, int64_t uid),
|
||||
const char * (*lookup_uname)(void *private, la_int64_t uid),
|
||||
void (*cleanup_uname)(void *private))
|
||||
{
|
||||
struct archive_read_disk *a = (struct archive_read_disk *)_a;
|
||||
|
@ -856,7 +856,12 @@ next_entry(struct archive_read_disk *a, struct tree *t,
|
|||
const struct stat *st; /* info to use for this entry */
|
||||
const struct stat *lst;/* lstat() information */
|
||||
const char *name;
|
||||
int descend, r;
|
||||
int delayed, delayed_errno, descend, r;
|
||||
struct archive_string delayed_str;
|
||||
|
||||
delayed = ARCHIVE_OK;
|
||||
delayed_errno = 0;
|
||||
archive_string_init(&delayed_str);
|
||||
|
||||
st = NULL;
|
||||
lst = NULL;
|
||||
|
@ -885,14 +890,26 @@ next_entry(struct archive_read_disk *a, struct tree *t,
|
|||
case TREE_REGULAR:
|
||||
lst = tree_current_lstat(t);
|
||||
if (lst == NULL) {
|
||||
if (errno == ENOENT && t->depth > 0) {
|
||||
delayed = ARCHIVE_WARN;
|
||||
delayed_errno = errno;
|
||||
if (delayed_str.length == 0) {
|
||||
archive_string_sprintf(&delayed_str,
|
||||
"%s", tree_current_path(t));
|
||||
} else {
|
||||
archive_string_sprintf(&delayed_str,
|
||||
" %s", tree_current_path(t));
|
||||
}
|
||||
} else {
|
||||
archive_set_error(&a->archive, errno,
|
||||
"%s: Cannot stat",
|
||||
tree_current_path(t));
|
||||
tree_enter_initial_dir(t);
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while (lst == NULL);
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
@ -1083,6 +1100,18 @@ next_entry(struct archive_read_disk *a, struct tree *t,
|
|||
r = archive_read_disk_entry_from_file(&(a->archive), entry,
|
||||
t->entry_fd, st);
|
||||
|
||||
if (r == ARCHIVE_OK) {
|
||||
r = delayed;
|
||||
if (r != ARCHIVE_OK) {
|
||||
archive_string_sprintf(&delayed_str, ": %s",
|
||||
"File removed before we read it");
|
||||
archive_set_error(&(a->archive), delayed_errno,
|
||||
"%s", delayed_str.s);
|
||||
}
|
||||
}
|
||||
if (!archive_string_empty(&delayed_str))
|
||||
archive_string_free(&delayed_str);
|
||||
|
||||
return (r);
|
||||
}
|
||||
|
||||
|
@ -1266,10 +1295,23 @@ archive_read_disk_descend(struct archive *_a)
|
|||
if (t->visit_type != TREE_REGULAR || !t->descend)
|
||||
return (ARCHIVE_OK);
|
||||
|
||||
/*
|
||||
* We must not treat the initial specified path as a physical dir,
|
||||
* because if we do then we will try and ascend out of it by opening
|
||||
* ".." which is (a) wrong and (b) causes spurious permissions errors
|
||||
* if ".." is not readable by us. Instead, treat it as if it were a
|
||||
* symlink. (This uses an extra fd, but it can only happen once at the
|
||||
* top level of a traverse.) But we can't necessarily assume t->st is
|
||||
* valid here (though t->lst is), which complicates the logic a
|
||||
* little.
|
||||
*/
|
||||
if (tree_current_is_physical_dir(t)) {
|
||||
tree_push(t, t->basename, t->current_filesystem_id,
|
||||
t->lst.st_dev, t->lst.st_ino, &t->restore_time);
|
||||
t->stack->flags |= isDir;
|
||||
if (t->stack->parent->parent != NULL)
|
||||
t->stack->flags |= isDir;
|
||||
else
|
||||
t->stack->flags |= isDirLink;
|
||||
} else if (tree_current_is_dir(t)) {
|
||||
tree_push(t, t->basename, t->current_filesystem_id,
|
||||
t->st.st_dev, t->st.st_ino, &t->restore_time);
|
||||
|
@ -2122,6 +2164,17 @@ tree_open(const char *path, int symlink_mode, int restore_time)
|
|||
static struct tree *
|
||||
tree_reopen(struct tree *t, const char *path, int restore_time)
|
||||
{
|
||||
#if defined(O_PATH)
|
||||
/* Linux */
|
||||
const int o_flag = O_PATH;
|
||||
#elif defined(O_SEARCH)
|
||||
/* SunOS */
|
||||
const int o_flag = O_SEARCH;
|
||||
#elif defined(O_EXEC)
|
||||
/* FreeBSD */
|
||||
const int o_flag = O_EXEC;
|
||||
#endif
|
||||
|
||||
t->flags = (restore_time != 0)?needsRestoreTimes:0;
|
||||
t->flags |= onInitialDir;
|
||||
t->visit_type = 0;
|
||||
|
@ -2143,6 +2196,15 @@ tree_reopen(struct tree *t, const char *path, int restore_time)
|
|||
t->stack->flags = needsFirstVisit;
|
||||
t->maxOpenCount = t->openCount = 1;
|
||||
t->initial_dir_fd = open(".", O_RDONLY | O_CLOEXEC);
|
||||
#if defined(O_PATH) || defined(O_SEARCH) || defined(O_EXEC)
|
||||
/*
|
||||
* Most likely reason to fail opening "." is that it's not readable,
|
||||
* so try again for execute. The consequences of not opening this are
|
||||
* unhelpful and unnecessary errors later.
|
||||
*/
|
||||
if (t->initial_dir_fd < 0)
|
||||
t->initial_dir_fd = open(".", o_flag | O_CLOEXEC);
|
||||
#endif
|
||||
__archive_ensure_cloexec_flag(t->initial_dir_fd);
|
||||
t->working_dir_fd = tree_dup(t->initial_dir_fd);
|
||||
return (t);
|
||||
|
@ -2450,7 +2512,7 @@ tree_current_stat(struct tree *t)
|
|||
#else
|
||||
if (tree_enter_working_dir(t) != 0)
|
||||
return NULL;
|
||||
if (stat(tree_current_access_path(t), &t->st) != 0)
|
||||
if (la_stat(tree_current_access_path(t), &t->st) != 0)
|
||||
#endif
|
||||
return NULL;
|
||||
t->flags |= hasStat;
|
||||
|
|
|
@ -117,7 +117,7 @@ struct filesystem {
|
|||
*/
|
||||
|
||||
#define MAX_OVERLAPPED 8
|
||||
#define BUFFER_SIZE (1024 * 8)
|
||||
#define READ_BUFFER_SIZE (1024 * 64) /* Default to 64KB per https://technet.microsoft.com/en-us/library/cc938632.aspx */
|
||||
#define DIRECT_IO 0/* Disabled */
|
||||
#define ASYNC_IO 1/* Enabled */
|
||||
|
||||
|
@ -299,8 +299,155 @@ static int close_and_restore_time(HANDLE, struct tree *,
|
|||
struct restore_time *);
|
||||
static int setup_sparse_from_disk(struct archive_read_disk *,
|
||||
struct archive_entry *, HANDLE);
|
||||
static int la_linkname_from_handle(HANDLE, wchar_t **, int *);
|
||||
static int la_linkname_from_pathw(const wchar_t *, wchar_t **, int *);
|
||||
static void entry_symlink_from_pathw(struct archive_entry *,
|
||||
const wchar_t *path);
|
||||
|
||||
typedef struct _REPARSE_DATA_BUFFER {
|
||||
ULONG ReparseTag;
|
||||
USHORT ReparseDataLength;
|
||||
USHORT Reserved;
|
||||
union {
|
||||
struct {
|
||||
USHORT SubstituteNameOffset;
|
||||
USHORT SubstituteNameLength;
|
||||
USHORT PrintNameOffset;
|
||||
USHORT PrintNameLength;
|
||||
ULONG Flags;
|
||||
WCHAR PathBuffer[1];
|
||||
} SymbolicLinkReparseBuffer;
|
||||
struct {
|
||||
USHORT SubstituteNameOffset;
|
||||
USHORT SubstituteNameLength;
|
||||
USHORT PrintNameOffset;
|
||||
USHORT PrintNameLength;
|
||||
WCHAR PathBuffer[1];
|
||||
} MountPointReparseBuffer;
|
||||
struct {
|
||||
UCHAR DataBuffer[1];
|
||||
} GenericReparseBuffer;
|
||||
} DUMMYUNIONNAME;
|
||||
} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
|
||||
|
||||
/*
|
||||
* Reads the target of a symbolic link
|
||||
*
|
||||
* Returns 0 on success and -1 on failure
|
||||
* outbuf is allocated in the function
|
||||
*/
|
||||
static int
|
||||
la_linkname_from_handle(HANDLE h, wchar_t **linkname, int *linktype)
|
||||
{
|
||||
DWORD inbytes;
|
||||
REPARSE_DATA_BUFFER *buf;
|
||||
BY_HANDLE_FILE_INFORMATION st;
|
||||
size_t len;
|
||||
BOOL ret;
|
||||
BYTE *indata;
|
||||
wchar_t *tbuf;
|
||||
|
||||
ret = GetFileInformationByHandle(h, &st);
|
||||
if (ret == 0 ||
|
||||
(st.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) == 0) {
|
||||
return (-1);
|
||||
}
|
||||
|
||||
indata = malloc(MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
|
||||
ret = DeviceIoControl(h, FSCTL_GET_REPARSE_POINT, NULL, 0, indata,
|
||||
1024, &inbytes, NULL);
|
||||
if (ret == 0) {
|
||||
la_dosmaperr(GetLastError());
|
||||
free(indata);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
buf = (REPARSE_DATA_BUFFER *) indata;
|
||||
if (buf->ReparseTag != IO_REPARSE_TAG_SYMLINK) {
|
||||
free(indata);
|
||||
/* File is not a symbolic link */
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
len = buf->SymbolicLinkReparseBuffer.SubstituteNameLength;
|
||||
if (len <= 0) {
|
||||
free(indata);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
tbuf = malloc(len + 1 * sizeof(wchar_t));
|
||||
if (tbuf == NULL) {
|
||||
free(indata);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
memcpy(tbuf, &((BYTE *)buf->SymbolicLinkReparseBuffer.PathBuffer)
|
||||
[buf->SymbolicLinkReparseBuffer.SubstituteNameOffset], len);
|
||||
free(indata);
|
||||
|
||||
tbuf[len / sizeof(wchar_t)] = L'\0';
|
||||
|
||||
*linkname = tbuf;
|
||||
|
||||
/*
|
||||
* Translate backslashes to slashes for libarchive internal use
|
||||
*/
|
||||
while(*tbuf != L'\0') {
|
||||
if (*tbuf == L'\\')
|
||||
*tbuf = L'/';
|
||||
tbuf++;
|
||||
}
|
||||
|
||||
if ((st.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
|
||||
*linktype = AE_SYMLINK_TYPE_FILE;
|
||||
else
|
||||
*linktype = AE_SYMLINK_TYPE_DIRECTORY;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns AE_SYMLINK_TYPE_FILE, AE_SYMLINK_TYPE_DIRECTORY or -1 on error
|
||||
*/
|
||||
static int
|
||||
la_linkname_from_pathw(const wchar_t *path, wchar_t **outbuf, int *linktype)
|
||||
{
|
||||
HANDLE h;
|
||||
const DWORD flag = FILE_FLAG_BACKUP_SEMANTICS |
|
||||
FILE_FLAG_OPEN_REPARSE_POINT;
|
||||
int ret;
|
||||
|
||||
h = CreateFileW(path, 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, flag,
|
||||
NULL);
|
||||
if (h == INVALID_HANDLE_VALUE) {
|
||||
la_dosmaperr(GetLastError());
|
||||
return (-1);
|
||||
}
|
||||
|
||||
ret = la_linkname_from_handle(h, outbuf, linktype);
|
||||
CloseHandle(h);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static void
|
||||
entry_symlink_from_pathw(struct archive_entry *entry, const wchar_t *path)
|
||||
{
|
||||
wchar_t *linkname = NULL;
|
||||
int ret, linktype;
|
||||
|
||||
ret = la_linkname_from_pathw(path, &linkname, &linktype);
|
||||
if (ret != 0)
|
||||
return;
|
||||
if (linktype >= 0) {
|
||||
archive_entry_copy_symlink_w(entry, linkname);
|
||||
archive_entry_set_symlink_type(entry, linktype);
|
||||
}
|
||||
free(linkname);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static struct archive_vtable *
|
||||
archive_read_disk_vtable(void)
|
||||
|
@ -320,7 +467,7 @@ archive_read_disk_vtable(void)
|
|||
}
|
||||
|
||||
const char *
|
||||
archive_read_disk_gname(struct archive *_a, int64_t gid)
|
||||
archive_read_disk_gname(struct archive *_a, la_int64_t gid)
|
||||
{
|
||||
struct archive_read_disk *a = (struct archive_read_disk *)_a;
|
||||
if (ARCHIVE_OK != __archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
|
||||
|
@ -332,7 +479,7 @@ archive_read_disk_gname(struct archive *_a, int64_t gid)
|
|||
}
|
||||
|
||||
const char *
|
||||
archive_read_disk_uname(struct archive *_a, int64_t uid)
|
||||
archive_read_disk_uname(struct archive *_a, la_int64_t uid)
|
||||
{
|
||||
struct archive_read_disk *a = (struct archive_read_disk *)_a;
|
||||
if (ARCHIVE_OK != __archive_check_magic(_a, ARCHIVE_READ_DISK_MAGIC,
|
||||
|
@ -346,7 +493,7 @@ archive_read_disk_uname(struct archive *_a, int64_t uid)
|
|||
int
|
||||
archive_read_disk_set_gname_lookup(struct archive *_a,
|
||||
void *private_data,
|
||||
const char * (*lookup_gname)(void *private, int64_t gid),
|
||||
const char * (*lookup_gname)(void *private, la_int64_t gid),
|
||||
void (*cleanup_gname)(void *private))
|
||||
{
|
||||
struct archive_read_disk *a = (struct archive_read_disk *)_a;
|
||||
|
@ -567,7 +714,7 @@ start_next_async_read(struct archive_read_disk *a, struct tree *t)
|
|||
/* Allocate read buffer. */
|
||||
if (olp->buff == NULL) {
|
||||
void *p;
|
||||
size_t s = (size_t)align_num_per_sector(t, BUFFER_SIZE);
|
||||
size_t s = (size_t)align_num_per_sector(t, READ_BUFFER_SIZE);
|
||||
p = VirtualAlloc(NULL, s, MEM_COMMIT, PAGE_READWRITE);
|
||||
if (p == NULL) {
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
|
@ -683,7 +830,7 @@ _archive_read_data_block(struct archive *_a, const void **buff,
|
|||
break;
|
||||
} while (r == ARCHIVE_OK && t->ol_num_doing < MAX_OVERLAPPED);
|
||||
} else {
|
||||
if (start_next_async_read(a, t) == ARCHIVE_FATAL)
|
||||
if ((r = start_next_async_read(a, t)) == ARCHIVE_FATAL)
|
||||
goto abort_read_data;
|
||||
}
|
||||
|
||||
|
@ -899,6 +1046,19 @@ next_entry(struct archive_read_disk *a, struct tree *t,
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* File attributes
|
||||
*/
|
||||
if ((a->flags & ARCHIVE_READDISK_NO_FFLAGS) == 0) {
|
||||
const int supported_attrs =
|
||||
FILE_ATTRIBUTE_READONLY |
|
||||
FILE_ATTRIBUTE_HIDDEN |
|
||||
FILE_ATTRIBUTE_SYSTEM;
|
||||
DWORD file_attrs = st->dwFileAttributes & supported_attrs;
|
||||
if (file_attrs != 0)
|
||||
archive_entry_set_fflags(entry, file_attrs, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Invoke a meta data filter callback.
|
||||
*/
|
||||
|
@ -923,6 +1083,7 @@ next_entry(struct archive_read_disk *a, struct tree *t,
|
|||
t->entry_fh = CreateFileW(tree_current_access_path(t),
|
||||
GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, flags, NULL);
|
||||
if (t->entry_fh == INVALID_HANDLE_VALUE) {
|
||||
la_dosmaperr(GetLastError());
|
||||
archive_set_error(&a->archive, errno,
|
||||
"Couldn't open %ls", tree_current_path(a->tree));
|
||||
return (ARCHIVE_FAILED);
|
||||
|
@ -1837,9 +1998,10 @@ entry_copy_bhfi(struct archive_entry *entry, const wchar_t *path,
|
|||
mode |= S_IWUSR | S_IWGRP | S_IWOTH;
|
||||
if ((bhfi->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
|
||||
findData != NULL &&
|
||||
findData->dwReserved0 == IO_REPARSE_TAG_SYMLINK)
|
||||
findData->dwReserved0 == IO_REPARSE_TAG_SYMLINK) {
|
||||
mode |= S_IFLNK;
|
||||
else if (bhfi->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||
entry_symlink_from_pathw(entry, path);
|
||||
} else if (bhfi->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||
mode |= S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH;
|
||||
else {
|
||||
const wchar_t *p;
|
||||
|
@ -2138,6 +2300,8 @@ archive_read_disk_entry_from_file(struct archive *_a,
|
|||
fileAttributes = bhfi.dwFileAttributes;
|
||||
} else {
|
||||
archive_entry_copy_stat(entry, st);
|
||||
if (st->st_mode & S_IFLNK)
|
||||
entry_symlink_from_pathw(entry, path);
|
||||
h = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
|
@ -2149,6 +2313,19 @@ archive_read_disk_entry_from_file(struct archive *_a,
|
|||
if (name != NULL)
|
||||
archive_entry_copy_gname(entry, name);
|
||||
|
||||
/*
|
||||
* File attributes
|
||||
*/
|
||||
if ((a->flags & ARCHIVE_READDISK_NO_FFLAGS) == 0) {
|
||||
const int supported_attrs =
|
||||
FILE_ATTRIBUTE_READONLY |
|
||||
FILE_ATTRIBUTE_HIDDEN |
|
||||
FILE_ATTRIBUTE_SYSTEM;
|
||||
DWORD file_attrs = fileAttributes & supported_attrs;
|
||||
if (file_attrs != 0)
|
||||
archive_entry_set_fflags(entry, file_attrs, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Can this file be sparse file ?
|
||||
*/
|
||||
|
@ -2275,10 +2452,10 @@ setup_sparse_from_disk(struct archive_read_disk *a,
|
|||
if (range.Length.QuadPart > 0)
|
||||
continue;
|
||||
} else {
|
||||
/* The remaining data is hole. */
|
||||
/* The entire file is a hole. Add one data block of size 0 at the end. */
|
||||
archive_entry_sparse_add_entry(entry,
|
||||
range.FileOffset.QuadPart,
|
||||
range.Length.QuadPart);
|
||||
entry_size,
|
||||
0);
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
.Nm archive_read_support_filter_rpm ,
|
||||
.Nm archive_read_support_filter_uu ,
|
||||
.Nm archive_read_support_filter_xz ,
|
||||
.Nm archive_read_support_filter_zstd ,
|
||||
.Nm archive_read_support_filter_program ,
|
||||
.Nm archive_read_support_filter_program_signature
|
||||
.Nd functions for reading streaming archives
|
||||
|
@ -73,6 +74,8 @@ Streaming Archive Library (libarchive, -larchive)
|
|||
.Ft int
|
||||
.Fn archive_read_support_filter_xz "struct archive *"
|
||||
.Ft int
|
||||
.Fn archive_read_support_filter_zstd "struct archive *"
|
||||
.Ft int
|
||||
.Fo archive_read_support_filter_program
|
||||
.Fa "struct archive *"
|
||||
.Fa "const char *cmd"
|
||||
|
@ -99,7 +102,8 @@ Streaming Archive Library (libarchive, -larchive)
|
|||
.Fn archive_read_support_filter_none ,
|
||||
.Fn archive_read_support_filter_rpm ,
|
||||
.Fn archive_read_support_filter_uu ,
|
||||
.Fn archive_read_support_filter_xz
|
||||
.Fn archive_read_support_filter_xz ,
|
||||
.Fn archive_read_support_filter_zstd ,
|
||||
.Xc
|
||||
Enables auto-detection code and decompression support for the
|
||||
specified compression.
|
||||
|
|
|
@ -174,8 +174,7 @@ file_close(struct archive *a, void *client_data)
|
|||
struct read_FILE_data *mine = (struct read_FILE_data *)client_data;
|
||||
|
||||
(void)a; /* UNUSED */
|
||||
if (mine->buffer != NULL)
|
||||
free(mine->buffer);
|
||||
free(mine->buffer);
|
||||
free(mine);
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
|
|
@ -98,6 +98,8 @@ struct archive_read_filter {
|
|||
int (*close)(struct archive_read_filter *self);
|
||||
/* Function that handles switching from reading one block to the next/prev */
|
||||
int (*sswitch)(struct archive_read_filter *self, unsigned int iindex);
|
||||
/* Read any header metadata if available. */
|
||||
int (*read_header)(struct archive_read_filter *self, struct archive_entry *entry);
|
||||
/* My private data. */
|
||||
void *data;
|
||||
|
||||
|
@ -250,6 +252,7 @@ int64_t __archive_read_seek(struct archive_read*, int64_t, int);
|
|||
int64_t __archive_read_filter_seek(struct archive_read_filter *, int64_t, int);
|
||||
int64_t __archive_read_consume(struct archive_read *, int64_t);
|
||||
int64_t __archive_read_filter_consume(struct archive_read_filter *, int64_t);
|
||||
int __archive_read_header(struct archive_read *, struct archive_entry *);
|
||||
int __archive_read_program(struct archive_read_filter *, const char *);
|
||||
void __archive_read_free_filters(struct archive_read *);
|
||||
struct archive_read_extract *__archive_read_get_extract(struct archive_read *);
|
||||
|
|
|
@ -73,6 +73,9 @@ archive_read_set_format(struct archive *_a, int code)
|
|||
case ARCHIVE_FORMAT_RAR:
|
||||
strcpy(str, "rar");
|
||||
break;
|
||||
case ARCHIVE_FORMAT_RAR_V5:
|
||||
strcpy(str, "rar5");
|
||||
break;
|
||||
case ARCHIVE_FORMAT_TAR:
|
||||
strcpy(str, "tar");
|
||||
break;
|
||||
|
|
|
@ -71,6 +71,8 @@ archive_read_support_filter_all(struct archive *a)
|
|||
archive_read_support_filter_grzip(a);
|
||||
/* Lz4 falls back to "lz4 -d" command-line program. */
|
||||
archive_read_support_filter_lz4(a);
|
||||
/* Zstd falls back to "zstd -d" command-line program. */
|
||||
archive_read_support_filter_zstd(a);
|
||||
|
||||
/* Note: We always return ARCHIVE_OK here, even if some of the
|
||||
* above return ARCHIVE_WARN. The intent here is to enable
|
||||
|
|
|
@ -37,6 +37,9 @@ __FBSDID("$FreeBSD$");
|
|||
#ifdef HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
#ifdef HAVE_LIMITS_H
|
||||
#include <limits.h>
|
||||
#endif
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
@ -45,6 +48,8 @@ __FBSDID("$FreeBSD$");
|
|||
#endif
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_entry.h"
|
||||
#include "archive_endian.h"
|
||||
#include "archive_private.h"
|
||||
#include "archive_read_private.h"
|
||||
|
||||
|
@ -56,6 +61,8 @@ struct private_data {
|
|||
size_t out_block_size;
|
||||
int64_t total_out;
|
||||
unsigned long crc;
|
||||
uint32_t mtime;
|
||||
char *name;
|
||||
char eof; /* True = found end of compressed data. */
|
||||
};
|
||||
|
||||
|
@ -123,7 +130,8 @@ archive_read_support_filter_gzip(struct archive *_a)
|
|||
* count of bits verified, suitable for use by bidder.
|
||||
*/
|
||||
static ssize_t
|
||||
peek_at_header(struct archive_read_filter *filter, int *pbits)
|
||||
peek_at_header(struct archive_read_filter *filter, int *pbits,
|
||||
struct private_data *state)
|
||||
{
|
||||
const unsigned char *p;
|
||||
ssize_t avail, len;
|
||||
|
@ -144,7 +152,9 @@ peek_at_header(struct archive_read_filter *filter, int *pbits)
|
|||
return (0);
|
||||
bits += 3;
|
||||
header_flags = p[3];
|
||||
/* Bytes 4-7 are mod time. */
|
||||
/* Bytes 4-7 are mod time in little endian. */
|
||||
if (state)
|
||||
state->mtime = archive_le32dec(p + 4);
|
||||
/* Byte 8 is deflate flags. */
|
||||
/* XXXX TODO: return deflate flags back to consume_header for use
|
||||
in initializing the decompressor. */
|
||||
|
@ -161,6 +171,7 @@ peek_at_header(struct archive_read_filter *filter, int *pbits)
|
|||
|
||||
/* Null-terminated optional filename. */
|
||||
if (header_flags & 8) {
|
||||
ssize_t file_start = len;
|
||||
do {
|
||||
++len;
|
||||
if (avail < len)
|
||||
|
@ -169,6 +180,12 @@ peek_at_header(struct archive_read_filter *filter, int *pbits)
|
|||
if (p == NULL)
|
||||
return (0);
|
||||
} while (p[len - 1] != 0);
|
||||
|
||||
if (state) {
|
||||
/* Reset the name in case of repeat header reads. */
|
||||
free(state->name);
|
||||
state->name = strdup((const char *)&p[file_start]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Null-terminated optional comment. */
|
||||
|
@ -214,11 +231,28 @@ gzip_bidder_bid(struct archive_read_filter_bidder *self,
|
|||
|
||||
(void)self; /* UNUSED */
|
||||
|
||||
if (peek_at_header(filter, &bits_checked))
|
||||
if (peek_at_header(filter, &bits_checked, NULL))
|
||||
return (bits_checked);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
gzip_read_header(struct archive_read_filter *self, struct archive_entry *entry)
|
||||
{
|
||||
struct private_data *state;
|
||||
|
||||
state = (struct private_data *)self->data;
|
||||
|
||||
/* A mtime of 0 is considered invalid/missing. */
|
||||
if (state->mtime != 0)
|
||||
archive_entry_set_mtime(entry, state->mtime, 0);
|
||||
|
||||
/* If the name is available, extract it. */
|
||||
if (state->name)
|
||||
archive_entry_set_pathname(entry, state->name);
|
||||
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
#ifndef HAVE_ZLIB_H
|
||||
|
||||
|
@ -272,6 +306,7 @@ gzip_bidder_init(struct archive_read_filter *self)
|
|||
self->read = gzip_filter_read;
|
||||
self->skip = NULL; /* not supported */
|
||||
self->close = gzip_filter_close;
|
||||
self->read_header = gzip_read_header;
|
||||
|
||||
state->in_stream = 0; /* We're not actually within a stream yet. */
|
||||
|
||||
|
@ -289,7 +324,7 @@ consume_header(struct archive_read_filter *self)
|
|||
state = (struct private_data *)self->data;
|
||||
|
||||
/* If this is a real header, consume it. */
|
||||
len = peek_at_header(self->upstream, NULL);
|
||||
len = peek_at_header(self->upstream, NULL, state);
|
||||
if (len == 0)
|
||||
return (ARCHIVE_EOF);
|
||||
__archive_read_filter_consume(self->upstream, len);
|
||||
|
@ -374,7 +409,7 @@ gzip_filter_read(struct archive_read_filter *self, const void **p)
|
|||
{
|
||||
struct private_data *state;
|
||||
size_t decompressed;
|
||||
ssize_t avail_in;
|
||||
ssize_t avail_in, max_in;
|
||||
int ret;
|
||||
|
||||
state = (struct private_data *)self->data;
|
||||
|
@ -408,6 +443,12 @@ gzip_filter_read(struct archive_read_filter *self, const void **p)
|
|||
"truncated gzip input");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
if (UINT_MAX >= SSIZE_MAX)
|
||||
max_in = SSIZE_MAX;
|
||||
else
|
||||
max_in = UINT_MAX;
|
||||
if (avail_in > max_in)
|
||||
avail_in = max_in;
|
||||
state->stream.avail_in = (uInt)avail_in;
|
||||
|
||||
/* Decompress and consume some of that data. */
|
||||
|
@ -469,6 +510,7 @@ gzip_filter_close(struct archive_read_filter *self)
|
|||
}
|
||||
}
|
||||
|
||||
free(state->name);
|
||||
free(state->out_block);
|
||||
free(state);
|
||||
return (ret);
|
||||
|
|
|
@ -494,7 +494,7 @@ lz4_filter_read_data_block(struct archive_read_filter *self, const void **p)
|
|||
if (read_buf == NULL)
|
||||
goto truncated_error;
|
||||
compressed_size = archive_le32dec(read_buf);
|
||||
if ((compressed_size & ~(1 << 31)) > state->flags.block_maximum_size)
|
||||
if ((compressed_size & 0x7fffffff) > state->flags.block_maximum_size)
|
||||
goto malformed_error;
|
||||
/* A compressed size == 0 means the end of stream blocks. */
|
||||
if (compressed_size == 0) {
|
||||
|
@ -504,8 +504,8 @@ lz4_filter_read_data_block(struct archive_read_filter *self, const void **p)
|
|||
|
||||
checksum_size = state->flags.block_checksum;
|
||||
/* Check if the block is uncompressed. */
|
||||
if (compressed_size & (1 << 31)) {
|
||||
compressed_size &= ~(1 << 31);
|
||||
if (compressed_size & 0x80000000U) {
|
||||
compressed_size &= 0x7fffffff;
|
||||
uncompressed_size = compressed_size;
|
||||
} else
|
||||
uncompressed_size = 0;/* Unknown yet. */
|
||||
|
|
|
@ -0,0 +1,292 @@
|
|||
/*-
|
||||
* Copyright (c) 2009-2011 Sean Purcell
|
||||
* 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
|
||||
|
||||
#ifdef HAVE_ERRNO_H
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#ifdef HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#if HAVE_ZSTD_H
|
||||
#include <zstd.h>
|
||||
#endif
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_endian.h"
|
||||
#include "archive_private.h"
|
||||
#include "archive_read_private.h"
|
||||
|
||||
#if HAVE_ZSTD_H && HAVE_LIBZSTD
|
||||
|
||||
struct private_data {
|
||||
ZSTD_DStream *dstream;
|
||||
unsigned char *out_block;
|
||||
size_t out_block_size;
|
||||
int64_t total_out;
|
||||
char in_frame; /* True = in the middle of a zstd frame. */
|
||||
char eof; /* True = found end of compressed data. */
|
||||
};
|
||||
|
||||
/* Zstd Filter. */
|
||||
static ssize_t zstd_filter_read(struct archive_read_filter *, const void**);
|
||||
static int zstd_filter_close(struct archive_read_filter *);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Note that we can detect zstd compressed files even if we can't decompress
|
||||
* them. (In fact, we like detecting them because we can give better error
|
||||
* messages.) So the bid framework here gets compiled even if no zstd library
|
||||
* is available.
|
||||
*/
|
||||
static int zstd_bidder_bid(struct archive_read_filter_bidder *,
|
||||
struct archive_read_filter *);
|
||||
static int zstd_bidder_init(struct archive_read_filter *);
|
||||
|
||||
int
|
||||
archive_read_support_filter_zstd(struct archive *_a)
|
||||
{
|
||||
struct archive_read *a = (struct archive_read *)_a;
|
||||
struct archive_read_filter_bidder *bidder;
|
||||
|
||||
archive_check_magic(_a, ARCHIVE_READ_MAGIC,
|
||||
ARCHIVE_STATE_NEW, "archive_read_support_filter_zstd");
|
||||
|
||||
if (__archive_read_get_bidder(a, &bidder) != ARCHIVE_OK)
|
||||
return (ARCHIVE_FATAL);
|
||||
|
||||
bidder->data = NULL;
|
||||
bidder->name = "zstd";
|
||||
bidder->bid = zstd_bidder_bid;
|
||||
bidder->init = zstd_bidder_init;
|
||||
bidder->options = NULL;
|
||||
bidder->free = NULL;
|
||||
#if HAVE_ZSTD_H && HAVE_LIBZSTD
|
||||
return (ARCHIVE_OK);
|
||||
#else
|
||||
archive_set_error(_a, ARCHIVE_ERRNO_MISC,
|
||||
"Using external zstd program for zstd decompression");
|
||||
return (ARCHIVE_WARN);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Test whether we can handle this data.
|
||||
*/
|
||||
static int
|
||||
zstd_bidder_bid(struct archive_read_filter_bidder *self,
|
||||
struct archive_read_filter *filter)
|
||||
{
|
||||
const unsigned char *buffer;
|
||||
ssize_t avail;
|
||||
unsigned prefix;
|
||||
|
||||
/* Zstd frame magic values */
|
||||
const unsigned zstd_magic = 0xFD2FB528U;
|
||||
|
||||
(void) self; /* UNUSED */
|
||||
|
||||
buffer = __archive_read_filter_ahead(filter, 4, &avail);
|
||||
if (buffer == NULL)
|
||||
return (0);
|
||||
|
||||
prefix = archive_le32dec(buffer);
|
||||
if (prefix == zstd_magic)
|
||||
return (32);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
#if !(HAVE_ZSTD_H && HAVE_LIBZSTD)
|
||||
|
||||
/*
|
||||
* If we don't have the library on this system, we can't do the
|
||||
* decompression directly. We can, however, try to run "zstd -d"
|
||||
* in case that's available.
|
||||
*/
|
||||
static int
|
||||
zstd_bidder_init(struct archive_read_filter *self)
|
||||
{
|
||||
int r;
|
||||
|
||||
r = __archive_read_program(self, "zstd -d -qq");
|
||||
/* Note: We set the format here even if __archive_read_program()
|
||||
* above fails. We do, after all, know what the format is
|
||||
* even if we weren't able to read it. */
|
||||
self->code = ARCHIVE_FILTER_ZSTD;
|
||||
self->name = "zstd";
|
||||
return (r);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
* Initialize the filter object
|
||||
*/
|
||||
static int
|
||||
zstd_bidder_init(struct archive_read_filter *self)
|
||||
{
|
||||
struct private_data *state;
|
||||
const size_t out_block_size = ZSTD_DStreamOutSize();
|
||||
void *out_block;
|
||||
ZSTD_DStream *dstream;
|
||||
|
||||
self->code = ARCHIVE_FILTER_ZSTD;
|
||||
self->name = "zstd";
|
||||
|
||||
state = (struct private_data *)calloc(sizeof(*state), 1);
|
||||
out_block = (unsigned char *)malloc(out_block_size);
|
||||
dstream = ZSTD_createDStream();
|
||||
|
||||
if (state == NULL || out_block == NULL || dstream == NULL) {
|
||||
free(out_block);
|
||||
free(state);
|
||||
ZSTD_freeDStream(dstream); /* supports free on NULL */
|
||||
archive_set_error(&self->archive->archive, ENOMEM,
|
||||
"Can't allocate data for zstd decompression");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
self->data = state;
|
||||
|
||||
state->out_block_size = out_block_size;
|
||||
state->out_block = out_block;
|
||||
state->dstream = dstream;
|
||||
self->read = zstd_filter_read;
|
||||
self->skip = NULL; /* not supported */
|
||||
self->close = zstd_filter_close;
|
||||
|
||||
state->eof = 0;
|
||||
state->in_frame = 0;
|
||||
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
zstd_filter_read(struct archive_read_filter *self, const void **p)
|
||||
{
|
||||
struct private_data *state;
|
||||
size_t decompressed;
|
||||
ssize_t avail_in;
|
||||
ZSTD_outBuffer out;
|
||||
ZSTD_inBuffer in;
|
||||
|
||||
state = (struct private_data *)self->data;
|
||||
|
||||
out = (ZSTD_outBuffer) { state->out_block, state->out_block_size, 0 };
|
||||
|
||||
/* Try to fill the output buffer. */
|
||||
while (out.pos < out.size && !state->eof) {
|
||||
if (!state->in_frame) {
|
||||
const size_t ret = ZSTD_initDStream(state->dstream);
|
||||
if (ZSTD_isError(ret)) {
|
||||
archive_set_error(&self->archive->archive,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"Error initializing zstd decompressor: %s",
|
||||
ZSTD_getErrorName(ret));
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
}
|
||||
in.src = __archive_read_filter_ahead(self->upstream, 1,
|
||||
&avail_in);
|
||||
if (avail_in < 0) {
|
||||
return avail_in;
|
||||
}
|
||||
if (in.src == NULL && avail_in == 0) {
|
||||
if (!state->in_frame) {
|
||||
/* end of stream */
|
||||
state->eof = 1;
|
||||
break;
|
||||
} else {
|
||||
archive_set_error(&self->archive->archive,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"Truncated zstd input");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
}
|
||||
in.size = avail_in;
|
||||
in.pos = 0;
|
||||
|
||||
{
|
||||
const size_t ret =
|
||||
ZSTD_decompressStream(state->dstream, &out, &in);
|
||||
|
||||
if (ZSTD_isError(ret)) {
|
||||
archive_set_error(&self->archive->archive,
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
"Zstd decompression failed: %s",
|
||||
ZSTD_getErrorName(ret));
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
/* Decompressor made some progress */
|
||||
__archive_read_filter_consume(self->upstream, in.pos);
|
||||
|
||||
/* ret guaranteed to be > 0 if frame isn't done yet */
|
||||
state->in_frame = (ret != 0);
|
||||
}
|
||||
}
|
||||
|
||||
decompressed = out.pos;
|
||||
state->total_out += decompressed;
|
||||
if (decompressed == 0)
|
||||
*p = NULL;
|
||||
else
|
||||
*p = state->out_block;
|
||||
return (decompressed);
|
||||
}
|
||||
|
||||
/*
|
||||
* Clean up the decompressor.
|
||||
*/
|
||||
static int
|
||||
zstd_filter_close(struct archive_read_filter *self)
|
||||
{
|
||||
struct private_data *state;
|
||||
|
||||
state = (struct private_data *)self->data;
|
||||
|
||||
ZSTD_freeDStream(state->dstream);
|
||||
free(state->out_block);
|
||||
free(state);
|
||||
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
#endif /* HAVE_ZLIB_H && HAVE_LIBZSTD */
|
|
@ -975,18 +975,6 @@ decode_codec_id(const unsigned char *codecId, size_t id_size)
|
|||
return (id);
|
||||
}
|
||||
|
||||
static void *
|
||||
ppmd_alloc(void *p, size_t size)
|
||||
{
|
||||
(void)p;
|
||||
return malloc(size);
|
||||
}
|
||||
static void
|
||||
ppmd_free(void *p, void *address)
|
||||
{
|
||||
(void)p;
|
||||
free(address);
|
||||
}
|
||||
static Byte
|
||||
ppmd_read(void *p)
|
||||
{
|
||||
|
@ -1006,8 +994,6 @@ ppmd_read(void *p)
|
|||
return (b);
|
||||
}
|
||||
|
||||
static ISzAlloc g_szalloc = { ppmd_alloc, ppmd_free };
|
||||
|
||||
static int
|
||||
init_decompression(struct archive_read *a, struct _7zip *zip,
|
||||
const struct _7z_coder *coder1, const struct _7z_coder *coder2)
|
||||
|
@ -1237,7 +1223,7 @@ init_decompression(struct archive_read *a, struct _7zip *zip,
|
|||
|
||||
if (zip->ppmd7_valid) {
|
||||
__archive_ppmd7_functions.Ppmd7_Free(
|
||||
&zip->ppmd7_context, &g_szalloc);
|
||||
&zip->ppmd7_context);
|
||||
zip->ppmd7_valid = 0;
|
||||
}
|
||||
|
||||
|
@ -1256,7 +1242,7 @@ init_decompression(struct archive_read *a, struct _7zip *zip,
|
|||
}
|
||||
__archive_ppmd7_functions.Ppmd7_Construct(&zip->ppmd7_context);
|
||||
r = __archive_ppmd7_functions.Ppmd7_Alloc(
|
||||
&zip->ppmd7_context, msize, &g_szalloc);
|
||||
&zip->ppmd7_context, msize);
|
||||
if (r == 0) {
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
"Coludn't allocate memory for PPMd");
|
||||
|
@ -1636,7 +1622,7 @@ free_decompression(struct archive_read *a, struct _7zip *zip)
|
|||
#endif
|
||||
if (zip->ppmd7_valid) {
|
||||
__archive_ppmd7_functions.Ppmd7_Free(
|
||||
&zip->ppmd7_context, &g_szalloc);
|
||||
&zip->ppmd7_context);
|
||||
zip->ppmd7_valid = 0;
|
||||
}
|
||||
return (r);
|
||||
|
@ -2569,6 +2555,7 @@ read_Header(struct archive_read *a, struct _7z_header_info *h,
|
|||
case kDummy:
|
||||
if (ll == 0)
|
||||
break;
|
||||
__LA_FALLTHROUGH;
|
||||
default:
|
||||
if (header_bytes(a, ll) == NULL)
|
||||
return (-1);
|
||||
|
@ -2977,13 +2964,7 @@ get_uncompressed_data(struct archive_read *a, const void **buff, size_t size,
|
|||
if (zip->codec == _7Z_COPY && zip->codec2 == (unsigned long)-1) {
|
||||
/* Copy mode. */
|
||||
|
||||
/*
|
||||
* Note: '1' here is a performance optimization.
|
||||
* Recall that the decompression layer returns a count of
|
||||
* available bytes; asking for more than that forces the
|
||||
* decompressor to combine reads by copying data.
|
||||
*/
|
||||
*buff = __archive_read_ahead(a, 1, &bytes_avail);
|
||||
*buff = __archive_read_ahead(a, minimum, &bytes_avail);
|
||||
if (bytes_avail <= 0) {
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
|
@ -3336,8 +3317,7 @@ setup_decode_folder(struct archive_read *a, struct _7z_folder *folder,
|
|||
* Release the memory which the previous folder used for BCJ2.
|
||||
*/
|
||||
for (i = 0; i < 3; i++) {
|
||||
if (zip->sub_stream_buff[i] != NULL)
|
||||
free(zip->sub_stream_buff[i]);
|
||||
free(zip->sub_stream_buff[i]);
|
||||
zip->sub_stream_buff[i] = NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -72,6 +72,7 @@ archive_read_support_format_all(struct archive *a)
|
|||
archive_read_support_format_7zip(a);
|
||||
archive_read_support_format_cab(a);
|
||||
archive_read_support_format_rar(a);
|
||||
archive_read_support_format_rar5(a);
|
||||
archive_read_support_format_iso9660(a);
|
||||
/* Seek is really bad, since it forces the read-ahead
|
||||
* logic to discard buffered data. */
|
||||
|
|
|
@ -138,8 +138,7 @@ archive_read_format_ar_cleanup(struct archive_read *a)
|
|||
struct ar *ar;
|
||||
|
||||
ar = (struct ar *)(a->format->data);
|
||||
if (ar->strtab)
|
||||
free(ar->strtab);
|
||||
free(ar->strtab);
|
||||
free(ar);
|
||||
(a->format->data) = NULL;
|
||||
return (ARCHIVE_OK);
|
||||
|
@ -388,9 +387,10 @@ _ar_read_header(struct archive_read *a, struct archive_entry *entry,
|
|||
|
||||
/*
|
||||
* "/" is the SVR4/GNU archive symbol table.
|
||||
* "/SYM64/" is the SVR4/GNU 64-bit variant archive symbol table.
|
||||
*/
|
||||
if (strcmp(filename, "/") == 0) {
|
||||
archive_entry_copy_pathname(entry, "/");
|
||||
if (strcmp(filename, "/") == 0 || strcmp(filename, "/SYM64/") == 0) {
|
||||
archive_entry_copy_pathname(entry, filename);
|
||||
/* Parse the time, owner, mode, size fields. */
|
||||
r = ar_parse_common_header(ar, entry, h);
|
||||
/* Force the file type to a regular file. */
|
||||
|
@ -459,6 +459,7 @@ ar_parse_common_header(struct ar *ar, struct archive_entry *entry,
|
|||
uint64_t n;
|
||||
|
||||
/* Copy remaining header */
|
||||
archive_entry_set_filetype(entry, AE_IFREG);
|
||||
archive_entry_set_mtime(entry,
|
||||
(time_t)ar_atol10(h + AR_date_offset, AR_date_size), 0L);
|
||||
archive_entry_set_uid(entry,
|
||||
|
|
|
@ -60,6 +60,9 @@ archive_read_support_format_by_code(struct archive *a, int format_code)
|
|||
case ARCHIVE_FORMAT_RAR:
|
||||
return archive_read_support_format_rar(a);
|
||||
break;
|
||||
case ARCHIVE_FORMAT_RAR_V5:
|
||||
return archive_read_support_format_rar5(a);
|
||||
break;
|
||||
case ARCHIVE_FORMAT_TAR:
|
||||
return archive_read_support_format_tar(a);
|
||||
break;
|
||||
|
|
|
@ -116,19 +116,11 @@ struct lzx_dec {
|
|||
* coding tree, which is a binary tree. But a use of a large
|
||||
* index table causes L1 cache read miss many times.
|
||||
*/
|
||||
#define HTBL_BITS 10
|
||||
int max_bits;
|
||||
int shift_bits;
|
||||
int tbl_bits;
|
||||
int tree_used;
|
||||
int tree_avail;
|
||||
/* Direct access table. */
|
||||
uint16_t *tbl;
|
||||
/* Binary tree table for extra bits over the direct access. */
|
||||
struct htree_t {
|
||||
uint16_t left;
|
||||
uint16_t right;
|
||||
} *tree;
|
||||
} at, lt, mt, pt;
|
||||
|
||||
int loop;
|
||||
|
@ -352,7 +344,6 @@ static int lzx_huffman_init(struct huffman *, size_t, int);
|
|||
static void lzx_huffman_free(struct huffman *);
|
||||
static int lzx_make_huffman_table(struct huffman *);
|
||||
static inline int lzx_decode_huffman(struct huffman *, unsigned);
|
||||
static int lzx_decode_huffman_tree(struct huffman *, unsigned, int);
|
||||
|
||||
|
||||
int
|
||||
|
@ -1518,8 +1509,8 @@ cab_read_ahead_cfdata_deflate(struct archive_read *a, ssize_t *avail)
|
|||
}
|
||||
if (mszip == 1 && cab->stream.next_in[0] != 0x4b)
|
||||
goto nomszip;
|
||||
else if (cab->stream.next_in[0] != 0x43 ||
|
||||
cab->stream.next_in[1] != 0x4b)
|
||||
else if (mszip == 2 && (cab->stream.next_in[0] != 0x43 ||
|
||||
cab->stream.next_in[1] != 0x4b))
|
||||
goto nomszip;
|
||||
cab->stream.next_in += mszip;
|
||||
cab->stream.avail_in -= mszip;
|
||||
|
@ -3127,7 +3118,6 @@ getdata:
|
|||
static int
|
||||
lzx_huffman_init(struct huffman *hf, size_t len_size, int tbl_bits)
|
||||
{
|
||||
int bits;
|
||||
|
||||
if (hf->bitlen == NULL || hf->len_size != (int)len_size) {
|
||||
free(hf->bitlen);
|
||||
|
@ -3138,21 +3128,11 @@ lzx_huffman_init(struct huffman *hf, size_t len_size, int tbl_bits)
|
|||
} else
|
||||
memset(hf->bitlen, 0, len_size * sizeof(hf->bitlen[0]));
|
||||
if (hf->tbl == NULL) {
|
||||
if (tbl_bits < HTBL_BITS)
|
||||
bits = tbl_bits;
|
||||
else
|
||||
bits = HTBL_BITS;
|
||||
hf->tbl = malloc(((size_t)1 << bits) * sizeof(hf->tbl[0]));
|
||||
hf->tbl = malloc(((size_t)1 << tbl_bits) * sizeof(hf->tbl[0]));
|
||||
if (hf->tbl == NULL)
|
||||
return (ARCHIVE_FATAL);
|
||||
hf->tbl_bits = tbl_bits;
|
||||
}
|
||||
if (hf->tree == NULL && tbl_bits > HTBL_BITS) {
|
||||
hf->tree_avail = 1 << (tbl_bits - HTBL_BITS + 4);
|
||||
hf->tree = malloc(hf->tree_avail * sizeof(hf->tree[0]));
|
||||
if (hf->tree == NULL)
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
|
@ -3161,7 +3141,6 @@ lzx_huffman_free(struct huffman *hf)
|
|||
{
|
||||
free(hf->bitlen);
|
||||
free(hf->tbl);
|
||||
free(hf->tree);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -3174,7 +3153,7 @@ lzx_make_huffman_table(struct huffman *hf)
|
|||
const unsigned char *bitlen;
|
||||
int bitptn[17], weight[17];
|
||||
int i, maxbits = 0, ptn, tbl_size, w;
|
||||
int diffbits, len_avail;
|
||||
int len_avail;
|
||||
|
||||
/*
|
||||
* Initialize bit patterns.
|
||||
|
@ -3205,28 +3184,11 @@ lzx_make_huffman_table(struct huffman *hf)
|
|||
weight[i] >>= ebits;
|
||||
}
|
||||
}
|
||||
if (maxbits > HTBL_BITS) {
|
||||
int htbl_max;
|
||||
uint16_t *p;
|
||||
|
||||
diffbits = maxbits - HTBL_BITS;
|
||||
for (i = 1; i <= HTBL_BITS; i++) {
|
||||
bitptn[i] >>= diffbits;
|
||||
weight[i] >>= diffbits;
|
||||
}
|
||||
htbl_max = bitptn[HTBL_BITS] +
|
||||
weight[HTBL_BITS] * hf->freq[HTBL_BITS];
|
||||
p = &(hf->tbl[htbl_max]);
|
||||
while (p < &hf->tbl[1U<<HTBL_BITS])
|
||||
*p++ = 0;
|
||||
} else
|
||||
diffbits = 0;
|
||||
hf->shift_bits = diffbits;
|
||||
|
||||
/*
|
||||
* Make the table.
|
||||
*/
|
||||
tbl_size = 1 << HTBL_BITS;
|
||||
tbl_size = 1 << hf->tbl_bits;
|
||||
tbl = hf->tbl;
|
||||
bitlen = hf->bitlen;
|
||||
len_avail = hf->len_size;
|
||||
|
@ -3234,120 +3196,32 @@ lzx_make_huffman_table(struct huffman *hf)
|
|||
for (i = 0; i < len_avail; i++) {
|
||||
uint16_t *p;
|
||||
int len, cnt;
|
||||
uint16_t bit;
|
||||
int extlen;
|
||||
struct htree_t *ht;
|
||||
|
||||
if (bitlen[i] == 0)
|
||||
continue;
|
||||
/* Get a bit pattern */
|
||||
len = bitlen[i];
|
||||
if (len > tbl_size)
|
||||
return (0);
|
||||
ptn = bitptn[len];
|
||||
cnt = weight[len];
|
||||
if (len <= HTBL_BITS) {
|
||||
/* Calculate next bit pattern */
|
||||
if ((bitptn[len] = ptn + cnt) > tbl_size)
|
||||
return (0);/* Invalid */
|
||||
/* Update the table */
|
||||
p = &(tbl[ptn]);
|
||||
while (--cnt >= 0)
|
||||
p[cnt] = (uint16_t)i;
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* A bit length is too big to be housed to a direct table,
|
||||
* so we use a tree model for its extra bits.
|
||||
*/
|
||||
bitptn[len] = ptn + cnt;
|
||||
bit = 1U << (diffbits -1);
|
||||
extlen = len - HTBL_BITS;
|
||||
|
||||
p = &(tbl[ptn >> diffbits]);
|
||||
if (*p == 0) {
|
||||
*p = len_avail + hf->tree_used;
|
||||
ht = &(hf->tree[hf->tree_used++]);
|
||||
if (hf->tree_used > hf->tree_avail)
|
||||
return (0);/* Invalid */
|
||||
ht->left = 0;
|
||||
ht->right = 0;
|
||||
} else {
|
||||
if (*p < len_avail ||
|
||||
*p >= (len_avail + hf->tree_used))
|
||||
return (0);/* Invalid */
|
||||
ht = &(hf->tree[*p - len_avail]);
|
||||
}
|
||||
while (--extlen > 0) {
|
||||
if (ptn & bit) {
|
||||
if (ht->left < len_avail) {
|
||||
ht->left = len_avail + hf->tree_used;
|
||||
ht = &(hf->tree[hf->tree_used++]);
|
||||
if (hf->tree_used > hf->tree_avail)
|
||||
return (0);/* Invalid */
|
||||
ht->left = 0;
|
||||
ht->right = 0;
|
||||
} else {
|
||||
ht = &(hf->tree[ht->left - len_avail]);
|
||||
}
|
||||
} else {
|
||||
if (ht->right < len_avail) {
|
||||
ht->right = len_avail + hf->tree_used;
|
||||
ht = &(hf->tree[hf->tree_used++]);
|
||||
if (hf->tree_used > hf->tree_avail)
|
||||
return (0);/* Invalid */
|
||||
ht->left = 0;
|
||||
ht->right = 0;
|
||||
} else {
|
||||
ht = &(hf->tree[ht->right - len_avail]);
|
||||
}
|
||||
}
|
||||
bit >>= 1;
|
||||
}
|
||||
if (ptn & bit) {
|
||||
if (ht->left != 0)
|
||||
return (0);/* Invalid */
|
||||
ht->left = (uint16_t)i;
|
||||
} else {
|
||||
if (ht->right != 0)
|
||||
return (0);/* Invalid */
|
||||
ht->right = (uint16_t)i;
|
||||
}
|
||||
/* Calculate next bit pattern */
|
||||
if ((bitptn[len] = ptn + cnt) > tbl_size)
|
||||
return (0);/* Invalid */
|
||||
/* Update the table */
|
||||
p = &(tbl[ptn]);
|
||||
while (--cnt >= 0)
|
||||
p[cnt] = (uint16_t)i;
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int
|
||||
lzx_decode_huffman_tree(struct huffman *hf, unsigned rbits, int c)
|
||||
{
|
||||
struct htree_t *ht;
|
||||
int extlen;
|
||||
|
||||
ht = hf->tree;
|
||||
extlen = hf->shift_bits;
|
||||
while (c >= hf->len_size) {
|
||||
c -= hf->len_size;
|
||||
if (extlen-- <= 0 || c >= hf->tree_used)
|
||||
return (0);
|
||||
if (rbits & (1U << extlen))
|
||||
c = ht[c].left;
|
||||
else
|
||||
c = ht[c].right;
|
||||
}
|
||||
return (c);
|
||||
}
|
||||
|
||||
static inline int
|
||||
lzx_decode_huffman(struct huffman *hf, unsigned rbits)
|
||||
{
|
||||
int c;
|
||||
/*
|
||||
* At first search an index table for a bit pattern.
|
||||
* If it fails, search a huffman tree for.
|
||||
*/
|
||||
c = hf->tbl[rbits >> hf->shift_bits];
|
||||
c = hf->tbl[rbits];
|
||||
if (c < hf->len_size)
|
||||
return (c);
|
||||
/* This bit pattern needs to be found out at a huffman tree. */
|
||||
return (lzx_decode_huffman_tree(hf, rbits, c));
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
|
|
@ -165,7 +165,7 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_format_cpio.c 20116
|
|||
struct links_entry {
|
||||
struct links_entry *next;
|
||||
struct links_entry *previous;
|
||||
int links;
|
||||
unsigned int links;
|
||||
dev_t dev;
|
||||
int64_t ino;
|
||||
char *name;
|
||||
|
@ -633,6 +633,13 @@ header_newc(struct archive_read *a, struct cpio *cpio,
|
|||
/* Pad name to 2 more than a multiple of 4. */
|
||||
*name_pad = (2 - *namelength) & 3;
|
||||
|
||||
/* Make sure that the padded name length fits into size_t. */
|
||||
if (*name_pad > SIZE_MAX - *namelength) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"cpio archive has invalid namelength");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Note: entry_bytes_remaining is at least 64 bits and
|
||||
* therefore guaranteed to be big enough for a 33-bit file
|
||||
|
@ -948,8 +955,7 @@ archive_read_format_cpio_cleanup(struct archive_read *a)
|
|||
while (cpio->links_head != NULL) {
|
||||
struct links_entry *lp = cpio->links_head->next;
|
||||
|
||||
if (cpio->links_head->name)
|
||||
free(cpio->links_head->name);
|
||||
free(cpio->links_head->name);
|
||||
free(cpio->links_head);
|
||||
cpio->links_head = lp;
|
||||
}
|
||||
|
|
|
@ -409,7 +409,8 @@ static int next_entry_seek(struct archive_read *, struct iso9660 *,
|
|||
struct file_info **);
|
||||
static struct file_info *
|
||||
parse_file_info(struct archive_read *a,
|
||||
struct file_info *parent, const unsigned char *isodirrec);
|
||||
struct file_info *parent, const unsigned char *isodirrec,
|
||||
size_t reclen);
|
||||
static int parse_rockridge(struct archive_read *a,
|
||||
struct file_info *file, const unsigned char *start,
|
||||
const unsigned char *end);
|
||||
|
@ -1022,7 +1023,7 @@ read_children(struct archive_read *a, struct file_info *parent)
|
|||
if (*(p + DR_name_len_offset) == 1
|
||||
&& *(p + DR_name_offset) == '\001')
|
||||
continue;
|
||||
child = parse_file_info(a, parent, p);
|
||||
child = parse_file_info(a, parent, p, b - p);
|
||||
if (child == NULL) {
|
||||
__archive_read_consume(a, skip_size);
|
||||
return (ARCHIVE_FATAL);
|
||||
|
@ -1112,7 +1113,7 @@ choose_volume(struct archive_read *a, struct iso9660 *iso9660)
|
|||
*/
|
||||
seenJoliet = iso9660->seenJoliet;/* Save flag. */
|
||||
iso9660->seenJoliet = 0;
|
||||
file = parse_file_info(a, NULL, block);
|
||||
file = parse_file_info(a, NULL, block, vd->size);
|
||||
if (file == NULL)
|
||||
return (ARCHIVE_FATAL);
|
||||
iso9660->seenJoliet = seenJoliet;
|
||||
|
@ -1144,7 +1145,7 @@ choose_volume(struct archive_read *a, struct iso9660 *iso9660)
|
|||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
iso9660->seenJoliet = 0;
|
||||
file = parse_file_info(a, NULL, block);
|
||||
file = parse_file_info(a, NULL, block, vd->size);
|
||||
if (file == NULL)
|
||||
return (ARCHIVE_FATAL);
|
||||
iso9660->seenJoliet = seenJoliet;
|
||||
|
@ -1723,8 +1724,7 @@ archive_read_format_iso9660_cleanup(struct archive_read *a)
|
|||
free(iso9660->read_ce_req.reqs);
|
||||
archive_string_free(&iso9660->pathname);
|
||||
archive_string_free(&iso9660->previous_pathname);
|
||||
if (iso9660->pending_files.files)
|
||||
free(iso9660->pending_files.files);
|
||||
free(iso9660->pending_files.files);
|
||||
#ifdef HAVE_ZLIB_H
|
||||
free(iso9660->entry_zisofs.uncompressed_buffer);
|
||||
free(iso9660->entry_zisofs.block_pointers);
|
||||
|
@ -1749,7 +1749,7 @@ archive_read_format_iso9660_cleanup(struct archive_read *a)
|
|||
*/
|
||||
static struct file_info *
|
||||
parse_file_info(struct archive_read *a, struct file_info *parent,
|
||||
const unsigned char *isodirrec)
|
||||
const unsigned char *isodirrec, size_t reclen)
|
||||
{
|
||||
struct iso9660 *iso9660;
|
||||
struct file_info *file, *filep;
|
||||
|
@ -1763,16 +1763,20 @@ parse_file_info(struct archive_read *a, struct file_info *parent,
|
|||
|
||||
iso9660 = (struct iso9660 *)(a->format->data);
|
||||
|
||||
dr_len = (size_t)isodirrec[DR_length_offset];
|
||||
if (reclen != 0)
|
||||
dr_len = (size_t)isodirrec[DR_length_offset];
|
||||
/*
|
||||
* Sanity check that reclen is not zero and dr_len is greater than
|
||||
* reclen but at least 34
|
||||
*/
|
||||
if (reclen == 0 || reclen < dr_len || dr_len < 34) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Invalid length of directory record");
|
||||
return (NULL);
|
||||
}
|
||||
name_len = (size_t)isodirrec[DR_name_len_offset];
|
||||
location = archive_le32dec(isodirrec + DR_extent_offset);
|
||||
fsize = toi(isodirrec + DR_size_offset, DR_size_size);
|
||||
/* Sanity check that dr_len needs at least 34. */
|
||||
if (dr_len < 34) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Invalid length of directory record");
|
||||
return (NULL);
|
||||
}
|
||||
/* Sanity check that name_len doesn't exceed dr_len. */
|
||||
if (dr_len - 33 < name_len || name_len == 0) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
|
@ -2097,6 +2101,7 @@ parse_rockridge(struct archive_read *a, struct file_info *file,
|
|||
const unsigned char *p, const unsigned char *end)
|
||||
{
|
||||
struct iso9660 *iso9660;
|
||||
int entry_seen = 0;
|
||||
|
||||
iso9660 = (struct iso9660 *)(a->format->data);
|
||||
|
||||
|
@ -2252,8 +2257,16 @@ parse_rockridge(struct archive_read *a, struct file_info *file,
|
|||
}
|
||||
|
||||
p += p[2];
|
||||
entry_seen = 1;
|
||||
}
|
||||
|
||||
if (entry_seen)
|
||||
return (ARCHIVE_OK);
|
||||
else {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Tried to parse Rockridge extensions, but none found");
|
||||
return (ARCHIVE_WARN);
|
||||
}
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -3021,10 +3034,10 @@ heap_add_entry(struct archive_read *a, struct heap_queue *heap,
|
|||
ENOMEM, "Out of memory");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
memcpy(new_pending_files, heap->files,
|
||||
heap->allocated * sizeof(new_pending_files[0]));
|
||||
if (heap->files != NULL)
|
||||
free(heap->files);
|
||||
if (heap->allocated)
|
||||
memcpy(new_pending_files, heap->files,
|
||||
heap->allocated * sizeof(new_pending_files[0]));
|
||||
free(heap->files);
|
||||
heap->files = new_pending_files;
|
||||
heap->allocated = new_size;
|
||||
}
|
||||
|
|
|
@ -701,6 +701,12 @@ archive_read_format_lha_read_header(struct archive_read *a,
|
|||
* Prepare variables used to read a file content.
|
||||
*/
|
||||
lha->entry_bytes_remaining = lha->compsize;
|
||||
if (lha->entry_bytes_remaining < 0) {
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Invalid LHa entry size");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
lha->entry_offset = 0;
|
||||
lha->entry_crc_calculated = 0;
|
||||
|
||||
|
|
|
@ -45,10 +45,14 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_format_mtree.c 2011
|
|||
#ifdef HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
#ifdef HAVE_CTYPE_H
|
||||
#include <ctype.h>
|
||||
#endif
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_entry.h"
|
||||
#include "archive_private.h"
|
||||
#include "archive_rb.h"
|
||||
#include "archive_read_private.h"
|
||||
#include "archive_string.h"
|
||||
#include "archive_pack_dev.h"
|
||||
|
@ -75,7 +79,7 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_format_mtree.c 2011
|
|||
#define MTREE_HAS_OPTIONAL 0x0800
|
||||
#define MTREE_HAS_NOCHANGE 0x1000 /* FreeBSD specific */
|
||||
|
||||
#define MTREE_HASHTABLE_SIZE 1024
|
||||
#define MAX_LINE_LEN (1024 * 1024)
|
||||
|
||||
struct mtree_option {
|
||||
struct mtree_option *next;
|
||||
|
@ -83,13 +87,13 @@ struct mtree_option {
|
|||
};
|
||||
|
||||
struct mtree_entry {
|
||||
struct archive_rb_node rbnode;
|
||||
struct mtree_entry *next_dup;
|
||||
struct mtree_entry *next;
|
||||
struct mtree_option *options;
|
||||
char *name;
|
||||
char full;
|
||||
char used;
|
||||
unsigned int name_hash;
|
||||
struct mtree_entry *hashtable_next;
|
||||
};
|
||||
|
||||
struct mtree {
|
||||
|
@ -102,11 +106,12 @@ struct mtree {
|
|||
const char *archive_format_name;
|
||||
struct mtree_entry *entries;
|
||||
struct mtree_entry *this_entry;
|
||||
struct mtree_entry *entry_hashtable[MTREE_HASHTABLE_SIZE];
|
||||
struct archive_rb_tree entry_rbtree;
|
||||
struct archive_string current_dir;
|
||||
struct archive_string contents_name;
|
||||
|
||||
struct archive_entry_linkresolver *resolver;
|
||||
struct archive_rb_tree rbtree;
|
||||
|
||||
int64_t cur_size;
|
||||
char checkfs;
|
||||
|
@ -115,7 +120,6 @@ struct mtree {
|
|||
static int bid_keycmp(const char *, const char *, ssize_t);
|
||||
static int cleanup(struct archive_read *);
|
||||
static int detect_form(struct archive_read *, int *);
|
||||
static unsigned int hash(const char *);
|
||||
static int mtree_bid(struct archive_read *, int);
|
||||
static int parse_file(struct archive_read *, struct archive_entry *,
|
||||
struct mtree *, struct mtree_entry *, int *);
|
||||
|
@ -130,9 +134,7 @@ static ssize_t readline(struct archive_read *, struct mtree *, char **, ssize_t)
|
|||
static int skip(struct archive_read *a);
|
||||
static int read_header(struct archive_read *,
|
||||
struct archive_entry *);
|
||||
static int64_t mtree_atol10(char **);
|
||||
static int64_t mtree_atol8(char **);
|
||||
static int64_t mtree_atol(char **);
|
||||
static int64_t mtree_atol(char **, int base);
|
||||
|
||||
/*
|
||||
* There's no standard for TIME_T_MAX/TIME_T_MIN. So we compute them
|
||||
|
@ -219,9 +221,30 @@ free_options(struct mtree_option *head)
|
|||
}
|
||||
}
|
||||
|
||||
static int
|
||||
mtree_cmp_node(const struct archive_rb_node *n1,
|
||||
const struct archive_rb_node *n2)
|
||||
{
|
||||
const struct mtree_entry *e1 = (const struct mtree_entry *)n1;
|
||||
const struct mtree_entry *e2 = (const struct mtree_entry *)n2;
|
||||
|
||||
return (strcmp(e1->name, e2->name));
|
||||
}
|
||||
|
||||
static int
|
||||
mtree_cmp_key(const struct archive_rb_node *n, const void *key)
|
||||
{
|
||||
const struct mtree_entry *e = (const struct mtree_entry *)n;
|
||||
|
||||
return (strcmp(e->name, key));
|
||||
}
|
||||
|
||||
int
|
||||
archive_read_support_format_mtree(struct archive *_a)
|
||||
{
|
||||
static const struct archive_rb_tree_ops rb_ops = {
|
||||
mtree_cmp_node, mtree_cmp_key,
|
||||
};
|
||||
struct archive_read *a = (struct archive_read *)_a;
|
||||
struct mtree *mtree;
|
||||
int r;
|
||||
|
@ -237,6 +260,8 @@ archive_read_support_format_mtree(struct archive *_a)
|
|||
}
|
||||
mtree->fd = -1;
|
||||
|
||||
__archive_rb_tree_init(&mtree->rbtree, &rb_ops);
|
||||
|
||||
r = __archive_read_register_format(a, mtree, "mtree",
|
||||
mtree_bid, archive_read_format_mtree_options, read_header, read_data, skip, NULL, cleanup, NULL, NULL);
|
||||
|
||||
|
@ -336,6 +361,14 @@ next_line(struct archive_read *a,
|
|||
size_t nbytes_req = (*ravail+1023) & ~1023U;
|
||||
ssize_t tested;
|
||||
|
||||
/*
|
||||
* Place an arbitrary limit on the line length.
|
||||
* mtree is almost free-form input and without line length limits,
|
||||
* it can consume a lot of memory.
|
||||
*/
|
||||
if (len >= MAX_LINE_LEN)
|
||||
return (-1);
|
||||
|
||||
/* Increase reading bytes if it is not enough to at least
|
||||
* new two lines. */
|
||||
if (nbytes_req < (size_t)*ravail + 160)
|
||||
|
@ -867,12 +900,11 @@ process_add_entry(struct archive_read *a, struct mtree *mtree,
|
|||
struct mtree_option **global, const char *line, ssize_t line_len,
|
||||
struct mtree_entry **last_entry, int is_form_d)
|
||||
{
|
||||
struct mtree_entry *entry, *ht_iter;
|
||||
struct mtree_entry *entry;
|
||||
struct mtree_option *iter;
|
||||
const char *next, *eq, *name, *end;
|
||||
size_t name_len, len;
|
||||
int r, i;
|
||||
unsigned int ht_idx;
|
||||
|
||||
if ((entry = malloc(sizeof(*entry))) == NULL) {
|
||||
archive_set_error(&a->archive, errno, "Can't allocate memory");
|
||||
|
@ -883,8 +915,6 @@ process_add_entry(struct archive_read *a, struct mtree *mtree,
|
|||
entry->name = NULL;
|
||||
entry->used = 0;
|
||||
entry->full = 0;
|
||||
entry->name_hash = 0;
|
||||
entry->hashtable_next = NULL;
|
||||
|
||||
/* Add this entry to list. */
|
||||
if (*last_entry == NULL)
|
||||
|
@ -937,15 +967,17 @@ process_add_entry(struct archive_read *a, struct mtree *mtree,
|
|||
memcpy(entry->name, name, name_len);
|
||||
entry->name[name_len] = '\0';
|
||||
parse_escapes(entry->name, entry);
|
||||
entry->name_hash = hash(entry->name);
|
||||
|
||||
ht_idx = entry->name_hash % MTREE_HASHTABLE_SIZE;
|
||||
if ((ht_iter = mtree->entry_hashtable[ht_idx]) != NULL) {
|
||||
while (ht_iter->hashtable_next)
|
||||
ht_iter = ht_iter->hashtable_next;
|
||||
ht_iter->hashtable_next = entry;
|
||||
} else {
|
||||
mtree->entry_hashtable[ht_idx] = entry;
|
||||
entry->next_dup = NULL;
|
||||
if (entry->full) {
|
||||
if (!__archive_rb_tree_insert_node(&mtree->rbtree, &entry->rbnode)) {
|
||||
struct mtree_entry *alt;
|
||||
alt = (struct mtree_entry *)__archive_rb_tree_find_node(
|
||||
&mtree->rbtree, entry->name);
|
||||
while (alt->next_dup)
|
||||
alt = alt->next_dup;
|
||||
alt->next_dup = entry;
|
||||
}
|
||||
}
|
||||
|
||||
for (iter = *global; iter != NULL; iter = iter->next) {
|
||||
|
@ -982,7 +1014,7 @@ read_mtree(struct archive_read *a, struct mtree *mtree)
|
|||
{
|
||||
ssize_t len;
|
||||
uintmax_t counter;
|
||||
char *p;
|
||||
char *p, *s;
|
||||
struct mtree_option *global;
|
||||
struct mtree_entry *last_entry;
|
||||
int r, is_form_d;
|
||||
|
@ -996,6 +1028,7 @@ read_mtree(struct archive_read *a, struct mtree *mtree)
|
|||
(void)detect_form(a, &is_form_d);
|
||||
|
||||
for (counter = 1; ; ++counter) {
|
||||
r = ARCHIVE_OK;
|
||||
len = readline(a, mtree, &p, 65536);
|
||||
if (len == 0) {
|
||||
mtree->this_entry = mtree->entries;
|
||||
|
@ -1016,6 +1049,15 @@ read_mtree(struct archive_read *a, struct mtree *mtree)
|
|||
continue;
|
||||
if (*p == '\r' || *p == '\n' || *p == '\0')
|
||||
continue;
|
||||
/* Non-printable characters are not allowed */
|
||||
for (s = p;s < p + len - 1; s++) {
|
||||
if (!isprint(*s)) {
|
||||
r = ARCHIVE_FATAL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (r != ARCHIVE_OK)
|
||||
break;
|
||||
if (*p != '/') {
|
||||
r = process_add_entry(a, mtree, &global, p, len,
|
||||
&last_entry, is_form_d);
|
||||
|
@ -1140,14 +1182,13 @@ parse_file(struct archive_read *a, struct archive_entry *entry,
|
|||
* with pathname canonicalization, which is a very
|
||||
* tricky subject.)
|
||||
*/
|
||||
for (mp = mentry->hashtable_next; mp != NULL; mp = mp->hashtable_next) {
|
||||
if (mp->full && !mp->used
|
||||
&& mentry->name_hash == mp->name_hash
|
||||
&& strcmp(mentry->name, mp->name) == 0) {
|
||||
mp = (struct mtree_entry *)__archive_rb_tree_find_node(
|
||||
&mtree->rbtree, mentry->name);
|
||||
for (; mp; mp = mp->next_dup) {
|
||||
if (mp->full && !mp->used) {
|
||||
/* Later lines override earlier ones. */
|
||||
mp->used = 1;
|
||||
r1 = parse_line(a, entry, mtree, mp,
|
||||
&parsed_kws);
|
||||
r1 = parse_line(a, entry, mtree, mp, &parsed_kws);
|
||||
if (r1 < r)
|
||||
r = r1;
|
||||
}
|
||||
|
@ -1418,7 +1459,7 @@ parse_device(dev_t *pdev, struct archive *a, char *val)
|
|||
"Too many arguments");
|
||||
return ARCHIVE_WARN;
|
||||
}
|
||||
numbers[argc++] = (unsigned long)mtree_atol(&p);
|
||||
numbers[argc++] = (unsigned long)mtree_atol(&p, 0);
|
||||
}
|
||||
if (argc < 2) {
|
||||
archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
|
@ -1433,7 +1474,7 @@ parse_device(dev_t *pdev, struct archive *a, char *val)
|
|||
}
|
||||
} else {
|
||||
/* file system raw value. */
|
||||
result = (dev_t)mtree_atol(&val);
|
||||
result = (dev_t)mtree_atol(&val, 0);
|
||||
}
|
||||
*pdev = result;
|
||||
return ARCHIVE_OK;
|
||||
|
@ -1491,6 +1532,7 @@ parse_keyword(struct archive_read *a, struct mtree *mtree,
|
|||
}
|
||||
if (strcmp(key, "cksum") == 0)
|
||||
break;
|
||||
__LA_FALLTHROUGH;
|
||||
case 'd':
|
||||
if (strcmp(key, "device") == 0) {
|
||||
/* stat(2) st_rdev field, e.g. the major/minor IDs
|
||||
|
@ -1504,16 +1546,18 @@ parse_keyword(struct archive_read *a, struct mtree *mtree,
|
|||
archive_entry_set_rdev(entry, dev);
|
||||
return r;
|
||||
}
|
||||
__LA_FALLTHROUGH;
|
||||
case 'f':
|
||||
if (strcmp(key, "flags") == 0) {
|
||||
*parsed_kws |= MTREE_HAS_FFLAGS;
|
||||
archive_entry_copy_fflags_text(entry, val);
|
||||
break;
|
||||
}
|
||||
__LA_FALLTHROUGH;
|
||||
case 'g':
|
||||
if (strcmp(key, "gid") == 0) {
|
||||
*parsed_kws |= MTREE_HAS_GID;
|
||||
archive_entry_set_gid(entry, mtree_atol10(&val));
|
||||
archive_entry_set_gid(entry, mtree_atol(&val, 10));
|
||||
break;
|
||||
}
|
||||
if (strcmp(key, "gname") == 0) {
|
||||
|
@ -1521,39 +1565,44 @@ parse_keyword(struct archive_read *a, struct mtree *mtree,
|
|||
archive_entry_copy_gname(entry, val);
|
||||
break;
|
||||
}
|
||||
__LA_FALLTHROUGH;
|
||||
case 'i':
|
||||
if (strcmp(key, "inode") == 0) {
|
||||
archive_entry_set_ino(entry, mtree_atol10(&val));
|
||||
archive_entry_set_ino(entry, mtree_atol(&val, 10));
|
||||
break;
|
||||
}
|
||||
__LA_FALLTHROUGH;
|
||||
case 'l':
|
||||
if (strcmp(key, "link") == 0) {
|
||||
archive_entry_copy_symlink(entry, val);
|
||||
break;
|
||||
}
|
||||
__LA_FALLTHROUGH;
|
||||
case 'm':
|
||||
if (strcmp(key, "md5") == 0 || strcmp(key, "md5digest") == 0)
|
||||
break;
|
||||
if (strcmp(key, "mode") == 0) {
|
||||
if (val[0] >= '0' && val[0] <= '9') {
|
||||
if (val[0] >= '0' && val[0] <= '7') {
|
||||
*parsed_kws |= MTREE_HAS_PERM;
|
||||
archive_entry_set_perm(entry,
|
||||
(mode_t)mtree_atol8(&val));
|
||||
(mode_t)mtree_atol(&val, 8));
|
||||
} else {
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Symbolic mode \"%s\" unsupported", val);
|
||||
"Symbolic or non-octal mode \"%s\" unsupported", val);
|
||||
return ARCHIVE_WARN;
|
||||
}
|
||||
break;
|
||||
}
|
||||
__LA_FALLTHROUGH;
|
||||
case 'n':
|
||||
if (strcmp(key, "nlink") == 0) {
|
||||
*parsed_kws |= MTREE_HAS_NLINK;
|
||||
archive_entry_set_nlink(entry,
|
||||
(unsigned int)mtree_atol10(&val));
|
||||
(unsigned int)mtree_atol(&val, 10));
|
||||
break;
|
||||
}
|
||||
__LA_FALLTHROUGH;
|
||||
case 'r':
|
||||
if (strcmp(key, "resdevice") == 0) {
|
||||
/* stat(2) st_dev field, e.g. the device ID where the
|
||||
|
@ -1569,6 +1618,7 @@ parse_keyword(struct archive_read *a, struct mtree *mtree,
|
|||
if (strcmp(key, "rmd160") == 0 ||
|
||||
strcmp(key, "rmd160digest") == 0)
|
||||
break;
|
||||
__LA_FALLTHROUGH;
|
||||
case 's':
|
||||
if (strcmp(key, "sha1") == 0 || strcmp(key, "sha1digest") == 0)
|
||||
break;
|
||||
|
@ -1582,9 +1632,10 @@ parse_keyword(struct archive_read *a, struct mtree *mtree,
|
|||
strcmp(key, "sha512digest") == 0)
|
||||
break;
|
||||
if (strcmp(key, "size") == 0) {
|
||||
archive_entry_set_size(entry, mtree_atol10(&val));
|
||||
archive_entry_set_size(entry, mtree_atol(&val, 10));
|
||||
break;
|
||||
}
|
||||
__LA_FALLTHROUGH;
|
||||
case 't':
|
||||
if (strcmp(key, "tags") == 0) {
|
||||
/*
|
||||
|
@ -1601,13 +1652,13 @@ parse_keyword(struct archive_read *a, struct mtree *mtree,
|
|||
long ns = 0;
|
||||
|
||||
*parsed_kws |= MTREE_HAS_MTIME;
|
||||
m = mtree_atol10(&val);
|
||||
m = mtree_atol(&val, 10);
|
||||
/* Replicate an old mtree bug:
|
||||
* 123456789.1 represents 123456789
|
||||
* seconds and 1 nanosecond. */
|
||||
if (*val == '.') {
|
||||
++val;
|
||||
ns = (long)mtree_atol10(&val);
|
||||
ns = (long)mtree_atol(&val, 10);
|
||||
if (ns < 0)
|
||||
ns = 0;
|
||||
else if (ns > 999999999)
|
||||
|
@ -1627,18 +1678,21 @@ parse_keyword(struct archive_read *a, struct mtree *mtree,
|
|||
archive_entry_set_filetype(entry, AE_IFBLK);
|
||||
break;
|
||||
}
|
||||
__LA_FALLTHROUGH;
|
||||
case 'c':
|
||||
if (strcmp(val, "char") == 0) {
|
||||
archive_entry_set_filetype(entry,
|
||||
AE_IFCHR);
|
||||
break;
|
||||
}
|
||||
__LA_FALLTHROUGH;
|
||||
case 'd':
|
||||
if (strcmp(val, "dir") == 0) {
|
||||
archive_entry_set_filetype(entry,
|
||||
AE_IFDIR);
|
||||
break;
|
||||
}
|
||||
__LA_FALLTHROUGH;
|
||||
case 'f':
|
||||
if (strcmp(val, "fifo") == 0) {
|
||||
archive_entry_set_filetype(entry,
|
||||
|
@ -1650,12 +1704,14 @@ parse_keyword(struct archive_read *a, struct mtree *mtree,
|
|||
AE_IFREG);
|
||||
break;
|
||||
}
|
||||
__LA_FALLTHROUGH;
|
||||
case 'l':
|
||||
if (strcmp(val, "link") == 0) {
|
||||
archive_entry_set_filetype(entry,
|
||||
AE_IFLNK);
|
||||
break;
|
||||
}
|
||||
__LA_FALLTHROUGH;
|
||||
default:
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
|
@ -1667,10 +1723,11 @@ parse_keyword(struct archive_read *a, struct mtree *mtree,
|
|||
*parsed_kws |= MTREE_HAS_TYPE;
|
||||
break;
|
||||
}
|
||||
__LA_FALLTHROUGH;
|
||||
case 'u':
|
||||
if (strcmp(key, "uid") == 0) {
|
||||
*parsed_kws |= MTREE_HAS_UID;
|
||||
archive_entry_set_uid(entry, mtree_atol10(&val));
|
||||
archive_entry_set_uid(entry, mtree_atol(&val, 10));
|
||||
break;
|
||||
}
|
||||
if (strcmp(key, "uname") == 0) {
|
||||
|
@ -1678,6 +1735,7 @@ parse_keyword(struct archive_read *a, struct mtree *mtree,
|
|||
archive_entry_copy_uname(entry, val);
|
||||
break;
|
||||
}
|
||||
__LA_FALLTHROUGH;
|
||||
default:
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Unrecognized key %s=%s", key, val);
|
||||
|
@ -1825,77 +1883,9 @@ parse_escapes(char *src, struct mtree_entry *mentry)
|
|||
*dest = '\0';
|
||||
}
|
||||
|
||||
/*
|
||||
* Note that this implementation does not (and should not!) obey
|
||||
* locale settings; you cannot simply substitute strtol here, since
|
||||
* it does obey locale.
|
||||
*/
|
||||
static int64_t
|
||||
mtree_atol8(char **p)
|
||||
{
|
||||
int64_t l, limit, last_digit_limit;
|
||||
int digit, base;
|
||||
|
||||
base = 8;
|
||||
limit = INT64_MAX / base;
|
||||
last_digit_limit = INT64_MAX % base;
|
||||
|
||||
l = 0;
|
||||
digit = **p - '0';
|
||||
while (digit >= 0 && digit < base) {
|
||||
if (l>limit || (l == limit && digit > last_digit_limit)) {
|
||||
l = INT64_MAX; /* Truncate on overflow. */
|
||||
break;
|
||||
}
|
||||
l = (l * base) + digit;
|
||||
digit = *++(*p) - '0';
|
||||
}
|
||||
return (l);
|
||||
}
|
||||
|
||||
/*
|
||||
* Note that this implementation does not (and should not!) obey
|
||||
* locale settings; you cannot simply substitute strtol here, since
|
||||
* it does obey locale.
|
||||
*
|
||||
* Convert the number pointed to by 'p' into a 64-bit signed integer.
|
||||
* On return, 'p' points to the first non-digit following the number.
|
||||
* On overflow, the function returns INT64_MIN or INT64_MAX.
|
||||
*/
|
||||
static int64_t
|
||||
mtree_atol10(char **p)
|
||||
{
|
||||
const int base = 10;
|
||||
const int64_t limit = INT64_MAX / base;
|
||||
const int64_t last_digit_limit = INT64_MAX % base;
|
||||
int64_t l;
|
||||
int sign;
|
||||
|
||||
if (**p == '-') {
|
||||
sign = -1;
|
||||
++(*p);
|
||||
} else {
|
||||
sign = 1;
|
||||
}
|
||||
|
||||
l = 0;
|
||||
while (**p >= '0' && **p < '0' + base) {
|
||||
int digit = **p - '0';
|
||||
if (l > limit || (l == limit && digit > last_digit_limit)) {
|
||||
while (**p >= '0' && **p < '0' + base) {
|
||||
++(*p);
|
||||
}
|
||||
return (sign < 0) ? INT64_MIN : INT64_MAX;
|
||||
}
|
||||
l = (l * base) + digit;
|
||||
++(*p);
|
||||
}
|
||||
return (sign < 0) ? -l : l;
|
||||
}
|
||||
|
||||
/* Parse a hex digit. */
|
||||
static int
|
||||
parsehex(char c)
|
||||
parsedigit(char c)
|
||||
{
|
||||
if (c >= '0' && c <= '9')
|
||||
return c - '0';
|
||||
|
@ -1913,45 +1903,50 @@ parsehex(char c)
|
|||
* it does obey locale.
|
||||
*/
|
||||
static int64_t
|
||||
mtree_atol16(char **p)
|
||||
mtree_atol(char **p, int base)
|
||||
{
|
||||
int64_t l, limit, last_digit_limit;
|
||||
int base, digit, sign;
|
||||
int64_t l, limit;
|
||||
int digit, last_digit_limit;
|
||||
|
||||
base = 16;
|
||||
if (base == 0) {
|
||||
if (**p != '0')
|
||||
base = 10;
|
||||
else if ((*p)[1] == 'x' || (*p)[1] == 'X') {
|
||||
*p += 2;
|
||||
base = 16;
|
||||
} else {
|
||||
base = 8;
|
||||
}
|
||||
}
|
||||
|
||||
if (**p == '-') {
|
||||
sign = -1;
|
||||
limit = ((uint64_t)(INT64_MAX) + 1) / base;
|
||||
last_digit_limit = ((uint64_t)(INT64_MAX) + 1) % base;
|
||||
limit = INT64_MIN / base;
|
||||
last_digit_limit = INT64_MIN % base;
|
||||
++(*p);
|
||||
|
||||
l = 0;
|
||||
digit = parsedigit(**p);
|
||||
while (digit >= 0 && digit < base) {
|
||||
if (l < limit || (l == limit && digit > last_digit_limit))
|
||||
return INT64_MIN;
|
||||
l = (l * base) - digit;
|
||||
digit = parsedigit(*++(*p));
|
||||
}
|
||||
return l;
|
||||
} else {
|
||||
sign = 1;
|
||||
limit = INT64_MAX / base;
|
||||
last_digit_limit = INT64_MAX % base;
|
||||
}
|
||||
|
||||
l = 0;
|
||||
digit = parsehex(**p);
|
||||
while (digit >= 0 && digit < base) {
|
||||
if (l > limit || (l == limit && digit > last_digit_limit))
|
||||
return (sign < 0) ? INT64_MIN : INT64_MAX;
|
||||
l = (l * base) + digit;
|
||||
digit = parsehex(*++(*p));
|
||||
l = 0;
|
||||
digit = parsedigit(**p);
|
||||
while (digit >= 0 && digit < base) {
|
||||
if (l > limit || (l == limit && digit > last_digit_limit))
|
||||
return INT64_MAX;
|
||||
l = (l * base) + digit;
|
||||
digit = parsedigit(*++(*p));
|
||||
}
|
||||
return l;
|
||||
}
|
||||
return (sign < 0) ? -l : l;
|
||||
}
|
||||
|
||||
static int64_t
|
||||
mtree_atol(char **p)
|
||||
{
|
||||
if (**p != '0')
|
||||
return mtree_atol10(p);
|
||||
if ((*p)[1] == 'x' || (*p)[1] == 'X') {
|
||||
*p += 2;
|
||||
return mtree_atol16(p);
|
||||
}
|
||||
return mtree_atol8(p);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2027,19 +2022,3 @@ readline(struct archive_read *a, struct mtree *mtree, char **start,
|
|||
find_off = u - mtree->line.s;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
hash(const char *p)
|
||||
{
|
||||
/* A 32-bit version of Peter Weinberger's (PJW) hash algorithm,
|
||||
as used by ELF for hashing function names. */
|
||||
unsigned g, h = 0;
|
||||
while (*p != '\0') {
|
||||
h = (h << 4) + *p++;
|
||||
if ((g = h & 0xF0000000) != 0) {
|
||||
h ^= g >> 24;
|
||||
h &= 0x0FFFFFFF;
|
||||
}
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
|
|
@ -258,6 +258,7 @@ struct rar
|
|||
struct data_block_offsets *dbo;
|
||||
unsigned int cursor;
|
||||
unsigned int nodes;
|
||||
char filename_must_match;
|
||||
|
||||
/* LZSS members */
|
||||
struct huffman_code maincode;
|
||||
|
@ -604,20 +605,6 @@ lzss_emit_match(struct rar *rar, int offset, int length)
|
|||
rar->lzss.position += length;
|
||||
}
|
||||
|
||||
static void *
|
||||
ppmd_alloc(void *p, size_t size)
|
||||
{
|
||||
(void)p;
|
||||
return malloc(size);
|
||||
}
|
||||
static void
|
||||
ppmd_free(void *p, void *address)
|
||||
{
|
||||
(void)p;
|
||||
free(address);
|
||||
}
|
||||
static ISzAlloc g_szalloc = { ppmd_alloc, ppmd_free };
|
||||
|
||||
static Byte
|
||||
ppmd_read(void *p)
|
||||
{
|
||||
|
@ -1037,8 +1024,10 @@ archive_read_format_rar_read_data(struct archive_read *a, const void **buff,
|
|||
case COMPRESS_METHOD_GOOD:
|
||||
case COMPRESS_METHOD_BEST:
|
||||
ret = read_data_compressed(a, buff, size, offset);
|
||||
if (ret != ARCHIVE_OK && ret != ARCHIVE_WARN)
|
||||
__archive_ppmd7_functions.Ppmd7_Free(&rar->ppmd7_context, &g_szalloc);
|
||||
if (ret != ARCHIVE_OK && ret != ARCHIVE_WARN) {
|
||||
__archive_ppmd7_functions.Ppmd7_Free(&rar->ppmd7_context);
|
||||
rar->start_new_table = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -1253,7 +1242,7 @@ archive_read_format_rar_cleanup(struct archive_read *a)
|
|||
free(rar->dbo);
|
||||
free(rar->unp_buffer);
|
||||
free(rar->lzss.window);
|
||||
__archive_ppmd7_functions.Ppmd7_Free(&rar->ppmd7_context, &g_szalloc);
|
||||
__archive_ppmd7_functions.Ppmd7_Free(&rar->ppmd7_context);
|
||||
free(rar);
|
||||
(a->format->data) = NULL;
|
||||
return (ARCHIVE_OK);
|
||||
|
@ -1496,7 +1485,11 @@ read_header(struct archive_read *a, struct archive_entry *entry,
|
|||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
filename[filename_size++] = '\0';
|
||||
filename[filename_size++] = '\0';
|
||||
/*
|
||||
* Do not increment filename_size here as the computations below
|
||||
* add the space for the terminating NUL explicitly.
|
||||
*/
|
||||
filename[filename_size] = '\0';
|
||||
|
||||
/* Decoded unicode form is UTF-16BE, so we have to update a string
|
||||
* conversion object for it. */
|
||||
|
@ -1570,6 +1563,12 @@ read_header(struct archive_read *a, struct archive_entry *entry,
|
|||
}
|
||||
return ret;
|
||||
}
|
||||
else if (rar->filename_must_match)
|
||||
{
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Mismatch of file parts split across multi-volume archive");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
rar->filename_save = (char*)realloc(rar->filename_save,
|
||||
filename_size + 1);
|
||||
|
@ -1654,7 +1653,7 @@ read_header(struct archive_read *a, struct archive_entry *entry,
|
|||
rar->unp_offset = 0;
|
||||
rar->unp_buffer_size = UNP_BUFFER_SIZE;
|
||||
memset(rar->lengthtable, 0, sizeof(rar->lengthtable));
|
||||
__archive_ppmd7_functions.Ppmd7_Free(&rar->ppmd7_context, &g_szalloc);
|
||||
__archive_ppmd7_functions.Ppmd7_Free(&rar->ppmd7_context);
|
||||
rar->ppmd_valid = rar->ppmd_eod = 0;
|
||||
|
||||
/* Don't set any archive entries for non-file header types */
|
||||
|
@ -1750,7 +1749,7 @@ read_exttime(const char *p, struct rar *rar, const char *endp)
|
|||
return (-1);
|
||||
for (j = 0; j < count; j++)
|
||||
{
|
||||
rem = ((*p) << 16) | (rem >> 8);
|
||||
rem = (((unsigned)(unsigned char)*p) << 16) | (rem >> 8);
|
||||
p++;
|
||||
}
|
||||
tm = localtime(&t);
|
||||
|
@ -2118,7 +2117,7 @@ parse_codes(struct archive_read *a)
|
|||
|
||||
/* Make sure ppmd7_contest is freed before Ppmd7_Construct
|
||||
* because reading a broken file cause this abnormal sequence. */
|
||||
__archive_ppmd7_functions.Ppmd7_Free(&rar->ppmd7_context, &g_szalloc);
|
||||
__archive_ppmd7_functions.Ppmd7_Free(&rar->ppmd7_context);
|
||||
|
||||
rar->bytein.a = a;
|
||||
rar->bytein.Read = &ppmd_read;
|
||||
|
@ -2133,7 +2132,7 @@ parse_codes(struct archive_read *a)
|
|||
}
|
||||
|
||||
if (!__archive_ppmd7_functions.Ppmd7_Alloc(&rar->ppmd7_context,
|
||||
rar->dictionary_size, &g_szalloc))
|
||||
rar->dictionary_size))
|
||||
{
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
"Out of memory");
|
||||
|
@ -2310,6 +2309,11 @@ parse_codes(struct archive_read *a)
|
|||
new_size = DICTIONARY_MAX_SIZE;
|
||||
else
|
||||
new_size = rar_fls((unsigned int)rar->unp_size) << 1;
|
||||
if (new_size == 0) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Zero window size is invalid.");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
new_window = realloc(rar->lzss.window, new_size);
|
||||
if (new_window == NULL) {
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
|
@ -2938,12 +2942,14 @@ rar_read_ahead(struct archive_read *a, size_t min, ssize_t *avail)
|
|||
else if (*avail == 0 && rar->main_flags & MHD_VOLUME &&
|
||||
rar->file_flags & FHD_SPLIT_AFTER)
|
||||
{
|
||||
rar->filename_must_match = 1;
|
||||
ret = archive_read_format_rar_read_header(a, a->entry);
|
||||
if (ret == (ARCHIVE_EOF))
|
||||
{
|
||||
rar->has_endarc_header = 1;
|
||||
ret = archive_read_format_rar_read_header(a, a->entry);
|
||||
}
|
||||
rar->filename_must_match = 0;
|
||||
if (ret != (ARCHIVE_OK))
|
||||
return NULL;
|
||||
return rar_read_ahead(a, min, avail);
|
||||
|
|
4030
external/bsd/libarchive/dist/libarchive/archive_read_support_format_rar5.c
vendored
Normal file
4030
external/bsd/libarchive/dist/libarchive/archive_read_support_format_rar5.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
|
@ -120,7 +120,9 @@ archive_read_format_raw_read_header(struct archive_read *a,
|
|||
archive_entry_set_filetype(entry, AE_IFREG);
|
||||
archive_entry_set_perm(entry, 0644);
|
||||
/* I'm deliberately leaving most fields unset here. */
|
||||
return (ARCHIVE_OK);
|
||||
|
||||
/* Let the filter fill out any fields it might have. */
|
||||
return __archive_read_header(a, entry);
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
|
@ -251,15 +251,15 @@ archive_read_support_format_tar(struct archive *_a)
|
|||
ARCHIVE_STATE_NEW, "archive_read_support_format_tar");
|
||||
|
||||
tar = (struct tar *)calloc(1, sizeof(*tar));
|
||||
#ifdef HAVE_COPYFILE_H
|
||||
/* Set this by default on Mac OS. */
|
||||
tar->process_mac_extensions = 1;
|
||||
#endif
|
||||
if (tar == NULL) {
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
"Can't allocate tar data");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
#ifdef HAVE_COPYFILE_H
|
||||
/* Set this by default on Mac OS. */
|
||||
tar->process_mac_extensions = 1;
|
||||
#endif
|
||||
|
||||
r = __archive_read_register_format(a, tar, "tar",
|
||||
archive_read_format_tar_bid,
|
||||
|
@ -694,11 +694,13 @@ tar_read_header(struct archive_read *a, struct tar *tar,
|
|||
struct archive_entry *entry, size_t *unconsumed)
|
||||
{
|
||||
ssize_t bytes;
|
||||
int err;
|
||||
int err, eof_vol_header;
|
||||
const char *h;
|
||||
const struct archive_entry_header_ustar *header;
|
||||
const struct archive_entry_header_gnutar *gnuheader;
|
||||
|
||||
eof_vol_header = 0;
|
||||
|
||||
/* Loop until we find a workable header record. */
|
||||
for (;;) {
|
||||
tar_flush_unconsumed(a, unconsumed);
|
||||
|
@ -788,6 +790,8 @@ tar_read_header(struct archive_read *a, struct tar *tar,
|
|||
break;
|
||||
case 'V': /* GNU volume header */
|
||||
err = header_volume(a, tar, entry, h, unconsumed);
|
||||
if (err == ARCHIVE_EOF)
|
||||
eof_vol_header = 1;
|
||||
break;
|
||||
case 'X': /* Used by SUN tar; same as 'x'. */
|
||||
a->archive.archive_format = ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE;
|
||||
|
@ -862,9 +866,17 @@ tar_read_header(struct archive_read *a, struct tar *tar,
|
|||
}
|
||||
return (err);
|
||||
}
|
||||
if (err == ARCHIVE_EOF)
|
||||
/* EOF when recursively reading a header is bad. */
|
||||
archive_set_error(&a->archive, EINVAL, "Damaged tar archive");
|
||||
if (err == ARCHIVE_EOF) {
|
||||
if (!eof_vol_header) {
|
||||
/* EOF when recursively reading a header is bad. */
|
||||
archive_set_error(&a->archive, EINVAL,
|
||||
"Damaged tar archive");
|
||||
} else {
|
||||
/* If we encounter just a GNU volume header treat
|
||||
* this situation as an empty archive */
|
||||
return (ARCHIVE_EOF);
|
||||
}
|
||||
}
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
|
@ -1942,6 +1954,15 @@ pax_attribute(struct archive_read *a, struct tar *tar,
|
|||
pax_time(value, &s, &n);
|
||||
archive_entry_set_birthtime(entry, s, n);
|
||||
}
|
||||
if (strcmp(key, "LIBARCHIVE.symlinktype") == 0) {
|
||||
if (strcmp(value, "file") == 0) {
|
||||
archive_entry_set_symlink_type(entry,
|
||||
AE_SYMLINK_TYPE_FILE);
|
||||
} else if (strcmp(value, "dir") == 0) {
|
||||
archive_entry_set_symlink_type(entry,
|
||||
AE_SYMLINK_TYPE_DIRECTORY);
|
||||
}
|
||||
}
|
||||
if (memcmp(key, "LIBARCHIVE.xattr.", 17) == 0)
|
||||
pax_attribute_xattr(entry, key, value);
|
||||
break;
|
||||
|
@ -2241,7 +2262,7 @@ gnu_add_sparse_entry(struct archive_read *a, struct tar *tar,
|
|||
else
|
||||
tar->sparse_list = p;
|
||||
tar->sparse_last = p;
|
||||
if (remaining < 0 || offset < 0) {
|
||||
if (remaining < 0 || offset < 0 || offset > INT64_MAX - remaining) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Malformed sparse map data");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
|
|
@ -386,6 +386,11 @@ _warc_read(struct archive_read *a, const void **buf, size_t *bsz, int64_t *off)
|
|||
return (ARCHIVE_EOF);
|
||||
}
|
||||
|
||||
if (w->unconsumed) {
|
||||
__archive_read_consume(a, w->unconsumed);
|
||||
w->unconsumed = 0U;
|
||||
}
|
||||
|
||||
rab = __archive_read_ahead(a, 1U, &nrd);
|
||||
if (nrd < 0) {
|
||||
*bsz = 0U;
|
||||
|
@ -739,8 +744,9 @@ _warc_rdlen(const char *buf, size_t bsz)
|
|||
/* there must be at least one digit */
|
||||
if (!isdigit((unsigned char)*val))
|
||||
return -1;
|
||||
errno = 0;
|
||||
len = strtol(val, &on, 10);
|
||||
if (on != eol) {
|
||||
if (errno != 0 || on != eol) {
|
||||
/* line must end here */
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -167,6 +167,9 @@ struct xar_file {
|
|||
#define HAS_FFLAGS 0x01000
|
||||
#define HAS_XATTR 0x02000
|
||||
#define HAS_ACL 0x04000
|
||||
#define HAS_CTIME 0x08000
|
||||
#define HAS_MTIME 0x10000
|
||||
#define HAS_ATIME 0x20000
|
||||
|
||||
uint64_t id;
|
||||
uint64_t length;
|
||||
|
@ -695,9 +698,15 @@ xar_read_header(struct archive_read *a, struct archive_entry *entry)
|
|||
*/
|
||||
file_free(file);
|
||||
}
|
||||
archive_entry_set_atime(entry, file->atime, 0);
|
||||
archive_entry_set_ctime(entry, file->ctime, 0);
|
||||
archive_entry_set_mtime(entry, file->mtime, 0);
|
||||
if (file->has & HAS_ATIME) {
|
||||
archive_entry_set_atime(entry, file->atime, 0);
|
||||
}
|
||||
if (file->has & HAS_CTIME) {
|
||||
archive_entry_set_ctime(entry, file->ctime, 0);
|
||||
}
|
||||
if (file->has & HAS_MTIME) {
|
||||
archive_entry_set_mtime(entry, file->mtime, 0);
|
||||
}
|
||||
archive_entry_set_gid(entry, file->gid);
|
||||
if (file->gname.length > 0 &&
|
||||
archive_entry_copy_gname_l(entry, file->gname.s,
|
||||
|
@ -789,7 +798,8 @@ xar_read_header(struct archive_read *a, struct archive_entry *entry)
|
|||
xattr = file->xattr_list;
|
||||
while (xattr != NULL) {
|
||||
const void *d;
|
||||
size_t outbytes, used;
|
||||
size_t outbytes = 0;
|
||||
size_t used = 0;
|
||||
|
||||
r = move_reading_point(a, xattr->offset);
|
||||
if (r != ARCHIVE_OK)
|
||||
|
@ -811,8 +821,18 @@ xar_read_header(struct archive_read *a, struct archive_entry *entry)
|
|||
r = checksum_final(a,
|
||||
xattr->a_sum.val, xattr->a_sum.len,
|
||||
xattr->e_sum.val, xattr->e_sum.len);
|
||||
if (r != ARCHIVE_OK)
|
||||
if (r != ARCHIVE_OK) {
|
||||
archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC,
|
||||
"Xattr checksum error");
|
||||
r = ARCHIVE_WARN;
|
||||
break;
|
||||
}
|
||||
if (xattr->name.s == NULL) {
|
||||
archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC,
|
||||
"Xattr name error");
|
||||
r = ARCHIVE_WARN;
|
||||
break;
|
||||
}
|
||||
archive_entry_xattr_add_entry(entry,
|
||||
xattr->name.s, d, outbytes);
|
||||
xattr = xattr->next;
|
||||
|
@ -838,7 +858,7 @@ xar_read_data(struct archive_read *a,
|
|||
const void **buff, size_t *size, int64_t *offset)
|
||||
{
|
||||
struct xar *xar;
|
||||
size_t used;
|
||||
size_t used = 0;
|
||||
int r;
|
||||
|
||||
xar = (struct xar *)(a->format->data);
|
||||
|
@ -967,7 +987,7 @@ move_reading_point(struct archive_read *a, uint64_t offset)
|
|||
return ((int)step);
|
||||
xar->offset += step;
|
||||
} else {
|
||||
int64_t pos = __archive_read_seek(a, offset, SEEK_SET);
|
||||
int64_t pos = __archive_read_seek(a, xar->h_base + offset, SEEK_SET);
|
||||
if (pos == ARCHIVE_FAILED) {
|
||||
archive_set_error(&(a->archive),
|
||||
ARCHIVE_ERRNO_MISC,
|
||||
|
@ -1040,6 +1060,9 @@ atol10(const char *p, size_t char_cnt)
|
|||
uint64_t l;
|
||||
int digit;
|
||||
|
||||
if (char_cnt == 0)
|
||||
return (0);
|
||||
|
||||
l = 0;
|
||||
digit = *p - '0';
|
||||
while (digit >= 0 && digit < 10 && char_cnt-- > 0) {
|
||||
|
@ -1054,7 +1077,10 @@ atol8(const char *p, size_t char_cnt)
|
|||
{
|
||||
int64_t l;
|
||||
int digit;
|
||||
|
||||
|
||||
if (char_cnt == 0)
|
||||
return (0);
|
||||
|
||||
l = 0;
|
||||
while (char_cnt-- > 0) {
|
||||
if (*p >= '0' && *p <= '7')
|
||||
|
@ -1214,8 +1240,7 @@ heap_add_entry(struct archive_read *a,
|
|||
}
|
||||
memcpy(new_pending_files, heap->files,
|
||||
heap->allocated * sizeof(new_pending_files[0]));
|
||||
if (heap->files != NULL)
|
||||
free(heap->files);
|
||||
free(heap->files);
|
||||
heap->files = new_pending_files;
|
||||
heap->allocated = new_size;
|
||||
}
|
||||
|
@ -1761,8 +1786,8 @@ file_new(struct archive_read *a, struct xar *xar, struct xmlattr_list *list)
|
|||
}
|
||||
file->parent = xar->file;
|
||||
file->mode = 0777 | AE_IFREG;
|
||||
file->atime = time(NULL);
|
||||
file->mtime = time(NULL);
|
||||
file->atime = 0;
|
||||
file->mtime = 0;
|
||||
xar->file = file;
|
||||
xar->xattr = NULL;
|
||||
for (attr = list->first; attr != NULL; attr = attr->next) {
|
||||
|
@ -2623,6 +2648,14 @@ strappend_base64(struct xar *xar,
|
|||
archive_strncat(as, (const char *)buff, len);
|
||||
}
|
||||
|
||||
static int
|
||||
is_string(const char *known, const char *data, size_t len)
|
||||
{
|
||||
if (strlen(known) != len)
|
||||
return -1;
|
||||
return memcmp(data, known, len);
|
||||
}
|
||||
|
||||
static void
|
||||
xml_data(void *userData, const char *s, int len)
|
||||
{
|
||||
|
@ -2674,26 +2707,26 @@ xml_data(void *userData, const char *s, int len)
|
|||
archive_strncpy(&(xar->file->symlink), s, len);
|
||||
break;
|
||||
case FILE_TYPE:
|
||||
if (strncmp("file", s, len) == 0 ||
|
||||
strncmp("hardlink", s, len) == 0)
|
||||
if (is_string("file", s, len) == 0 ||
|
||||
is_string("hardlink", s, len) == 0)
|
||||
xar->file->mode =
|
||||
(xar->file->mode & ~AE_IFMT) | AE_IFREG;
|
||||
if (strncmp("directory", s, len) == 0)
|
||||
if (is_string("directory", s, len) == 0)
|
||||
xar->file->mode =
|
||||
(xar->file->mode & ~AE_IFMT) | AE_IFDIR;
|
||||
if (strncmp("symlink", s, len) == 0)
|
||||
if (is_string("symlink", s, len) == 0)
|
||||
xar->file->mode =
|
||||
(xar->file->mode & ~AE_IFMT) | AE_IFLNK;
|
||||
if (strncmp("character special", s, len) == 0)
|
||||
if (is_string("character special", s, len) == 0)
|
||||
xar->file->mode =
|
||||
(xar->file->mode & ~AE_IFMT) | AE_IFCHR;
|
||||
if (strncmp("block special", s, len) == 0)
|
||||
if (is_string("block special", s, len) == 0)
|
||||
xar->file->mode =
|
||||
(xar->file->mode & ~AE_IFMT) | AE_IFBLK;
|
||||
if (strncmp("socket", s, len) == 0)
|
||||
if (is_string("socket", s, len) == 0)
|
||||
xar->file->mode =
|
||||
(xar->file->mode & ~AE_IFMT) | AE_IFSOCK;
|
||||
if (strncmp("fifo", s, len) == 0)
|
||||
if (is_string("fifo", s, len) == 0)
|
||||
xar->file->mode =
|
||||
(xar->file->mode & ~AE_IFMT) | AE_IFIFO;
|
||||
xar->file->has |= HAS_TYPE;
|
||||
|
@ -2737,15 +2770,15 @@ xml_data(void *userData, const char *s, int len)
|
|||
xar->file->uid = atol10(s, len);
|
||||
break;
|
||||
case FILE_CTIME:
|
||||
xar->file->has |= HAS_TIME;
|
||||
xar->file->has |= HAS_TIME | HAS_CTIME;
|
||||
xar->file->ctime = parse_time(s, len);
|
||||
break;
|
||||
case FILE_MTIME:
|
||||
xar->file->has |= HAS_TIME;
|
||||
xar->file->has |= HAS_TIME | HAS_MTIME;
|
||||
xar->file->mtime = parse_time(s, len);
|
||||
break;
|
||||
case FILE_ATIME:
|
||||
xar->file->has |= HAS_TIME;
|
||||
xar->file->has |= HAS_TIME | HAS_ATIME;
|
||||
xar->file->atime = parse_time(s, len);
|
||||
break;
|
||||
case FILE_DATA_LENGTH:
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -202,7 +202,8 @@ archive_string_append(struct archive_string *as, const char *p, size_t s)
|
|||
{
|
||||
if (archive_string_ensure(as, as->length + s + 1) == NULL)
|
||||
return (NULL);
|
||||
memmove(as->s + as->length, p, s);
|
||||
if (s)
|
||||
memmove(as->s + as->length, p, s);
|
||||
as->length += s;
|
||||
as->s[as->length] = 0;
|
||||
return (as);
|
||||
|
@ -213,7 +214,8 @@ archive_wstring_append(struct archive_wstring *as, const wchar_t *p, size_t s)
|
|||
{
|
||||
if (archive_wstring_ensure(as, as->length + s + 1) == NULL)
|
||||
return (NULL);
|
||||
wmemmove(as->s + as->length, p, s);
|
||||
if (s)
|
||||
wmemmove(as->s + as->length, p, s);
|
||||
as->length += s;
|
||||
as->s[as->length] = 0;
|
||||
return (as);
|
||||
|
@ -1510,8 +1512,10 @@ get_current_codepage(void)
|
|||
p = strrchr(locale, '.');
|
||||
if (p == NULL)
|
||||
return (GetACP());
|
||||
if (strcmp(p+1, "utf8") == 0)
|
||||
return CP_UTF8;
|
||||
cp = my_atoi(p+1);
|
||||
if (cp <= 0)
|
||||
if ((int)cp <= 0)
|
||||
return (GetACP());
|
||||
return (cp);
|
||||
}
|
||||
|
@ -4048,6 +4052,7 @@ archive_mstring_copy_utf8(struct archive_mstring *aes, const char *utf8)
|
|||
{
|
||||
if (utf8 == NULL) {
|
||||
aes->aes_set = 0;
|
||||
return (0);
|
||||
}
|
||||
aes->aes_set = AES_SET_UTF8;
|
||||
archive_string_empty(&(aes->aes_mbs));
|
||||
|
@ -4062,6 +4067,7 @@ archive_mstring_copy_wcs_len(struct archive_mstring *aes, const wchar_t *wcs,
|
|||
{
|
||||
if (wcs == NULL) {
|
||||
aes->aes_set = 0;
|
||||
return (0);
|
||||
}
|
||||
aes->aes_set = AES_SET_WCS; /* Only WCS form set. */
|
||||
archive_string_empty(&(aes->aes_mbs));
|
||||
|
|
|
@ -140,7 +140,7 @@ archive_compression_name(struct archive *a)
|
|||
/*
|
||||
* Return a count of the number of compressed bytes processed.
|
||||
*/
|
||||
int64_t
|
||||
la_int64_t
|
||||
archive_position_compressed(struct archive *a)
|
||||
{
|
||||
return archive_filter_bytes(a, -1);
|
||||
|
@ -149,7 +149,7 @@ archive_position_compressed(struct archive *a)
|
|||
/*
|
||||
* Return a count of the number of uncompressed bytes processed.
|
||||
*/
|
||||
int64_t
|
||||
la_int64_t
|
||||
archive_position_uncompressed(struct archive *a)
|
||||
{
|
||||
return archive_filter_bytes(a, 0);
|
||||
|
@ -449,7 +449,7 @@ __archive_mktemp(const char *tmpdir)
|
|||
temp_name.s[temp_name.length-1] = '\0';
|
||||
temp_name.length --;
|
||||
}
|
||||
if (stat(temp_name.s, &st) < 0)
|
||||
if (la_stat(temp_name.s, &st) < 0)
|
||||
goto exit_tmpfile;
|
||||
if (!S_ISDIR(st.st_mode)) {
|
||||
errno = ENOTDIR;
|
||||
|
|
|
@ -45,6 +45,9 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_util.c 201098 2009-12-28 02:58:1
|
|||
#ifdef HAVE_LZ4_H
|
||||
#include <lz4.h>
|
||||
#endif
|
||||
#ifdef HAVE_ZSTD_H
|
||||
#include <zstd.h>
|
||||
#endif
|
||||
|
||||
#include "archive.h"
|
||||
#include "archive_private.h"
|
||||
|
@ -59,6 +62,7 @@ archive_version_details(void)
|
|||
const char *liblzma = archive_liblzma_version();
|
||||
const char *bzlib = archive_bzlib_version();
|
||||
const char *liblz4 = archive_liblz4_version();
|
||||
const char *libzstd = archive_libzstd_version();
|
||||
|
||||
if (!init) {
|
||||
archive_string_init(&str);
|
||||
|
@ -84,6 +88,10 @@ archive_version_details(void)
|
|||
archive_strcat(&str, " liblz4/");
|
||||
archive_strcat(&str, liblz4);
|
||||
}
|
||||
if (libzstd) {
|
||||
archive_strcat(&str, " libzstd/");
|
||||
archive_strcat(&str, libzstd);
|
||||
}
|
||||
}
|
||||
return str.s;
|
||||
}
|
||||
|
@ -131,3 +139,13 @@ archive_liblz4_version(void)
|
|||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
const char *
|
||||
archive_libzstd_version(void)
|
||||
{
|
||||
#if HAVE_ZSTD_H && HAVE_LIBZSTD
|
||||
return ZSTD_VERSION_STRING;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -48,7 +48,7 @@ archive_filter_name(struct archive *a, int n)
|
|||
return ((a->vtable->archive_filter_name)(a, n));
|
||||
}
|
||||
|
||||
int64_t
|
||||
la_int64_t
|
||||
archive_filter_bytes(struct archive *a, int n)
|
||||
{
|
||||
return ((a->vtable->archive_filter_bytes)(a, n));
|
||||
|
@ -124,14 +124,15 @@ archive_write_finish_entry(struct archive *a)
|
|||
return ((a->vtable->archive_write_finish_entry)(a));
|
||||
}
|
||||
|
||||
ssize_t
|
||||
la_ssize_t
|
||||
archive_write_data(struct archive *a, const void *buff, size_t s)
|
||||
{
|
||||
return ((a->vtable->archive_write_data)(a, buff, s));
|
||||
}
|
||||
|
||||
ssize_t
|
||||
archive_write_data_block(struct archive *a, const void *buff, size_t s, int64_t o)
|
||||
la_ssize_t
|
||||
archive_write_data_block(struct archive *a, const void *buff, size_t s,
|
||||
la_int64_t o)
|
||||
{
|
||||
if (a->vtable->archive_write_data_block == NULL) {
|
||||
archive_set_error(a, ARCHIVE_ERRNO_MISC,
|
||||
|
@ -156,7 +157,7 @@ archive_read_next_header2(struct archive *a, struct archive_entry *entry)
|
|||
|
||||
int
|
||||
archive_read_data_block(struct archive *a,
|
||||
const void **buff, size_t *s, int64_t *o)
|
||||
const void **buff, size_t *s, la_int64_t *o)
|
||||
{
|
||||
return ((a->vtable->archive_read_data_block)(a, buff, s, o));
|
||||
}
|
||||
|
|
|
@ -445,7 +445,8 @@ fileTimeToUTC(const FILETIME *filetime, time_t *t, long *ns)
|
|||
* Windows' stat() does not accept the path added "\\?\" especially "?"
|
||||
* character.
|
||||
* It means we cannot access the long name path longer than MAX_PATH.
|
||||
* So I've implemented simular Windows' stat() to access the long name path.
|
||||
* So I've implemented a function similar to Windows' stat() to access the
|
||||
* long name path.
|
||||
* And I've added some feature.
|
||||
* 1. set st_ino by nFileIndexHigh and nFileIndexLow of
|
||||
* BY_HANDLE_FILE_INFORMATION.
|
||||
|
|
|
@ -112,10 +112,7 @@
|
|||
#if !defined(__BORLANDC__) && !defined(__WATCOMC__)
|
||||
#define setmode _setmode
|
||||
#endif
|
||||
#ifdef stat
|
||||
#undef stat
|
||||
#endif
|
||||
#define stat(path,stref) __la_stat(path,stref)
|
||||
#define la_stat(path,stref) __la_stat(path,stref)
|
||||
#if !defined(__WATCOMC__)
|
||||
#if !defined(__BORLANDC__)
|
||||
#define strdup _strdup
|
||||
|
|
|
@ -71,7 +71,7 @@ support.
|
|||
.\"
|
||||
.Ss Set options
|
||||
See
|
||||
.Xr archive_read_set_options 3 .
|
||||
.Xr archive_write_set_options 3 .
|
||||
.\"
|
||||
.Ss Open archive
|
||||
See
|
||||
|
|
|
@ -190,7 +190,7 @@ archive_write_get_bytes_in_last_block(struct archive *_a)
|
|||
* an archive to itself recursively.
|
||||
*/
|
||||
int
|
||||
archive_write_set_skip_file(struct archive *_a, int64_t d, int64_t i)
|
||||
archive_write_set_skip_file(struct archive *_a, la_int64_t d, la_int64_t i)
|
||||
{
|
||||
struct archive_write *a = (struct archive_write *)_a;
|
||||
archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC,
|
||||
|
|
|
@ -53,6 +53,7 @@ struct { int code; int (*setter)(struct archive *); } codes[] =
|
|||
{ ARCHIVE_FILTER_LZOP, archive_write_add_filter_lzip },
|
||||
{ ARCHIVE_FILTER_UU, archive_write_add_filter_uuencode },
|
||||
{ ARCHIVE_FILTER_XZ, archive_write_add_filter_xz },
|
||||
{ ARCHIVE_FILTER_ZSTD, archive_write_add_filter_zstd },
|
||||
{ -1, NULL }
|
||||
};
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue