e.g.
-- Reuslt of previous bsdtar.
%bsdtar tvf test_read_format_iso_multi_extent.iso
dr-xr-xr-x 2 1 2 2048 1 2 1970 .
-r--r--r-- 1 1 2 129024 1 2 1970 file
-r--r--r-- 1 1 2 129024 1 2 1970 file
-r--r--r-- 1 1 2 4232 1 2 1970 file
-- After patch.
%bsdtar tvf test_read_format_iso_multi_extent.iso
dr-xr-xr-x 2 1 2 2048 1 2 1970 .
-r--r--r-- 1 1 2 262280 1 2 1970 file
SVN-Revision: 1537
libarchive/test/test_read_format_gtar_lzma.c \
libarchive/test/test_read_format_gtar_sparse.c \
libarchive/test/test_read_format_iso_gz.c \
+ libarchive/test/test_read_format_iso_multi_extent.c \
libarchive/test/test_read_format_isojoliet_bz2.c \
libarchive/test/test_read_format_isojoliet_long.c \
libarchive/test/test_read_format_isojoliet_rr.c \
libarchive/test/test_read_format_gtar_sparse_1_17_posix10.tar.uu \
libarchive/test/test_read_format_gtar_sparse_1_17_posix10_modified.tar.uu \
libarchive/test/test_read_format_iso_gz.iso.gz.uu \
+ libarchive/test/test_read_format_iso_multi_extent.iso.gz.uu \
libarchive/test/test_read_format_isojoliet_bz2.iso.bz2.uu \
libarchive/test/test_read_format_isojoliet_long.iso.bz2.uu \
libarchive/test/test_read_format_isojoliet_rr.iso.bz2.uu \
};
#endif
+struct content {
+ uint64_t offset;/* Offset on disk. */
+ uint64_t size; /* File size in bytes. */
+ struct content *next;
+};
+
/* In-memory storage for a directory record. */
struct file_info {
struct file_info *parent;
int pz;
int pz_log2_bs; /* Log2 of block size */
uint64_t pz_uncompressed_size;
+ /* Set 1 if this file is multi extent. */
+ int multi_extent;
+ struct {
+ struct content *first;
+ struct content **last;
+ } contents;
};
struct heap_queue {
off_t entry_sparse_offset;
int64_t entry_bytes_remaining;
struct zisofs entry_zisofs;
+ struct content *entry_content;
};
static int archive_read_format_iso9660_bid(struct archive_read *);
{
struct iso9660 *iso9660;
const unsigned char *b, *p;
+ struct file_info *multi;
size_t step;
iso9660 = (struct iso9660 *)(a->format->data);
}
__archive_read_consume(a, step);
iso9660->current_position += step;
+ multi = NULL;
while (step) {
p = b;
b += iso9660->logical_block_size;
if (child->cl_offset)
heap_add_entry(iso9660,
&(iso9660->cl_files), child);
- else
- add_entry(iso9660, child);
+ 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) {
+ release_file(iso9660, child);
+ 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;
+ release_file(iso9660, child);
+ }
+ } else
+ add_entry(iso9660, child);
+ }
}
}
iso9660->previous_number = file->number;
archive_strcpy(&iso9660->previous_pathname, iso9660->pathname.s);
+ /* Reset entry_bytes_remaining if the file is multi extent. */
+ iso9660->entry_content = file->contents.first;
+ if (iso9660->entry_content != NULL)
+ iso9660->entry_bytes_remaining = iso9660->entry_content->size;
+
if (archive_entry_filetype(entry) == AE_IFDIR) {
/* Overwrite nlinks by proper link number which is
* calculated from number of sub directories. */
iso9660 = (struct iso9660 *)(a->format->data);
if (iso9660->entry_bytes_remaining <= 0) {
- *buff = NULL;
- *size = 0;
- *offset = iso9660->entry_sparse_offset;
- return (ARCHIVE_EOF);
+ if (iso9660->entry_content != NULL)
+ iso9660->entry_content = iso9660->entry_content->next;
+ if (iso9660->entry_content == NULL) {
+ *buff = NULL;
+ *size = 0;
+ *offset = iso9660->entry_sparse_offset;
+ return (ARCHIVE_EOF);
+ }
+ /* Seek forward to the start of the entry. */
+ if (iso9660->current_position < iso9660->entry_content->offset) {
+ int64_t step;
+
+ step = iso9660->entry_content->offset -
+ iso9660->current_position;
+ step = __archive_read_skip(a, step);
+ if (step < 0)
+ return ((int)step);
+ iso9660->current_position =
+ iso9660->entry_content->offset;
+ }
+ if (iso9660->entry_content->offset < iso9660->current_position) {
+ 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);
+ iso9660->entry_bytes_remaining = 0;
+ iso9660->entry_sparse_offset = 0;
+ return (ARCHIVE_WARN);
+ }
+ iso9660->entry_bytes_remaining = iso9660->entry_content->size;
}
if (iso9660->entry_zisofs.pz)
return (zisofs_read_data(a, buff, size, offset));
file->mode = AE_IFDIR | 0700;
else
file->mode = AE_IFREG | 0400;
+ if (flags & 0x80)
+ file->multi_extent = 1;
+ else
+ file->multi_extent = 0;
/*
* Use location for file number.
* File number is treated as inode number to find out harlink
release_file(struct iso9660 *iso9660, struct file_info *file)
{
struct file_info *parent;
+ struct content *con, *connext;
if (file == NULL)
return;
parent = file->parent;
archive_string_free(&file->name);
archive_string_free(&file->symlink);
+ con = file->contents.first;
+ while (con != NULL) {
+ connext = con->next;
+ free(con);
+ con = connext;
+ }
free(file);
if (parent != NULL) {
parent->refcount--;
test_read_format_gtar_lzma.c
test_read_format_gtar_sparse.c
test_read_format_iso_gz.c
+ test_read_format_iso_multi_extent.c
test_read_format_isojoliet_bz2.c
test_read_format_isojoliet_long.c
test_read_format_isojoliet_rr.c
--- /dev/null
+/*-
+ * Copyright (c) 2003-2007 Tim Kientzle
+ * Copyright (c) 2009 Michihiro NAKAJIMA
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "test.h"
+
+DEFINE_TEST(test_read_format_iso_multi_extent)
+{
+ const char *refname = "test_read_format_iso_multi_extent.iso.bz2";
+ struct archive_entry *ae;
+ struct archive *a;
+ const void *p;
+ size_t size;
+ off_t offset;
+ int i;
+ int r;
+
+ extract_reference_file(refname);
+ assert((a = archive_read_new()) != NULL);
+ r = archive_read_support_compression_bzip2(a);
+ if (r == ARCHIVE_WARN) {
+ skipping("bzip2 reading not fully supported on this platform");
+ assertEqualInt(0, archive_read_finish(a));
+ return;
+ }
+ assertEqualInt(0, r);
+ assertEqualInt(0, archive_read_support_format_all(a));
+ assertEqualInt(ARCHIVE_OK,
+ archive_read_open_filename(a, refname, 10240));
+
+ /* Retrieve each of the 2 files on the ISO image and
+ * verify that each one is what we expect. */
+ for (i = 0; i < 2; ++i) {
+ assertEqualInt(0, archive_read_next_header(a, &ae));
+
+ if (strcmp(".", archive_entry_pathname(ae)) == 0) {
+ /* '.' root directory. */
+ assertEqualInt(AE_IFDIR, archive_entry_filetype(ae));
+ assertEqualInt(2048, archive_entry_size(ae));
+ assertEqualInt(86401, archive_entry_mtime(ae));
+ assertEqualInt(0, archive_entry_mtime_nsec(ae));
+ assertEqualInt(2, archive_entry_stat(ae)->st_nlink);
+ assertEqualInt(1, archive_entry_uid(ae));
+ assertEqualIntA(a, ARCHIVE_EOF,
+ archive_read_data_block(a, &p, &size, &offset));
+ assertEqualInt((int)size, 0);
+ } else if (strcmp("file", archive_entry_pathname(ae)) == 0) {
+ /* A regular file. */
+ assertEqualString("file", archive_entry_pathname(ae));
+ assertEqualInt(AE_IFREG, archive_entry_filetype(ae));
+ assertEqualInt(262280, archive_entry_size(ae));
+ assertEqualInt(0,
+ archive_read_data_block(a, &p, &size, &offset));
+ assertEqualInt(0, offset);
+ assertEqualMem(p, "head--head--head", 16);
+ assertEqualInt(86401, archive_entry_mtime(ae));
+ assertEqualInt(86401, archive_entry_atime(ae));
+ assertEqualInt(1, archive_entry_stat(ae)->st_nlink);
+ assertEqualInt(1, archive_entry_uid(ae));
+ assertEqualInt(2, archive_entry_gid(ae));
+ } else {
+ failure("Saw a file that shouldn't have been there");
+ assertEqualString(archive_entry_pathname(ae), "");
+ }
+ }
+
+ /* End of archive. */
+ assertEqualInt(ARCHIVE_EOF, archive_read_next_header(a, &ae));
+
+ /* Verify archive format. */
+ assertEqualInt(archive_compression(a), ARCHIVE_COMPRESSION_BZIP2);
+ assertEqualInt(archive_format(a), ARCHIVE_FORMAT_ISO9660_ROCKRIDGE);
+
+ /* Close the archive. */
+ assertEqualInt(0, archive_read_close(a));
+ assertEqualInt(0, archive_read_finish(a));
+}
+
+
--- /dev/null
+begin 644 test_read_format_iso_multi_extent.iso.bz2
+M0EIH.3%!62936?,G"4,``1Y_[??U9_?6%_FZ/^_?X;]GG89@Z,`"``4!```"
+M@$C0`V\$@Z6W'77#**>C48IZ:0>C(F@`&CU&AH#0#30``'J&@/4]0-!$:$;4
+MF(:`R``-``````:``!H#32"*9/TH/4::`````9&0``#0&@``'`T!H-&@9-``
+M:``Q-#30--`#1HT`#1H(DD$B;133/4T:GJ!DTV0R`RAAJ#3:`F`T#0"`("P7
+M`D/7M82QF:&0!.)GBD1`8:9M'Y,CE3`2M`J59X%MJMB-H22,$<2(!R(`:T_B
+M;$07,$0$3FP4`%RP!4\=U+FS9YH*"JAIC["B&(!1`@BZ-2AJ*HBACC0KR!2*
+M#5I)*&X^L^]+!K_+>PN+FJ]FSH"O[16Z".[5(HD@AUXJ=F:>K6.>XDU"M79,
+M$ZR;+`WEI4[;W.3C%ME<(,H#TUFTMNWBSU47WEIK\T,K[72N@TH.)JU7\HPQ
+MP%H^!\C2K3B6VTV+"$)!(!!(&&+(68C0;P[5&QV+@?N"Z^Q_?Z79Q+YT7/<0
+M+%)P12P]3<3+84W7&CAU\;C@I^^`;Y@FD.4N5L*0HB$C_54R*:Z0\VZF#8?J
+M(-,,!3::,]+%W3VRD_DP7LCK=NU6JW&2G.(1G,HI(Y)ZBQ03(0!$(=,@=#2M
+MPH7MZ]B+XOALU^&CG3J^K,UA0M$;*K*5-:IA8/BTW0HOG1HDH^S@6H/,DH8$
+M(#%"0B]*7F9-[W)UDWD^$3-PO!JT^?@&D:,`O&&P<=L.1>'K8(;8^G.&P-PP
+M;7T/MW[]]PP,IE/]6*>HI!:V`2:1#%(10D2L(1LUSVJY-V?FBLQAQW_`;:9E
+MS%@<2+@B2,Q7]7?]J<1=B$`::Z`X)CQ4&$(3<8`2Q0]^N<#B;6,#<R<8FO6!
+MHUJ7&.4ZQ!]Z9DH,4R'S])FS"-L:(^&4(I"9IM=0I,A:A!6PF&!1&X,6PCB<
+M*4H%`Z]$,:)Q)8E!)31@,6OZ2A5@<)M"*@^BL04-:93@V$YZ$J2F3C%0L\+,
+M`<0FO!D8<CXHY8:SFV<`J27A)!'(X`P,YLP-#RKS#5"B,M#9#:"41K[<(J5)
+M'`B2QW"*<C)9B/4U@(*^`(,$!FP*I@:K;@%M`OF*ME/B!.(5XM$R`K5Z*9!_
+M-\B285-`QFBVZR4$72#.@A&@1C#OEE[FY'U9L]92'VR#C=*#GH1(3QE80ZPI
+=,+<O4!D:N9?-_F@8"(BA@F]_XNY(IPH2'F3A*&``
+`
+end