Import libarchive 2.2.3 fixing a few memory leaks and other fixes.
authorPeter Avalos <pavalos@dragonflybsd.org>
Sun, 3 Jun 2007 21:26:40 +0000 (21:26 +0000)
committerPeter Avalos <pavalos@dragonflybsd.org>
Sun, 3 Jun 2007 21:26:40 +0000 (21:26 +0000)
16 files changed:
contrib/libarchive-2/NEWS
contrib/libarchive-2/libarchive/archive.h.in
contrib/libarchive-2/libarchive/archive_entry.3
contrib/libarchive-2/libarchive/archive_entry.c
contrib/libarchive-2/libarchive/archive_entry.h
contrib/libarchive-2/libarchive/archive_read.3
contrib/libarchive-2/libarchive/archive_read_support_compression_bzip2.c
contrib/libarchive-2/libarchive/archive_read_support_compression_gzip.c
contrib/libarchive-2/libarchive/archive_read_support_format_tar.c
contrib/libarchive-2/libarchive/archive_read_support_format_zip.c
contrib/libarchive-2/libarchive/archive_write.3
contrib/libarchive-2/libarchive/archive_write_disk.c
contrib/libarchive-2/libarchive/archive_write_disk_set_standard_lookup.c
contrib/libarchive-2/libarchive/archive_write_set_format_shar.c
contrib/libarchive-2/tar/read.c
contrib/libarchive-2/version

index b6826f6..3b5c88a 100644 (file)
@@ -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 <sigh>.
index 747beb1..7a085d0 100644 (file)
@@ -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
 }
index 807fd32..ff6066f 100644 (file)
@@ -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 ,
 .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 ,
 .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 *
 .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 *
 .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"
 .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"
index a3932fa..908987d 100644 (file)
@@ -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);
 }
 
index c9c61be..3c42f16 100644 (file)
@@ -28,7 +28,9 @@
 #ifndef ARCHIVE_ENTRY_H_INCLUDED
 #define        ARCHIVE_ENTRY_H_INCLUDED
 
+#include <sys/types.h>
 #include <stddef.h>  /* for wchar_t */
+#include <time.h>
 #include <unistd.h>
 
 #ifdef __cplusplus
index e50a28e..e6955da 100644 (file)
@@ -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.
index ca0ac25..c924940 100644 (file)
@@ -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. */
index 8b6cb97..b2e0d8b 100644 (file)
@@ -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;
                        }
                }
index c2243b1..14c5535 100644 (file)
@@ -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 <errno.h>
@@ -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);
index a1c1d53..25ec437 100644 (file)
@@ -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);
index d3f19fb..07c26a0 100644 (file)
 .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 ,
 .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
index 052cd25..ac2bcbd 100644 (file)
@@ -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 <sys/types.h>
@@ -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);
+}
index a750545..4448b3e 100644 (file)
@@ -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);
index 40e7ced..f99c305 100644 (file)
@@ -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 <errno.h>
@@ -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);
                }
        }
 
index e84725b..ff457e3 100644 (file)
@@ -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 <sys/types.h>
@@ -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");
index fae692e..6b4d157 100644 (file)
@@ -1 +1 @@
-2.2.1
\ No newline at end of file
+2.2.3
\ No newline at end of file