1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-15 10:17:20 +00:00

MFhead@r324148

This commit is contained in:
Enji Cooper 2017-10-01 02:28:16 +00:00
commit d5db4328ad
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/projects/runtime-coverage/; revision=324149
87 changed files with 2290 additions and 325 deletions

View File

@ -180,10 +180,12 @@ build${libcompat}: .PHONY
.endfor
${_+_}cd ${.CURDIR}; \
${LIBCOMPATWMAKE} -f Makefile.inc1 -DNO_FSCHG libraries
.if ${libcompat} == "32" && !defined(NO_RTLD)
.if ${libcompat} == "32"
.for _t in ${_obj} all
.if !defined(NO_RTLD)
${_+_}cd ${.CURDIR}/libexec/rtld-elf; PROG=ld-elf32.so.1 ${LIBCOMPATWMAKE} \
-DNO_FSCHG DIRPRFX=libexec/rtld-elf/ ${_t}
.endif
${_+_}cd ${.CURDIR}/usr.bin/ldd; PROG=ldd32 ${LIBCOMPATWMAKE} \
DIRPRFX=usr.bin/ldd ${_t}
.endfor
@ -193,9 +195,11 @@ distribute${libcompat} install${libcompat}: .PHONY
.for _dir in ${_LC_LIBDIRS.yes}
${_+_}cd ${.CURDIR}/${_dir}; ${LIBCOMPATIMAKE} ${.TARGET:S/${libcompat}$//}
.endfor
.if ${libcompat} == "32" && !defined(NO_RTLD)
.if ${libcompat} == "32"
.if !defined(NO_RTLD)
${_+_}cd ${.CURDIR}/libexec/rtld-elf; \
PROG=ld-elf32.so.1 ${LIBCOMPATIMAKE} ${.TARGET:S/32$//}
.endif
${_+_}cd ${.CURDIR}/usr.bin/ldd; PROG=ldd32 ${LIBCOMPATIMAKE} \
${.TARGET:S/32$//}
.endif

View File

@ -1,6 +1,8 @@
# @(#)Makefile 8.1 (Berkeley) 6/6/93
# $FreeBSD$
.include <src.opts.mk>
PACKAGE=runtime
PROG= chflags

View File

@ -1,6 +1,8 @@
# @(#)Makefile 8.1 (Berkeley) 5/31/93
# $FreeBSD$
.include <src.opts.mk>
PACKAGE=runtime
PROG= mkdir

View File

@ -1,6 +1,8 @@
# @(#)Makefile 8.1 (Berkeley) 7/19/93
# $FreeBSD$
.include <src.opts.mk>
PACKAGE=rcmds
PROG= rcp
SRCS= rcp.c util.c

View File

@ -1,9 +1,10 @@
# @(#)Makefile 8.1 (Berkeley) 5/31/93
# $FreeBSD$
.include <src.opts.mk>
PACKAGE=runtime
PROG= rmdir
HAS_TESTS=
SUBDIR.${MK_TESTS}+= tests

View File

@ -0,0 +1,4 @@
begin 644 test_empty.zst
-*+4O_010`0``F>G840``
`
end

View File

@ -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");
}
}

View File

@ -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

View File

@ -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");
}
}

View File

@ -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.

View File

@ -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 }
};

View File

@ -269,6 +269,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 */
@ -546,6 +547,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;

View File

@ -111,7 +111,8 @@ enum {
OPTION_PRESERVE_OWNER,
OPTION_QUIET,
OPTION_UUENCODE,
OPTION_VERSION
OPTION_VERSION,
OPTION_ZSTD,
};
int cpio_getopt(struct cpio *cpio);

View File

@ -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

View File

@ -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");
}
}

View File

@ -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);
}

View File

@ -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
@ -433,6 +435,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 *);
@ -778,6 +781,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. */

View File

@ -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)

View File

@ -52,6 +52,17 @@
#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

View File

@ -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);

View File

@ -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,

View File

@ -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.

View File

@ -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

View File

@ -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 */

View File

@ -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

View File

@ -77,6 +77,8 @@ __FBSDID("$FreeBSD$");
#define MTREE_HASHTABLE_SIZE 1024
#define MAX_LINE_LEN (1024 * 1024)
struct mtree_option {
struct mtree_option *next;
char *value;
@ -334,6 +336,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)

View File

@ -1496,7 +1496,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. */

View File

@ -2243,7 +2243,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);
}

View File

@ -1040,6 +1040,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 +1057,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')
@ -2623,6 +2629,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 +2688,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;

View File

@ -723,6 +723,11 @@ process_extra(struct archive_read *a, const char *p, size_t extra_length, struct
}
case 0x9901:
/* WinZip AES extra data field. */
if (datasize < 6) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
"Incomplete AES field");
return ARCHIVE_FAILED;
}
if (p[offset + 2] == 'A' && p[offset + 3] == 'E') {
/* Vendor version. */
zip_entry->aes_extra.vendor =

View File

@ -214,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);

View File

@ -45,6 +45,9 @@ __FBSDID("$FreeBSD$");
#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
}

View File

@ -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

View File

@ -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 }
};

View File

@ -57,6 +57,7 @@ struct { const char *name; int (*setter)(struct archive *); } names[] =
{ "lzop", archive_write_add_filter_lzop },
{ "uuencode", archive_write_add_filter_uuencode },
{ "xz", archive_write_add_filter_xz },
{ "zstd", archive_write_add_filter_zstd },
{ NULL, NULL }
};

View File

@ -0,0 +1,335 @@
/*-
* 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 "archive_platform.h"
__FBSDID("$FreeBSD$");
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#ifdef HAVE_ZSTD_H
#include <zstd.h>
#endif
#include "archive.h"
#include "archive_private.h"
#include "archive_string.h"
#include "archive_write_private.h"
/* Don't compile this if we don't have zstd.h */
struct private_data {
int compression_level;
#if HAVE_ZSTD_H && HAVE_LIBZSTD
ZSTD_CStream *cstream;
int64_t total_in;
ZSTD_outBuffer out;
#else
struct archive_write_program_data *pdata;
#endif
};
static int archive_compressor_zstd_options(struct archive_write_filter *,
const char *, const char *);
static int archive_compressor_zstd_open(struct archive_write_filter *);
static int archive_compressor_zstd_write(struct archive_write_filter *,
const void *, size_t);
static int archive_compressor_zstd_close(struct archive_write_filter *);
static int archive_compressor_zstd_free(struct archive_write_filter *);
#if HAVE_ZSTD_H && HAVE_LIBZSTD
static int drive_compressor(struct archive_write_filter *,
struct private_data *, int, const void *, size_t);
#endif
/*
* Add a zstd compression filter to this write handle.
*/
int
archive_write_add_filter_zstd(struct archive *_a)
{
struct archive_write *a = (struct archive_write *)_a;
struct archive_write_filter *f = __archive_write_allocate_filter(_a);
struct private_data *data;
archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC,
ARCHIVE_STATE_NEW, "archive_write_add_filter_zstd");
data = calloc(1, sizeof(*data));
if (data == NULL) {
archive_set_error(&a->archive, ENOMEM, "Out of memory");
return (ARCHIVE_FATAL);
}
f->data = data;
f->open = &archive_compressor_zstd_open;
f->options = &archive_compressor_zstd_options;
f->close = &archive_compressor_zstd_close;
f->free = &archive_compressor_zstd_free;
f->code = ARCHIVE_FILTER_ZSTD;
f->name = "zstd";
data->compression_level = 3; /* Default level used by the zstd CLI */
#if HAVE_ZSTD_H && HAVE_LIBZSTD
data->cstream = ZSTD_createCStream();
if (data->cstream == NULL) {
free(data);
archive_set_error(&a->archive, ENOMEM,
"Failed to allocate zstd compressor object");
return (ARCHIVE_FATAL);
}
return (ARCHIVE_OK);
#else
data->pdata = __archive_write_program_allocate("zstd");
if (data->pdata == NULL) {
free(data);
archive_set_error(&a->archive, ENOMEM, "Out of memory");
return (ARCHIVE_FATAL);
}
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Using external zstd program");
return (ARCHIVE_WARN);
#endif
}
static int
archive_compressor_zstd_free(struct archive_write_filter *f)
{
struct private_data *data = (struct private_data *)f->data;
#if HAVE_ZSTD_H && HAVE_LIBZSTD
ZSTD_freeCStream(data->cstream);
free(data->out.dst);
#else
__archive_write_program_free(data->pdata);
#endif
free(data);
f->data = NULL;
return (ARCHIVE_OK);
}
/*
* Set write options.
*/
static int
archive_compressor_zstd_options(struct archive_write_filter *f, const char *key,
const char *value)
{
struct private_data *data = (struct private_data *)f->data;
if (strcmp(key, "compression-level") == 0) {
int level = atoi(value);
#if HAVE_ZSTD_H && HAVE_LIBZSTD
if (level < 1 || level > ZSTD_maxCLevel()) {
#else
/* If we don't have the library, hard-code the max level */
if (level < 1 || level > 22) {
#endif
return (ARCHIVE_WARN);
}
data->compression_level = level;
return (ARCHIVE_OK);
}
/* Note: The "warn" return is just to inform the options
* supervisor that we didn't handle it. It will generate
* a suitable error if no one used this option. */
return (ARCHIVE_WARN);
}
#if HAVE_ZSTD_H && HAVE_LIBZSTD
/*
* Setup callback.
*/
static int
archive_compressor_zstd_open(struct archive_write_filter *f)
{
struct private_data *data = (struct private_data *)f->data;
int ret;
ret = __archive_write_open_filter(f->next_filter);
if (ret != ARCHIVE_OK)
return (ret);
if (data->out.dst == NULL) {
size_t bs = ZSTD_CStreamOutSize(), bpb;
if (f->archive->magic == ARCHIVE_WRITE_MAGIC) {
/* Buffer size should be a multiple number of
* the of bytes per block for performance. */
bpb = archive_write_get_bytes_per_block(f->archive);
if (bpb > bs)
bs = bpb;
else if (bpb != 0)
bs -= bs % bpb;
}
data->out.size = bs;
data->out.pos = 0;
data->out.dst
= (unsigned char *)malloc(data->out.size);
if (data->out.dst == NULL) {
archive_set_error(f->archive, ENOMEM,
"Can't allocate data for compression buffer");
return (ARCHIVE_FATAL);
}
}
f->write = archive_compressor_zstd_write;
if (ZSTD_isError(ZSTD_initCStream(data->cstream,
data->compression_level))) {
archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
"Internal error initializing zstd compressor object");
return (ARCHIVE_FATAL);
}
return (ARCHIVE_OK);
}
/*
* Write data to the compressed stream.
*/
static int
archive_compressor_zstd_write(struct archive_write_filter *f, const void *buff,
size_t length)
{
struct private_data *data = (struct private_data *)f->data;
int ret;
/* Update statistics */
data->total_in += length;
if ((ret = drive_compressor(f, data, 0, buff, length)) != ARCHIVE_OK)
return (ret);
return (ARCHIVE_OK);
}
/*
* Finish the compression...
*/
static int
archive_compressor_zstd_close(struct archive_write_filter *f)
{
struct private_data *data = (struct private_data *)f->data;
int r1, r2;
/* Finish zstd frame */
r1 = drive_compressor(f, data, 1, NULL, 0);
r2 = __archive_write_close_filter(f->next_filter);
return r1 < r2 ? r1 : r2;
}
/*
* Utility function to push input data through compressor,
* writing full output blocks as necessary.
*
* Note that this handles both the regular write case (finishing ==
* false) and the end-of-archive case (finishing == true).
*/
static int
drive_compressor(struct archive_write_filter *f,
struct private_data *data, int finishing, const void *src, size_t length)
{
ZSTD_inBuffer in = (ZSTD_inBuffer) { src, length, 0 };
for (;;) {
if (data->out.pos == data->out.size) {
const int ret = __archive_write_filter(f->next_filter,
data->out.dst, data->out.size);
if (ret != ARCHIVE_OK)
return (ARCHIVE_FATAL);
data->out.pos = 0;
}
/* If there's nothing to do, we're done. */
if (!finishing && in.pos == in.size)
return (ARCHIVE_OK);
{
const size_t zstdret = !finishing ?
ZSTD_compressStream(data->cstream, &data->out, &in)
: ZSTD_endStream(data->cstream, &data->out);
if (ZSTD_isError(zstdret)) {
archive_set_error(f->archive,
ARCHIVE_ERRNO_MISC,
"Zstd compression failed: %s",
ZSTD_getErrorName(zstdret));
return (ARCHIVE_FATAL);
}
/* If we're finishing, 0 means nothing left to flush */
if (finishing && zstdret == 0) {
const int ret = __archive_write_filter(f->next_filter,
data->out.dst, data->out.pos);
return (ret);
}
}
}
}
#else /* HAVE_ZSTD_H && HAVE_LIBZSTD */
static int
archive_compressor_zstd_open(struct archive_write_filter *f)
{
struct private_data *data = (struct private_data *)f->data;
struct archive_string as;
int r;
archive_string_init(&as);
archive_string_sprintf(&as, "zstd -%d", data->compression_level);
f->write = archive_compressor_zstd_write;
r = __archive_write_program_open(f, data->pdata, as.s);
archive_string_free(&as);
return (r);
}
static int
archive_compressor_zstd_write(struct archive_write_filter *f, const void *buff,
size_t length)
{
struct private_data *data = (struct private_data *)f->data;
return __archive_write_program_write(f, data->pdata, buff, length);
}
static int
archive_compressor_zstd_close(struct archive_write_filter *f)
{
struct private_data *data = (struct private_data *)f->data;
return __archive_write_program_close(f, data->pdata);
}
#endif /* HAVE_ZSTD_H && HAVE_LIBZSTD */

