Date: Tue, 29 Nov 2016 22:14:42 +0000 (UTC) From: Martin Matuska <mm@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r309300 - in head: contrib/libarchive contrib/libarchive/libarchive contrib/libarchive/libarchive/test contrib/libarchive/tar/test lib/libarchive/tests Message-ID: <201611292214.uATMEgQH079904@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: mm Date: Tue Nov 29 22:14:42 2016 New Revision: 309300 URL: https://svnweb.freebsd.org/changeset/base/309300 Log: MFV r309299: Sync libarchive with vendor. Important vendor bugfixes (relevant to FreeBSD): #821: tar -P cannot extract hardlinks through symlinks #825: Add sanity check of tar "uid, "gid" and "mtime" fields PR: 213255 Reported by: Tijl Coosemans <tilj@FreeBSD.org> MFC after: 1 week Added: head/contrib/libarchive/libarchive/test/test_compat_gtar_2.tar.uu - copied unchanged from r309299, vendor/libarchive/dist/libarchive/test/test_compat_gtar_2.tar.uu head/contrib/libarchive/libarchive/test/test_compat_star_acl_posix1e.c - copied unchanged from r309299, vendor/libarchive/dist/libarchive/test/test_compat_star_acl_posix1e.c head/contrib/libarchive/libarchive/test/test_compat_star_acl_posix1e.tar.uu - copied unchanged from r309299, vendor/libarchive/dist/libarchive/test/test_compat_star_acl_posix1e.tar.uu head/contrib/libarchive/libarchive/test/test_read_format_raw.bufr.uu - copied unchanged from r309299, vendor/libarchive/dist/libarchive/test/test_read_format_raw.bufr.uu Modified: head/contrib/libarchive/NEWS head/contrib/libarchive/libarchive/archive_acl.c head/contrib/libarchive/libarchive/archive_entry.c head/contrib/libarchive/libarchive/archive_entry.h head/contrib/libarchive/libarchive/archive_entry_acl.3 head/contrib/libarchive/libarchive/archive_read_disk_entry_from_file.c head/contrib/libarchive/libarchive/archive_read_support_filter_xz.c head/contrib/libarchive/libarchive/archive_read_support_format_tar.c head/contrib/libarchive/libarchive/archive_read_support_format_xar.c head/contrib/libarchive/libarchive/archive_write_disk_posix.c head/contrib/libarchive/libarchive/test/test_compat_gtar.c head/contrib/libarchive/libarchive/test/test_read_format_raw.c head/contrib/libarchive/libarchive/test/test_sparse_basic.c head/contrib/libarchive/tar/test/test_symlink_dir.c head/lib/libarchive/tests/Makefile Directory Properties: head/contrib/libarchive/ (props changed) Modified: head/contrib/libarchive/NEWS ============================================================================== --- head/contrib/libarchive/NEWS Tue Nov 29 21:53:16 2016 (r309299) +++ head/contrib/libarchive/NEWS Tue Nov 29 22:14:42 2016 (r309300) @@ -1,3 +1,5 @@ +Oct 26, 2016: Remove liblzmadec support + Oct 23, 2016: libarchive 3.2.2 released Security release Modified: head/contrib/libarchive/libarchive/archive_acl.c ============================================================================== --- head/contrib/libarchive/libarchive/archive_acl.c Tue Nov 29 21:53:16 2016 (r309299) +++ head/contrib/libarchive/libarchive/archive_acl.c Tue Nov 29 22:14:42 2016 (r309300) @@ -94,6 +94,7 @@ archive_acl_clear(struct archive_acl *ac acl->acl_text = NULL; } acl->acl_p = NULL; + acl->acl_types = 0; acl->acl_state = 0; /* Not counting. */ } @@ -284,8 +285,11 @@ acl_new_entry(struct archive_acl *acl, aq = NULL; while (ap != NULL) { if (ap->type == type && ap->tag == tag && ap->id == id) { - ap->permset = permset; - return (ap); + if (id != -1 || (tag != ARCHIVE_ENTRY_ACL_USER && + tag != ARCHIVE_ENTRY_ACL_GROUP)) { + ap->permset = permset; + return (ap); + } } aq = ap; ap = ap->next; Modified: head/contrib/libarchive/libarchive/archive_entry.c ============================================================================== --- head/contrib/libarchive/libarchive/archive_entry.c Tue Nov 29 21:53:16 2016 (r309299) +++ head/contrib/libarchive/libarchive/archive_entry.c Tue Nov 29 22:14:42 2016 (r309300) @@ -1442,6 +1442,15 @@ archive_entry_acl_add_entry_w(struct arc } /* + * Return a bitmask of ACL types in an archive entry ACL list + */ +int +archive_entry_acl_types(struct archive_entry *entry) +{ + return ((&entry->acl)->acl_types); +} + +/* * Return a count of entries matching "want_type". */ int Modified: head/contrib/libarchive/libarchive/archive_entry.h ============================================================================== --- head/contrib/libarchive/libarchive/archive_entry.h Tue Nov 29 21:53:16 2016 (r309299) +++ head/contrib/libarchive/libarchive/archive_entry.h Tue Nov 29 22:14:42 2016 (r309300) @@ -508,6 +508,9 @@ __LA_DECL const wchar_t *archive_entry_a __LA_DECL const char *archive_entry_acl_text(struct archive_entry *, int /* flags */); +/* Return bitmask of ACL types in an archive entry */ +__LA_DECL int archive_entry_acl_types(struct archive_entry *); + /* Return a count of entries matching 'want_type' */ __LA_DECL int archive_entry_acl_count(struct archive_entry *, int /* want_type */); Modified: head/contrib/libarchive/libarchive/archive_entry_acl.3 ============================================================================== --- head/contrib/libarchive/libarchive/archive_entry_acl.3 Tue Nov 29 21:53:16 2016 (r309299) +++ head/contrib/libarchive/libarchive/archive_entry_acl.3 Tue Nov 29 22:14:42 2016 (r309300) @@ -33,7 +33,8 @@ .Nm archive_entry_acl_next , .Nm archive_entry_acl_next_w , .Nm archive_entry_acl_reset , -.Nm archive_entry_acl_text_w +.Nm archive_entry_acl_text_w , +.Nm archive_entry_acl_types .Nd functions for manipulating Access Control Lists in archive entry descriptions .Sh LIBRARY Streaming Archive Library (libarchive, -larchive) @@ -85,6 +86,8 @@ Streaming Archive Library (libarchive, - .Fn archive_entry_acl_reset "struct archive_entry *a" "int type" .Ft const wchar_t * .Fn archive_entry_acl_text_w "struct archive_entry *a" "int flags" +.Ft int +.Fn archive_entry_acl_types "struct archive_entry *a" .\" enum? .Sh DESCRIPTION An @@ -192,6 +195,11 @@ The returned long string is valid until .Fn archive_entry_acl_add_entry_w or .Fn archive_entry_acl_text_w . +.Pp +.Fn archive_entry_acl_types +get ACL entry types contained in an archive entry's ACL. As POSIX.1e and NFSv4 +ACL entries cannot be mixed, this function is a very efficient way to detect if +an ACL already contains POSIX.1e or NFSv4 ACL entries. .Sh RETURN VALUES .Fn archive_entry_acl_count and @@ -225,6 +233,9 @@ The returned long string is valid until .Fn archive_entry_acl_add_entry_w or .Fn archive_entry_acl_text_w . +.Pp +.Fn archive_entry_acl_types +returns a bitmask of ACL entry types or 0 if archive entry has no ACL entries. .Sh SEE ALSO .Xr archive_entry 3 .Xr libarchive 3 , Modified: head/contrib/libarchive/libarchive/archive_read_disk_entry_from_file.c ============================================================================== --- head/contrib/libarchive/libarchive/archive_read_disk_entry_from_file.c Tue Nov 29 21:53:16 2016 (r309299) +++ head/contrib/libarchive/libarchive/archive_read_disk_entry_from_file.c Tue Nov 29 22:14:42 2016 (r309300) @@ -125,6 +125,10 @@ static int setup_xattrs(struct archive_r struct archive_entry *, int *fd); static int setup_sparse(struct archive_read_disk *, struct archive_entry *, int *fd); +#if defined(HAVE_LINUX_FIEMAP_H) +static int setup_sparse_fiemap(struct archive_read_disk *, + struct archive_entry *, int *fd); +#endif int archive_read_disk_entry_from_file(struct archive *_a, @@ -1124,7 +1128,7 @@ setup_xattrs(struct archive_read_disk *a #if defined(HAVE_LINUX_FIEMAP_H) /* - * Linux sparse interface. + * Linux FIEMAP sparse interface. * * The FIEMAP ioctl returns an "extent" for each physical allocation * on disk. We need to process those to generate a more compact list @@ -1139,7 +1143,7 @@ setup_xattrs(struct archive_read_disk *a */ static int -setup_sparse(struct archive_read_disk *a, +setup_sparse_fiemap(struct archive_read_disk *a, struct archive_entry *entry, int *fd) { char buff[4096]; @@ -1191,7 +1195,7 @@ setup_sparse(struct archive_read_disk *a /* When something error happens, it is better we * should return ARCHIVE_OK because an earlier * version(<2.6.28) cannot perfom FS_IOC_FIEMAP. */ - goto exit_setup_sparse; + goto exit_setup_sparse_fiemap; } if (fm->fm_mapped_extents == 0) { if (iters == 0) { @@ -1226,14 +1230,24 @@ setup_sparse(struct archive_read_disk *a } else break; } -exit_setup_sparse: +exit_setup_sparse_fiemap: return (exit_sts); } -#elif defined(SEEK_HOLE) && defined(SEEK_DATA) && defined(_PC_MIN_HOLE_SIZE) +#if !defined(SEEK_HOLE) || !defined(SEEK_DATA) +static int +setup_sparse(struct archive_read_disk *a, + struct archive_entry *entry, int *fd) +{ + return setup_sparse_fiemap(a, entry, fd); +} +#endif +#endif /* defined(HAVE_LINUX_FIEMAP_H) */ + +#if defined(SEEK_HOLE) && defined(SEEK_DATA) /* - * FreeBSD and Solaris sparse interface. + * SEEK_HOLE sparse interface (FreeBSD, Linux, Solaris) */ static int @@ -1241,8 +1255,8 @@ setup_sparse(struct archive_read_disk *a struct archive_entry *entry, int *fd) { int64_t size; - off_t initial_off; /* FreeBSD/Solaris only, so off_t okay here */ - off_t off_s, off_e; /* FreeBSD/Solaris only, so off_t okay here */ + off_t initial_off; + off_t off_s, off_e; int exit_sts = ARCHIVE_OK; int check_fully_sparse = 0; @@ -1268,8 +1282,10 @@ setup_sparse(struct archive_read_disk *a } if (*fd >= 0) { +#ifdef _PC_MIN_HOLE_SIZE if (fpathconf(*fd, _PC_MIN_HOLE_SIZE) <= 0) return (ARCHIVE_OK); +#endif initial_off = lseek(*fd, 0, SEEK_CUR); if (initial_off != 0) lseek(*fd, 0, SEEK_SET); @@ -1280,8 +1296,10 @@ setup_sparse(struct archive_read_disk *a if (path == NULL) path = archive_entry_pathname(entry); +#ifdef _PC_MIN_HOLE_SIZE if (pathconf(path, _PC_MIN_HOLE_SIZE) <= 0) return (ARCHIVE_OK); +#endif *fd = open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC); if (*fd < 0) { archive_set_error(&a->archive, errno, @@ -1292,6 +1310,19 @@ setup_sparse(struct archive_read_disk *a initial_off = 0; } +#ifndef _PC_MIN_HOLE_SIZE + /* Check if the underlying filesystem supports seek hole */ + off_s = lseek(*fd, 0, SEEK_HOLE); + if (off_s < 0) +#if defined(HAVE_LINUX_FIEMAP_H) + return setup_sparse_fiemap(a, entry, fd); +#else + goto exit_setup_sparse; +#endif + else if (off_s > 0) + lseek(*fd, 0, SEEK_SET); +#endif + off_s = 0; size = archive_entry_size(entry); while (off_s < size) { @@ -1341,7 +1372,7 @@ exit_setup_sparse: return (exit_sts); } -#else +#elif !defined(HAVE_LINUX_FIEMAP_H) /* * Generic (stub) sparse support. Modified: head/contrib/libarchive/libarchive/archive_read_support_filter_xz.c ============================================================================== --- head/contrib/libarchive/libarchive/archive_read_support_filter_xz.c Tue Nov 29 21:53:16 2016 (r309299) +++ head/contrib/libarchive/libarchive/archive_read_support_filter_xz.c Tue Nov 29 22:14:42 2016 (r309300) @@ -43,8 +43,6 @@ __FBSDID("$FreeBSD$"); #endif #if HAVE_LZMA_H #include <lzma.h> -#elif HAVE_LZMADEC_H -#include <lzmadec.h> #endif #include "archive.h" @@ -82,19 +80,6 @@ static ssize_t xz_filter_read(struct arc static int xz_filter_close(struct archive_read_filter *); static int xz_lzma_bidder_init(struct archive_read_filter *); -#elif HAVE_LZMADEC_H && HAVE_LIBLZMADEC - -struct private_data { - lzmadec_stream stream; - unsigned char *out_block; - size_t out_block_size; - int64_t total_out; - char eof; /* True = found end of compressed data. */ -}; - -/* Lzma-only filter */ -static ssize_t lzma_filter_read(struct archive_read_filter *, const void **); -static int lzma_filter_close(struct archive_read_filter *); #endif /* @@ -178,8 +163,6 @@ archive_read_support_filter_lzma(struct bidder->free = NULL; #if HAVE_LZMA_H && HAVE_LIBLZMA return (ARCHIVE_OK); -#elif HAVE_LZMADEC_H && HAVE_LIBLZMADEC - return (ARCHIVE_OK); #else archive_set_error(_a, ARCHIVE_ERRNO_MISC, "Using external lzma program for lzma decompression"); @@ -763,175 +746,6 @@ xz_filter_close(struct archive_read_filt #else -#if HAVE_LZMADEC_H && HAVE_LIBLZMADEC - -/* - * If we have the older liblzmadec library, then we can handle - * LZMA streams but not XZ streams. - */ - -/* - * Setup the callbacks. - */ -static int -lzma_bidder_init(struct archive_read_filter *self) -{ - static const size_t out_block_size = 64 * 1024; - void *out_block; - struct private_data *state; - ssize_t ret, avail_in; - - self->code = ARCHIVE_FILTER_LZMA; - self->name = "lzma"; - - state = (struct private_data *)calloc(sizeof(*state), 1); - out_block = (unsigned char *)malloc(out_block_size); - if (state == NULL || out_block == NULL) { - archive_set_error(&self->archive->archive, ENOMEM, - "Can't allocate data for lzma decompression"); - free(out_block); - free(state); - return (ARCHIVE_FATAL); - } - - self->data = state; - state->out_block_size = out_block_size; - state->out_block = out_block; - self->read = lzma_filter_read; - self->skip = NULL; /* not supported */ - self->close = lzma_filter_close; - - /* Prime the lzma library with 18 bytes of input. */ - state->stream.next_in = (unsigned char *)(uintptr_t) - __archive_read_filter_ahead(self->upstream, 18, &avail_in); - if (state->stream.next_in == NULL) - return (ARCHIVE_FATAL); - state->stream.avail_in = avail_in; - state->stream.next_out = state->out_block; - state->stream.avail_out = state->out_block_size; - - /* Initialize compression library. */ - ret = lzmadec_init(&(state->stream)); - __archive_read_filter_consume(self->upstream, - avail_in - state->stream.avail_in); - if (ret == LZMADEC_OK) - return (ARCHIVE_OK); - - /* Library setup failed: Clean up. */ - archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC, - "Internal error initializing lzma library"); - - /* Override the error message if we know what really went wrong. */ - switch (ret) { - case LZMADEC_HEADER_ERROR: - archive_set_error(&self->archive->archive, - ARCHIVE_ERRNO_MISC, - "Internal error initializing compression library: " - "invalid header"); - break; - case LZMADEC_MEM_ERROR: - archive_set_error(&self->archive->archive, ENOMEM, - "Internal error initializing compression library: " - "out of memory"); - break; - } - - free(state->out_block); - free(state); - self->data = NULL; - return (ARCHIVE_FATAL); -} - -/* - * Return the next block of decompressed data. - */ -static ssize_t -lzma_filter_read(struct archive_read_filter *self, const void **p) -{ - struct private_data *state; - size_t decompressed; - ssize_t avail_in, ret; - - state = (struct private_data *)self->data; - - /* Empty our output buffer. */ - state->stream.next_out = state->out_block; - state->stream.avail_out = state->out_block_size; - - /* Try to fill the output buffer. */ - while (state->stream.avail_out > 0 && !state->eof) { - state->stream.next_in = (unsigned char *)(uintptr_t) - __archive_read_filter_ahead(self->upstream, 1, &avail_in); - if (state->stream.next_in == NULL && avail_in < 0) { - archive_set_error(&self->archive->archive, - ARCHIVE_ERRNO_MISC, - "truncated lzma input"); - return (ARCHIVE_FATAL); - } - state->stream.avail_in = avail_in; - - /* Decompress as much as we can in one pass. */ - ret = lzmadec_decode(&(state->stream), avail_in == 0); - switch (ret) { - case LZMADEC_STREAM_END: /* Found end of stream. */ - state->eof = 1; - /* FALL THROUGH */ - case LZMADEC_OK: /* Decompressor made some progress. */ - __archive_read_filter_consume(self->upstream, - avail_in - state->stream.avail_in); - break; - case LZMADEC_BUF_ERROR: /* Insufficient input data? */ - archive_set_error(&self->archive->archive, - ARCHIVE_ERRNO_MISC, - "Insufficient compressed data"); - return (ARCHIVE_FATAL); - default: - /* Return an error. */ - archive_set_error(&self->archive->archive, - ARCHIVE_ERRNO_MISC, - "Lzma decompression failed"); - return (ARCHIVE_FATAL); - } - } - - decompressed = state->stream.next_out - state->out_block; - state->total_out += decompressed; - if (decompressed == 0) - *p = NULL; - else - *p = state->out_block; - return (decompressed); -} - -/* - * Clean up the decompressor. - */ -static int -lzma_filter_close(struct archive_read_filter *self) -{ - struct private_data *state; - int ret; - - state = (struct private_data *)self->data; - ret = ARCHIVE_OK; - switch (lzmadec_end(&(state->stream))) { - case LZMADEC_OK: - break; - default: - archive_set_error(&(self->archive->archive), - ARCHIVE_ERRNO_MISC, - "Failed to clean up %s compressor", - self->archive->archive.compression_name); - ret = ARCHIVE_FATAL; - } - - free(state->out_block); - free(state); - return (ret); -} - -#else - /* * * If we have no suitable library on this system, we can't actually do @@ -953,9 +767,6 @@ lzma_bidder_init(struct archive_read_fil return (r); } -#endif /* HAVE_LZMADEC_H */ - - static int xz_bidder_init(struct archive_read_filter *self) { @@ -984,5 +795,4 @@ lzip_bidder_init(struct archive_read_fil return (r); } - #endif /* HAVE_LZMA_H */ Modified: head/contrib/libarchive/libarchive/archive_read_support_format_tar.c ============================================================================== --- head/contrib/libarchive/libarchive/archive_read_support_format_tar.c Tue Nov 29 21:53:16 2016 (r309299) +++ head/contrib/libarchive/libarchive/archive_read_support_format_tar.c Tue Nov 29 22:14:42 2016 (r309300) @@ -294,6 +294,46 @@ archive_read_format_tar_cleanup(struct a return (ARCHIVE_OK); } +static int +validate_number_field(const char* p_field, size_t i_size) +{ + unsigned char marker = (unsigned char)p_field[0]; + /* octal? */ + if ((marker >= '0' && marker <= '7') || marker == ' ') { + size_t i = 0; + int octal_found = 0; + for (i = 0; i < i_size; ++i) { + switch (p_field[i]) + { + case ' ': /* skip any leading spaces and trailing space*/ + if (octal_found == 0 || i == i_size - 1) { + continue; + } + break; + case '\0': /* null is allowed only at the end */ + if (i != i_size - 1) { + return 0; + } + break; + /* rest must be octal digits */ + case '0': case '1': case '2': case '3': + case '4': case '5': case '6': case '7': + ++octal_found; + break; + } + } + return octal_found > 0; + } + /* base 256 (i.e. binary number) */ + else if (marker == 128 || marker == 255 || marker == 0) { + /* nothing to check */ + return 1; + } + /* not a number field */ + else { + return 0; + } +} static int archive_read_format_tar_bid(struct archive_read *a, int best_bid) @@ -346,23 +386,23 @@ archive_read_format_tar_bid(struct archi return (0); bid += 2; /* 6 bits of variation in an 8-bit field leaves 2 bits. */ - /* Sanity check: Look at first byte of mode field. */ - switch (255 & (unsigned)header->mode[0]) { - case 0: case 255: - /* Base-256 value: No further verification possible! */ - break; - case ' ': /* Not recommended, but not illegal, either. */ - break; - case '0': case '1': case '2': case '3': - case '4': case '5': case '6': case '7': - /* Octal Value. */ - /* TODO: Check format of remainder of this field. */ - break; - default: - /* Not a valid mode; bail out here. */ - return (0); + /* + * Check format of mode/uid/gid/mtime/size/rdevmajor/rdevminor fields. + * These are usually octal numbers but GNU tar encodes "big" values as + * base256 and leading zeroes are sometimes replaced by spaces. + * Even the null terminator is sometimes omitted. Anyway, must be checked + * to avoid false positives. + */ + if (bid > 0 && + (validate_number_field(header->mode, sizeof(header->mode)) == 0 || + validate_number_field(header->uid, sizeof(header->uid)) == 0 || + validate_number_field(header->gid, sizeof(header->gid)) == 0 || + validate_number_field(header->mtime, sizeof(header->mtime)) == 0 || + validate_number_field(header->size, sizeof(header->size)) == 0 || + validate_number_field(header->rdevmajor, sizeof(header->rdevmajor)) == 0 || + validate_number_field(header->rdevminor, sizeof(header->rdevminor)) == 0)) { + bid = 0; } - /* TODO: Sanity test uid/gid/size/mtime/rdevmajor/rdevminor fields. */ return (bid); } Modified: head/contrib/libarchive/libarchive/archive_read_support_format_xar.c ============================================================================== --- head/contrib/libarchive/libarchive/archive_read_support_format_xar.c Tue Nov 29 21:53:16 2016 (r309299) +++ head/contrib/libarchive/libarchive/archive_read_support_format_xar.c Tue Nov 29 22:14:42 2016 (r309300) @@ -43,8 +43,6 @@ __FBSDID("$FreeBSD$"); #endif #if HAVE_LZMA_H #include <lzma.h> -#elif HAVE_LZMADEC_H -#include <lzmadec.h> #endif #ifdef HAVE_ZLIB_H #include <zlib.h> @@ -334,9 +332,6 @@ struct xar { #if HAVE_LZMA_H && HAVE_LIBLZMA lzma_stream lzstream; int lzstream_valid; -#elif HAVE_LZMADEC_H && HAVE_LIBLZMADEC - lzmadec_stream lzstream; - int lzstream_valid; #endif /* * For Checksum data. @@ -1526,34 +1521,6 @@ decompression_init(struct archive_read * xar->lzstream.total_in = 0; xar->lzstream.total_out = 0; break; -#elif defined(HAVE_LZMADEC_H) && defined(HAVE_LIBLZMADEC) - case LZMA: - if (xar->lzstream_valid) - lzmadec_end(&(xar->lzstream)); - r = lzmadec_init(&(xar->lzstream)); - if (r != LZMADEC_OK) { - switch (r) { - case LZMADEC_HEADER_ERROR: - archive_set_error(&a->archive, - ARCHIVE_ERRNO_MISC, - "Internal error initializing " - "compression library: " - "invalid header"); - break; - case LZMADEC_MEM_ERROR: - archive_set_error(&a->archive, - ENOMEM, - "Internal error initializing " - "compression library: " - "out of memory"); - break; - } - return (ARCHIVE_FATAL); - } - xar->lzstream_valid = 1; - xar->lzstream.total_in = 0; - xar->lzstream.total_out = 0; - break; #endif /* * Unsupported compression. @@ -1563,9 +1530,7 @@ decompression_init(struct archive_read * case BZIP2: #endif #if !defined(HAVE_LZMA_H) || !defined(HAVE_LIBLZMA) -#if !defined(HAVE_LZMADEC_H) || !defined(HAVE_LIBLZMADEC) case LZMA: -#endif case XZ: #endif switch (xar->entry_encoding) { @@ -1685,46 +1650,12 @@ decompress(struct archive_read *a, const *used = avail_in - xar->lzstream.avail_in; *outbytes = avail_out - xar->lzstream.avail_out; break; -#elif defined(HAVE_LZMADEC_H) && defined(HAVE_LIBLZMADEC) - case LZMA: - xar->lzstream.next_in = (unsigned char *)(uintptr_t)b; - xar->lzstream.avail_in = avail_in; - xar->lzstream.next_out = (unsigned char *)outbuff; - xar->lzstream.avail_out = avail_out; - r = lzmadec_decode(&(xar->lzstream), 0); - switch (r) { - case LZMADEC_STREAM_END: /* Found end of stream. */ - switch (lzmadec_end(&(xar->lzstream))) { - case LZMADEC_OK: - break; - default: - archive_set_error(&(a->archive), - ARCHIVE_ERRNO_MISC, - "Failed to clean up lzmadec decompressor"); - return (ARCHIVE_FATAL); - } - xar->lzstream_valid = 0; - /* FALLTHROUGH */ - case LZMADEC_OK: /* Decompressor made some progress. */ - break; - default: - archive_set_error(&(a->archive), - ARCHIVE_ERRNO_MISC, - "lzmadec decompression failed(%d)", - r); - return (ARCHIVE_FATAL); - } - *used = avail_in - xar->lzstream.avail_in; - *outbytes = avail_out - xar->lzstream.avail_out; - break; #endif #if !defined(HAVE_BZLIB_H) || !defined(BZ_CONFIG_ERROR) case BZIP2: #endif #if !defined(HAVE_LZMA_H) || !defined(HAVE_LIBLZMA) -#if !defined(HAVE_LZMADEC_H) || !defined(HAVE_LIBLZMADEC) case LZMA: -#endif case XZ: #endif case NONE: Modified: head/contrib/libarchive/libarchive/archive_write_disk_posix.c ============================================================================== --- head/contrib/libarchive/libarchive/archive_write_disk_posix.c Tue Nov 29 21:53:16 2016 (r309299) +++ head/contrib/libarchive/libarchive/archive_write_disk_posix.c Tue Nov 29 22:14:42 2016 (r309300) @@ -336,14 +336,19 @@ struct archive_write_disk { #define HFS_BLOCKS(s) ((s) >> 12) -static int check_symlinks_fsobj(char *path, int *error_number, struct archive_string *error_string, int flags); +static void fsobj_error(int *, struct archive_string *, int, const char *, + const char *); +static int check_symlinks_fsobj(char *, int *, struct archive_string *, + int); static int check_symlinks(struct archive_write_disk *); static int create_filesystem_object(struct archive_write_disk *); -static struct fixup_entry *current_fixup(struct archive_write_disk *, const char *pathname); +static struct fixup_entry *current_fixup(struct archive_write_disk *, + const char *pathname); #if defined(HAVE_FCHDIR) && defined(PATH_MAX) static void edit_deep_directories(struct archive_write_disk *ad); #endif -static int cleanup_pathname_fsobj(char *path, int *error_number, struct archive_string *error_string, int flags); +static int cleanup_pathname_fsobj(char *, int *, struct archive_string *, + int); static int cleanup_pathname(struct archive_write_disk *); static int create_dir(struct archive_write_disk *, char *); static int create_parent_dir(struct archive_write_disk *, char *); @@ -374,11 +379,14 @@ static struct archive_vtable *archive_wr static int _archive_write_disk_close(struct archive *); static int _archive_write_disk_free(struct archive *); -static int _archive_write_disk_header(struct archive *, struct archive_entry *); +static int _archive_write_disk_header(struct archive *, + struct archive_entry *); static int64_t _archive_write_disk_filter_bytes(struct archive *, int); static int _archive_write_disk_finish_entry(struct archive *); -static ssize_t _archive_write_disk_data(struct archive *, const void *, size_t); -static ssize_t _archive_write_disk_data_block(struct archive *, const void *, size_t, int64_t); +static ssize_t _archive_write_disk_data(struct archive *, const void *, + size_t); +static ssize_t _archive_write_disk_data_block(struct archive *, const void *, + size_t, int64_t); static int lazy_stat(struct archive_write_disk *a) @@ -649,7 +657,8 @@ _archive_write_disk_header(struct archiv if (a->restore_pwd >= 0) { r = fchdir(a->restore_pwd); if (r != 0) { - archive_set_error(&a->archive, errno, "chdir() failure"); + archive_set_error(&a->archive, errno, + "chdir() failure"); ret = ARCHIVE_FATAL; } close(a->restore_pwd); @@ -697,7 +706,8 @@ _archive_write_disk_header(struct archiv } if (archive_entry_birthtime_is_set(entry)) { fe->birthtime = archive_entry_birthtime(entry); - fe->birthtime_nanos = archive_entry_birthtime_nsec(entry); + fe->birthtime_nanos = archive_entry_birthtime_nsec( + entry); } else { /* If birthtime is unset, use mtime. */ fe->birthtime = fe->mtime; @@ -723,7 +733,8 @@ _archive_write_disk_header(struct archiv return (ARCHIVE_FATAL); fe->mac_metadata = malloc(metadata_size); if (fe->mac_metadata != NULL) { - memcpy(fe->mac_metadata, metadata, metadata_size); + memcpy(fe->mac_metadata, metadata, + metadata_size); fe->mac_metadata_size = metadata_size; fe->fixup |= TODO_MAC_METADATA; } @@ -1480,7 +1491,8 @@ _archive_write_disk_data_block(struct ar return (r); if ((size_t)r < size) { archive_set_error(&a->archive, 0, - "Too much data: Truncating file at %ju bytes", (uintmax_t)a->filesize); + "Too much data: Truncating file at %ju bytes", + (uintmax_t)a->filesize); return (ARCHIVE_WARN); } #if ARCHIVE_VERSION_NUMBER < 3999000 @@ -2005,8 +2017,9 @@ restore_entry(struct archive_write_disk if (en) { /* Everything failed; give up here. */ - archive_set_error(&a->archive, en, "Can't create '%s'", - a->name); + if ((&a->archive)->error == NULL) + archive_set_error(&a->archive, en, "Can't create '%s'", + a->name); return (ARCHIVE_FAILED); } @@ -2043,19 +2056,32 @@ create_filesystem_object(struct archive_ if (linkname_copy == NULL) { return (EPERM); } - /* TODO: consider using the cleaned-up path as the link target? */ - r = cleanup_pathname_fsobj(linkname_copy, &error_number, &error_string, a->flags); + /* + * TODO: consider using the cleaned-up path as the link + * target? + */ + r = cleanup_pathname_fsobj(linkname_copy, &error_number, + &error_string, a->flags); if (r != ARCHIVE_OK) { - archive_set_error(&a->archive, error_number, "%s", error_string.s); + archive_set_error(&a->archive, error_number, "%s", + error_string.s); free(linkname_copy); - /* EPERM is more appropriate than error_number for our callers */ + /* + * EPERM is more appropriate than error_number for our + * callers + */ return (EPERM); } - r = check_symlinks_fsobj(linkname_copy, &error_number, &error_string, a->flags); + r = check_symlinks_fsobj(linkname_copy, &error_number, + &error_string, a->flags); if (r != ARCHIVE_OK) { - archive_set_error(&a->archive, error_number, "%s", error_string.s); + archive_set_error(&a->archive, error_number, "%s", + error_string.s); free(linkname_copy); - /* EPERM is more appropriate than error_number for our callers */ + /* + * EPERM is more appropriate than error_number for our + * callers + */ return (EPERM); } free(linkname_copy); @@ -2076,8 +2102,8 @@ create_filesystem_object(struct archive_ a->todo = 0; a->deferred = 0; } else if (r == 0 && a->filesize > 0) { - a->fd = open(a->name, - O_WRONLY | O_TRUNC | O_BINARY | O_CLOEXEC | O_NOFOLLOW); + a->fd = open(a->name, O_WRONLY | O_TRUNC | O_BINARY + | O_CLOEXEC | O_NOFOLLOW); __archive_ensure_cloexec_flag(a->fd); if (a->fd < 0) r = errno; @@ -2388,6 +2414,17 @@ current_fixup(struct archive_write_disk return (a->current_fixup); } +/* Error helper for new *_fsobj functions */ +static void +fsobj_error(int *a_eno, struct archive_string *a_estr, + int err, const char *errstr, const char *path) +{ + if (a_eno) + *a_eno = err; + if (a_estr) + archive_string_sprintf(a_estr, errstr, path); +} + /* * TODO: Someday, integrate this with the deep dir support; they both * scan the path and both can be optimized by comparing against other @@ -2400,7 +2437,8 @@ current_fixup(struct archive_write_disk * ARCHIVE_OK if there are none, otherwise puts an error in errmsg. */ static int -check_symlinks_fsobj(char *path, int *error_number, struct archive_string *error_string, int flags) +check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr, + int flags) { #if !defined(HAVE_LSTAT) /* Platform doesn't have lstat, so we can't look for symlinks. */ @@ -2433,7 +2471,8 @@ check_symlinks_fsobj(char *path, int *er * - if it's a directory and it's not the last chunk, cd into it * As we go: * head points to the current (relative) path - * tail points to the temporary \0 terminating the segment we're currently examining + * tail points to the temporary \0 terminating the segment we're + * currently examining * c holds what used to be in *tail * last is 1 if this is the last tail */ @@ -2455,7 +2494,9 @@ check_symlinks_fsobj(char *path, int *er * Exiting the loop with break is okay; continue is not. */ while (!last) { - /* Skip the separator we just consumed, plus any adjacent ones */ + /* + * Skip the separator we just consumed, plus any adjacent ones + */ while (*tail == '/') ++tail; /* Skip the next path element. */ @@ -2474,19 +2515,20 @@ check_symlinks_fsobj(char *path, int *er if (errno == ENOENT) { break; } else { - /* Treat any other error as fatal - best to be paranoid here - * Note: This effectively disables deep directory - * support when security checks are enabled. - * Otherwise, very long pathnames that trigger - * an error here could evade the sandbox. - * TODO: We could do better, but it would probably - * require merging the symlink checks with the - * deep-directory editing. */ - if (error_number) *error_number = errno; - if (error_string) - archive_string_sprintf(error_string, - "Could not stat %s", - path); + /* + * Treat any other error as fatal - best to be + * paranoid here. + * Note: This effectively disables deep + * directory support when security checks are + * enabled. Otherwise, very long pathnames that + * trigger an error here could evade the + * sandbox. + * TODO: We could do better, but it would + * probably require merging the symlink checks + * with the deep-directory editing. + */ + fsobj_error(a_eno, a_estr, errno, + "Could not stat %s", path); res = ARCHIVE_FAILED; break; } @@ -2494,11 +2536,8 @@ check_symlinks_fsobj(char *path, int *er if (!last) { if (chdir(head) != 0) { tail[0] = c; - if (error_number) *error_number = errno; - if (error_string) - archive_string_sprintf(error_string, - "Could not chdir %s", - path); + fsobj_error(a_eno, a_estr, errno, + "Could not chdir %s", path); res = (ARCHIVE_FATAL); break; } @@ -2514,11 +2553,9 @@ check_symlinks_fsobj(char *path, int *er */ if (unlink(head)) { tail[0] = c; - if (error_number) *error_number = errno; - if (error_string) - archive_string_sprintf(error_string, - "Could not remove symlink %s", - path); + fsobj_error(a_eno, a_estr, errno, + "Could not remove symlink %s", + path); res = ARCHIVE_FAILED; break; } @@ -2529,13 +2566,14 @@ check_symlinks_fsobj(char *path, int *er * symlink with another symlink. */ tail[0] = c; - /* FIXME: not sure how important this is to restore + /* + * FIXME: not sure how important this is to + * restore + */ + /* if (!S_ISLNK(path)) { - if (error_number) *error_number = 0; - if (error_string) - archive_string_sprintf(error_string, - "Removing symlink %s", - path); + fsobj_error(a_eno, a_estr, 0, + "Removing symlink %s", path); } */ /* Symlink gone. No more problem! */ @@ -2545,22 +2583,60 @@ check_symlinks_fsobj(char *path, int *er /* User asked us to remove problems. */ if (unlink(head) != 0) { tail[0] = c; - if (error_number) *error_number = 0; - if (error_string) - archive_string_sprintf(error_string, - "Cannot remove intervening symlink %s", - path); + fsobj_error(a_eno, a_estr, 0, + "Cannot remove intervening " + "symlink %s", path); res = ARCHIVE_FAILED; break; } tail[0] = c; + } else if ((flags & + ARCHIVE_EXTRACT_SECURE_SYMLINKS) == 0) { + /* + * We are not the last element and we want to + * follow symlinks if they are a directory. + * + * This is needed to extract hardlinks over + * symlinks. + */ + r = stat(head, &st); + if (r != 0) { + tail[0] = c; + if (errno == ENOENT) { + break; + } else { + fsobj_error(a_eno, a_estr, + errno, + "Could not stat %s", path); + res = (ARCHIVE_FAILED); + break; + } + } else if (S_ISDIR(st.st_mode)) { + if (chdir(head) != 0) { + tail[0] = c; + fsobj_error(a_eno, a_estr, + errno, + "Could not chdir %s", path); + res = (ARCHIVE_FATAL); + break; + } + /* + * Our view is now from inside + * this dir: + */ + head = tail + 1; + } else { *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201611292214.uATMEgQH079904>