Import libarchive-2.8.5.
authorPeter Avalos <pavalos@dragonflybsd.org>
Tue, 20 Sep 2011 21:15:23 +0000 (14:15 -0700)
committerPeter Avalos <pavalos@dragonflybsd.org>
Tue, 20 Sep 2011 21:15:23 +0000 (14:15 -0700)
* Now reads ISO images created by NetBSD makefs and other tools.
* Relax an lzma compression test to remove false negatives.
* Better handling of open failures and interrupted writes.
* Corrected compile warnings on various platforms.

19 files changed:
contrib/libarchive/NEWS
contrib/libarchive/README.DELETED
contrib/libarchive/build/version
contrib/libarchive/libarchive/archive.h
contrib/libarchive/libarchive/archive_read.c
contrib/libarchive/libarchive/archive_read_extract.c
contrib/libarchive/libarchive/archive_read_support_compression_uu.c
contrib/libarchive/libarchive/archive_read_support_format_iso9660.c
contrib/libarchive/libarchive/archive_read_support_format_mtree.c
contrib/libarchive/libarchive/archive_string.h
contrib/libarchive/libarchive/archive_write_disk.c
contrib/libarchive/libarchive/archive_write_open_fd.c
contrib/libarchive/libarchive/archive_write_open_file.c
contrib/libarchive/libarchive/archive_write_open_filename.c
contrib/libarchive/libarchive/archive_write_set_compression_xz.c
contrib/libarchive/libarchive/archive_write_set_format_ar.c
contrib/libarchive/libarchive/archive_write_set_format_shar.c
contrib/libarchive/libarchive/archive_write_set_format_ustar.c
contrib/libarchive/libarchive/archive_write_set_format_zip.c

index b1d83e3..4a25fe3 100644 (file)
@@ -1,6 +1,11 @@
+Feb 05, 2011: Fix issue 134: Improve handling of open failures
+Dec 06, 2010: Fix issue 119: Relax ISO verification
+Dec 06, 2010: Fix issue 121: mtree parsing
+Dec 05, 2010: Fix extraction of GNU tar 'D' directory entries
+Dec 05, 2010: Be less demanding in LZMA/XZ compression tests
 Jun 30, 2010: libarchive 2.8.4 released
 Jun 30, 2010: Improved reliability of hash function detection
-Jun 30, 2010: Fix issues on ancient FreeBSD, QNX, ancient NetBSD and Minux
+Jun 30, 2010: Fix issues on ancient FreeBSD, QNX, ancient NetBSD and Minix
 
 Mar 14, 2010: libarchive 2.8.3 released
 Mar 14, 2010: Symlink dereference fix for Linux broke the build there; corrected.
index 7886d32..bd8eb86 100644 (file)
@@ -9,7 +9,6 @@ build/bump-version.sh
 build/clean.sh
 build/cmake/
 build/pkgconfig/
-build/windows/
 config.h.in
 configure
 configure.ac
index 5ca28eb..140df54 100644 (file)
@@ -52,7 +52,7 @@
 /* These should match the types used in 'struct stat' */
 #if defined(_WIN32) && !defined(__CYGWIN__)
 #define        __LA_INT64_T    __int64
-# if defined(_SSIZE_T_DEFINED)
+# if defined(_SSIZE_T_DEFINED) || defined(_SSIZE_T_)
 #  define      __LA_SSIZE_T    ssize_t
 # elif defined(_WIN64)
 #  define      __LA_SSIZE_T    __int64
 # define __LA_DECL
 #endif
 
+#if defined(__GNUC__) && __GNUC__ >= 3
+#define        __LA_PRINTF(fmtarg, firstvararg) \
+       __attribute__((__format__ (__printf__, fmtarg, firstvararg)))
+#else
+#define        __LA_PRINTF(fmtarg, firstvararg)        /* nothing */
+#endif
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -129,13 +136,13 @@ extern "C" {
  *             (ARCHIVE_API_VERSION * 1000000 + ARCHIVE_API_FEATURE * 1000)
  * #endif
  */
-#define        ARCHIVE_VERSION_NUMBER 2008004
+#define        ARCHIVE_VERSION_NUMBER 2008005
 __LA_DECL int          archive_version_number(void);
 
 /*
  * Textual name/version of the library, useful for version displays.
  */
-#define        ARCHIVE_VERSION_STRING "libarchive 2.8.4"
+#define        ARCHIVE_VERSION_STRING "libarchive 2.8.5"
 __LA_DECL const char * archive_version_string(void);
 
 #if ARCHIVE_VERSION_NUMBER < 3000000
@@ -719,7 +726,7 @@ __LA_DECL const char        *archive_format_name(struct archive *);
 __LA_DECL int           archive_format(struct archive *);
 __LA_DECL void          archive_clear_error(struct archive *);
 __LA_DECL void          archive_set_error(struct archive *, int _err,
-                           const char *fmt, ...);
+                           const char *fmt, ...) __LA_PRINTF(3, 4);
 __LA_DECL void          archive_copy_error(struct archive *dest,
                            struct archive *src);
 __LA_DECL int           archive_file_count(struct archive *);
index f39f5ce..b1558b6 100644 (file)
@@ -377,6 +377,12 @@ build_stream(struct archive_read *a)
 
                /* If no bidder, we're done. */
                if (best_bidder == NULL) {
+                       /* Verify the final pipelin by asking it for some data. */
+                       __archive_read_filter_ahead(a->filter, 1, &avail);
+                       if (avail < 0) {
+                               cleanup_filters(a);
+                               return (ARCHIVE_FATAL);
+                       }
                        a->archive.compression_name = a->filter->name;
                        a->archive.compression_code = a->filter->code;
                        return (ARCHIVE_OK);
@@ -389,17 +395,11 @@ build_stream(struct archive_read *a)
                filter->bidder = best_bidder;
                filter->archive = a;
                filter->upstream = a->filter;
-               r = (best_bidder->init)(filter);
-               if (r != ARCHIVE_OK) {
-                       free(filter);
-                       return (r);
-               }
                a->filter = filter;
-               /* Verify the filter by asking it for some data. */
-               __archive_read_filter_ahead(filter, 1, &avail);
-               if (avail < 0) {
+               r = (best_bidder->init)(a->filter);
+               if (r != ARCHIVE_OK) {
                        cleanup_filters(a);
-                       return (ARCHIVE_FATAL);
+                       return (r);
                }
        }
 }