View File

@ -42,7 +42,8 @@
.Nm archive_write_add_filter_none ,
.Nm archive_write_add_filter_program ,
.Nm archive_write_add_filter_uuencode ,
.Nm archive_write_add_filter_xz
.Nm archive_write_add_filter_xz ,
.Nm archive_write_add_filter_zstd ,
.Nd functions enabling output filters
.Sh LIBRARY
Streaming Archive Library (libarchive, -larchive)
@ -76,6 +77,8 @@ Streaming Archive Library (libarchive, -larchive)
.Fn archive_write_add_filter_uuencode "struct archive *"
.Ft int
.Fn archive_write_add_filter_xz "struct archive *"
.Ft int
.Fn archive_write_add_filter_zstd "struct archive *"
.Sh DESCRIPTION
.Bl -tag -width indent
.It Xo
@ -89,6 +92,7 @@ Streaming Archive Library (libarchive, -larchive)
.Fn archive_write_add_filter_lzma ,
.Fn archive_write_add_filter_lzop ,
.Fn archive_write_add_filter_xz ,
.Fn archive_write_add_filter_zstd ,
.Xc
The resulting archive will be compressed as specified.
Note that the compressed output is always properly blocked.

View File

@ -1654,7 +1654,7 @@ build_pax_attribute_name(char *dest, const char *src)
* GNU PAX Format 1.0 requires the special name, which pattern is:
* <dir>/GNUSparseFile.<pid>/<original file name>
*
* Since reproducable archives are more important, use 0 as pid.
* Since reproducible archives are more important, use 0 as pid.
*
* This function is used for only Sparse file, a file type of which
* is regular file.

View File

@ -207,3 +207,8 @@ DEFINE_TEST(test_archive_write_add_filter_by_name_xz)
{
test_filter_by_name("xz", ARCHIVE_FILTER_XZ, cannot);
}
DEFINE_TEST(test_archive_write_add_filter_by_name_zstd)
{
test_filter_by_name("zstd", ARCHIVE_FILTER_ZSTD, canZstd);
}

View File

@ -0,0 +1,82 @@
/*-
* 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$");
/*
* Verify our ability to read sample files compatibly with 'zstd -d'.
*
* In particular:
* * zstd -d will read multiple zstd streams, concatenating the output
* * zstd -d will skip over zstd skippable frames
*/
static void
compat_zstd(const char *name)
{
const char *n[7] = { "f1", "f2", "f3", "d1/f1", "d1/f2", "d1/f3", NULL };
struct archive_entry *ae;
struct archive *a;
int i, r;
assert((a = archive_read_new()) != NULL);
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
r = archive_read_support_filter_zstd(a);
if (r == ARCHIVE_WARN) {
skipping("zstd reading not fully supported on this platform");
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
return;
}
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
extract_reference_file(name);
assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, name, 2));
/* Read entries, match up names with list above. */
for (i = 0; i < 6; ++i) {
failure("Could not read file %d (%s) from %s", i, n[i], name);
assertEqualIntA(a, ARCHIVE_OK,
archive_read_next_header(a, &ae));
assertEqualString(n[i], archive_entry_pathname(ae));
}
/* Verify the end-of-archive. */
assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
/* Verify that the format detection worked. */
assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_ZSTD);
assertEqualString(archive_filter_name(a, 0), "zstd");
assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR);
assertEqualInt(ARCHIVE_OK, archive_read_close(a));
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
}
DEFINE_TEST(test_compat_zstd)
{
/* This sample was compressed as 3 separate streams with a zstd skippable
* frame placed in the middle */
compat_zstd("test_compat_zstd_1.tar.zst");
}

View File

@ -0,0 +1,12 @@
begin 644 test_compat_zstd_1.tar.zst
M*+4O_010)0,`HL0.%;`Q&>>\/$2[#IQF[<1+Z3T<0CX]!77&0@R.6+/F,0+I
M.$1A$QE2`J!+*_6[_YT9_W_M1KC-EG*V>10.`,M`%3*@#F#\`-FT#J:1#U1"
M`H1!&R#<!.<"@#3@M58XY1,8`DMMD\@HM2_]!%!=`P`B!1`5H#D!0!.SELJ"
M5#509I*T/YQ^]?H/3T1D>A5\*'"JYIJ;C&4=B2CL(L)*E-IJT/RV?.:A_]_N
MB&[7SDG;/=4&#P";0!5D0`=8T0&R&19,)1^HA`0(@S9`N`G.!0!IP&NM<,K!
M-#8!%A]U]K10*DT8!`````$"`P0HM2_]!%!]`P`B11`6H+$)"%]@,Z6OH`"L
MM$R2MAN&*MSG`W?OJ7+4P*B::VXR`NM(1&$7&58"J*U'_&V^S$/_O]U1N%T[
M)VW7J'+4!A``_4$%^T`],J`8P.0!L@D63"4?J(0$"(,V0+@)S@4`:<!KK7!J
)P51V`E@!9CD#
`
end

View File

@ -412,6 +412,12 @@ DEFINE_TEST(test_fuzz_tar)
"test_compat_lzop_1.tar.lzo",
NULL
};
#endif
#if HAVE_ZSTD_H && HAVE_LIBZSTD
static const char *fileset10[] = {
"test_compat_zstd_1.tar.zst",
NULL
};
#endif
static const struct files filesets[] = {
{0, fileset1}, /* Exercise bzip2 decompressor. */
@ -425,6 +431,9 @@ DEFINE_TEST(test_fuzz_tar)
{0, fileset8},
#if HAVE_LIBLZO2 && HAVE_LZO_LZO1X_H && HAVE_LZO_LZOCONF_H
{0, fileset9}, /* Exercise lzo decompressor. */
#endif
#if HAVE_ZSTD_H && HAVE_LIBZSTD
{0, fileset10}, /* Excercise zstd decompressor. */
#endif
{1, NULL}
};

View File

@ -0,0 +1,201 @@
/*-
* 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
* in this position and unchanged.
* 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_write_filter_zstd)
{
struct archive_entry *ae;
struct archive *a;
char *buff, *data;
size_t buffsize, datasize;
char path[16];
size_t used1, used2;
int i, r;
buffsize = 2000000;
assert(NULL != (buff = (char *)malloc(buffsize)));
if (buff == NULL)
return;
datasize = 10000;
assert(NULL != (data = (char *)malloc(datasize)));
if (data == NULL) {
free(buff);
return;
}
memset(data, 0, datasize);
/*
* Write a 100 files and read them all back.
*/
assert((a = archive_write_new()) != NULL);
assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a));
r = archive_write_add_filter_zstd(a);
if (r != ARCHIVE_OK) {
skipping("zstd writing not supported on this platform");
assertEqualInt(ARCHIVE_OK, archive_write_free(a));
free(buff);
free(data);
return;
}
assertEqualIntA(a, ARCHIVE_OK,
archive_write_set_bytes_per_block(a, 10));
assertEqualInt(ARCHIVE_FILTER_ZSTD, archive_filter_code(a, 0));
assertEqualString("zstd", archive_filter_name(a, 0));
assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, buffsize, &used1));
assertEqualInt(ARCHIVE_FILTER_ZSTD, archive_filter_code(a, 0));
assertEqualString("zstd", archive_filter_name(a, 0));
assert((ae = archive_entry_new()) != NULL);
archive_entry_set_filetype(ae, AE_IFREG);
archive_entry_set_size(ae, datasize);
for (i = 0; i < 100; i++) {
sprintf(path, "file%03d", i);
archive_entry_copy_pathname(ae, path);
assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
assertA(datasize
== (size_t)archive_write_data(a, data, datasize));
}
archive_entry_free(ae);
assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a));
assertEqualInt(ARCHIVE_OK, archive_write_free(a));
assert((a = archive_read_new()) != NULL);
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
r = archive_read_support_filter_zstd(a);
if (r == ARCHIVE_WARN) {
skipping("Can't verify zstd writing by reading back;"
" zstd reading not fully supported on this platform");
} else {
assertEqualIntA(a, ARCHIVE_OK,
archive_read_support_filter_all(a));
assertEqualIntA(a, ARCHIVE_OK,
archive_read_open_memory(a, buff, used1));
for (i = 0; i < 100; i++) {
sprintf(path, "file%03d", i);
if (!assertEqualInt(ARCHIVE_OK,
archive_read_next_header(a, &ae)))
break;
assertEqualString(path, archive_entry_pathname(ae));
assertEqualInt((int)datasize, archive_entry_size(ae));
}
assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
}
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
/*
* Repeat the cycle again, this time setting some compression
* options.
*/
assert((a = archive_write_new()) != NULL);
assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a));
assertEqualIntA(a, ARCHIVE_OK,
archive_write_set_bytes_per_block(a, 10));
assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_zstd(a));
assertEqualIntA(a, ARCHIVE_FAILED,
archive_write_set_filter_option(a, NULL, "nonexistent-option", "0"));
assertEqualIntA(a, ARCHIVE_FAILED,
archive_write_set_filter_option(a, NULL, "compression-level", "abc"));
assertEqualIntA(a, ARCHIVE_FAILED,
archive_write_set_filter_option(a, NULL, "compression-level", "25")); /* too big */
assertEqualIntA(a, ARCHIVE_OK,
archive_write_set_filter_option(a, NULL, "compression-level", "9"));
assertEqualIntA(a, ARCHIVE_OK,
archive_write_set_filter_option(a, NULL, "compression-level", "15"));
assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, buffsize, &used2));
for (i = 0; i < 100; i++) {
sprintf(path, "file%03d", i);
assert((ae = archive_entry_new()) != NULL);
archive_entry_copy_pathname(ae, path);
archive_entry_set_size(ae, datasize);
archive_entry_set_filetype(ae, AE_IFREG);
assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
assertA(datasize == (size_t)archive_write_data(a, data, datasize));
archive_entry_free(ae);
}
assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a));
assertEqualInt(ARCHIVE_OK, archive_write_free(a));
failure("compression-level=15 wrote %d bytes, default wrote %d bytes",
(int)used2, (int)used1);
assert(used2 < used1);
assert((a = archive_read_new()) != NULL);
assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
r = archive_read_support_filter_zstd(a);
if (r == ARCHIVE_WARN) {
skipping("zstd reading not fully supported on this platform");
} else {
assertEqualIntA(a, ARCHIVE_OK,
archive_read_support_filter_all(a));
assertEqualIntA(a, ARCHIVE_OK,
archive_read_open_memory(a, buff, used2));
for (i = 0; i < 100; i++) {
sprintf(path, "file%03d", i);
failure("Trying to read %s", path);
if (!assertEqualIntA(a, ARCHIVE_OK,
archive_read_next_header(a, &ae)))
break;
assertEqualString(path, archive_entry_pathname(ae));
assertEqualInt((int)datasize, archive_entry_size(ae));
}
assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
}
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
/*
* Test various premature shutdown scenarios to make sure we
* don't crash or leak memory.
*/
assert((a = archive_write_new()) != NULL);
assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_zstd(a));
assertEqualInt(ARCHIVE_OK, archive_write_free(a));
assert((a = archive_write_new()) != NULL);
assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_zstd(a));
assertEqualInt(ARCHIVE_OK, archive_write_close(a));
assertEqualInt(ARCHIVE_OK, archive_write_free(a));
assert((a = archive_write_new()) != NULL);
assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a));
assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_zstd(a));
assertEqualInt(ARCHIVE_OK, archive_write_close(a));
assertEqualInt(ARCHIVE_OK, archive_write_free(a));
assert((a = archive_write_new()) != NULL);
assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_ustar(a));
assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_zstd(a));
assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, buffsize, &used2));
assertEqualInt(ARCHIVE_OK, archive_write_close(a));
assertEqualInt(ARCHIVE_OK, archive_write_free(a));
/*
* Clean up.
*/
free(data);
free(buff);
}

View File

