From eb792538962c218a0df9be5067f539703f32142b Mon Sep 17 00:00:00 2001 From: Peter Avalos Date: Sun, 3 Jun 2007 21:26:40 +0000 Subject: [PATCH] Import libarchive 2.2.3 fixing a few memory leaks and other fixes. --- contrib/libarchive-2/NEWS | 16 +++++ contrib/libarchive-2/libarchive/archive.h.in | 8 ++- .../libarchive-2/libarchive/archive_entry.3 | 32 ++++++++++ .../libarchive-2/libarchive/archive_entry.c | 22 ++++++- .../libarchive-2/libarchive/archive_entry.h | 2 + .../libarchive-2/libarchive/archive_read.3 | 8 +++ .../archive_read_support_compression_bzip2.c | 18 ++++-- .../archive_read_support_compression_gzip.c | 21 ++++--- .../archive_read_support_format_tar.c | 4 +- .../archive_read_support_format_zip.c | 18 ++++-- .../libarchive-2/libarchive/archive_write.3 | 20 ++++-- .../libarchive/archive_write_disk.c | 61 +++++++++++++++++-- .../archive_write_disk_set_standard_lookup.c | 8 +-- .../archive_write_set_format_shar.c | 13 +++- contrib/libarchive-2/tar/read.c | 3 +- contrib/libarchive-2/version | 2 +- 16 files changed, 213 insertions(+), 43 deletions(-) diff --git a/contrib/libarchive-2/NEWS b/contrib/libarchive-2/NEWS index b6826f6c97..3b5c88a6e3 100644 --- a/contrib/libarchive-2/NEWS +++ b/contrib/libarchive-2/NEWS @@ -1,4 +1,20 @@ +May 26, 2007: libarchive 2.2.3 released +May 26, 2007: Fix memory leaks in ZIP reader and shar writer, add some + missing system headers to archive_entry.h, dead code cleanup + from Colin Percival, more tests for gzip/bzip2, fix an + EOF anomaly in bzip2 decompression. + +May 12, 2007: libarchive 2.2.2 released +May 12, 2007: Fix archive_write_disk permission restore by cloning + entry passed into write_header so that permission info is + still available at finish_entry time. (archive_read_extract() + worked okay because it held onto the passed-in entry, but + direct consumers of archive_write_disk would break). This + required fixing archive_entry_clone(), which now works and has + a reasonably complete test case. +May 10, 2007: Skeletal cpio implementation. + May 06, 2007: libarchive 2.2.1 released May 06, 2007: Flesh out a lot more of test_entry.c so as to catch problems such as the device node breakage before releasing . diff --git a/contrib/libarchive-2/libarchive/archive.h.in b/contrib/libarchive-2/libarchive/archive.h.in index 747beb1fdb..7a085d0a44 100644 --- a/contrib/libarchive-2/libarchive/archive.h.in +++ b/contrib/libarchive-2/libarchive/archive.h.in @@ -22,7 +22,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $FreeBSD: src/lib/libarchive/archive.h.in,v 1.42 2007/04/14 22:34:10 kientzle Exp $ + * $FreeBSD: src/lib/libarchive/archive.h.in,v 1.43 2007/05/02 05:29:55 cperciva Exp $ */ #ifndef ARCHIVE_H_INCLUDED @@ -322,6 +322,10 @@ int archive_read_data_into_fd(struct archive *, int fd); #define ARCHIVE_EXTRACT_SECURE_SYMLINKS (256) /* Default: Do not reject entries with '..' as path elements. */ #define ARCHIVE_EXTRACT_SECURE_NODOTDOT (512) +/* Default: Create parent directories as needed. */ +#define ARCHIVE_EXTRACT_NO_AUTODIR (1024) +/* Default: Overwrite files, even if one on disk is newer. */ +#define ARCHIVE_EXTRACT_NO_OVERWRITE_NEWER (2048) int archive_read_extract(struct archive *, struct archive_entry *, int flags); @@ -499,7 +503,7 @@ const char *archive_format_name(struct archive *); int archive_format(struct archive *); void archive_clear_error(struct archive *); void archive_set_error(struct archive *, int _err, const char *fmt, ...); -void archive_copy_error(struct archive *dest, struct archive *src); +void archive_copy_error(struct archive *dest, struct archive *src); #ifdef __cplusplus } diff --git a/contrib/libarchive-2/libarchive/archive_entry.3 b/contrib/libarchive-2/libarchive/archive_entry.3 index 807fd32744..ff6066fe78 100644 --- a/contrib/libarchive-2/libarchive/archive_entry.3 +++ b/contrib/libarchive-2/libarchive/archive_entry.3 @@ -50,6 +50,9 @@ .Nm archive_entry_copy_symlink_w , .Nm archive_entry_copy_uname_w , .Nm archive_entry_dev , +.Nm archive_entry_devmajor , +.Nm archive_entry_devminor , +.Nm archive_entry_filetype , .Nm archive_entry_fflags , .Nm archive_entry_fflags_text , .Nm archive_entry_free , @@ -60,12 +63,19 @@ .Nm archive_entry_mode , .Nm archive_entry_mtime , .Nm archive_entry_mtime_nsec , +.Nm archive_entry_nlink , .Nm archive_entry_new , .Nm archive_entry_pathname , .Nm archive_entry_pathname_w , .Nm archive_entry_rdev , .Nm archive_entry_rdevmajor , .Nm archive_entry_rdevminor , +.Nm archive_entry_set_atime , +.Nm archive_entry_set_ctime , +.Nm archive_entry_set_dev , +.Nm archive_entry_set_devmajor , +.Nm archive_entry_set_devminor , +.Nm archive_entry_set_filetype , .Nm archive_entry_set_fflags , .Nm archive_entry_set_gid , .Nm archive_entry_set_gname , @@ -132,6 +142,12 @@ .Fn archive_entry_copy_uname_w "struct archive_entry *" "const wchar_t *" .Ft dev_t .Fn archive_entry_dev "struct archive_entry *" +.Ft dev_t +.Fn archive_entry_devmajor "struct archive_entry *" +.Ft dev_t +.Fn archive_entry_devminor "struct archive_entry *" +.Ft mode_t +.Fn archive_entry_filetype "struct archive_entry *" .Ft void .Fn archive_entry_fflags "struct archive_entry *" "unsigned long *set" "unsigned long *clear" .Ft const char * @@ -150,6 +166,8 @@ .Fn archive_entry_mtime "struct archive_entry *" .Ft long .Fn archive_entry_mtime_nsec "struct archive_entry *" +.Ft unsigned int +.Fn archive_entry_nlink "struct archive_entry *" .Ft struct archive_entry * .Fn archive_entry_new "void" .Ft const char * @@ -163,6 +181,14 @@ .Ft dev_t .Fn archive_entry_rdevminor "struct archive_entry *" .Ft void +.Fn archive_entry_set_dev "struct archive_entry *" "dev_t" +.Ft void +.Fn archive_entry_set_devmajor "struct archive_entry *" "dev_t" +.Ft void +.Fn archive_entry_set_devminor "struct archive_entry *" "dev_t" +.Ft void +.Fn archive_entry_set_filetype "struct archive_entry *" "unsigned int" +.Ft void .Fn archive_entry_set_fflags "struct archive_entry *" "unsigned long set" "unsigned long clear" .Ft void .Fn archive_entry_set_gid "struct archive_entry *" "gid_t" @@ -171,14 +197,20 @@ .Ft void .Fn archive_entry_set_hardlink "struct archive_entry *" "const char *" .Ft void +.Fn archive_entry_set_ino "struct archive_entry *" "unsigned long" +.Ft void .Fn archive_entry_set_link "struct archive_entry *" "const char *" .Ft void .Fn archive_entry_set_mode "struct archive_entry *" "mode_t" .Ft void .Fn archive_entry_set_mtime "struct archive_entry *" "time_t" "long nanos" .Ft void +.Fn archive_entry_set_nlink "struct archive_entry *" "unsigned int" +.Ft void .Fn archive_entry_set_pathname "struct archive_entry *" "const char *" .Ft void +.Fn archive_entry_set_rdev "struct archive_entry *" "dev_t" +.Ft void .Fn archive_entry_set_rdevmajor "struct archive_entry *" "dev_t" .Ft void .Fn archive_entry_set_rdevminor "struct archive_entry *" "dev_t" diff --git a/contrib/libarchive-2/libarchive/archive_entry.c b/contrib/libarchive-2/libarchive/archive_entry.c index a3932fa19c..908987d420 100644 --- a/contrib/libarchive-2/libarchive/archive_entry.c +++ b/contrib/libarchive-2/libarchive/archive_entry.c @@ -311,6 +311,8 @@ struct archive_entry * archive_entry_clone(struct archive_entry *entry) { struct archive_entry *entry2; + struct ae_acl *ap, *ap2; + struct ae_xattr *xp; /* Allocate new structure and copy over all of the fields. */ entry2 = (struct archive_entry *)malloc(sizeof(*entry2)); @@ -328,8 +330,24 @@ archive_entry_clone(struct archive_entry *entry) aes_copy(&entry2->ae_symlink, &entry->ae_symlink); aes_copy(&entry2->ae_uname, &entry->ae_uname); - /* XXX TODO: Copy ACL data over as well. XXX */ - /* XXX TODO: Copy xattr data over as well. XXX */ + /* Copy ACL data over. */ + ap = entry->acl_head; + while (ap != NULL) { + ap2 = acl_new_entry(entry2, + ap->type, ap->permset, ap->tag, ap->id); + if (ap2 != NULL) + aes_copy(&ap2->name, &ap->name); + ap = ap->next; + } + + /* Copy xattr data over. */ + xp = entry->xattr_head; + while (xp != NULL) { + archive_entry_xattr_add_entry(entry2, + xp->name, xp->value, xp->size); + xp = xp->next; + } + return (entry2); } diff --git a/contrib/libarchive-2/libarchive/archive_entry.h b/contrib/libarchive-2/libarchive/archive_entry.h index c9c61beef6..3c42f16fad 100644 --- a/contrib/libarchive-2/libarchive/archive_entry.h +++ b/contrib/libarchive-2/libarchive/archive_entry.h @@ -28,7 +28,9 @@ #ifndef ARCHIVE_ENTRY_H_INCLUDED #define ARCHIVE_ENTRY_H_INCLUDED +#include #include /* for wchar_t */ +#include #include #ifdef __cplusplus diff --git a/contrib/libarchive-2/libarchive/archive_read.3 b/contrib/libarchive-2/libarchive/archive_read.3 index e50a28e15e..e6955da6b0 100644 --- a/contrib/libarchive-2/libarchive/archive_read.3 +++ b/contrib/libarchive-2/libarchive/archive_read.3 @@ -34,6 +34,7 @@ .Nm archive_read_support_compression_compress , .Nm archive_read_support_compression_gzip , .Nm archive_read_support_compression_none , +.Nm archive_read_support_compression_program , .Nm archive_read_support_format_all , .Nm archive_read_support_format_cpio , .Nm archive_read_support_format_empty , @@ -74,6 +75,8 @@ .Ft int .Fn archive_read_support_compression_none "struct archive *" .Ft int +.Fn archive_read_support_compression_program "struct archive *" "const char *cmd" +.Ft int .Fn archive_read_support_format_all "struct archive *" .Ft int .Fn archive_read_support_format_cpio "struct archive *" @@ -142,6 +145,11 @@ is always enabled by default. For convenience, .Fn archive_read_support_compression_all enables all available decompression code. +.It Fn archive_read_support_compression_program +Data is fed through the specified external program before being dearchived. +Note that this disables automatic detection of the compression format, +so it makes no sense to specify this in conjunction with any other +decompression option. .It Fn archive_read_support_format_all , Fn archive_read_support_format_cpio , Fn archive_read_support_format_empty , Fn archive_read_support_format_iso9660 , Fn archive_read_support_format_tar, Fn archive_read_support_format_zip Enables support---including auto-detection code---for the specified archive format. diff --git a/contrib/libarchive-2/libarchive/archive_read_support_compression_bzip2.c b/contrib/libarchive-2/libarchive/archive_read_support_compression_bzip2.c index ca0ac2574d..c92494020a 100644 --- a/contrib/libarchive-2/libarchive/archive_read_support_compression_bzip2.c +++ b/contrib/libarchive-2/libarchive/archive_read_support_compression_bzip2.c @@ -55,6 +55,7 @@ struct private_data { size_t uncompressed_buffer_size; char *read_next; int64_t total_out; + char eof; /* True = found end of compressed data. */ }; static int finish(struct archive_read *); @@ -63,7 +64,7 @@ static ssize_t read_consume(struct archive_read *, size_t); static int drive_decompressor(struct archive_read *a, struct private_data *); #endif -/* These two functions are defined even if we lack bzlib. See below. */ +/* These two functions are defined even if we lack the library. See below. */ static int bid(const void *, size_t); static int init(struct archive_read *, const void *, size_t); @@ -133,9 +134,9 @@ bid(const void *buff, size_t len) #ifndef HAVE_BZLIB_H /* - * If we don't have bzlib on this system, we can't actually do the - * decompression. We can, however, still detect bzip2-compressed - * archives and emit a useful message. + * If we don't have the library on this system, we can't actually do the + * decompression. We can, however, still detect compressed archives + * and emit a useful message. */ static int init(struct archive_read *a, const void *buff, size_t n) @@ -233,7 +234,7 @@ init(struct archive_read *a, const void *buff, size_t n) "invalid setup parameter"); break; case BZ_MEM_ERROR: - archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + archive_set_error(&a->archive, ENOMEM, "Internal error initializing compression library: " "out of memory"); break; @@ -280,8 +281,10 @@ read_ahead(struct archive_read *a, const void **p, size_t min) while (read_avail < min && /* Haven't satisfied min. */ read_avail < state->uncompressed_buffer_size) { /* !full */ was_avail = read_avail; - if ((ret = drive_decompressor(a, state)) != ARCHIVE_OK) + if ((ret = drive_decompressor(a, state)) < ARCHIVE_OK) return (ret); + if (ret == ARCHIVE_EOF) + break; /* Break on EOF even if we haven't met min. */ read_avail = state->stream.next_out - state->read_next; if (was_avail == read_avail) /* No progress? */ break; @@ -348,6 +351,8 @@ drive_decompressor(struct archive_read *a, struct private_data *state) char *output; const void *read_buf; + if (state->eof) + return (ARCHIVE_EOF); total_decompressed = 0; for (;;) { if (state->stream.avail_in == 0) { @@ -389,6 +394,7 @@ drive_decompressor(struct archive_read *a, struct private_data *state) return (ARCHIVE_OK); break; case BZ_STREAM_END: /* Found end of stream. */ + state->eof = 1; return (ARCHIVE_OK); default: /* Any other return value is an error. */ diff --git a/contrib/libarchive-2/libarchive/archive_read_support_compression_gzip.c b/contrib/libarchive-2/libarchive/archive_read_support_compression_gzip.c index 8b6cb97781..b2e0d8bd95 100644 --- a/contrib/libarchive-2/libarchive/archive_read_support_compression_gzip.c +++ b/contrib/libarchive-2/libarchive/archive_read_support_compression_gzip.c @@ -57,6 +57,7 @@ struct private_data { int64_t total_out; unsigned long crc; char header_done; + char eof; /* True = found end of compressed data. */ }; static int finish(struct archive_read *); @@ -65,7 +66,7 @@ static ssize_t read_consume(struct archive_read *, size_t); static int drive_decompressor(struct archive_read *a, struct private_data *); #endif -/* These two functions are defined even if we lack zlib. See below. */ +/* These two functions are defined even if we lack the library. See below. */ static int bid(const void *, size_t); static int init(struct archive_read *, const void *, size_t); @@ -73,7 +74,7 @@ int archive_read_support_compression_gzip(struct archive *_a) { struct archive_read *a = (struct archive_read *)_a; - if(__archive_read_register_compression(a, bid, init) != NULL) + if (__archive_read_register_compression(a, bid, init) != NULL) return (ARCHIVE_OK); return (ARCHIVE_FATAL); } @@ -134,9 +135,9 @@ bid(const void *buff, size_t len) #ifndef HAVE_ZLIB_H /* - * If we don't have zlib on this system, we can't actually do the - * decompression. We can, however, still detect gzip-compressed - * archives and emit a useful message. + * If we don't have the library on this system, we can't actually do the + * decompression. We can, however, still detect compressed archives + * and emit a useful message. */ static int init(struct archive_read *a, const void *buff, size_t n) @@ -285,8 +286,10 @@ read_ahead(struct archive_read *a, const void **p, size_t min) while (read_avail < min && /* Haven't satisfied min. */ read_avail < state->uncompressed_buffer_size) { /* !full */ was_avail = read_avail; - if ((ret = drive_decompressor(a, state)) != ARCHIVE_OK) + if ((ret = drive_decompressor(a, state)) < ARCHIVE_OK) return (ret); + if (ret == ARCHIVE_EOF) + break; /* Break on EOF even if we haven't met min. */ read_avail = state->stream.next_out - state->read_next; if (was_avail == read_avail) /* No progress? */ break; @@ -355,6 +358,8 @@ drive_decompressor(struct archive_read *a, struct private_data *state) unsigned char b; const void *read_buf; + if (state->eof) + return (ARCHIVE_EOF); flags = 0; count = 0; header_state = 0; @@ -524,12 +529,10 @@ drive_decompressor(struct archive_read *a, struct private_data *state) * TODO: Verify gzip trailer * (uncompressed length and CRC). */ + state->eof = 1; return (ARCHIVE_OK); default: /* Any other return value is an error. */ - archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, - "gzip decompression failed (%s)", - state->stream.msg); goto fatal; } } diff --git a/contrib/libarchive-2/libarchive/archive_read_support_format_tar.c b/contrib/libarchive-2/libarchive/archive_read_support_format_tar.c index c2243b1fcf..14c5535f6b 100644 --- a/contrib/libarchive-2/libarchive/archive_read_support_format_tar.c +++ b/contrib/libarchive-2/libarchive/archive_read_support_format_tar.c @@ -24,7 +24,7 @@ */ #include "archive_platform.h" -__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_support_format_tar.c,v 1.54 2007/04/15 00:53:38 kientzle Exp $"); +__FBSDID("$FreeBSD: src/lib/libarchive/archive_read_support_format_tar.c,v 1.55 2007/05/21 04:45:24 cperciva Exp $"); #ifdef HAVE_ERRNO_H #include @@ -1149,7 +1149,7 @@ pax_header(struct archive_read *a, struct tar *tar, return (-1); while (*wp && *wp != L'=') ++wp; - if (*wp == L'\0' || wp == NULL) { + if (*wp == L'\0') { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Invalid pax extended attributes"); return (ARCHIVE_WARN); diff --git a/contrib/libarchive-2/libarchive/archive_read_support_format_zip.c b/contrib/libarchive-2/libarchive/archive_read_support_format_zip.c index a1c1d53b0b..25ec437290 100644 --- a/contrib/libarchive-2/libarchive/archive_read_support_format_zip.c +++ b/contrib/libarchive-2/libarchive/archive_read_support_format_zip.c @@ -79,6 +79,7 @@ struct zip { size_t uncompressed_buffer_size; #ifdef HAVE_ZLIB_H z_stream stream; + char stream_valid; #endif struct archive_string pathname; @@ -535,13 +536,19 @@ zip_read_data_deflate(struct archive_read *a, const void **buff, /* If we haven't yet read any data, initialize the decompressor. */ if (!zip->decompress_init) { - r = inflateInit2(&zip->stream, - -15 /* Don't check for zlib header */); + if (zip->stream_valid) + r = inflateReset(&zip->stream); + else + r = inflateInit2(&zip->stream, + -15 /* Don't check for zlib header */); if (r != Z_OK) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Can't initialize ZIP decompression."); return (ARCHIVE_FATAL); } + /* Stream structure has been set up. */ + zip->stream_valid = 1; + /* We've initialized decompression for this stream. */ zip->decompress_init = 1; } @@ -667,8 +674,11 @@ archive_read_format_zip_cleanup(struct archive_read *a) struct zip *zip; zip = (struct zip *)(a->format->data); - if (zip->uncompressed_buffer != NULL) - free(zip->uncompressed_buffer); +#ifdef HAVE_ZLIB_H + if (zip->stream_valid) + inflateEnd(&zip->stream); +#endif + free(zip->uncompressed_buffer); archive_string_free(&(zip->pathname)); archive_string_free(&(zip->extra)); free(zip); diff --git a/contrib/libarchive-2/libarchive/archive_write.3 b/contrib/libarchive-2/libarchive/archive_write.3 index d3f19fb4ab..07c26a0ff7 100644 --- a/contrib/libarchive-2/libarchive/archive_write.3 +++ b/contrib/libarchive-2/libarchive/archive_write.3 @@ -38,8 +38,10 @@ .Nm archive_write_get_bytes_per_block , .Nm archive_write_set_bytes_per_block , .Nm archive_write_set_bytes_in_last_block , -.Nm archive_write_set_compressor_gzip , -.Nm archive_write_set_compressor_bzip2 , +.Nm archive_write_set_compression_bzip2 , +.Nm archive_write_set_compression_gzip , +.Nm archive_write_set_compression_none , +.Nm archive_write_set_compression_program , .Nm archive_write_open , .Nm archive_write_open_fd , .Nm archive_write_open_FILE , @@ -62,9 +64,13 @@ .Ft int .Fn archive_write_set_bytes_in_last_block "struct archive *" "int" .Ft int -.Fn archive_write_set_compressor_gzip "struct archive *" +.Fn archive_write_set_compression_bzip2 "struct archive *" .Ft int -.Fn archive_write_set_compressor_bzip2 "struct archive *" +.Fn archive_write_set_compression_gzip "struct archive *" +.Ft int +.Fn archive_write_set_compression_none "struct archive *" +.Ft int +.Fn archive_write_set_compression_program "struct archive *" "const char * cmd" .Ft int .Fn archive_write_set_format_cpio "struct archive *" .Ft int @@ -168,9 +174,13 @@ filenames, linknames, uids, sizes, etc. is the library default; this is the same as pax format, but suppresses the pax extended header for most normal files. In most cases, this will result in ordinary ustar archives. -.It Fn archive_write_set_compression_gzip , Fn archive_write_set_compression_bzip2 +.It Fn archive_write_set_compression_bzip2 , Fn archive_write_set_compression_gzip , Fn archive_write_set_compression_none The resulting archive will be compressed as specified. Note that the compressed output is always properly blocked. +.It Fn archive_write_set_compression_program +The archive will be fed into the specified compression program. +The output of that program is blocked and written to the client +write callbacks. .It Fn archive_write_open Freeze the settings, open the archive, and prepare for writing entries. This is the most generic form of this function, which accepts diff --git a/contrib/libarchive-2/libarchive/archive_write_disk.c b/contrib/libarchive-2/libarchive/archive_write_disk.c index 052cd25e6b..ac2bcbde0a 100644 --- a/contrib/libarchive-2/libarchive/archive_write_disk.c +++ b/contrib/libarchive-2/libarchive/archive_write_disk.c @@ -25,7 +25,7 @@ */ #include "archive_platform.h" -__FBSDID("$FreeBSD: src/lib/libarchive/archive_write_disk.c,v 1.10 2007/04/15 04:43:12 kientzle Exp $"); +__FBSDID("$FreeBSD: src/lib/libarchive/archive_write_disk.c,v 1.11 2007/05/21 04:22:38 cperciva Exp $"); #ifdef HAVE_SYS_TYPES_H #include @@ -204,6 +204,7 @@ static void edit_deep_directories(struct archive_write_disk *ad); 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 *); +static int older(struct stat *, struct archive_entry *); static int restore_entry(struct archive_write_disk *); #ifdef HAVE_POSIX_ACL static int set_acl(struct archive_write_disk *, int fd, struct archive_entry *, @@ -292,7 +293,11 @@ _archive_write_header(struct archive *_a, struct archive_entry *entry) a->pst = NULL; a->current_fixup = NULL; a->deferred = 0; - a->entry = entry; + if (a->entry) { + archive_entry_free(a->entry); + a->entry = NULL; + } + a->entry = archive_entry_clone(entry); a->fd = -1; a->offset = 0; a->uid = a->user_uid; @@ -544,6 +549,11 @@ _archive_write_finish_entry(struct archive *_a) close(a->fd); a->fd = -1; } + /* If there's an entry, we can release it now. */ + if (a->entry) { + archive_entry_free(a->entry); + a->entry = NULL; + } a->archive.state = ARCHIVE_STATE_HEADER; return (ret); } @@ -682,7 +692,8 @@ restore_entry(struct archive_write_disk *a) /* Try creating it first; if this fails, we'll try to recover. */ en = create_filesystem_object(a); - if (en == ENOTDIR || en == ENOENT) { + if ((en == ENOTDIR || en == ENOENT) + && !(a->flags & ARCHIVE_EXTRACT_NO_AUTODIR)) { /* If the parent dir doesn't exist, try creating it. */ create_parent_dir(a, a->name); /* Now try to create the object again. */ @@ -725,6 +736,14 @@ restore_entry(struct archive_write_disk *a) /* TODO: if it's a symlink... */ + if (a->flags & ARCHIVE_EXTRACT_NO_OVERWRITE_NEWER) { + if (!older(&(a->st), a->entry)) { + archive_set_error(&a->archive, 0, + "File on disk is not older; skipping."); + return (ARCHIVE_FAILED); + } + } + /* If it's our archive, we're done. */ if (a->skip_file_dev > 0 && a->skip_file_ino > 0 && @@ -1287,7 +1306,6 @@ create_dir(struct archive_write_disk *a, char *path) /* Check for special names and just skip them. */ slash = strrchr(path, '/'); - base = strrchr(path, '/'); if (slash == NULL) base = path; else @@ -2017,3 +2035,38 @@ trivial_lookup_uid(void *private_data, const char *uname, uid_t uid) (void)uname; /* UNUSED */ return (uid); } + +/* + * Test if file on disk is older than entry. + */ +static int +older(struct stat *st, struct archive_entry *entry) +{ + /* First, test the seconds and return if we have a definite answer. */ + /* Definitely older. */ + if (st->st_mtime < archive_entry_mtime(entry)) + return (1); + /* Definitely younger. */ + if (st->st_mtime > archive_entry_mtime(entry)) + return (0); + /* If this platform supports fractional seconds, try those. */ +#if HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC + /* Definitely older. */ + if (st->st_mtimespec.tv_nsec < archive_entry_mtime_nsec(entry)) + return (1); + /* Definitely younger. */ + if (st->st_mtimespec.tv_nsec > archive_entry_mtime_nsec(entry)) + return (0); +#elif HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC + /* Definitely older. */ + if (st->st_mtim.tv_nsec < archive_entry_mtime_nsec(entry)) + return (1); + /* Definitely older. */ + if (st->st_mtim.tv_nsec > archive_entry_mtime_nsec(entry)) + return (0); +#else + /* This system doesn't have high-res timestamps. */ +#endif + /* Same age, so not older. */ + return (0); +} diff --git a/contrib/libarchive-2/libarchive/archive_write_disk_set_standard_lookup.c b/contrib/libarchive-2/libarchive/archive_write_disk_set_standard_lookup.c index a750545a86..4448b3e07d 100644 --- a/contrib/libarchive-2/libarchive/archive_write_disk_set_standard_lookup.c +++ b/contrib/libarchive-2/libarchive/archive_write_disk_set_standard_lookup.c @@ -84,10 +84,10 @@ static void cleanup(void *); int archive_write_disk_set_standard_lookup(struct archive *a) { - struct bucket *ucache = malloc(sizeof(struct bucket[cache_size])); - struct bucket *gcache = malloc(sizeof(struct bucket[cache_size])); - memset(ucache, 0, sizeof(struct bucket[cache_size])); - memset(gcache, 0, sizeof(struct bucket[cache_size])); + struct bucket *ucache = malloc(cache_size * sizeof(struct bucket)); + struct bucket *gcache = malloc(cache_size * sizeof(struct bucket)); + memset(ucache, 0, cache_size * sizeof(struct bucket)); + memset(gcache, 0, cache_size * sizeof(struct bucket)); archive_write_disk_set_group_lookup(a, gcache, lookup_gid, cleanup); archive_write_disk_set_user_lookup(a, ucache, lookup_uid, cleanup); return (ARCHIVE_OK); diff --git a/contrib/libarchive-2/libarchive/archive_write_set_format_shar.c b/contrib/libarchive-2/libarchive/archive_write_set_format_shar.c index 40e7ced715..f99c305cdf 100644 --- a/contrib/libarchive-2/libarchive/archive_write_set_format_shar.c +++ b/contrib/libarchive-2/libarchive/archive_write_set_format_shar.c @@ -24,7 +24,7 @@ */ #include "archive_platform.h" -__FBSDID("$FreeBSD: src/lib/libarchive/archive_write_set_format_shar.c,v 1.16 2007/03/03 07:37:36 kientzle Exp $"); +__FBSDID("$FreeBSD: src/lib/libarchive/archive_write_set_format_shar.c,v 1.17 2007/05/19 05:09:09 cperciva Exp $"); #ifdef HAVE_ERRNO_H #include @@ -208,11 +208,14 @@ archive_write_shar_header(struct archive_write *a, struct archive_entry *entry) /* Try to avoid a lot of redundant mkdir commands. */ if (strcmp(p, ".") == 0) { /* Don't try to "mkdir ." */ + free(p); } else if (shar->last_dir == NULL) { ret = shar_printf(a, "mkdir -p %s > /dev/null 2>&1\n", p); - if (ret != ARCHIVE_OK) + if (ret != ARCHIVE_OK) { + free(p); return (ret); + } shar->last_dir = p; } else if (strcmp(p, shar->last_dir) == 0) { /* We've already created this exact dir. */ @@ -224,11 +227,15 @@ archive_write_shar_header(struct archive_write *a, struct archive_entry *entry) } else { ret = shar_printf(a, "mkdir -p %s > /dev/null 2>&1\n", p); - if (ret != ARCHIVE_OK) + if (ret != ARCHIVE_OK) { + free(p); return (ret); + } free(shar->last_dir); shar->last_dir = p; } + } else { + free(p); } } diff --git a/contrib/libarchive-2/tar/read.c b/contrib/libarchive-2/tar/read.c index e84725b758..ff457e334c 100644 --- a/contrib/libarchive-2/tar/read.c +++ b/contrib/libarchive-2/tar/read.c @@ -24,7 +24,7 @@ */ #include "bsdtar_platform.h" -__FBSDID("$FreeBSD: src/usr.bin/tar/read.c,v 1.31 2007/04/16 04:04:50 cperciva Exp $"); +__FBSDID("$FreeBSD: src/usr.bin/tar/read.c,v 1.32 2007/05/08 15:22:21 kientzle Exp $"); #ifdef HAVE_SYS_TYPES_H #include @@ -209,6 +209,7 @@ read_archive(struct bsdtar *bsdtar, char mode) fprintf(out, "\n"); bsdtar_warnc(bsdtar, 0, "%s", archive_error_string(a)); + bsdtar->return_value = 1; break; } fprintf(out, "\n"); diff --git a/contrib/libarchive-2/version b/contrib/libarchive-2/version index fae692e41d..6b4d157738 100644 --- a/contrib/libarchive-2/version +++ b/contrib/libarchive-2/version @@ -1 +1 @@ -2.2.1 \ No newline at end of file +2.2.3 \ No newline at end of file -- 2.41.0