index e102799..ea44f7b 100644 (file)
@@ -40,6 +40,7 @@ __FBSDID("$FreeBSD: src/lib/libarchive/archive_read_extract.c,v 1.61 2008/05/26
 #endif
 
 #include "archive.h"
+#include "archive_entry.h"
 #include "archive_private.h"
 #include "archive_read_private.h"
 #include "archive_write_disk_private.h"
@@ -107,7 +108,7 @@ archive_read_extract2(struct archive *_a, struct archive_entry *entry,
        if (r != ARCHIVE_OK)
                /* If _write_header failed, copy the error. */
                archive_copy_error(&a->archive, ad);
-       else
+       else if (archive_entry_size(entry) > 0)
                /* Otherwise, pour data into the entry. */
                r = copy_data(_a, ad);
        r2 = archive_write_finish_entry(ad);
index 1e30520..f7bea82 100644 (file)
@@ -381,7 +381,17 @@ ensure_in_buff_size(struct archive_read_filter *self,
                unsigned char *ptr;
                size_t newsize;
 
-               newsize = uudecode->in_allocated << 1;
+               /*
+                * Calculate a new buffer size for in_buff.
+                * Increase its value until it has enough size we need.
+                */
+               newsize = uudecode->in_allocated;
+               do {
+                       if (newsize < IN_BUFF_SIZE*32)
+                               newsize <<= 1;
+                       else
+                               newsize += IN_BUFF_SIZE;
+               } while (size > newsize);
                ptr = malloc(newsize);
                if (ptr == NULL ||
                    newsize < uudecode->in_allocated) {
@@ -478,9 +488,9 @@ read_more:
                switch (uudecode->state) {
                default:
                case ST_FIND_HEAD:
-                       if (len - nl > 13 && memcmp(b, "begin ", 6) == 0)
+                       if (len - nl >= 11 && memcmp(b, "begin ", 6) == 0)
                                l = 6;
-                       else if (len - nl > 18 &&
+                       else if (len - nl >= 18 &&
                            memcmp(b, "begin-base64 ", 13) == 0)
                                l = 13;
                        else
index 0c640c8..813df7a 100644 (file)
@@ -1,7 +1,7 @@
 /*-
  * Copyright (c) 2003-2007 Tim Kientzle
  * Copyright (c) 2009 Andreas Henriksson <andreas@fatal.se>
- * Copyright (c) 2009 Michihiro NAKAJIMA
+ * Copyright (c) 2009-2011 Michihiro NAKAJIMA
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -261,13 +261,17 @@ struct file_info {
        struct file_info        *use_next;
        struct file_info        *parent;
        struct file_info        *next;
+       struct file_info        *re_next;
        int              subdirs;
        uint64_t         key;           /* Heap Key.                    */
        uint64_t         offset;        /* Offset on disk.              */
        uint64_t         size;          /* File size in bytes.          */
        uint32_t         ce_offset;     /* Offset of CE.                */
        uint32_t         ce_size;       /* Size of CE.                  */
+       char             rr_moved;      /* Flag to rr_moved.            */
+       char             rr_moved_has_re_only;
        char             re;            /* Having RRIP "RE" extension.  */
+       char             re_descendant;
        uint64_t         cl_offset;     /* Having RRIP "CL" extension.  */
        int              birthtime_is_set;
        time_t           birthtime;     /* File created time.           */
@@ -294,7 +298,10 @@ struct file_info {
                struct content  *first;
                struct content  **last;
        } contents;
-       char             exposed;
+       struct {
+               struct file_info        *first;
+               struct file_info        **last;
+       } rede_files;
 };
 
 struct heap_queue {
@@ -317,8 +324,6 @@ struct iso9660 {
 
        unsigned char   suspOffset;
        struct file_info *rr_moved;
-       struct heap_queue                re_dirs;
-       struct heap_queue                cl_files;
        struct read_ce_queue {
                struct read_ce_req {
                        uint64_t         offset;/* Offset of CE on disk. */
@@ -337,6 +342,10 @@ struct iso9660 {
                struct file_info        *first;
                struct file_info        **last;
        }       cache_files;
+       struct {
+               struct file_info        *first;
+               struct file_info        **last;
+       }       re_files;
 
        uint64_t current_position;
        ssize_t logical_block_size;
@@ -377,7 +386,8 @@ static int  isJolietSVD(struct iso9660 *, const unsigned char *);
 static int     isSVD(struct iso9660 *, const unsigned char *);
 static int     isEVD(struct iso9660 *, const unsigned char *);
 static int     isPVD(struct iso9660 *, const unsigned char *);
-static struct file_info *next_cache_entry(struct iso9660 *iso9660);
+static int     next_cache_entry(struct archive_read *, struct iso9660 *,
+                   struct file_info **);
 static int     next_entry_seek(struct archive_read *a, struct iso9660 *iso9660,
                    struct file_info **pfile);
 static struct file_info *
@@ -400,10 +410,12 @@ static void       parse_rockridge_ZF1(struct file_info *,
 static void    register_file(struct iso9660 *, struct file_info *);
 static void    release_files(struct iso9660 *);
 static unsigned        toi(const void *p, int n);
+static inline void re_add_entry(struct iso9660 *, struct file_info *);
+static inline struct file_info * re_get_entry(struct iso9660 *);
+static inline int rede_add_entry(struct file_info *);
+static inline struct file_info * rede_get_entry(struct file_info *);
 static inline void cache_add_entry(struct iso9660 *iso9660,
                    struct file_info *file);
-static inline void cache_add_to_next_of_parent(struct iso9660 *iso9660,
-                   struct file_info *file);
 static inline struct file_info *cache_get_entry(struct iso9660 *iso9660);
 static void    heap_add_entry(struct heap_queue *heap,
                    struct file_info *file, uint64_t key);
@@ -430,6 +442,8 @@ archive_read_support_format_iso9660(struct archive *_a)
        iso9660->magic = ISO9660_MAGIC;
        iso9660->cache_files.first = NULL;
        iso9660->cache_files.last = &(iso9660->cache_files.first);
+       iso9660->re_files.first = NULL;
+       iso9660->re_files.last = &(iso9660->re_files.first);
        /* Enable to support Joliet extensions by default.      */
        iso9660->opt_support_joliet = 1;
        /* Enable to support Rock Ridge extensions by default.  */
@@ -709,16 +723,18 @@ isSVD(struct iso9660 *iso9660, const unsigned char *h)
 
        /* Location of Occurrence of Type L Path Table must be
         * available location,
-        * > SYSTEM_AREA_BLOCK(16) + 2 and < Volume Space Size. */
+        * >= SYSTEM_AREA_BLOCK(16) + 2 and < Volume Space Size. */
        location = archive_le32dec(h+SVD_type_L_path_table_offset);
-       if (location <= SYSTEM_AREA_BLOCK+2 || location >= volume_block)
+       if (location < SYSTEM_AREA_BLOCK+2 || location >= volume_block)
                return (0);
 
-       /* Location of Occurrence of Type M Path Table must be
-        * available location,
-        * > SYSTEM_AREA_BLOCK(16) + 2 and < Volume Space Size. */
+       /* The Type M Path Table must be at a valid location (WinISO
+        * and probably other programs omit this, so we allow zero)
+        *
+        * >= SYSTEM_AREA_BLOCK(16) + 2 and < Volume Space Size. */
        location = archive_be32dec(h+SVD_type_M_path_table_offset);
-       if (location <= SYSTEM_AREA_BLOCK+2 || location >= volume_block)
+       if ((location > 0 && location < SYSTEM_AREA_BLOCK+2)
+           || location >= volume_block)
                return (0);
 
        /* Read Root Directory Record in Volume Descriptor. */
@@ -781,16 +797,17 @@ isEVD(struct iso9660 *iso9660, const unsigned char *h)
 
        /* Location of Occurrence of Type L Path Table must be
         * available location,
-        * > SYSTEM_AREA_BLOCK(16) + 2 and < Volume Space Size. */
+        * >= SYSTEM_AREA_BLOCK(16) + 2 and < Volume Space Size. */
        location = archive_le32dec(h+PVD_type_1_path_table_offset);
-       if (location <= SYSTEM_AREA_BLOCK+2 || location >= volume_block)
+       if (location < SYSTEM_AREA_BLOCK+2 || location >= volume_block)
                return (0);
 
        /* Location of Occurrence of Type M Path Table must be
         * available location,
-        * > SYSTEM_AREA_BLOCK(16) + 2 and < Volume Space Size. */
+        * >= SYSTEM_AREA_BLOCK(16) + 2 and < Volume Space Size. */
        location = archive_be32dec(h+PVD_type_m_path_table_offset);
-       if (location <= SYSTEM_AREA_BLOCK+2 || location >= volume_block)
+       if ((location > 0 && location < SYSTEM_AREA_BLOCK+2)
+           || location >= volume_block)
                return (0);
 
        /* Reserved field must be 0. */
@@ -862,14 +879,17 @@ isPVD(struct iso9660 *iso9660, const unsigned char *h)
         * available location,
         * > SYSTEM_AREA_BLOCK(16) + 2 and < Volume Space Size. */
        location = archive_le32dec(h+PVD_type_1_path_table_offset);
-       if (location <= SYSTEM_AREA_BLOCK+2 || location >= volume_block)
+       if (location < SYSTEM_AREA_BLOCK+2 || location >= volume_block)
                return (0);
 
-       /* Location of Occurrence of Type M Path Table must be
-        * available location,
-        * > SYSTEM_AREA_BLOCK(16) + 2 and < Volume Space Size. */
+       /* The Type M Path Table must also be at a valid location
+        * (although ECMA 119 requires a Type M Path Table, WinISO and
+        * probably other programs omit it, so we permit a zero here)
+        *
+        * >= SYSTEM_AREA_BLOCK(16) + 2 and < Volume Space Size. */
        location = archive_be32dec(h+PVD_type_m_path_table_offset);
-       if (location <= SYSTEM_AREA_BLOCK+2 || location >= volume_block)
+       if ((location > 0 && location < SYSTEM_AREA_BLOCK+2)
+           || location >= volume_block)
                return (0);
 
        /* Reserved field must be 0. */
@@ -912,14 +932,14 @@ read_children(struct archive_read *a, struct file_info *parent)
                archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
                    "Ignoring out-of-order directory (%s) %jd > %jd",
                    parent->name.s,
-                   iso9660->current_position,
-                   parent->offset);
+                   (intmax_t)iso9660->current_position,
+                   (intmax_t)parent->offset);
                return (ARCHIVE_WARN);
        }
        if (parent->offset + parent->size > iso9660->volume_size) {
                archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
                    "Directory is beyond end-of-media: %s",
-                   parent->name);
+                   parent->name.s);
                return (ARCHIVE_WARN);
        }
        if (iso9660->current_position < parent->offset) {
@@ -967,42 +987,38 @@ read_children(struct archive_read *a, struct file_info *parent)
                        child = parse_file_info(a, parent, p);
                        if (child == NULL)
                                return (ARCHIVE_FATAL);
-                       if (child->cl_offset)
-                               heap_add_entry(&(iso9660->cl_files),
-                                   child, child->cl_offset);
-                       else {
-                               if (child->multi_extent || multi != NULL) {
-                                       struct content *con;
-
-                                       if (multi == NULL) {
-                                               multi = child;
-                                               multi->contents.first = NULL;
-                                               multi->contents.last =
-                                                   &(multi->contents.first);
-                                       }
-                                       con = malloc(sizeof(struct content));
-                                       if (con == NULL) {
-                                               archive_set_error(
-                                                   &a->archive, ENOMEM,
-                                                   "No memory for "
-                                                   "multi extent");
-                                               return (ARCHIVE_FATAL);
-                                       }
-                                       con->offset = child->offset;
-                                       con->size = child->size;
-                                       con->next = NULL;
-                                       *multi->contents.last = con;
-                                       multi->contents.last = &(con->next);
-                                       if (multi == child)
-                                               add_entry(iso9660, child);
-                                       else {
-                                               multi->size += child->size;
-                                               if (!child->multi_extent)
-                                                       multi = NULL;
-                                       }
-                               } else
+                       if (child->cl_offset == 0 &&
+                           (child->multi_extent || multi != NULL)) {
+                               struct content *con;
+
+                               if (multi == NULL) {
+                                       multi = child;
+                                       multi->contents.first = NULL;
+                                       multi->contents.last =
+                                           &(multi->contents.first);
+                               }
+                               con = malloc(sizeof(struct content));
+                               if (con == NULL) {
+                                       archive_set_error(
+                                           &a->archive, ENOMEM,
+                                           "No memory for "
+                                           "multi extent");
+                                       return (ARCHIVE_FATAL);
+                               }
+                               con->offset = child->offset;
+                               con->size = child->size;
+                               con->next = NULL;
+                               *multi->contents.last = con;
+                               multi->contents.last = &(con->next);
+                               if (multi == child)
                                        add_entry(iso9660, child);
-                       }
+                               else {
+                                       multi->size += child->size;
+                                       if (!child->multi_extent)
+                                               multi = NULL;
+                               }
+                       } else
+                               add_entry(iso9660, child);
                }
        }
 
@@ -1013,103 +1029,13 @@ read_children(struct archive_read *a, struct file_info *parent)
        return (ARCHIVE_OK);
 }
 
-static int
-relocate_dir(struct iso9660 *iso9660, struct file_info *file)
-{
-       struct file_info *re;
-
-       re = heap_get_entry(&(iso9660->re_dirs));
-       while (re != NULL && re->offset < file->cl_offset) {
-               /* This case is wrong pattern.
-                * But dont't reject this directory entry to be robust. */
-               cache_add_entry(iso9660, re);
-               re = heap_get_entry(&(iso9660->re_dirs));
-       }
-       if (re == NULL)
-               /* This case is wrong pattern. */
-               return (0);
-       if (re->offset == file->cl_offset) {
-               re->parent->subdirs--;
-               re->parent = file->parent;
-               re->parent->subdirs++;
-               cache_add_to_next_of_parent(iso9660, re);
-               return (1);
-       } else
-               /* This case is wrong pattern. */
-               heap_add_entry(&(iso9660->re_dirs), re, re->offset);
-       return (0);
-}
-
-static int
-read_entries(struct archive_read *a)
-{
-       struct iso9660 *iso9660;
-       struct file_info *file;
-       int r;
-
-       iso9660 = (struct iso9660 *)(a->format->data);
-
-       while ((file = next_entry(iso9660)) != NULL &&
-           (file->mode & AE_IFMT) == AE_IFDIR) {
-               r = read_children(a, file);
-               if (r != ARCHIVE_OK)
-                       return (r);
-
-               if (iso9660->seenRockridge &&
-                   file->parent != NULL &&
-                   file->parent->parent == NULL &&
-                   iso9660->rr_moved == NULL &&
-                   (strcmp(file->name.s, "rr_moved") == 0 ||
-                    strcmp(file->name.s, ".rr_moved") == 0)) {
-                       iso9660->rr_moved = file;
-               } else if (file->re)
-                       heap_add_entry(&(iso9660->re_dirs), file,
-                           file->offset);
-               else
-                       cache_add_entry(iso9660, file);
-       }
-       if (file != NULL)
-               add_entry(iso9660, file);
-
-       if (iso9660->rr_moved != NULL) {
-               /*
-                * Relocate directory which rr_moved has.
-                */
-               while ((file = heap_get_entry(&(iso9660->cl_files))) != NULL)
-                       relocate_dir(iso9660, file);
-
-               /* If rr_moved directory still has children,
-                * Add rr_moved into pending_files to show
-                */
-               if (iso9660->rr_moved->subdirs) {
-                       cache_add_entry(iso9660, iso9660->rr_moved);
-                       /* If entries which have "RE" extension are still
-                        * remaining(this case is unlikely except ISO image
-                        * is broken), the entries won't be exposed. */
-                       while ((file = heap_get_entry(&(iso9660->re_dirs))) != NULL)
-                               cache_add_entry(iso9660, file);
-               } else
-                       iso9660->rr_moved->parent->subdirs--;
-       } else {
-               /*
-                * In case ISO image is broken. If the name of rr_moved
-                * directory has been changed by damage, subdirectories
-                * of rr_moved entry won't be exposed.
-                */
-               while ((file = heap_get_entry(&(iso9660->re_dirs))) != NULL)
-                       cache_add_entry(iso9660, file);
-       }
-
-       return (ARCHIVE_OK);
-}
-
 static int
 archive_read_format_iso9660_read_header(struct archive_read *a,
     struct archive_entry *entry)
 {
        struct iso9660 *iso9660;
        struct file_info *file;
-       int r, rd_r;
+       int r, rd_r = ARCHIVE_OK;
 
        iso9660 = (struct iso9660 *)(a->format->data);
 
@@ -1199,11 +1125,7 @@ archive_read_format_iso9660_read_header(struct archive_read *a,
                        a->archive.archive_format_name =
                            "ISO9660 with Rockridge extensions";
                }
-               rd_r = read_entries(a);
-               if (rd_r == ARCHIVE_FATAL)
-                       return (ARCHIVE_FATAL);
-       } else
-               rd_r = ARCHIVE_OK;
+       }
 
        /* Get the next entry that appears after the current offset. */
        r = next_entry_seek(a, iso9660, &file);
@@ -1215,7 +1137,7 @@ archive_read_format_iso9660_read_header(struct archive_read *a,
 
        if (file->offset + file->size > iso9660->volume_size) {
                archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-                   "File is beyond end-of-media: %s", file->name);
+                   "File is beyond end-of-media: %s", file->name.s);
                iso9660->entry_bytes_remaining = 0;
                iso9660->entry_sparse_offset = 0;
                return (ARCHIVE_WARN);
@@ -1274,10 +1196,10 @@ archive_read_format_iso9660_read_header(struct archive_read *a,
        if ((file->mode & AE_IFMT) != AE_IFDIR &&
            file->offset < iso9660->current_position) {
                archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
-                   "Ignoring out-of-order file @%x (%s) %jd < %jd",
-                   file,
+                   "Ignoring out-of-order file (%s) %jd < %jd",
                    iso9660->pathname.s,
-                   file->offset, iso9660->current_position);
+                   (intmax_t)file->offset,
+                   (intmax_t)iso9660->current_position);
                iso9660->entry_bytes_remaining = 0;
                iso9660->entry_sparse_offset = 0;
                return (ARCHIVE_WARN);
@@ -1316,7 +1238,6 @@ archive_read_format_iso9660_read_header(struct archive_read *a,
                /* Directory data has been read completely. */
                iso9660->entry_bytes_remaining = 0;
                iso9660->entry_sparse_offset = 0;
-               file->exposed = 1;
        }
 
        if (rd_r != ARCHIVE_OK)
@@ -1601,8 +1522,8 @@ archive_read_format_iso9660_read_data(struct archive_read *a,
                        archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
                            "Ignoring out-of-order file (%s) %jd < %jd",
                            iso9660->pathname.s,
-                           iso9660->entry_content->offset,
-                           iso9660->current_position);
+                           (intmax_t)iso9660->entry_content->offset,
+                           (intmax_t)iso9660->current_position);
                        *buff = NULL;
                        *size = 0;
                        *offset = iso9660->entry_sparse_offset;
@@ -1643,10 +1564,6 @@ archive_read_format_iso9660_cleanup(struct archive_read *a)
        archive_string_free(&iso9660->previous_pathname);
        if (iso9660->pending_files.files)
                free(iso9660->pending_files.files);
-       if (iso9660->re_dirs.files)
-               free(iso9660->re_dirs.files);
-       if (iso9660->cl_files.files)
-               free(iso9660->cl_files.files);
 #ifdef HAVE_ZLIB_H
        free(iso9660->entry_zisofs.uncompressed_buffer);
        free(iso9660->entry_zisofs.block_pointers);
@@ -1677,6 +1594,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent,
        const unsigned char *rr_start, *rr_end;
        const unsigned char *p;
        size_t dr_len;
+       uint64_t fsize;
        int32_t location;
        int flags;
 
@@ -1685,6 +1603,7 @@ parse_file_info(struct archive_read *a, struct file_info *parent,
        dr_len = (size_t)isodirrec[DR_length_offset];
        name_len = (size_t)isodirrec[DR_name_len_offset];
        location = archive_le32dec(isodirrec + DR_extent_offset);
+       fsize = toi(isodirrec + DR_size_offset, DR_size_size);
        /* Sanity check that dr_len needs at least 34. */
        if (dr_len < 34) {
                archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
@@ -1703,7 +1622,9 @@ parse_file_info(struct archive_read *a, struct file_info *parent,
         * link or file size is zero. As far as I know latest mkisofs
         * do that.
         */
-       if (location >= iso9660->volume_block) {
+       if (location > 0 &&
+           (location + ((fsize + iso9660->logical_block_size -1)
+              / iso9660->logical_block_size)) > iso9660->volume_block) {
                archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
                    "Invalid location of extent of file");
                return (NULL);
@@ -1719,9 +1640,11 @@ parse_file_info(struct archive_read *a, struct file_info *parent,
        memset(file, 0, sizeof(*file));
        file->parent = parent;
        file->offset = iso9660->logical_block_size * (uint64_t)location;
-       file->size = toi(isodirrec + DR_size_offset, DR_size_size);
+       file->size = fsize;
        file->mtime = isodate7(isodirrec + DR_date_offset);
        file->ctime = file->atime = file->mtime;
+       file->rede_files.first = NULL;
+       file->rede_files.last = &(file->rede_files.first);
 
        p = isodirrec + DR_name_offset;
        /* Rockridge extensions (if any) follow name.  Compute this
@@ -1860,9 +1783,43 @@ parse_file_info(struct archive_read *a, struct file_info *parent,
 
        file->nlinks = 1;/* Reset nlink. we'll calculate it later. */
        /* Tell file's parent how many children that parent has. */
-       if (parent != NULL && (flags & 0x02) && file->cl_offset == 0)
+       if (parent != NULL && (flags & 0x02))
                parent->subdirs++;
 
+       if (iso9660->seenRockridge) {
+               if (parent != NULL && parent->parent == NULL &&
+                   (flags & 0x02) && iso9660->rr_moved == NULL &&
+                   (strcmp(file->name.s, "rr_moved") == 0 ||
+                    strcmp(file->name.s, ".rr_moved") == 0)) {
+                       iso9660->rr_moved = file;
+                       file->rr_moved = 1;
+                       file->rr_moved_has_re_only = 1;
+                       file->re = 0;
+                       parent->subdirs--;
+               } else if (file->re) {
+                       /* This file's parent is not rr_moved, clear invalid
+                        * "RE" mark. */
+                       if (parent == NULL || parent->rr_moved == 0)
+                               file->re = 0;
+                       else if ((flags & 0x02) == 0) {
+                               file->rr_moved_has_re_only = 0;
+                               file->re = 0;
+                       }
+               } else if (parent != NULL && parent->rr_moved)
+                       file->rr_moved_has_re_only = 0;
+               else if (parent != NULL && (flags & 0x02) &&
+                   (parent->re || parent->re_descendant))
+                       file->re_descendant = 1;
+               if (file->cl_offset != 0) {
+                       parent->subdirs++;
+                       /* Overwrite an offset and a number of this "CL" entry
+                        * to appear before other dirs. "+1" to those is to
+                        * make sure to appear after "RE" entry which this
+                        * "CL" entry should be connected with. */
+                       file->offset = file->number = file->cl_offset + 1;
+               }
+       }
+
 #if DEBUG
        /* DEBUGGING: Warn about attributes I don't yet fully support. */
        if ((flags & ~0x02) != 0) {
@@ -2476,10 +2433,12 @@ next_entry_seek(struct archive_read *a, struct iso9660 *iso9660,
     struct file_info **pfile)
 {
        struct file_info *file;
+       int r;
 
-       *pfile = file = next_cache_entry(iso9660);
-       if (file == NULL)
-               return (ARCHIVE_EOF);
+       r = next_cache_entry(a, iso9660, pfile);
+       if (r != ARCHIVE_OK)
+               return (r);
+       file = *pfile;
 
        /* Don't waste time seeking for zero-length bodies. */
        if (file->size == 0)
@@ -2500,8 +2459,9 @@ next_entry_seek(struct archive_read *a, struct iso9660 *iso9660,
        return (ARCHIVE_OK);
 }
 
-static struct file_info *
-next_cache_entry(struct iso9660 *iso9660)
+static int
+next_cache_entry(struct archive_read *a, struct iso9660 *iso9660,
+    struct file_info **pfile)
 {
        struct file_info *file;
        struct {
@@ -2513,21 +2473,131 @@ next_cache_entry(struct iso9660 *iso9660)
 
        file = cache_get_entry(iso9660);
        if (file != NULL) {
-               while (file->parent != NULL && !file->parent->exposed) {
-                       /* If file's parent is not exposed, it's moved
-                        * to next entry of its parent. */
-                       cache_add_to_next_of_parent(iso9660, file);
-                       file = cache_get_entry(iso9660);
-               }
-               return (file);
+               *pfile = file;
+               return (ARCHIVE_OK);
        }
 
-       file = next_entry(iso9660);
-       if (file == NULL)
-               return (NULL);
+       for (;;) {
+               struct file_info *re, *d;
+
+               *pfile = file = next_entry(iso9660);
+               if (file == NULL) {
+                       /*
+                        * If directory entries all which are descendant of
+                        * rr_moved are stil remaning, expose their. 
+                        */
+                       if (iso9660->re_files.first != NULL && 
+                           iso9660->rr_moved != NULL &&
+                           iso9660->rr_moved->rr_moved_has_re_only)
+                               /* Expose "rr_moved" entry. */
+                               cache_add_entry(iso9660, iso9660->rr_moved);
+                       while ((re = re_get_entry(iso9660)) != NULL) {
+                               /* Expose its descendant dirs. */
+                               while ((d = rede_get_entry(re)) != NULL)
+                                       cache_add_entry(iso9660, d);
+                       }
+                       if (iso9660->cache_files.first != NULL)
+                               return (next_cache_entry(a, iso9660, pfile));
+                       return (ARCHIVE_EOF);
+               }
+
+               if (file->cl_offset) {
+                       struct file_info *first_re = NULL;
+                       int nexted_re = 0;
+
+                       /*
+                        * Find "RE" dir for the current file, which
+                        * has "CL" flag.
+                        */
+                       while ((re = re_get_entry(iso9660))
+                           != first_re) {
+                               if (first_re == NULL)
+                                       first_re = re;
+                               if (re->offset == file->cl_offset) {
+                                       re->parent->subdirs--;
+                                       re->parent = file->parent;
+                                       re->re = 0;
+                                       if (re->parent->re_descendant) {
+                                               nexted_re = 1;
+                                               re->re_descendant = 1;
+                                               if (rede_add_entry(re) < 0)
+                                                       goto fatal_rr;
+                                               /* Move a list of descendants
+                                                * to a new ancestor. */
+                                               while ((d = rede_get_entry(
+                                                   re)) != NULL)
+                                                       if (rede_add_entry(d)
+                                                           < 0)
+                                                               goto fatal_rr;
+                                               break;
+                                       }
+                                       /* Replace the current file
+                                        * with "RE" dir */
+                                       *pfile = file = re;
+                                       /* Expose its descendant */
+                                       while ((d = rede_get_entry(
+                                           file)) != NULL)
+                                               cache_add_entry(
+                                                   iso9660, d);
+                                       break;
+                               } else
+                                       re_add_entry(iso9660, re);
+                       }
+                       if (nexted_re) {
+                               /*
+                                * Do not expose this at this time
+                                * because we have not gotten its full-path
+                                * name yet.
+                                */
+                               continue;
+                       }
+               } else if ((file->mode & AE_IFMT) == AE_IFDIR) {
+                       int r;
+
+                       /* Read file entries in this dir. */
+                       r = read_children(a, file);
+                       if (r != ARCHIVE_OK)
+                               return (r);
+
+                       /*
+                        * Handle a special dir of Rockridge extensions,
+                        * "rr_moved".
+                        */
+                       if (file->rr_moved) {
+                               /*
+                                * If this has only the subdirectories which
+                                * have "RE" flags, do not expose at this time.
+                                */
+                               if (file->rr_moved_has_re_only)
+                                       continue;
+                               /* Otherwise expose "rr_moved" entry. */
+                       } else if (file->re) {
+                               /*
+                                * Do not expose this at this time
+                                * because we have not gotten its full-path
+                                * name yet.
+                                */
+                               re_add_entry(iso9660, file);
+                               continue;
+                       } else if (file->re_descendant) {
+                               /*
+                                * If the top level "RE" entry of this entry
+                                * is not exposed, we, accordingly, should not
+                                * expose this entry at this time because
+                                * we cannot make its proper full-path name.
+                                */
+                               if (rede_add_entry(file) == 0)
+                                       continue;
+                               /* Otherwise we can expose this entry because
+                                * it seems its top level "RE" has already been
+                                * exposed. */
+                       }
+               }
+               break;
+       }
 
        if ((file->mode & AE_IFMT) != AE_IFREG || file->number == -1)
-               return (file);
+               return (ARCHIVE_OK);
 
        count = 0;
        number = file->number;
@@ -2560,8 +2630,10 @@ next_cache_entry(struct iso9660 *iso9660)
                file = next_entry(iso9660);
        }
 
-       if (count == 0)
-               return (file);
+       if (count == 0) {
+               *pfile = file;
+               return ((file == NULL)?ARCHIVE_EOF:ARCHIVE_OK);
+       }
        if (file->number == -1) {
                file->next = NULL;
                *empty_files.last = file;
@@ -2586,24 +2658,75 @@ next_cache_entry(struct iso9660 *iso9660)
                *iso9660->cache_files.last = empty_files.first;
                iso9660->cache_files.last = empty_files.last;
        }
-       return (cache_get_entry(iso9660));
+       *pfile = cache_get_entry(iso9660);
+       return ((*pfile == NULL)?ARCHIVE_EOF:ARCHIVE_OK);
+
+fatal_rr:
+       archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+           "Failed to connect 'CL' pointer to 'RE' rr_moved pointer of"
+           "Rockridge extensions");
+       return (ARCHIVE_FATAL);
 }
 
 static inline void
-cache_add_entry(struct iso9660 *iso9660, struct file_info *file)
+re_add_entry(struct iso9660 *iso9660, struct file_info *file)
 {
-       file->next = NULL;
-       *iso9660->cache_files.last = file;
-       iso9660->cache_files.last = &(file->next);
+       file->re_next = NULL;
+       *iso9660->re_files.last = file;
+       iso9660->re_files.last = &(file->re_next);
+}
+
+static inline struct file_info *
+re_get_entry(struct iso9660 *iso9660)
+{
+       struct file_info *file;
+
+       if ((file = iso9660->re_files.first) != NULL) {
+               iso9660->re_files.first = file->re_next;
+               if (iso9660->re_files.first == NULL)
+                       iso9660->re_files.last =
+                           &(iso9660->re_files.first);
+       }
+       return (file);
+}
+
+static inline int
+rede_add_entry(struct file_info *file)
+{
+       struct file_info *re;
+
+       re = file->parent;
+       while (re != NULL && !re->re)
+               re = re->parent;
+       if (re == NULL)
+               return (-1);
+
+       file->re_next = NULL;
+       *re->rede_files.last = file;
+       re->rede_files.last = &(file->re_next);
+       return (0);
+}
+
+static inline struct file_info *
+rede_get_entry(struct file_info *re)
+{
+       struct file_info *file;
+
+       if ((file = re->rede_files.first) != NULL) {
+               re->rede_files.first = file->re_next;
+               if (re->rede_files.first == NULL)
+                       re->rede_files.last =
+                           &(re->rede_files.first);
+       }
+       return (file);
 }
 
 static inline void
-cache_add_to_next_of_parent(struct iso9660 *iso9660, struct file_info *file)
+cache_add_entry(struct iso9660 *iso9660, struct file_info *file)
 {
-       file->next = file->parent->next;
-       file->parent->next = file;
-       if (iso9660->cache_files.last == &(file->parent->next))
-               iso9660->cache_files.last = &(file->next);
+       file->next = NULL;
+       *iso9660->cache_files.last = file;
+       iso9660->cache_files.last = &(file->next);
 }
 
 static inline struct file_info *
index 21d421e..811d1a3 100644 (file)
@@ -525,6 +525,7 @@ parse_file(struct archive_read *a, struct archive_entry *entry,
        /* Initialize reasonable defaults. */
        mtree->filetype = AE_IFREG;
        archive_entry_set_size(entry, 0);
+       archive_string_empty(&mtree->contents_name);
 
        /* Parse options from this line. */
        parsed_kws = 0;
@@ -613,9 +614,8 @@ parse_file(struct archive_read *a, struct archive_entry *entry,
        }
 
        /*
-        * If there is a contents file on disk, use that size;
-        * otherwise leave it as-is (it might have been set from
-        * the mtree size= keyword).
+        * Check for a mismatch between the type in the specification and
+        * the type of the contents object on disk.
         */
        if (st != NULL) {
                mismatched_type = 0;
@@ -660,6 +660,11 @@ parse_file(struct archive_read *a, struct archive_entry *entry,
                }
        }
 
+       /*
+        * If there is a contents file on disk, pick some of the metadata
+        * from that file.  For most of these, we only set it from the contents
+        * if it wasn't already parsed from the specification.
+        */
        if (st != NULL) {
                if ((parsed_kws & MTREE_HAS_DEVICE) == 0 &&
                    (archive_entry_filetype(entry) == AE_IFCHR ||
index 25d7a8b..782c1b1 100644 (file)
@@ -44,6 +44,8 @@
 #include <wchar.h>
 #endif
 
+#include "archive.h"
+
 /*
  * Basic resizable/reusable string support a la Java's "StringBuffer."
  *
@@ -134,10 +136,11 @@ void      __archive_string_free(struct archive_string *);
 
 /* Like 'vsprintf', but resizes the underlying string as necessary. */
 void   __archive_string_vsprintf(struct archive_string *, const char *,
-           va_list);
+           va_list) __LA_PRINTF(2, 0);
 #define        archive_string_vsprintf __archive_string_vsprintf
 
-void   __archive_string_sprintf(struct archive_string *, const char *, ...);
+void   __archive_string_sprintf(struct archive_string *, const char *, ...)
+           __LA_PRINTF(2, 3);
 #define        archive_string_sprintf  __archive_string_sprintf
 
 /* Allocates a fresh buffer and converts as (assumed to be UTF-8) into it.
index caf958e..f6f72c2 100644 (file)
@@ -1730,7 +1730,7 @@ create_dir(struct archive_write_disk *a, char *path)
                if (unlink(path) != 0) {
                        archive_set_error(&a->archive, errno,
                            "Can't create directory '%s': "
-                           "Conflicting file cannot be removed");
+                           "Conflicting file cannot be removed", path);
                        return (ARCHIVE_FAILED);
                }
        } else if (errno != ENOENT && errno != ENOTDIR) {
index 3a60398..d5c426c 100644 (file)
@@ -51,7 +51,6 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_write_open_fd.c 201093 2009-12-2
 #include "archive.h"
 
 struct write_fd_data {
-       off_t           offset;
        int             fd;
 };
 
@@ -122,12 +121,16 @@ file_write(struct archive *a, void *client_data, const void *buff, size_t length
        ssize_t bytesWritten;
 
        mine = (struct write_fd_data *)client_data;
-       bytesWritten = write(mine->fd, buff, length);
-       if (bytesWritten <= 0) {
-               archive_set_error(a, errno, "Write error");
-               return (-1);
+       for (;;) {
+               bytesWritten = write(mine->fd, buff, length);
+               if (bytesWritten <= 0) {
+                       if (errno == EINTR)
+                               continue;
+                       archive_set_error(a, errno, "Write error");
+                       return (-1);
+               }
+               return (bytesWritten);
        }
-       return (bytesWritten);
 }
 
 static int
index 5c0c737..f6b1412 100644 (file)
@@ -86,12 +86,16 @@ file_write(struct archive *a, void *client_data, const void *buff, size_t length
        size_t  bytesWritten;
 
        mine = client_data;
-       bytesWritten = fwrite(buff, 1, length, mine->f);
-       if (bytesWritten < length) {
-               archive_set_error(a, errno, "Write error");
-               return (-1);
+       for (;;) {
+               bytesWritten = fwrite(buff, 1, length, mine->f);
+               if (bytesWritten <= 0) {
+                       if (errno == EINTR)
+                               continue;
+                       archive_set_error(a, errno, "Write error");
+                       return (-1);
+               }
+               return (bytesWritten);
        }
-       return (bytesWritten);
 }
 
 static int
index 6a9c778..8a4cd35 100644 (file)
@@ -142,12 +142,16 @@ file_write(struct archive *a, void *client_data, const void *buff, size_t length
        ssize_t bytesWritten;
 
        mine = (struct write_file_data *)client_data;
-       bytesWritten = write(mine->fd, buff, length);
-       if (bytesWritten <= 0) {
-               archive_set_error(a, errno, "Write error");
-               return (-1);
+       for (;;) {
+               bytesWritten = write(mine->fd, buff, length);
+               if (bytesWritten <= 0) {
+                       if (errno == EINTR)
+                               continue;
+                       archive_set_error(a, errno, "Write error");
+                       return (-1);
+               }
+               return (bytesWritten);
        }
-       return (bytesWritten);
 }
 
 static int
index f82f6db..3193eb4 100644 (file)
@@ -132,9 +132,10 @@ static int
 archive_compressor_xz_init_stream(struct archive_write *a,
     struct private_data *state)
 {
+       static const lzma_stream lzma_stream_init_data = LZMA_STREAM_INIT;
        int ret;
 
-       state->stream = (lzma_stream)LZMA_STREAM_INIT;
+       state->stream = lzma_stream_init_data;
        state->stream.next_out = state->compressed;
        state->stream.avail_out = state->compressed_buffer_size;
        if (a->archive.compression_code == ARCHIVE_COMPRESSION_XZ)
@@ -421,8 +422,8 @@ drive_compressor(struct archive_write *a, struct private_data *state, int finish
                        archive_set_error(&a->archive, ENOMEM,
                            "lzma compression error: "
                            "%ju MiB would have been needed",
-                           (lzma_memusage(&(state->stream)) + 1024 * 1024 -1)
-                           / (1024 * 1024));
+                           (uintmax_t)((lzma_memusage(&(state->stream)) + 1024 * 1024 -1)
+                               / (1024 * 1024)));
                        return (ARCHIVE_FATAL);
                default:
                        /* Any other return value indicates an error. */
index b492cea..2180fc9 100644 (file)
@@ -440,7 +440,7 @@ archive_write_ar_finish_entry(struct archive_write *a)
        if (ar->entry_padding != 1) {
                archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
                    "Padding wrong size: %d should be 1 or 0",
-                   ar->entry_padding);
+                   (int)ar->entry_padding);
                return (ARCHIVE_WARN);
        }
 
index 62a875b..235e4c1 100644 (file)
@@ -537,8 +537,7 @@ archive_write_shar_finish_entry(struct archive_write *a)
                }
 
                if ((p = archive_entry_fflags_text(shar->entry)) != NULL) {
-                       archive_string_sprintf(&shar->work, "chflags %s ",
-                           p, archive_entry_pathname(shar->entry));
+                       archive_string_sprintf(&shar->work, "chflags %s ", p);
                        shar_quote(&shar->work,
                            archive_entry_pathname(shar->entry), 1);
                        archive_strcat(&shar->work, "\n");
index 1de273f..9be4986 100644 (file)
@@ -168,7 +168,7 @@ archive_write_set_format_ustar(struct archive *_a)
 
        /* Basic internal sanity test. */
        if (sizeof(template_header) != 512) {
-               archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Internal: template_header wrong size: %d should be 512", sizeof(template_header));
+               archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Internal: template_header wrong size: %d should be 512", (int)sizeof(template_header));
                return (ARCHIVE_FATAL);
        }
 
index 14cc669..201152f 100644 (file)
@@ -502,6 +502,9 @@ archive_write_zip_finish(struct archive_write *a)
        int entries;
        int ret;
 
+       if (a->compressor.write == NULL)
+               return (ARCHIVE_OK);
+
        zip = a->format_data;
        l = zip->central_directory;