@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd February 25, 2017
.Dd October 1, 2017
.Dt TAR 1
.Os
.Sh NAME
@ -302,19 +302,18 @@ containing the string
Compress the resulting archive with
.Xr xz 1 .
In extract or list modes, this option is ignored.
Note that, unlike other
Note that this
.Nm tar
implementations, this implementation recognizes XZ compression
automatically when reading archives.
implementation recognizes XZ compression automatically when reading archives.
.It Fl j , Fl Fl bzip , Fl Fl bzip2 , Fl Fl bunzip2
(c mode only)
Compress the resulting archive with
.Xr bzip2 1 .
In extract or list modes, this option is ignored.
Note that, unlike other
Note that this
.Nm tar
implementations, this implementation recognizes bzip2 compression
automatically when reading archives.
implementation recognizes bzip2 compression automatically when reading
archives.
.It Fl k , Fl Fl keep-old-files
(x mode only)
Do not overwrite existing files.
@ -337,25 +336,41 @@ Issue a warning message unless all links to each file are archived.
Compress the resulting archive with
.Xr lrzip 1 .
In extract or list modes, this option is ignored.
Note that this
.Nm tar
implementation recognizes lrzip compression automatically when reading
archives.
.It Fl Fl lz4
(c mode only)
Compress the archive with lz4-compatible compression before writing it.
In input mode, this option is ignored; lz4 compression is recognized
automatically on input.
In extract or list modes, this option is ignored.
Note that this
.Nm tar
implementation recognizes lz4 compression automatically when reading archives.
.It Fl Fl zstd
(c mode only)
Compress the archive with zstd-compatible compression before writing it.
In extract or list modes, this option is ignored.
Note that this
.Nm tar
implementation recognizes zstd compression automatically when reading archives.
.It Fl Fl lzma
(c mode only) Compress the resulting archive with the original LZMA algorithm.
In extract or list modes, this option is ignored.
Use of this option is discouraged and new archives should be created with
.Fl Fl xz
instead.
Note that, unlike other
Note that this
.Nm tar
implementations, this implementation recognizes LZMA compression
automatically when reading archives.
implementation recognizes LZMA compression automatically when reading archives.
.It Fl Fl lzop
(c mode only)
Compress the resulting archive with
.Xr lzop 1 .
In extract or list modes, this option is ignored.
Note that this
.Nm tar
implementation recognizes LZO compression automatically when reading archives.
.It Fl m , Fl Fl modification-time
(x mode only)
Do not extract modification time.
@ -577,6 +592,8 @@ A decimal integer from 4 to 7 specifying the lz4 compression block size
.It Cm lz4:block-dependence
Use the previous block of the block being compressed for
a compression dictionary to improve compression ratio.
.It Cm zstd:compression-level
A decimal integer from 1 to 22 specifying the zstd compression level.
.It Cm lzop:compression-level
A decimal integer from 1 to 9 specifying the lzop compression level.
.It Cm xz:compression-level
@ -826,28 +843,28 @@ is run in x mode as root.
Compress the resulting archive with
.Xr bzip2 1 .
In extract or list modes, this option is ignored.
Note that, unlike other
Note that this
.Nm tar
implementations, this implementation recognizes bzip2 compression
automatically when reading archives.
implementation recognizes bzip2 compression automatically when reading
archives.
.It Fl Z , Fl Fl compress , Fl Fl uncompress
(c mode only)
Compress the resulting archive with
.Xr compress 1 .
In extract or list modes, this option is ignored.
Note that, unlike other
Note that this
.Nm tar
implementations, this implementation recognizes compress compression
automatically when reading archives.
implementation recognizes compress compression automatically when reading
archives.
.It Fl z , Fl Fl gunzip , Fl Fl gzip
(c mode only)
Compress the resulting archive with
.Xr gzip 1 .
In extract or list modes, this option is ignored.
Note that, unlike other
Note that this
.Nm tar
implementations, this implementation recognizes gzip compression
automatically when reading archives.
implementation recognizes gzip compression automatically when reading
archives.
.El
.Sh ENVIRONMENT
The following environment variables affect the execution of

View File

@ -419,6 +419,7 @@ main(int argc, char **argv)
case OPTION_LZIP: /* GNU tar beginning with 1.23 */
case OPTION_LZMA: /* GNU tar beginning with 1.20 */
case OPTION_LZOP: /* GNU tar beginning with 1.21 */
case OPTION_ZSTD:
if (compression != '\0')
lafe_errc(1, 0,
"Can't specify both -%c and -%c", opt,
@ -427,9 +428,10 @@ main(int argc, char **argv)
switch (opt) {
case OPTION_LRZIP: compression_name = "lrzip"; break;
case OPTION_LZ4: compression_name = "lz4"; break;
case OPTION_LZIP: compression_name = "lzip"; break;
case OPTION_LZMA: compression_name = "lzma"; break;
case OPTION_LZOP: compression_name = "lzop"; break;
case OPTION_LZIP: compression_name = "lzip"; break;
case OPTION_LZMA: compression_name = "lzma"; break;
case OPTION_LZOP: compression_name = "lzop"; break;
case OPTION_ZSTD: compression_name = "zstd"; break;
}
break;
case 'm': /* SUSv2 */

View File

@ -181,7 +181,8 @@ enum {
OPTION_USE_COMPRESS_PROGRAM,
OPTION_UUENCODE,
OPTION_VERSION,
OPTION_XATTRS
OPTION_XATTRS,
OPTION_ZSTD,
};
int bsdtar_getopt(struct bsdtar *);

View File

@ -160,6 +160,7 @@ static const struct bsdtar_option {
{ "version", 0, OPTION_VERSION },
{ "xattrs", 0, OPTION_XATTRS },
{ "xz", 0, 'J' },
{ "zstd", 0, OPTION_ZSTD },
{ NULL, 0, 0 }
};

View File

@ -80,9 +80,10 @@ get_filter_code(const char *suffix)
{ ".lzma", "lzma" },
{ ".uu", "uuencode" },
{ ".xz", "xz" },
{ ".zst", "zstd"},
{ NULL, NULL }
};
return get_suffix_code(filters, suffix);
}
@ -121,6 +122,7 @@ decompose_alias(const char *suffix)
{ ".tzo", ".tar.lzo" },
{ ".taZ", ".tar.Z" },
{ ".tZ", ".tar.Z" },
{ ".tzst", ".tar.zst" },
{ NULL, NULL }
};

View File

@ -0,0 +1,6 @@
begin 644 test_extract.tar.zst
M*+4O_010S0,`<L40$Z`5.(2U_RNV_[]L4V;Z_/R@1:7Y$3;9E`8$D$WI:W1)
M'58'D3->Y+>!0*5E/PM"$7^K^1VI3SS-AX&_W0KQWY!-Z1(`_4$%[$"]<T!A
L(*`#I!DXC4[J!6J8$!DJ$D"9$T*L]#G-$$/A`#`I`-(`UUKAU$Z@"`UXII``
`
end

View File

@ -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_tar_zstd)
{
const char *reffile = "test_extract.tar.zst";
int f;
extract_reference_file(reffile);
f = systemf("%s -tf %s >test.out 2>test.err", testprog, reffile);
if (f == 0 || canZstd()) {
assertEqualInt(0, systemf("%s -xf %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");
assertEmptyFile("test.err");
} else {
skipping("It seems zstd is not supported on this platform");
}
}

View File

@ -483,7 +483,7 @@ DEFINE_TEST(test_option_acls)
r = compare_acls("f", "acls_acls/f");
assertEqualInt(r, 1);
/* Extractl acls without acls */
/* Extract acls without acls */
assertMakeDir("acls_noacls", 0755);
clear_inheritance_flags("acls_noacls", acltype);
r = systemf("%s -x -C acls_noacls -p --no-acls -f acls.tar >acls_noacls.out 2>acls_noacls.err", testprog);

View File

@ -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 lz4 compression. */
r = systemf("%s -cf - --zstd f >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 bsdtar 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 bsdtar 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 bsdtar 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 lz4 signature. */
p = slurpfile(&s, "archive.out");
assert(s > 2);
assertEqualMem(p, "\x28\xb5\x2f\xfd", 4);
done:
free(p);
}

View File

@ -329,6 +329,9 @@ int canLrzip(void);
/* Return true if this platform can run the "lz4" program. */
int canLz4(void);
/* Return true if this platform can run the "zstd" program. */
int canZstd(void);
/* Return true if this platform can run the "lzip" program. */
int canLzip(void);

View File

@ -2318,6 +2318,21 @@ canLz4(void)
return (value);
}
/*
* Can this platform run the zstd program?
*/
int
canZstd(void)
{
static int tested = 0, value = 0;
if (!tested) {
tested = 1;
if (systemf("zstd -V %s", redirectArgs) == 0)
value = 1;
}
return (value);
}
/*
* Can this platform run the lzip program?
*/

View File

@ -53,6 +53,7 @@ tmpmfs_flags="-S" # Extra mdmfs options for the mfs /tmp
varmfs="AUTO" # Set to YES to always create an mfs /var, NO to never
varsize="32m" # Size of mfs /var if created
varmfs_flags="-S" # Extra mount options for the mfs /var
mfs_type="auto" # "md", "tmpfs", "auto" to prefer tmpfs with md as fallback
populate_var="AUTO" # Set to YES to always (re)populate /var, NO to never
cleanvar_enable="YES" # Clean the /var directory
local_startup="/usr/local/etc/rc.d" # startup script dirs.

View File

@ -195,10 +195,11 @@ handle_remount() { # $1 = mount point
to_umount="$b ${to_umount}"
}
# Create a generic memory disk (using tmpfs)
#
# Create a generic memory disk.
# The 'auto' parameter will attempt to use tmpfs(5), falls back to md(4).
# $1 is size in 512-byte sectors, $2 is the mount point.
mount_md() {
mount -t tmpfs -o size=$(($1 * 512)) tmpfs $2
/sbin/mdmfs -s $1 auto $2
}
# Create the memory filesystem if it has not already been created

View File

@ -1790,7 +1790,7 @@ mount_md()
if [ -n "$3" ]; then
flags="$3"
fi
/sbin/mdmfs $flags -s $1 md $2
/sbin/mdmfs $flags -s $1 ${mfs_type} $2
}
# Code common to scripts that need to load a kernel module

View File

@ -94,6 +94,7 @@ SRCS= archive_acl.c \
archive_read_support_filter_rpm.c \
archive_read_support_filter_uu.c \
archive_read_support_filter_xz.c \
archive_read_support_filter_zstd.c \
archive_read_support_format_7zip.c \
archive_read_support_format_all.c \
archive_read_support_format_ar.c \
@ -136,6 +137,7 @@ SRCS= archive_acl.c \
archive_write_add_filter_program.c \
archive_write_add_filter_uuencode.c \
archive_write_add_filter_xz.c \
archive_write_add_filter_zstd.c \
archive_write_set_format.c \
archive_write_set_format_7zip.c \
archive_write_set_format_ar.c \

View File

@ -83,6 +83,7 @@ TESTS_SRCS= \
test_compat_uudecode_large.c \
test_compat_xz.c \
test_compat_zip.c \
test_compat_zstd.c \
test_empty_write.c \
test_entry.c \
test_entry_strmode.c \
@ -240,6 +241,7 @@ TESTS_SRCS= \
test_write_filter_program.c \
test_write_filter_uuencode.c \
test_write_filter_xz.c \
test_write_filter_zstd.c \
test_write_format_7zip.c \
test_write_format_7zip_empty.c \
test_write_format_7zip_large.c \
@ -373,6 +375,7 @@ ${PACKAGE}FILES+= test_compat_zip_4.zip.uu
${PACKAGE}FILES+= test_compat_zip_5.zip.uu
${PACKAGE}FILES+= test_compat_zip_6.zip.uu
${PACKAGE}FILES+= test_compat_zip_7.xps.uu
${PACKAGE}FILES+= test_compat_zstd_1.tar.zst.uu
${PACKAGE}FILES+= test_fuzz.cab.uu
${PACKAGE}FILES+= test_fuzz.lzh.uu
${PACKAGE}FILES+= test_fuzz_1.iso.Z.uu

View File

@ -125,8 +125,7 @@ __collate_load_tables_l(const char *encoding, struct xlocale_collate *table)
return (_LDP_CACHE);
}
asprintf(&buf, "%s/%s/LC_COLLATE", _PathLocale, encoding);
if (buf == NULL)
if (asprintf(&buf, "%s/%s/LC_COLLATE", _PathLocale, encoding) == -1)
return (_LDP_ERROR);
if ((fd = _open(buf, O_RDONLY)) < 0) {

View File

@ -110,9 +110,8 @@ __setrunelocale(struct xlocale_ctype *l, const char *encoding)
}
/* Range checking not needed, encoding length already checked before */
asprintf(&path, "%s/%s/LC_CTYPE", _PathLocale, encoding);
if (path == NULL)
return (0);
if (asprintf(&path, "%s/%s/LC_CTYPE", _PathLocale, encoding) == -1)
return (errno);
if ((rl = _Read_RuneMagi(path)) == NULL) {
free(path);

View File

@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd September 9, 2016
.Dd September 9, 2017
.Dt MDMFS 8
.Os
.Sh NAME
@ -33,7 +33,9 @@
.Nm mount_mfs
.Nd configure and mount an in-memory file system using the
.Xr md 4
driver
driver or the
.Xr tmpfs 5
filesystem
.Sh SYNOPSIS
.Nm
.Op Fl DLlMNnPStTUX
@ -63,9 +65,13 @@ utility is designed to be a work-alike and look-alike of the deprecated
.Xr mount_mfs 8 .
The end result is essentially the same,
but is accomplished in a completely different way.
The
Based on
.Ar md-device ,
the
.Nm
utility configures an
utility either creates a
.Xr tmpfs 5
filesystem, or it configures an
.Xr md 4
disk using
.Xr mdconfig 8 ,
@ -81,6 +87,44 @@ compressed disk images, as long as the kernel supports this GEOM class.
All the command line options are passed to the appropriate program
at the appropriate stage in order to achieve the desired effect.
.Pp
When
.Ar md-device
is `auto',
.Nm
uses
.Xr tmpfs 5
if it is present in the kernel or can be loaded as a module,
otherwise it falls back to using
.Xr md 4
auto-unit as if `md' had been specified.
.Pp
When
.Ar md-device
is `tmpfs',
.Nm
mounts a
.Xr tmpfs 5
filesystem, translating the
.Fl s
size option, if present, into a `-o size=' mount option.
Any
.Fl o
options on the command line are passed through to the
.Xr tmpfs 5
mount.
Options specific to
.Xr mdconfig 8
or
.Xr newfs 8
are ignored.
.Pp
When
.Ar md-device
does not result in
.Xr tmpfs 5
being used, then an
.Xr md 4
device is configured instead.
By default,
.Nm
creates a swap-based
@ -219,14 +263,10 @@ is
.Em not
specified.
That is,
this will work for the default swap-backed
.Pq Dv MD_SWAP
disks,
and the optional
.Pq Fl M
.Xr malloc 9
backed disks
.Pq Dv MD_MALLOC .
this will work when the backing storage is some form of
memory, as opposed to a fixed-size file.
The size may include the usual SI suffixes (k, m, g, t, p).
A number without a suffix is interpreted as a count of 512-byte sectors.
.It Fl t
Turn on the TRIM enable flag for
.Xr newfs 8 .
@ -392,6 +432,7 @@ was given on the command line.
.Sh SEE ALSO
.Xr md 4 ,
.Xr fstab 5 ,
.Xr tmpfs 5 ,
.Xr mdconfig 8 ,
.Xr mount 8 ,
.Xr newfs 8

View File

@ -34,15 +34,19 @@
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/linker.h>
#include <sys/mdioctl.h>
#include <sys/module.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <assert.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <grp.h>
#include <inttypes.h>
#include <paths.h>
#include <pwd.h>
#include <stdarg.h>
@ -78,7 +82,8 @@ static void debugprintf(const char *, ...) __printflike(1, 2);
static void do_mdconfig_attach(const char *, const enum md_types);
static void do_mdconfig_attach_au(const char *, const enum md_types);
static void do_mdconfig_detach(void);
static void do_mount(const char *, const char *);
static void do_mount_md(const char *, const char *);
static void do_mount_tmpfs(const char *, const char *);
static void do_mtptsetup(const char *, struct mtpt_info *);
static void do_newfs(const char *);
static void extract_ugid(const char *, struct mtpt_info *);
@ -89,14 +94,15 @@ int
main(int argc, char **argv)
{
struct mtpt_info mi; /* Mountpoint info. */
intmax_t mdsize;
char *mdconfig_arg, *newfs_arg, /* Args to helper programs. */
*mount_arg;
enum md_types mdtype; /* The type of our memory disk. */
bool have_mdtype;
bool have_mdtype, mlmac;
bool detach, softdep, autounit, newfs;
char *mtpoint, *unitstr;
const char *mtpoint, *size_arg, *unitstr;
char *p;
int ch;
int ch, idx;
void *set;
unsigned long ul;
@ -105,11 +111,13 @@ main(int argc, char **argv)
detach = true;
softdep = true;
autounit = false;
mlmac = false;
newfs = true;
have_mdtype = false;
mdtype = MD_SWAP;
mdname = MD_NAME;
mdnamelen = strlen(mdname);
mdsize = 0;
/*
* Can't set these to NULL. They may be passed to the
* respective programs without modification. I.e., we may not
@ -119,6 +127,7 @@ main(int argc, char **argv)
mdconfig_arg = strdup("");
newfs_arg = strdup("");
mount_arg = strdup("");
size_arg = NULL;
/* If we were started as mount_mfs or mfs, imply -C. */
if (strcmp(getprogname(), "mount_mfs") == 0 ||
@ -175,6 +184,7 @@ main(int argc, char **argv)
loudsubs = true;
break;
case 'l':
mlmac = true;
argappend(&newfs_arg, "-l");
break;
case 'M':
@ -213,7 +223,7 @@ main(int argc, char **argv)
softdep = false;
break;
case 's':
argappend(&mdconfig_arg, "-s %s", optarg);
size_arg = optarg;
break;
case 't':
argappend(&newfs_arg, "-t");
@ -242,42 +252,107 @@ main(int argc, char **argv)
if (argc < 2)
usage();
/* Derive 'unit' (global). */
unitstr = argv[0];
if (strncmp(unitstr, "/dev/", 5) == 0)
unitstr += 5;
if (strncmp(unitstr, mdname, mdnamelen) == 0)
unitstr += mdnamelen;
if (!isdigit(*unitstr)) {
autounit = true;
unit = -1;
mdsuffix = unitstr;
} else {
ul = strtoul(unitstr, &p, 10);
if (ul == ULONG_MAX)
errx(1, "bad device unit: %s", unitstr);
unit = ul;
mdsuffix = p; /* can be empty */
/*
* Historically our size arg was passed directly to mdconfig, which
* treats a number without a suffix as a count of 512-byte sectors;
* tmpfs would treat it as a count of bytes. To get predictable
* behavior for 'auto' we document that the size always uses mdconfig
* rules. To make that work, decode the size here so it can be passed
* to either tmpfs or mdconfig as a count of bytes.
*/
if (size_arg != NULL) {
mdsize = (intmax_t)strtoumax(size_arg, &p, 0);
if (p == size_arg || (p[0] != 0 && p[1] != 0) || mdsize < 0)
errx(1, "invalid size '%s'", size_arg);
switch (*p) {
case 'p':
case 'P':
mdsize *= 1024;
case 't':
case 'T':
mdsize *= 1024;
case 'g':
case 'G':
mdsize *= 1024;
case 'm':
case 'M':
mdsize *= 1024;
case 'k':
case 'K':
mdsize *= 1024;
case 'b':
case 'B':
break;
case '\0':
mdsize *= 512;
break;
default:
errx(1, "invalid size suffix on '%s'", size_arg);
}
}
/*
* Based on the command line 'md-device' either mount a tmpfs filesystem
* or configure the md device then format and mount a filesystem on it.
* If the device is 'auto' use tmpfs if it is available and there is no
* request for multilabel MAC (which tmpfs does not support).
*/
unitstr = argv[0];
mtpoint = argv[1];
if (!have_mdtype)
mdtype = MD_SWAP;
if (softdep)
argappend(&newfs_arg, "-U");
if (mdtype != MD_VNODE && !newfs)
errx(1, "-P requires a vnode-backed disk");
/* Do the work. */
if (detach && !autounit)
do_mdconfig_detach();
if (autounit)
do_mdconfig_attach_au(mdconfig_arg, mdtype);
else
do_mdconfig_attach(mdconfig_arg, mdtype);
if (newfs)
do_newfs(newfs_arg);
do_mount(mount_arg, mtpoint);
if (strcmp(unitstr, "auto") == 0) {
if (mlmac)
idx = -1; /* Must use md for mlmac. */
else if ((idx = modfind("tmpfs")) == -1)
idx = kldload("tmpfs");
if (idx == -1)
unitstr = "md";
else
unitstr = "tmpfs";
}
if (strcmp(unitstr, "tmpfs") == 0) {
if (size_arg != NULL && mdsize != 0)
argappend(&mount_arg, "-o size=%jd", mdsize);
do_mount_tmpfs(mount_arg, mtpoint);
} else {
if (size_arg != NULL)
argappend(&mdconfig_arg, "-s %jdB", mdsize);
if (strncmp(unitstr, "/dev/", 5) == 0)
unitstr += 5;
if (strncmp(unitstr, mdname, mdnamelen) == 0)
unitstr += mdnamelen;
if (!isdigit(*unitstr)) {
autounit = true;
unit = -1;
mdsuffix = unitstr;
} else {
ul = strtoul(unitstr, &p, 10);
if (ul == ULONG_MAX)
errx(1, "bad device unit: %s", unitstr);
unit = ul;
mdsuffix = p; /* can be empty */
}
if (!have_mdtype)
mdtype = MD_SWAP;
if (softdep)
argappend(&newfs_arg, "-U");
if (mdtype != MD_VNODE && !newfs)
errx(1, "-P requires a vnode-backed disk");
/* Do the work. */
if (detach && !autounit)
do_mdconfig_detach();
if (autounit)
do_mdconfig_attach_au(mdconfig_arg, mdtype);
else
do_mdconfig_attach(mdconfig_arg, mdtype);
if (newfs)
do_newfs(newfs_arg);
do_mount_md(mount_arg, mtpoint);
}
do_mtptsetup(mtpoint, &mi);
return (0);
@ -434,7 +509,7 @@ do_mdconfig_detach(void)
* Mount the configured memory disk.
*/
static void
do_mount(const char *args, const char *mtpoint)
do_mount_md(const char *args, const char *mtpoint)
{
int rv;
@ -444,6 +519,19 @@ do_mount(const char *args, const char *mtpoint)
errx(1, "mount exited with error code %d", rv);
}
/*
* Mount the configured tmpfs.
*/
static void
do_mount_tmpfs(const char *args, const char *mtpoint)
{
int rv;
rv = run(NULL, "%s -t tmpfs %s tmp %s", _PATH_MOUNT, args, mtpoint);
if (rv)
errx(1, "tmpfs mount exited with error code %d", rv);
}
/*
* Various configuration of the mountpoint. Mostly, enact 'mip'.
*/

View File

@ -180,6 +180,7 @@ __DEFAULT_NO_OPTIONS = \
GNU_GREP_COMPAT \
HESIOD \
LIBSOFT \
LOADER_FORCE_LE \
NAND \
OFED \
OPENLDAP \

View File

@ -1041,10 +1041,10 @@ awg_ioctl(if_t ifp, u_long cmd, caddr_t data)
if_togglecapenable(ifp, IFCAP_RXCSUM);
if (mask & IFCAP_TXCSUM)
if_togglecapenable(ifp, IFCAP_TXCSUM);
if ((if_getcapenable(ifp) & (IFCAP_RXCSUM|IFCAP_TXCSUM)) != 0)
if_sethwassistbits(ifp, CSUM_IP, 0);
if ((if_getcapenable(ifp) & IFCAP_TXCSUM) != 0)
if_sethwassistbits(ifp, CSUM_IP | CSUM_UDP | CSUM_TCP, 0);
else
if_sethwassistbits(ifp, 0, CSUM_IP);
if_sethwassistbits(ifp, 0, CSUM_IP | CSUM_UDP | CSUM_TCP);
break;
default:
error = ether_ioctl(ifp, cmd, data);

View File

@ -115,9 +115,9 @@
#define EMAC_MII_DATA 0x4c
#define EMAC_ADDR_HIGH(n) (0x50 + (n) * 8)
#define EMAC_ADDR_LOW(n) (0x54 + (n) * 8)
#define EMAC_TX_DMA_STA 0x80
#define EMAC_TX_DMA_CUR_DESC 0x84
#define EMAC_TX_DMA_CUR_BUF 0x88
#define EMAC_TX_DMA_STA 0xb0
#define EMAC_TX_DMA_CUR_DESC 0xb4
#define EMAC_TX_DMA_CUR_BUF 0xb8
#define EMAC_RX_DMA_STA 0xc0
#define EMAC_RX_DMA_CUR_DESC 0xc4
#define EMAC_RX_DMA_CUR_BUF 0xc8

View File

@ -1,6 +1,6 @@
# $FreeBSD$
.include <bsd.own.mk>
.include <src.opts.mk>
SSP_CFLAGS=
@ -22,3 +22,11 @@ CFLAGS.clang+= -mfpu=none
# when this test succeeds rather than require dd to be a bootstrap tool.
DD_NOSTATUS!=(dd status=none count=0 2> /dev/null && echo status=none) || true
DD=dd ${DD_NOSTATUS}
.if ${MK_LOADER_FORCE_LE} != "no"
.if ${MACHINE_ARCH} == "powerpc64"
CFLAGS+= -mlittle-endian
.endif
.endif

View File

@ -40,8 +40,6 @@
* Author: Ken Merry <ken@FreeBSD.org>
*/
#define _CTL_C
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
@ -410,6 +408,11 @@ SYSCTL_INT(_kern_cam_ctl, OID_AUTO, debug, CTLFLAG_RWTUN,
static int ctl_lun_map_size = 1024;
SYSCTL_INT(_kern_cam_ctl, OID_AUTO, lun_map_size, CTLFLAG_RWTUN,
&ctl_lun_map_size, 0, "Size of per-port LUN map (max LUN + 1)");
#ifdef CTL_TIME_IO
static int ctl_time_io_secs = CTL_TIME_IO_DEFAULT_SECS;
SYSCTL_INT(_kern_cam_ctl, OID_AUTO, time_io_secs, CTLFLAG_RWTUN,
&ctl_time_io_secs, 0, "Log requests taking more seconds");
#endif
/*
* Supported pages (0x00), Serial number (0x80), Device ID (0x83),

View File

@ -40,12 +40,6 @@
#ifndef _CTL_IO_H_
#define _CTL_IO_H_
#ifdef _CTL_C
#define EXTERN(__var,__val) __var = __val
#else
#define EXTERN(__var,__val) extern __var
#endif
#define CTL_MAX_CDBLEN 32
/*
* Uncomment this next line to enable printing out times for I/Os
@ -55,7 +49,6 @@
#define CTL_TIME_IO
#ifdef CTL_TIME_IO
#define CTL_TIME_IO_DEFAULT_SECS 90
EXTERN(int ctl_time_io_secs, CTL_TIME_IO_DEFAULT_SECS);
#endif
/*

View File

@ -59,10 +59,11 @@
__FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <immintrin.h>
#include <crypto/aesni/aesni_os.h>
#include <crypto/aesni/sha_sse.h>
#include <immintrin.h>
void intel_sha1_step(uint32_t *digest, const char *data, uint32_t num_blks) {
__m128i abcd, e0, e1;
__m128i abcd_save, e_save;

View File

@ -59,10 +59,11 @@
__FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <immintrin.h>
#include <crypto/aesni/aesni_os.h>
#include <crypto/aesni/sha_sse.h>
#include <immintrin.h>
void intel_sha256_step(uint32_t *digest, const char *data, uint32_t num_blks) {
__m128i state0, state1;
__m128i msg;

View File

@ -1723,8 +1723,8 @@ mpr_setup_sysctl(struct mpr_softc *sc)
}
SYSCTL_ADD_PROC(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
OID_AUTO, "debug_level", CTLTYPE_STRING | CTLFLAG_RW, sc, 0,
mpr_debug_sysctl, "A", "mpr debug level");
OID_AUTO, "debug_level", CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_MPSAFE,
sc, 0, mpr_debug_sysctl, "A", "mpr debug level");
SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
OID_AUTO, "disable_msix", CTLFLAG_RD, &sc->disable_msix, 0,
@ -1839,7 +1839,7 @@ mpr_debug_sysctl(SYSCTL_HANDLER_ARGS)
{
struct mpr_softc *sc;
struct mpr_debug_string *string;
struct sbuf sbuf;
struct sbuf *sbuf;
char *buffer;
size_t sz;
int i, len, debug, error;
@ -1850,20 +1850,20 @@ mpr_debug_sysctl(SYSCTL_HANDLER_ARGS)
if (error != 0)
return (error);
sbuf_new_for_sysctl(&sbuf, NULL, 128, req);
sbuf = sbuf_new_for_sysctl(NULL, NULL, 128, req);
debug = sc->mpr_debug;
sbuf_printf(&sbuf, "%#x", debug);
sbuf_printf(sbuf, "%#x", debug);
sz = sizeof(mpr_debug_strings) / sizeof(mpr_debug_strings[0]);
for (i = 0; i < sz; i++) {
string = &mpr_debug_strings[i];
if (debug & string->flag)
sbuf_printf(&sbuf, ",%s", string->name);
sbuf_printf(sbuf, ",%s", string->name);
}
error = sbuf_finish(&sbuf);
sbuf_delete(&sbuf);
error = sbuf_finish(sbuf);
sbuf_delete(sbuf);
if (error || req->newptr == NULL)
return (error);

View File

@ -1585,8 +1585,8 @@ mps_setup_sysctl(struct mps_softc *sc)
}
SYSCTL_ADD_PROC(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
OID_AUTO, "debug_level", CTLTYPE_STRING | CTLFLAG_RW, sc, 0,
mps_debug_sysctl, "A", "mps debug level");
OID_AUTO, "debug_level", CTLTYPE_STRING | CTLFLAG_RW |CTLFLAG_MPSAFE,
sc, 0, mps_debug_sysctl, "A", "mps debug level");
SYSCTL_ADD_INT(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree),
OID_AUTO, "disable_msix", CTLFLAG_RD, &sc->disable_msix, 0,
@ -1679,7 +1679,7 @@ mps_setup_sysctl(struct mps_softc *sc)
"Use the phy number for enumeration");
}
struct mps_debug_string {
static struct mps_debug_string {
char *name;
int flag;
} mps_debug_strings[] = {
@ -1701,7 +1701,7 @@ mps_debug_sysctl(SYSCTL_HANDLER_ARGS)
{
struct mps_softc *sc;
struct mps_debug_string *string;
struct sbuf sbuf;
struct sbuf *sbuf;
char *buffer;
size_t sz;
int i, len, debug, error;
@ -1712,20 +1712,20 @@ mps_debug_sysctl(SYSCTL_HANDLER_ARGS)
if (error != 0)
return (error);
sbuf_new_for_sysctl(&sbuf, NULL, 128, req);
sbuf = sbuf_new_for_sysctl(NULL, NULL, 128, req);
debug = sc->mps_debug;
sbuf_printf(&sbuf, "%#x", debug);
sbuf_printf(sbuf, "%#x", debug);
sz = sizeof(mps_debug_strings) / sizeof(mps_debug_strings[0]);
for (i = 0; i < sz; i++) {
string = &mps_debug_strings[i];
if (debug & string->flag)
sbuf_printf(&sbuf, ",%s", string->name);
sbuf_printf(sbuf, ",%s", string->name);
}
error = sbuf_finish(&sbuf);
sbuf_delete(&sbuf);
error = sbuf_finish(sbuf);
sbuf_delete(sbuf);
if (error || req->newptr == NULL)
return (error);

View File

@ -2201,17 +2201,19 @@ uath_sysctl_node(struct uath_softc *sc)
#undef UATH_SYSCTL_STAT_ADD32
CTASSERT(sizeof(u_int) >= sizeof(uint32_t));
static void
uath_cmdeof(struct uath_softc *sc, struct uath_cmd *cmd)
{
struct uath_cmd_hdr *hdr;
int dlen;
uint32_t dlen;
hdr = (struct uath_cmd_hdr *)cmd->buf;
/* NB: msgid is passed thru w/o byte swapping */
#ifdef UATH_DEBUG
if (sc->sc_debug & UATH_DEBUG_CMDS) {
int len = be32toh(hdr->len);
uint32_t len = be32toh(hdr->len);
printf("%s: %s [ix %u] len %u status %u\n",
__func__, uath_codename(be32toh(hdr->code)),
hdr->msgid, len, be32toh(hdr->magic));
@ -2227,15 +2229,9 @@ uath_cmdeof(struct uath_softc *sc, struct uath_cmd *cmd)
switch (hdr->code & 0xff) {
/* reply to a read command */
default:
dlen = hdr->len - sizeof(*hdr);
if (dlen < 0) {
device_printf(sc->sc_dev,
"Invalid header length %d\n", dlen);
return;
}
DPRINTF(sc, UATH_DEBUG_RX_PROC | UATH_DEBUG_RECV_ALL,
"%s: code %d data len %u\n",
__func__, hdr->code & 0xff, dlen);
"%s: code %d hdr len %u\n",
__func__, hdr->code & 0xff, hdr->len);
/*
* The first response from the target after the
* HOST_AVAILABLE has an invalid msgid so we must
@ -2245,8 +2241,8 @@ uath_cmdeof(struct uath_softc *sc, struct uath_cmd *cmd)
uint32_t *rp = (uint32_t *)(hdr+1);
u_int olen;
if (!(sizeof(*hdr) <= hdr->len &&
hdr->len < UATH_MAX_CMDSZ)) {
if (sizeof(*hdr) > hdr->len ||
hdr->len >= UATH_MAX_CMDSZ) {
device_printf(sc->sc_dev,
"%s: invalid WDC msg length %u; "
"msg ignored\n", __func__, hdr->len);
@ -2258,7 +2254,8 @@ uath_cmdeof(struct uath_softc *sc, struct uath_cmd *cmd)
* number of bytes--unless it's 0 in which
* case a single 32-bit word should be present.
*/
if (dlen >= (int)sizeof(uint32_t)) {
dlen = hdr->len - sizeof(*hdr);
if (dlen >= sizeof(uint32_t)) {
olen = be32toh(rp[0]);
dlen -= sizeof(uint32_t);
if (olen == 0) {
@ -2278,7 +2275,7 @@ uath_cmdeof(struct uath_softc *sc, struct uath_cmd *cmd)
cmd->olen);
olen = cmd->olen;
}
if (olen > (u_int)dlen) {
if (olen > dlen) {
/* XXX complain, shouldn't happen */
device_printf(sc->sc_dev,
"%s: cmd 0x%x olen %u dlen %u\n",
@ -2300,8 +2297,10 @@ uath_cmdeof(struct uath_softc *sc, struct uath_cmd *cmd)
return;
}
dlen = hdr->len - sizeof(*hdr);
if (dlen != (int)sizeof(uint32_t)) {
/* XXX something wrong */
if (dlen != sizeof(uint32_t)) {
device_printf(sc->sc_dev,
"%s: dlen (%u) != %zu!\n",
__func__, dlen, sizeof(uint32_t));
return;
}
/* XXX have submitter do this */
@ -2330,6 +2329,7 @@ uath_intr_rx_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct uath_softc *sc = usbd_xfer_softc(xfer);
struct uath_cmd *cmd;
struct uath_cmd_hdr *hdr;
struct usb_page_cache *pc;
int actlen;
@ -2347,10 +2347,25 @@ uath_intr_rx_callback(struct usb_xfer *xfer, usb_error_t error)
STAILQ_INSERT_TAIL(&sc->sc_cmd_inactive, cmd, next);
UATH_STAT_INC(sc, st_cmd_inactive);
KASSERT(actlen >= (int)sizeof(struct uath_cmd_hdr),
("short xfer error"));
if (actlen < sizeof(struct uath_cmd_hdr)) {
device_printf(sc->sc_dev,
"%s: short xfer error (actlen %d)\n",
__func__, actlen);
goto setup;
}
pc = usbd_xfer_get_frame(xfer, 0);
usbd_copy_out(pc, 0, cmd->buf, actlen);
hdr = (struct uath_cmd_hdr *)cmd->buf;
hdr->len = be32toh(hdr->len);
if (hdr->len > (uint32_t)actlen) {
device_printf(sc->sc_dev,
"%s: truncated xfer (len %u, actlen %d)\n",
__func__, hdr->len, actlen);
goto setup;
}
uath_cmdeof(sc, cmd);
case USB_ST_SETUP:
setup:
@ -2451,6 +2466,8 @@ uath_update_rxstat(struct uath_softc *sc, uint32_t status)
}
}
CTASSERT(UATH_MIN_RXBUFSZ >= sizeof(struct uath_chunk));
static struct mbuf *
uath_data_rxeof(struct usb_xfer *xfer, struct uath_data *data,
struct uath_rx_desc **pdesc)
@ -2473,13 +2490,24 @@ uath_data_rxeof(struct usb_xfer *xfer, struct uath_data *data,
}
chunk = (struct uath_chunk *)data->buf;
if (chunk->seqnum == 0 && chunk->flags == 0 && chunk->length == 0) {
chunklen = be16toh(chunk->length);
if (chunk->seqnum == 0 && chunk->flags == 0 && chunklen == 0) {
device_printf(sc->sc_dev, "%s: strange response\n", __func__);
counter_u64_add(ic->ic_ierrors, 1);
UATH_RESET_INTRX(sc);
return (NULL);
}
if (chunklen > actlen) {
device_printf(sc->sc_dev,
"%s: invalid chunk length (len %u > actlen %d)\n",
__func__, chunklen, actlen);
counter_u64_add(ic->ic_ierrors, 1);
/* XXX cleanup? */
UATH_RESET_INTRX(sc);
return (NULL);
}
if (chunk->seqnum != sc->sc_intrx_nextnum) {
DPRINTF(sc, UATH_DEBUG_XMIT, "invalid seqnum %d, expected %d\n",
chunk->seqnum, sc->sc_intrx_nextnum);
@ -2496,9 +2524,19 @@ uath_data_rxeof(struct usb_xfer *xfer, struct uath_data *data,
chunk->flags & UATH_CFLAGS_RXMSG)
UATH_STAT_INC(sc, st_multichunk);
chunklen = be16toh(chunk->length);
if (chunk->flags & UATH_CFLAGS_FINAL)
if (chunk->flags & UATH_CFLAGS_FINAL) {
if (chunklen < sizeof(struct uath_rx_desc)) {
device_printf(sc->sc_dev,
"%s: invalid chunk length %d\n",
__func__, chunklen);
counter_u64_add(ic->ic_ierrors, 1);
if (sc->sc_intrx_head != NULL)
m_freem(sc->sc_intrx_head);
UATH_RESET_INTRX(sc);
return (NULL);
}
chunklen -= sizeof(struct uath_rx_desc);
}
if (chunklen > 0 &&
(!(chunk->flags & UATH_CFLAGS_FINAL) || !(chunk->seqnum == 0))) {
@ -2559,6 +2597,19 @@ uath_data_rxeof(struct usb_xfer *xfer, struct uath_data *data,
(struct uath_rx_desc *)(((uint8_t *)chunk) +
sizeof(struct uath_chunk) + be16toh(chunk->length) -
sizeof(struct uath_rx_desc));
if ((uint8_t *)chunk + actlen - sizeof(struct uath_rx_desc) <
(uint8_t *)desc) {
device_printf(sc->sc_dev,
"%s: wrong Rx descriptor pointer "
"(desc %p chunk %p actlen %d)\n",
__func__, desc, chunk, actlen);
counter_u64_add(ic->ic_ierrors, 1);
if (sc->sc_intrx_head != NULL)
m_freem(sc->sc_intrx_head);
UATH_RESET_INTRX(sc);
return (NULL);
}
*pdesc = desc;
DPRINTF(sc, UATH_DEBUG_RECV | UATH_DEBUG_RECV_ALL,
@ -2586,8 +2637,33 @@ uath_data_rxeof(struct usb_xfer *xfer, struct uath_data *data,
/* finalize mbuf */
if (sc->sc_intrx_head == NULL) {
m->m_pkthdr.len = m->m_len =
be32toh(desc->framelen) - UATH_RX_DUMMYSIZE;
uint32_t framelen;
if (be32toh(desc->framelen) < UATH_RX_DUMMYSIZE) {
device_printf(sc->sc_dev,
"%s: framelen too small (%u)\n",
__func__, be32toh(desc->framelen));
counter_u64_add(ic->ic_ierrors, 1);
if (sc->sc_intrx_head != NULL)
m_freem(sc->sc_intrx_head);
UATH_RESET_INTRX(sc);
return (NULL);
}
framelen = be32toh(desc->framelen) - UATH_RX_DUMMYSIZE;
if (framelen > actlen - sizeof(struct uath_chunk) ||
framelen < sizeof(struct ieee80211_frame_ack)) {
device_printf(sc->sc_dev,
"%s: wrong frame length (%u, actlen %d)!\n",
__func__, framelen, actlen);
counter_u64_add(ic->ic_ierrors, 1);
if (sc->sc_intrx_head != NULL)
m_freem(sc->sc_intrx_head);
UATH_RESET_INTRX(sc);
return (NULL);
}
m->m_pkthdr.len = m->m_len = framelen;
m->m_data += sizeof(struct uath_chunk);
} else {
mp = sc->sc_intrx_head;

View File

@ -258,9 +258,24 @@ struct nfscllayout {
#define NFSLY_RECALLALL 0x0040
#define NFSLY_RETONCLOSE 0x0080
#define NFSLY_WRITTEN 0x0100 /* Has been used to write to a DS. */
#define NFSLY_FLEXFILE 0x0200
/*
* MALLOC'd to the correct length to accommodate the file handle list.
* Flex file layout mirror specific stuff for nfsclflayout.
*/
struct nfsffm {
nfsv4stateid_t st;
char dev[NFSX_V4DEVICEID];
uint32_t eff;
uid_t user;
gid_t group;
struct nfsfh *fh[NFSDEV_MAXVERS];
uint16_t fhcnt;
};
/*
* MALLOC'd to the correct length to accommodate the file handle list for File
* layout and the list of mirrors for the Flex File Layout.
* These hang off of nfsly_flayread and nfsly_flayrw, sorted in increasing
* offset order.
* The nfsly_flayread list holds the ones with iomode == NFSLAYOUTIOMODE_READ,
@ -268,23 +283,49 @@ struct nfscllayout {
*/
struct nfsclflayout {
LIST_ENTRY(nfsclflayout) nfsfl_list;
uint8_t nfsfl_dev[NFSX_V4DEVICEID];
uint64_t nfsfl_off;
uint64_t nfsfl_end;
uint64_t nfsfl_patoff;
struct nfscldevinfo *nfsfl_devp;
uint32_t nfsfl_iomode;
uint32_t nfsfl_util;
uint32_t nfsfl_stripe1;
struct nfscldevinfo *nfsfl_devp;
uint16_t nfsfl_flags;
uint16_t nfsfl_fhcnt;
struct nfsfh *nfsfl_fh[1]; /* FH list for DS */
union {
struct {
uint64_t patoff;
uint32_t util;
uint32_t stripe1;
uint8_t dev[NFSX_V4DEVICEID];
uint16_t fhcnt;
} fl;
struct {
uint64_t stripeunit;
uint32_t fflags;
uint32_t statshint;
uint16_t mirrorcnt;
} ff;
} nfsfl_un;
union {
struct nfsfh *fh[0]; /* FH list for DS File layout */
struct nfsffm ffm[0]; /* Mirror list for Flex File */
} nfsfl_un2; /* Must be last. Malloc'd to correct array length */
};
#define nfsfl_patoff nfsfl_un.fl.patoff
#define nfsfl_util nfsfl_un.fl.util
#define nfsfl_stripe1 nfsfl_un.fl.stripe1
#define nfsfl_dev nfsfl_un.fl.dev
#define nfsfl_fhcnt nfsfl_un.fl.fhcnt
#define nfsfl_stripeunit nfsfl_un.ff.stripeunit
#define nfsfl_fflags nfsfl_un.ff.fflags
#define nfsfl_statshint nfsfl_un.ff.statshint
#define nfsfl_mirrorcnt nfsfl_un.ff.mirrorcnt
#define nfsfl_fh nfsfl_un2.fh
#define nfsfl_ffm nfsfl_un2.ffm
/*
* Flags for nfsfl_flags.
*/
#define NFSFL_RECALL 0x0001 /* File layout has been recalled */
#define NFSFL_FILE 0x0002 /* File layout */
#define NFSFL_FLEXFILE 0x0004 /* Flex File layout */
/*
* Structure that is used to store a LAYOUTRECALL.
@ -306,6 +347,7 @@ struct nfsclrecalllayout {
* - stripe indices, each stored as one byte, since there can be many
* of them. (This implies a limit of 256 on nfsdi_addrcnt, since the
* indices select which address.)
* For Flex File, the addrcnt is always one and no stripe indices exist.
*/
struct nfscldevinfo {
LIST_ENTRY(nfscldevinfo) nfsdi_list;
@ -313,10 +355,33 @@ struct nfscldevinfo {
struct nfsclclient *nfsdi_clp;
uint32_t nfsdi_refcnt;
uint32_t nfsdi_layoutrefs;
uint16_t nfsdi_stripecnt;
union {
struct {
uint16_t stripecnt;
} fl;
struct {
int versindex;
uint32_t vers;
uint32_t minorvers;
uint32_t rsize;
uint32_t wsize;
} ff;
} nfsdi_un;
uint16_t nfsdi_addrcnt;
uint16_t nfsdi_flags;
struct nfsclds *nfsdi_data[0];
};
#define nfsdi_stripecnt nfsdi_un.fl.stripecnt
#define nfsdi_versindex nfsdi_un.ff.versindex
#define nfsdi_vers nfsdi_un.ff.vers
#define nfsdi_minorvers nfsdi_un.ff.minorvers
#define nfsdi_rsize nfsdi_un.ff.rsize
#define nfsdi_wsize nfsdi_un.ff.wsize
/* Flags for nfsdi_flags. */
#define NFSDI_FILELAYOUT 0x0001
#define NFSDI_FLEXFILE 0x0002
#define NFSDI_TIGHTCOUPLED 0X0004
/* These inline functions return values from nfsdi_data[]. */
/*

View File

@ -350,7 +350,8 @@ tmpfs_free_node_locked(struct tmpfs_mount *tmp, struct tmpfs_node *node,
case VREG:
uobj = node->tn_reg.tn_aobj;
if (uobj != NULL) {
atomic_subtract_long(&tmp->tm_pages_used, uobj->size);
if (uobj->size != 0)
atomic_subtract_long(&tmp->tm_pages_used, uobj->size);
KASSERT((uobj->flags & OBJ_TMPFS) == 0,
("leaked OBJ_TMPFS node %p vm_obj %p", node, uobj));
vm_object_deallocate(uobj);
@ -1375,6 +1376,12 @@ tmpfs_reg_resize(struct vnode *vp, off_t newsize, boolean_t ignerr)
oldpages = OFF_TO_IDX(oldsize + PAGE_MASK);
MPASS(oldpages == uobj->size);
newpages = OFF_TO_IDX(newsize + PAGE_MASK);
if (__predict_true(newpages == oldpages && newsize >= oldsize)) {
node->tn_size = newsize;
return (0);
}
if (newpages > oldpages &&
tmpfs_pages_check_avail(tmp, newpages - oldpages) == 0)
return (ENOSPC);

View File

@ -209,12 +209,10 @@ uiomove_object_page(vm_object_t obj, size_t len, struct uio *uio)
}
vm_page_lock(m);
vm_page_hold(m);
if (m->queue == PQ_NONE) {
vm_page_deactivate(m);
} else {
/* Requeue to maintain LRU ordering. */
vm_page_requeue(m);
}
if (m->queue != PQ_ACTIVE)
vm_page_activate(m);
else
vm_page_reference(m);
vm_page_unlock(m);
VM_OBJECT_WUNLOCK(obj);
error = uiomove_fromphys(&m, offset, tlen, uio);

View File

@ -185,17 +185,14 @@ kmod_icmpstat_inc(int statnum)
void
icmp_error(struct mbuf *n, int type, int code, uint32_t dest, int mtu)
{
struct ip *oip = mtod(n, struct ip *), *nip;
unsigned oiphlen = oip->ip_hl << 2;
struct ip *oip, *nip;
struct icmp *icp;
struct mbuf *m;
unsigned icmplen, icmpelen, nlen;
unsigned icmplen, icmpelen, nlen, oiphlen;
KASSERT((u_int)type <= ICMP_MAXTYPE, ("%s: illegal ICMP type",
__func__));
KASSERT((u_int)type <= ICMP_MAXTYPE, ("%s: illegal ICMP type", __func__));
#ifdef ICMPPRINTFS
if (icmpprintfs)
printf("icmp_error(%p, %x, %d)\n", oip, type, code);
#endif
if (type != ICMP_REDIRECT)
ICMPSTAT_INC(icps_error);
/*
@ -207,19 +204,28 @@ icmp_error(struct mbuf *n, int type, int code, uint32_t dest, int mtu)
*/
if (n->m_flags & M_DECRYPTED)
goto freeit;
if (oip->ip_off & htons(~(IP_MF|IP_DF)))
goto freeit;
if (n->m_flags & (M_BCAST|M_MCAST))
goto freeit;
/* Drop if IP header plus 8 bytes is not contiguous in first mbuf. */
if (n->m_len < sizeof(struct ip) + ICMP_MINLEN)
goto freeit;
oip = mtod(n, struct ip *);
oiphlen = oip->ip_hl << 2;
if (n->m_len < oiphlen + ICMP_MINLEN)
goto freeit;
#ifdef ICMPPRINTFS
if (icmpprintfs)
printf("icmp_error(%p, %x, %d)\n", oip, type, code);
#endif
if (oip->ip_off & htons(~(IP_MF|IP_DF)))
goto freeit;
if (oip->ip_p == IPPROTO_ICMP && type != ICMP_REDIRECT &&
n->m_len >= oiphlen + ICMP_MINLEN &&
!ICMP_INFOTYPE(((struct icmp *)((caddr_t)oip + oiphlen))->icmp_type)) {
!ICMP_INFOTYPE(((struct icmp *)((caddr_t)oip +
oiphlen))->icmp_type)) {
ICMPSTAT_INC(icps_oldicmp);
goto freeit;
}
/* Drop if IP header plus 8 bytes is not contignous in first mbuf. */
if (oiphlen + 8 > n->m_len)
goto freeit;
/*
* Calculate length to quote from original packet and
* prevent the ICMP mbuf from overflowing.
@ -235,9 +241,10 @@ icmp_error(struct mbuf *n, int type, int code, uint32_t dest, int mtu)
n->m_next == NULL)
goto stdreply;
if (n->m_len < oiphlen + sizeof(struct tcphdr) &&
((n = m_pullup(n, oiphlen + sizeof(struct tcphdr))) == NULL))
(n = m_pullup(n, oiphlen + sizeof(struct tcphdr))) == NULL)
goto freeit;
th = (struct tcphdr *)((caddr_t)oip + oiphlen);
oip = mtod(n, struct ip *);
th = mtodo(n, oiphlen);
tcphlen = th->th_off << 2;
if (tcphlen < sizeof(struct tcphdr))
goto freeit;
@ -245,8 +252,8 @@ icmp_error(struct mbuf *n, int type, int code, uint32_t dest, int mtu)
goto freeit;
if (oiphlen + tcphlen > n->m_len && n->m_next == NULL)
goto stdreply;
if (n->m_len < oiphlen + tcphlen &&
((n = m_pullup(n, oiphlen + tcphlen)) == NULL))
if (n->m_len < oiphlen + tcphlen &&
(n = m_pullup(n, oiphlen + tcphlen)) == NULL)
goto freeit;
icmpelen = max(tcphlen, min(V_icmp_quotelen,
ntohs(oip->ip_len) - oiphlen));
@ -262,24 +269,31 @@ icmp_error(struct mbuf *n, int type, int code, uint32_t dest, int mtu)
if (n->m_len < oiphlen + sizeof(struct sctphdr) &&
(n = m_pullup(n, oiphlen + sizeof(struct sctphdr))) == NULL)
goto freeit;
oip = mtod(n, struct ip *);
icmpelen = max(sizeof(struct sctphdr),
min(V_icmp_quotelen, ntohs(oip->ip_len) - oiphlen));
sh = (struct sctphdr *)((caddr_t)oip + oiphlen);
sh = mtodo(n, oiphlen);
if (ntohl(sh->v_tag) == 0 &&
ntohs(oip->ip_len) >= oiphlen + sizeof(struct sctphdr) + 8 &&
ntohs(oip->ip_len) >= oiphlen +
sizeof(struct sctphdr) + 8 &&
(n->m_len >= oiphlen + sizeof(struct sctphdr) + 8 ||
n->m_next != NULL)) {
if (n->m_len < oiphlen + sizeof(struct sctphdr) + 8 &&
(n = m_pullup(n, oiphlen + sizeof(struct sctphdr) + 8)) == NULL)
(n = m_pullup(n, oiphlen +
sizeof(struct sctphdr) + 8)) == NULL)
goto freeit;
oip = mtod(n, struct ip *);
sh = mtodo(n, oiphlen);
ch = (struct sctp_chunkhdr *)(sh + 1);
if (ch->chunk_type == SCTP_INITIATION) {
icmpelen = max(sizeof(struct sctphdr) + 8,
min(V_icmp_quotelen, ntohs(oip->ip_len) - oiphlen));
min(V_icmp_quotelen, ntohs(oip->ip_len) -
oiphlen));
}
}
} else
stdreply: icmpelen = max(8, min(V_icmp_quotelen, ntohs(oip->ip_len) - oiphlen));
stdreply: icmpelen = max(8, min(V_icmp_quotelen, ntohs(oip->ip_len) -
oiphlen));
icmplen = min(oiphlen + icmpelen, nlen);
if (icmplen < sizeof(struct ip))
@ -294,7 +308,8 @@ stdreply: icmpelen = max(8, min(V_icmp_quotelen, ntohs(oip->ip_len) - oiphlen));
#ifdef MAC
mac_netinet_icmp_reply(n, m);
#endif
icmplen = min(icmplen, M_TRAILINGSPACE(m) - sizeof(struct ip) - ICMP_MINLEN);
icmplen = min(icmplen, M_TRAILINGSPACE(m) -
sizeof(struct ip) - ICMP_MINLEN);
m_align(m, ICMP_MINLEN + icmplen);
m->m_len = ICMP_MINLEN + icmplen;

View File

@ -110,22 +110,11 @@ smb_strdup(const char *s)
char *
smb_strdupin(char *s, size_t maxlen)
{
char *p, bt;
char *p;
int error;
size_t len;
len = 0;
for (p = s; ;p++) {
if (copyin(p, &bt, 1))
return NULL;
len++;
if (maxlen && len > maxlen)
return NULL;
if (bt == 0)
break;
}
p = malloc(len, M_SMBSTR, M_WAITOK);
error = copyin(s, p, len);
p = malloc(maxlen + 1, M_SMBSTR, M_WAITOK);
error = copyinstr(s, p, maxlen + 1, NULL);
if (error) {
free(p, M_SMBSTR);
return (NULL);

View File

@ -28,6 +28,7 @@ TESTS_SRCS= \
test_empty_gz.c \
test_empty_lz4.c \
test_empty_xz.c \
test_empty_zstd.c \
test_error.c \
test_error_mixed.c \
test_expand_Z.c \
@ -37,6 +38,7 @@ TESTS_SRCS= \
test_expand_mixed.c \
test_expand_plain.c \
test_expand_xz.c \
test_expand_zstd.c \
test_help.c \
test_version.c
@ -59,11 +61,13 @@ CLEANFILES+= list.h list.h.tmp
${PACKAGE}FILES+= test_empty.gz.uu
${PACKAGE}FILES+= test_empty.lz4.uu
${PACKAGE}FILES+= test_empty.xz.uu
${PACKAGE}FILES+= test_empty.zst.uu
${PACKAGE}FILES+= test_expand.Z.uu
${PACKAGE}FILES+= test_expand.bz2.uu
${PACKAGE}FILES+= test_expand.gz.uu
${PACKAGE}FILES+= test_expand.lz4.uu
${PACKAGE}FILES+= test_expand.plain.uu
${PACKAGE}FILES+= test_expand.xz.uu
${PACKAGE}FILES+= test_expand.zst.uu
.include <bsd.test.mk>

View File

@ -43,6 +43,7 @@ TESTS_SRCS= \
test_extract_cpio_lzma.c \
test_extract_cpio_lzo.c \
test_extract_cpio_xz.c \
test_extract_cpio_zstd.c \
test_format_newc.c \
test_gcpio_compat.c \
test_missing_file.c \
@ -73,6 +74,7 @@ TESTS_SRCS= \
test_option_xz.c \
test_option_y.c \
test_option_z.c \
test_option_zstd.c \
test_owner_parse.c \
test_passthrough_dotdot.c \
test_passthrough_reverse.c
@ -104,6 +106,7 @@ ${PACKAGE}FILES+= test_extract.cpio.lz4.uu
${PACKAGE}FILES+= test_extract.cpio.lzma.uu
${PACKAGE}FILES+= test_extract.cpio.lzo.uu
${PACKAGE}FILES+= test_extract.cpio.xz.uu
${PACKAGE}FILES+= test_extract.cpio.zst.uu
${PACKAGE}FILES+= test_gcpio_compat_ref.bin.uu
${PACKAGE}FILES+= test_gcpio_compat_ref.crc.uu
${PACKAGE}FILES+= test_gcpio_compat_ref.newc.uu

View File

@ -333,7 +333,7 @@ man_display_page() {
if [ -n "$use_width" ]; then
mandoc_args="-O width=${use_width}"
fi
testline="mandoc -Tlint -Wunsupp 2>/dev/null"
testline="mandoc -Tlint -Wunsupp >/dev/null 2>&1"
if [ -n "$tflag" ]; then
pipeline="mandoc -Tps $mandoc_args"
else

View File

@ -35,6 +35,7 @@ TESTS_SRCS= \
test_extract_tar_lzma.c \
test_extract_tar_lzo.c \
test_extract_tar_xz.c \
test_extract_tar_zstd.c \
test_format_newc.c \
test_help.c \
test_leading_slash.c \
@ -74,6 +75,7 @@ TESTS_SRCS= \
test_option_xattrs.c \
test_option_xz.c \
test_option_z.c \
test_option_zstd.c \
test_patterns.c \
test_print_longpath.c \
test_stdio.c \
@ -108,6 +110,7 @@ ${PACKAGE}FILES+= test_extract.tar.lz4.uu
${PACKAGE}FILES+= test_extract.tar.lzma.uu
${PACKAGE}FILES+= test_extract.tar.lzo.uu
${PACKAGE}FILES+= test_extract.tar.xz.uu
${PACKAGE}FILES+= test_extract.tar.zst.uu
${PACKAGE}FILES+= test_leading_slash.tar.uu
${PACKAGE}FILES+= test_option_keep_newer_files.tar.Z.uu
${PACKAGE}FILES+= test_option_passphrase.zip.uu

View File

@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd June 30, 2009
.Dd September 30, 2017
.Dt CPUCONTROL 8
.Os
.Sh NAME
@ -34,43 +34,43 @@
device
.Sh SYNOPSIS
.Nm
.Op Fl vh
.Op Fl v
.Fl m Ar msr
.Bk
.Ar device
.Ek
.Nm
.Op Fl vh
.Op Fl v
.Fl m Ar msr Ns = Ns Ar value
.Bk
.Ar device
.Ek
.Nm
.Op Fl vh
.Op Fl v
.Fl m Ar msr Ns &= Ns Ar mask
.Bk
.Ar device
.Ek
.Nm
.Op Fl vh
.Op Fl v
.Fl m Ar msr Ns |= Ns Ar mask
.Bk
.Ar device
.Ek
.Nm
.Op Fl vh
.Op Fl v
.Fl i Ar level
.Bk
.Ar device
.Ek
.Nm
.Op Fl vh
.Op Fl v
.Fl i Ar level,level_type
.Bk
.Ar device
.Ek
.Nm
.Op Fl vh
.Op Fl vn
.Op Fl d Ar datadir
.Fl u
.Bk
@ -88,8 +88,14 @@ It can also be used to apply CPU firmware updates.
The following options are available:
.Bl -tag -width indent
.It Fl d Ar datadir
Where to look for microcode images.
Directory paths where to look for microcode images.
The option can be specified multiple times.
The paths are added in order of the options appearance on the command
line, default directories are appended after the user-supplied paths.
.It Fl n
Do not look for the microcode images in the standard directories.
Currently standard directory to look for the microcode update files is
.Pa /usr/local/share/cpucontrol .
.It Fl m Ar msr
Show value of the specified MSR.
MSR register number should be given as a hexadecimal number.
@ -163,10 +169,10 @@ The command
will retrieve the CPUID level 0x1 from CPU 1.
.Pp
To perform firmware updates on CPU 0 from images located at
.Pa /usr/local/share/cpuctl/
.Pa /usr/local/share/cpuctl
use the following command:
.Pp
.Dq Li "cpucontrol -d /usr/local/share/cpuctl/ -u /dev/cpuctl0"
.Dq Li "cpucontrol -nd /usr/local/share/cpuctl -u /dev/cpuctl0"
.Sh SEE ALSO
.Xr cpuctl 4
.Sh HISTORY
@ -179,5 +185,3 @@ The
.Nm
utility and this manual page was written by
.An Stanislav Sedov Aq Mt stas@FreeBSD.org .
.Sh BUGS
Yes, probably, report if any.

View File

@ -60,6 +60,7 @@ int verbosity_level = 0;
#define FLAG_I 0x01
#define FLAG_M 0x02
#define FLAG_U 0x04
#define FLAG_N 0x08
#define OP_INVAL 0x00
#define OP_READ 0x01
@ -427,11 +428,7 @@ main(int argc, char *argv[])
error = 0;
cmdarg = ""; /* To keep gcc3 happy. */
/*
* Add all default data dirs to the list first.
*/
datadir_add(DEFAULT_DATADIR);
while ((c = getopt(argc, argv, "d:hi:m:uv")) != -1) {
while ((c = getopt(argc, argv, "d:hi:m:nuv")) != -1) {
switch (c) {
case 'd':
datadir_add(optarg);
@ -444,6 +441,9 @@ main(int argc, char *argv[])
flags |= FLAG_M;
cmdarg = optarg;
break;
case 'n':
flags |= FLAG_N;
break;
case 'u':
flags |= FLAG_U;
break;
@ -463,6 +463,8 @@ main(int argc, char *argv[])
usage();
/* NOTREACHED */
}
if ((flags & FLAG_N) == 0)
datadir_add(DEFAULT_DATADIR);
dev = argv[0];
c = flags & (FLAG_I | FLAG_M | FLAG_U);
switch (c) {

View File

@ -29,7 +29,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd August 24, 2009
.Dd September 30, 2017
.Dt TRACEROUTE6 8
.Os
.\"
@ -40,7 +40,7 @@
.Sh SYNOPSIS
.Nm
.Bk -words
.Op Fl adIlnNrvU
.Op Fl adIlnNrSTUv
.Ek
.Bk -words
.Op Fl f Ar firsthop
@ -79,7 +79,7 @@ uses the IPv6 protocol hop limit field to elicit an ICMPv6 TIME_EXCEEDED
response from each gateway along the path to some host.
.Pp
The only mandatory parameter is the destination host name or IPv6 address.
The default probe datagram carries 12 bytes of payload,
The default probe datagram carries 20 bytes of payload,
in addition to the IPv6 header.
The size of the payload can be specified by giving a length
(in bytes)
@ -96,9 +96,9 @@ Debug mode.
.It Fl f Ar firsthop
Specify how many hops to skip in trace.
.It Fl g Ar gateway
Specify intermediate gateway
.Nm (
uses routing header).
Specify intermediate gateway. Please note that
.Nm
tries to use routing headers.
.It Fl I
Use ICMP6 ECHO instead of UDP datagrams.
.It Fl l
@ -119,7 +119,7 @@ Do not resolve numeric address to hostname.
Use a packet with no upper layer header for the probes,
instead of UDP datagrams.
.It Fl p Ar port
Set UDP port number to
Set SCTP/TCP/UDP port number to
.Ar port .
.It Fl q Ar probes
Set the number of probe per hop count to
@ -138,6 +138,10 @@ that has no route through it
.It Fl s Ar src
.Ar Src
specifies the source IPv6 address to be used.
.It Fl S
Use SCTP packets for the probes.
.It Fl T
Use TCP segments for the probes.
.It Fl U
Use UDP datagrams for the probes.
This is the default.

View File

@ -271,6 +271,8 @@ static const char rcsid[] =
#include <netinet/ip6.h>
#include <netinet/icmp6.h>
#include <netinet/sctp.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#ifdef IPSEC
@ -289,23 +291,8 @@ static const char rcsid[] =
#define freehostent(x)
#endif
/*
* format of a (udp) probe packet.
*/
struct tv32 {
u_int32_t tv32_sec;
u_int32_t tv32_usec;
};
struct opacket {
u_char seq; /* sequence number of this packet */
u_char hops; /* hop limit of the packet */
u_char pad[2];
struct tv32 tv; /* time packet left */
} __attribute__((__packed__));
u_char packet[512]; /* last inbound (icmp) packet */
struct opacket *outpacket; /* last output (udp) packet */
char *outpacket; /* last output packet */
int main(int, char *[]);
int wait_for_reply(int, struct msghdr *);
@ -322,10 +309,14 @@ const char *pr_type(int);
int packet_ok(struct msghdr *, int, int);
void print(struct msghdr *, int);
const char *inetname(struct sockaddr *);
u_int32_t sctp_crc32c(void *, u_int32_t);
u_int16_t in_cksum(u_int16_t *addr, int);
u_int16_t tcp_chksum(struct sockaddr_in6 *, struct sockaddr_in6 *,
void *, u_int32_t);
void usage(void);
int rcvsock; /* receive (icmp) socket file descriptor */
int sndsock; /* send (udp) socket file descriptor */
int sndsock; /* send (raw/udp) socket file descriptor */
struct msghdr rcvmhdr;
struct iovec rcviov[2];
@ -333,7 +324,7 @@ int rcvhlim;
struct in6_pktinfo *rcvpktinfo;
struct sockaddr_in6 Src, Dst, Rcv;
u_long datalen; /* How much data */
u_long datalen = 20; /* How much data */
#define ICMP6ECHOLEN 8
/* XXX: 2064 = 127(max hops in type 0 rthdr) * sizeof(ip6_hdr) + 16(margin) */
char rtbuf[2064];
@ -362,9 +353,7 @@ char *as_server = NULL;
void *asn;
int
main(argc, argv)
int argc;
char *argv[];
main(int argc, char *argv[])
{
int mib[4] = { CTL_NET, PF_INET6, IPPROTO_IPV6, IPV6CTL_DEFHLIM };
char hbuf[NI_MAXHOST], src0[NI_MAXHOST], *ep;
@ -411,8 +400,9 @@ main(argc, argv)
#endif
seq = 0;
ident = htons(getpid() & 0xffff); /* same as ping6 */
while ((ch = getopt(argc, argv, "aA:df:g:Ilm:nNp:q:rs:Uvw:")) != -1)
while ((ch = getopt(argc, argv, "aA:df:g:Ilm:nNp:q:rs:STUvw:")) != -1)
switch (ch) {
case 'a':
as_path = 1;
@ -472,7 +462,6 @@ main(argc, argv)
break;
case 'I':
useproto = IPPROTO_ICMPV6;
ident = htons(getpid() & 0xffff); /* same as ping6 */
break;
case 'l':
lflag++;
@ -533,12 +522,18 @@ main(argc, argv)
*/
source = optarg;
break;
case 'v':
verbose++;
case 'S':
useproto = IPPROTO_SCTP;
break;
case 'T':
useproto = IPPROTO_TCP;
break;
case 'U':
useproto = IPPROTO_UDP;
break;
case 'v':
verbose++;
break;
case 'w':
ep = NULL;
errno = 0;
@ -574,13 +569,15 @@ main(argc, argv)
}
break;
case IPPROTO_NONE:
if ((sndsock = socket(AF_INET6, SOCK_RAW, IPPROTO_NONE)) < 0) {
case IPPROTO_SCTP:
case IPPROTO_TCP:
if ((sndsock = socket(AF_INET6, SOCK_RAW, useproto)) < 0) {
perror("socket(SOCK_RAW)");
exit(5);
}
break;
default:
fprintf(stderr, "traceroute6: unknown probe protocol %d",
fprintf(stderr, "traceroute6: unknown probe protocol %d\n",
useproto);
exit(5);
}
@ -641,7 +638,7 @@ main(argc, argv)
ep = NULL;
errno = 0;
datalen = strtoul(*argv, &ep, 0);
if (errno || !*argv || *ep) {
if (errno || *ep) {
fprintf(stderr,
"traceroute6: invalid packet length.\n");
exit(1);
@ -649,15 +646,21 @@ main(argc, argv)
}
switch (useproto) {
case IPPROTO_ICMPV6:
minlen = ICMP6ECHOLEN + sizeof(struct tv32);
minlen = ICMP6ECHOLEN;
break;
case IPPROTO_UDP:
minlen = sizeof(struct opacket);
minlen = sizeof(struct udphdr);
break;
case IPPROTO_NONE:
minlen = 0;
datalen = 0;
break;
case IPPROTO_SCTP:
minlen = sizeof(struct sctphdr);
break;
case IPPROTO_TCP:
minlen = sizeof(struct tcphdr);
break;
default:
fprintf(stderr, "traceroute6: unknown probe protocol %d.\n",
useproto);
@ -671,6 +674,8 @@ main(argc, argv)
minlen, MAXPACKET);
exit(1);
}
if (useproto == IPPROTO_UDP)
datalen -= sizeof(struct udphdr);
outpacket = malloc(datalen);
if (!outpacket) {
perror("malloc");
@ -735,8 +740,10 @@ main(argc, argv)
#ifdef SO_SNDBUF
i = datalen;
if (i == 0)
i = 1;
if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *)&i,
sizeof(i)) < 0 && useproto != IPPROTO_NONE) {
sizeof(i)) < 0) {
perror("setsockopt(SO_SNDBUF)");
exit(6);
}
@ -897,7 +904,8 @@ main(argc, argv)
if (source)
fprintf(stderr, " from %s", source);
fprintf(stderr, ", %lu hops max, %lu byte packets\n",
max_hops, datalen);
max_hops,
datalen + ((useproto == IPPROTO_UDP) ? sizeof(struct udphdr) : 0));
(void) fflush(stderr);
if (first_hop > 1)
@ -977,9 +985,7 @@ main(argc, argv)
}
int
wait_for_reply(sock, mhdr)
int sock;
struct msghdr *mhdr;
wait_for_reply(int sock, struct msghdr *mhdr)
{
#ifdef HAVE_POLL
struct pollfd pfd[1];
@ -1038,14 +1044,12 @@ setpolicy(so, policy)
#endif
void
send_probe(seq, hops)
int seq;
u_long hops;
send_probe(int seq, u_long hops)
{
struct icmp6_hdr *icp;
struct opacket *op;
struct timeval tv;
struct tv32 tv32;
struct sctphdr *sctp;
struct sctp_chunkhdr *chk;
struct tcphdr *tcp;
int i;
i = hops;
@ -1055,9 +1059,6 @@ send_probe(seq, hops)
}
Dst.sin6_port = htons(port + seq);
(void) gettimeofday(&tv, NULL);
tv32.tv32_sec = htonl(tv.tv_sec);
tv32.tv32_usec = htonl(tv.tv_usec);
switch (useproto) {
case IPPROTO_ICMPV6:
@ -1068,19 +1069,49 @@ send_probe(seq, hops)
icp->icmp6_cksum = 0;
icp->icmp6_id = ident;
icp->icmp6_seq = htons(seq);
bcopy(&tv32, ((u_int8_t *)outpacket + ICMP6ECHOLEN),
sizeof(tv32));
break;
case IPPROTO_UDP:
op = outpacket;
op->seq = seq;
op->hops = hops;
bcopy(&tv32, &op->tv, sizeof tv32);
break;
case IPPROTO_NONE:
/* No space for anything. No harm as seq/tv32 are decorative. */
break;
case IPPROTO_SCTP:
sctp = (struct sctphdr *)outpacket;
sctp->src_port = htons(ident);
sctp->dest_port = htons(port + seq);
sctp->v_tag = (sctp->src_port << 16) | sctp->dest_port;
sctp->checksum = htonl(0);
if (datalen >= (u_long)(sizeof(struct sctphdr) +
sizeof(struct sctp_chunkhdr))) {
chk = (struct sctp_chunkhdr *)(sctp + 1);
chk->chunk_type = SCTP_SHUTDOWN_ACK;
chk->chunk_flags = 0;
chk->chunk_length = htons(4);
}
if (datalen >= (u_long)(sizeof(struct sctphdr) +
2 * sizeof(struct sctp_chunkhdr))) {
chk = chk + 1;
chk->chunk_type = SCTP_PAD_CHUNK;
chk->chunk_flags = 0;
chk->chunk_length = htons((u_int16_t)(datalen -
sizeof(struct sctphdr) -
sizeof(struct sctp_chunkhdr)));
}
sctp->checksum = sctp_crc32c(outpacket, datalen);
break;
case IPPROTO_TCP:
tcp = (struct tcphdr *)outpacket;
tcp->th_sport = htons(ident);
tcp->th_dport = htons(port + seq);
tcp->th_seq = (tcp->th_sport << 16) | tcp->th_dport;
tcp->th_ack = 0;
tcp->th_off = 5;
tcp->th_flags = TH_SYN;
tcp->th_sum = 0;
tcp->th_sum = tcp_chksum(&Src, &Dst, outpacket, datalen);
break;
default:
fprintf(stderr, "Unknown probe protocol %d.\n", useproto);
exit(1);
@ -1098,8 +1129,7 @@ send_probe(seq, hops)
}
int
get_hoplim(mhdr)
struct msghdr *mhdr;
get_hoplim(struct msghdr *mhdr)
{
struct cmsghdr *cm;
@ -1115,8 +1145,7 @@ get_hoplim(mhdr)
}
double
deltaT(t1p, t2p)
struct timeval *t1p, *t2p;
deltaT(struct timeval *t1p, struct timeval *t2p)
{
double dt;
@ -1185,10 +1214,7 @@ pr_type(int t0)
}
int
packet_ok(mhdr, cc, seq)
struct msghdr *mhdr;
int cc;
int seq;
packet_ok(struct msghdr *mhdr, int cc, int seq)
{
struct icmp6_hdr *icp;
struct sockaddr_in6 *from = (struct sockaddr_in6 *)mhdr->msg_name;
@ -1262,6 +1288,10 @@ packet_ok(mhdr, cc, seq)
if ((type == ICMP6_TIME_EXCEEDED && code == ICMP6_TIME_EXCEED_TRANSIT)
|| type == ICMP6_DST_UNREACH) {
struct ip6_hdr *hip;
struct icmp6_hdr *icmp;
struct sctphdr *sctp;
struct tcphdr *tcp;
struct udphdr *udp;
void *up;
hip = (struct ip6_hdr *)(icp + 1);
@ -1272,14 +1302,34 @@ packet_ok(mhdr, cc, seq)
}
switch (useproto) {
case IPPROTO_ICMPV6:
if (((struct icmp6_hdr *)up)->icmp6_id == ident &&
((struct icmp6_hdr *)up)->icmp6_seq == htons(seq))
icmp = (struct icmp6_hdr *)up;
if (icmp->icmp6_id == ident &&
icmp->icmp6_seq == htons(seq))
return (type == ICMP6_TIME_EXCEEDED ?
-1 : code + 1);
break;
case IPPROTO_UDP:
if (((struct udphdr *)up)->uh_sport == htons(srcport) &&
((struct udphdr *)up)->uh_dport == htons(port + seq))
udp = (struct udphdr *)up;
if (udp->uh_sport == htons(srcport) &&
udp->uh_dport == htons(port + seq))
return (type == ICMP6_TIME_EXCEEDED ?
-1 : code + 1);
break;
case IPPROTO_SCTP:
sctp = (struct sctphdr *)up;
if (sctp->src_port == htons(ident) &&
sctp->dest_port == htons(port + seq) &&
sctp->v_tag ==
(u_int32_t)((sctp->src_port << 16) | sctp->dest_port))
return (type == ICMP6_TIME_EXCEEDED ?
-1 : code + 1);
break;
case IPPROTO_TCP:
tcp = (struct tcphdr *)up;
if (tcp->th_sport == htons(ident) &&
tcp->th_dport == htons(port + seq) &&
tcp->th_seq ==
(tcp_seq)((tcp->th_sport << 16) | tcp->th_dport))
return (type == ICMP6_TIME_EXCEEDED ?
-1 : code + 1);
break;
@ -1328,9 +1378,7 @@ packet_ok(mhdr, cc, seq)
* Increment pointer until find the UDP or ICMP header.
*/
void *
get_uphdr(ip6, lim)
struct ip6_hdr *ip6;
u_char *lim;
get_uphdr(struct ip6_hdr *ip6, u_char *lim)
{
u_char *cp = (u_char *)ip6, nh;
int hlen;
@ -1345,10 +1393,11 @@ get_uphdr(ip6, lim)
while (lim - cp >= (nh == IPPROTO_NONE ? 0 : 8)) {
switch (nh) {
case IPPROTO_ESP:
case IPPROTO_TCP:
return(NULL);
case IPPROTO_ICMPV6:
return(useproto == nh ? cp : NULL);
case IPPROTO_SCTP:
case IPPROTO_TCP:
case IPPROTO_UDP:
return(useproto == nh ? cp : NULL);
case IPPROTO_NONE:
@ -1374,9 +1423,7 @@ get_uphdr(ip6, lim)
}
void
print(mhdr, cc)
struct msghdr *mhdr;
int cc;
print(struct msghdr *mhdr, int cc)
{
struct sockaddr_in6 *from = (struct sockaddr_in6 *)mhdr->msg_name;
char hbuf[NI_MAXHOST];
@ -1412,8 +1459,7 @@ print(mhdr, cc)
* numeric value, otherwise try for symbolic name.
*/
const char *
inetname(sa)
struct sockaddr *sa;
inetname(struct sockaddr *sa)
{
static char line[NI_MAXHOST], domain[MAXHOSTNAMELEN + 1];
static int first = 1;
@ -1446,12 +1492,163 @@ inetname(sa)
return line;
}
/*
* CRC32C routine for the Stream Control Transmission Protocol
*/
#define CRC32C(c, d) (c = (c>>8) ^ crc_c[(c^(d))&0xFF])
static u_int32_t crc_c[256] = {
0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4,
0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB,
0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B,
0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24,
0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B,
0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384,
0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54,
0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B,
0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A,
0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35,
0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5,
0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA,
0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45,
0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A,
0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A,
0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595,
0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48,
0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957,
0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687,
0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198,
0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927,
0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38,
0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8,
0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7,
0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096,
0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789,
0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859,
0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46,
0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9,
0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6,
0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36,
0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829,
0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C,
0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93,
0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043,
0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C,
0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3,
0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC,
0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C,
0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033,
0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652,
0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D,
0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D,
0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982,
0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D,
0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622,
0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2,
0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED,
0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530,
0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F,
0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF,
0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0,
0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F,
0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540,
0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90,
0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F,
0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE,
0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1,
0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321,
0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E,
0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81,
0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E,
0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E,
0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351
};
u_int32_t
sctp_crc32c(void *packet, u_int32_t len)
{
u_int32_t i, crc32c;
u_int8_t byte0, byte1, byte2, byte3;
u_int8_t *buf = (u_int8_t *)packet;
crc32c = ~0;
for (i = 0; i < len; i++)
CRC32C(crc32c, buf[i]);
crc32c = ~crc32c;
byte0 = crc32c & 0xff;
byte1 = (crc32c>>8) & 0xff;
byte2 = (crc32c>>16) & 0xff;
byte3 = (crc32c>>24) & 0xff;
crc32c = ((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3);
return htonl(crc32c);
}
u_int16_t
in_cksum(u_int16_t *addr, int len)
{
int nleft = len;
u_int16_t *w = addr;
u_int16_t answer;
int sum = 0;
/*
* Our algorithm is simple, using a 32 bit accumulator (sum),
* we add sequential 16 bit words to it, and at the end, fold
* back all the carry bits from the top 16 bits into the lower
* 16 bits.
*/
while (nleft > 1) {
sum += *w++;
nleft -= 2;
}
/* mop up an odd byte, if necessary */
if (nleft == 1)
sum += *(u_char *)w;
/*
* add back carry outs from top 16 bits to low 16 bits
*/
sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
sum += (sum >> 16); /* add carry */
answer = ~sum; /* truncate to 16 bits */
return (answer);
}
u_int16_t
tcp_chksum(struct sockaddr_in6 *src, struct sockaddr_in6 *dst,
void *payload, u_int32_t len)
{
struct {
struct in6_addr src;
struct in6_addr dst;
u_int32_t len;
u_int8_t zero[3];
u_int8_t next;
} pseudo_hdr;
u_int16_t sum[2];
pseudo_hdr.src = src->sin6_addr;
pseudo_hdr.dst = dst->sin6_addr;
pseudo_hdr.len = htonl(len);
pseudo_hdr.zero[0] = 0;
pseudo_hdr.zero[1] = 0;
pseudo_hdr.zero[2] = 0;
pseudo_hdr.next = IPPROTO_TCP;
sum[1] = in_cksum((u_int16_t *)&pseudo_hdr, sizeof(pseudo_hdr));
sum[0] = in_cksum(payload, len);
return (~in_cksum(sum, sizeof(sum)));
}
void
usage()
usage(void)
{
fprintf(stderr,
"usage: traceroute6 [-adIlnNrUv] [-A as_server] [-f firsthop] [-g gateway]\n"
"usage: traceroute6 [-adIlnNrSTUv] [-A as_server] [-f firsthop] [-g gateway]\n"
" [-m hoplimit] [-p port] [-q probes] [-s src] [-w waittime] target\n"
" [datalen]\n");
exit(1);