following sub directories.
Add corresponding test.
Unfortunately, some tests need tweaks due to difference of ordering of
hardlink files(which have the same offset); it's characteristic of heap.
SVN-Revision: 1529
libarchive/test/test_read_format_isorr_bz2.c \
libarchive/test/test_read_format_isorr_ce.c \
libarchive/test/test_read_format_isorr_new_bz2.c \
+ libarchive/test/test_read_format_isorr_rr_moved.c \
libarchive/test/test_read_format_isozisofs_bz2.c \
libarchive/test/test_read_format_mtree.c \
libarchive/test/test_read_format_pax_bz2.c \
libarchive/test/test_read_format_isorr_bz2.iso.bz2.uu \
libarchive/test/test_read_format_isorr_ce.iso.bz2.uu \
libarchive/test/test_read_format_isorr_new_bz2.iso.bz2.uu \
+ libarchive/test/test_read_format_isorr_rr_moved.iso.bz2.uu \
libarchive/test/test_read_format_isozisofs_bz2.iso.bz2.uu \
libarchive/test/test_read_format_raw.data.Z.uu \
libarchive/test/test_read_format_raw.data.uu \
/* In-memory storage for a directory record. */
struct file_info {
struct file_info *parent;
+ struct file_info *next;
int refcount;
int subdirs;
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 re; /* Having RRIP "RE" extension. */
+ uint64_t cl_offset; /* Having RRIP "CL" extension. */
time_t birthtime; /* File created time. */
time_t mtime; /* File last modified time. */
time_t atime; /* File last accessed time. */
char seenJoliet;
unsigned char suspOffset;
+ struct file_info *rr_moved;
+ struct {
+ struct file_info *first;
+ struct file_info **last;
+ } re_dirs;
+ struct {
+ struct file_info *first;
+ struct file_info **last;
+ } cl_files;
struct {
struct read_ce_req {
uint64_t offset;/* Offset of CE on disk. */
int cnt;
int allocated;
} read_ce_req;
+
int64_t previous_number;
uint64_t previous_size;
struct archive_string previous_pathname;
int count;
int index;
} cache_files;
+ struct {
+ struct file_info *first;
+ struct file_info **last;
+ } pending_dirs;
+ int read_pending_dirs;
uint64_t current_position;
ssize_t logical_block_size;
}
memset(iso9660, 0, sizeof(*iso9660));
iso9660->magic = ISO9660_MAGIC;
+ iso9660->pending_dirs.first = NULL;
+ iso9660->pending_dirs.last = &(iso9660->pending_dirs.first);
+ iso9660->re_dirs.first = NULL;
+ iso9660->re_dirs.last = &(iso9660->re_dirs.first);
+ iso9660->cl_files.first = NULL;
+ iso9660->cl_files.last = &(iso9660->cl_files.first);
/* Enable to support Joliet extensions by default. */
iso9660->opt_support_joliet = 1;
/* Enable to support Rock Ridge extensions by default. */
size_t step;
iso9660 = (struct iso9660 *)(a->format->data);
+ if (iso9660->current_position > parent->offset) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
+ "Ignoring out-of-order directory (%s) %jd > %jd",
+ parent->name.s,
+ iso9660->current_position,
+ 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);
+ return (ARCHIVE_WARN);
+ }
+ if (iso9660->current_position < parent->offset) {
+ int64_t skipsize;
+
+ skipsize = parent->offset - iso9660->current_position;
+ skipsize = __archive_read_skip(a, skipsize);
+ if (skipsize < 0)
+ return ((int)skipsize);
+ iso9660->current_position = parent->offset;
+ }
step = ((parent->size + iso9660->logical_block_size -1) /
iso9660->logical_block_size) * iso9660->logical_block_size;
child = parse_file_info(a, parent, p);
if (child == NULL)
return (ARCHIVE_FATAL);
- add_entry(iso9660, child);
+ if (child->cl_offset) {
+ child->next = NULL;
+ *iso9660->cl_files.last = child;
+ iso9660->cl_files.last = &(child->next);
+ } else
+ add_entry(iso9660, child);
+ }
+ }
+
+ /* Read data which recorded by RRIP "CE" extension. */
+ if (read_CE(a, iso9660) != ARCHIVE_OK)
+ return (ARCHIVE_FATAL);
+
+ return (ARCHIVE_OK);
+}
+
+static int
+relocate_dir(struct iso9660 *iso9660, struct file_info *file)
+{
+ struct file_info **cl;
+ struct file_info *tmp;
+
+ for (cl = &iso9660->re_dirs.first; *cl != NULL;
+ cl = &((*cl)->next)) {
+ if ((*cl)->offset == file->cl_offset) {
+ tmp = *cl;
+ (*cl)->parent->refcount--;
+ file->parent->refcount++;
+ file->parent->subdirs++;
+ (*cl)->parent = file->parent;
+ *cl = (*cl)->next;
+ iso9660->rr_moved->subdirs--;
+ tmp->next = NULL;
+ tmp->refcount++;
+ *iso9660->pending_dirs.last = tmp;
+ iso9660->pending_dirs.last = &(tmp->next);
+ return (1);
+ }
+ }
+ 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) {
+ file->next = NULL;
+ *iso9660->re_dirs.last = file;
+ iso9660->re_dirs.last = &(file->next);
+ } else {
+ file->next = NULL;
+ file->refcount++;
+ *iso9660->pending_dirs.last = file;
+ iso9660->pending_dirs.last = &(file->next);
+ }
+ }
+ if (file != NULL)
+ add_entry(iso9660, file);
+
+ if (iso9660->rr_moved != NULL) {
+ struct file_info *next;
+
+ /*
+ * Relocate directory which rr_moved has.
+ */
+ for (file = iso9660->cl_files.first; file != NULL;
+ file = next) {
+ next = file->next;
+
+ relocate_dir(iso9660, file);
+ release_file(iso9660, file);
+ }
+
+ /* If rr_moved directory still has children,
+ * Add rr_moved into pending_files to show
+ */
+ if (iso9660->rr_moved->subdirs)
+ add_entry(iso9660, iso9660->rr_moved);
+ else {
+ iso9660->rr_moved->parent->subdirs--;
+ release_file(iso9660, iso9660->rr_moved);
}
}
+ iso9660->read_pending_dirs = 1;
+
return (ARCHIVE_OK);
}
{
struct iso9660 *iso9660;
struct file_info *file;
- int r;
+ int r, rd_r;
iso9660 = (struct iso9660 *)(a->format->data);
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);
* will give us support for whacky ISO images that require
* seeking while retaining the ability to read almost all ISO
* images in a streaming fashion. */
- if (file->offset < iso9660->current_position) {
+ 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,
iso9660->previous_number = file->number;
archive_strcpy(&iso9660->previous_pathname, iso9660->pathname.s);
- /* If this is a directory, read in all of the entries right now. */
if (archive_entry_filetype(entry) == AE_IFDIR) {
- r = read_children(a, file);
- if (r != ARCHIVE_OK) {
- release_file(iso9660, file);
- return (ARCHIVE_FATAL);
- }
/* Overwrite nlinks by proper link number which is
* calculated from number of sub directories. */
archive_entry_set_nlink(entry, 2 + file->subdirs);
}
release_file(iso9660, file);
+
+ if (rd_r != ARCHIVE_OK)
+ return (rd_r);
return (ARCHIVE_OK);
}
}
/* Tell file's parent how many children that parent has. */
- if (parent != NULL && (flags & 0x02))
+ if (parent != NULL && (flags & 0x02) && file->cl_offset == 0)
parent->subdirs++;
#if DEBUG
}
file_offset = file->offset + file->size;
+ file->refcount++;
/*
* Start with hole at end, walk it up tree to find insertion point.
iso9660 = (struct iso9660 *)(a->format->data);
- while (p + 4 < end /* Enough space for another entry. */
+ while (p + 4 <= end /* Enough space for another entry. */
&& p[0] >= 'A' && p[0] <= 'Z' /* Sanity-check 1st char of name. */
&& p[1] >= 'A' && p[1] <= 'Z' /* Sanity-check 2nd char of name. */
&& p[2] >= 4 /* Sanity-check length. */
}
break;
}
+ if (p[0] == 'C' && p[1] == 'L') {
+ if (version == 1 && data_length == 8) {
+ file->cl_offset = (uint64_t)
+ iso9660->logical_block_size *
+ (uint64_t)archive_le32dec(data);
+ iso9660->seenRockridge = 1;
+ }
+ break;
+ }
/* FALLTHROUGH */
case 'N':
if (p[0] == 'N' && p[1] == 'M') {
}
/* FALLTHROUGH */
case 'R':
+ if (p[0] == 'R' && p[1] == 'E' && version == 1) {
+ file->re = 1;
+ iso9660->seenRockridge = 1;
+ break;
+ }
if (p[0] == 'R' && p[1] == 'R' && version == 1) {
/*
* RR extension comprises:
if (file == NULL)
return (ARCHIVE_EOF);
- /* Read data which recorded by RRIP "CE" extension. */
- if (read_CE(a, iso9660) != ARCHIVE_OK)
- return (ARCHIVE_FATAL);
-
/* Don't waste time seeking for zero-length bodies. */
if (file->size == 0)
file->offset = iso9660->current_position;
int a, b, c;
struct file_info *r, *tmp;
+ if (iso9660->read_pending_dirs) {
+
+ r = iso9660->pending_dirs.first;
+ if (r != NULL) {
+ iso9660->pending_dirs.first = r->next;
+ r->refcount--;
+ return (r);
+ } else
+ iso9660->read_pending_dirs = 0;
+ }
+
if (iso9660->pending_files_used < 1)
return (NULL);
* The first file in the list is the earliest; we'll return this.
*/
r = iso9660->pending_files[0];
+ r->refcount--;
/*
* Move the last item in the heap to the root of the tree
test_read_format_isorr_bz2.c
test_read_format_isorr_ce.c
test_read_format_isorr_new_bz2.c
+ test_read_format_isorr_rr_moved.c
test_read_format_isozisofs_bz2.c
test_read_format_mtree.c
test_read_format_pax_bz2.c
test_read_format_isorr_bz2.c \
test_read_format_isorr_ce.c \
test_read_format_isorr_new_bz2.c \
+ test_read_format_isorr_rr_moved.c \
test_read_format_isozisofs_bz2.c \
test_read_format_mtree.c \
test_read_format_pax_bz2.c \
/* A regular file with two names ("hardlink" gets returned
* first, so it's not marked as a hardlink). */
assertEqualInt(0, archive_read_next_header(a, &ae));
- assertEqualString("hardlink", archive_entry_pathname(ae));
+ assertEqualString("long-joliet-file-name.textfile",
+ archive_entry_pathname(ae));
assertEqualInt(AE_IFREG, archive_entry_filetype(ae));
assert(archive_entry_hardlink(ae) == NULL);
assertEqualInt(6, archive_entry_size(ae));
/* Second name for the same regular file (this happens to be
* returned second, so does get marked as a hardlink). */
assertEqualInt(0, archive_read_next_header(a, &ae));
- assertEqualString("long-joliet-file-name.textfile",
- archive_entry_pathname(ae));
+ assertEqualString("hardlink", archive_entry_pathname(ae));
assertEqualInt(AE_IFREG, archive_entry_filetype(ae));
- assertEqualString("hardlink", archive_entry_hardlink(ae));
+ assertEqualString("long-joliet-file-name.textfile",
+ archive_entry_hardlink(ae));
assert(!archive_entry_size_is_set(ae));
/* A symlink to the regular file. */
assertEqualInt(86401, archive_entry_mtime(ae));
assertEqualInt(86401, archive_entry_atime(ae));
- /* A regular file with two names ("hardlink" gets returned
+ /* A regular file with two names (pathname gets returned
* first, so it's not marked as a hardlink). */
+ pathname[100] = '1';
+ pathname[101] = '2';
+ pathname[102] = '3';
+ pathname[103] = '\0';
assertEqualInt(0, archive_read_next_header(a, &ae));
- assertEqualString("hardlink", archive_entry_pathname(ae));
+ assertEqualString(pathname, archive_entry_pathname(ae));
assertEqualInt(AE_IFREG, archive_entry_filetype(ae));
assert(archive_entry_hardlink(ae) == NULL);
assertEqualInt(6, archive_entry_size(ae));
/* Second name for the same regular file (this happens to be
* returned second, so does get marked as a hardlink). */
- pathname[100] = '1';
- pathname[101] = '2';
- pathname[102] = '3';
- pathname[103] = '\0';
assertEqualInt(0, archive_read_next_header(a, &ae));
- assertEqualString(pathname, archive_entry_pathname(ae));
+ assertEqualString("hardlink", archive_entry_pathname(ae));
assertEqualInt(AE_IFREG, archive_entry_filetype(ae));
- assertEqualString("hardlink", archive_entry_hardlink(ae));
+ assertEqualString(pathname, archive_entry_hardlink(ae));
assert(!archive_entry_size_is_set(ae));
/* End of archive. */
/* A regular file with two names ("hardlink" gets returned
* first, so it's not marked as a hardlink). */
assertEqualInt(0, archive_read_next_header(a, &ae));
- assertEqualString("hardlink", archive_entry_pathname(ae));
+ assertEqualString("long-joliet-file-name.textfile",
+ archive_entry_pathname(ae));
assertEqualInt(AE_IFREG, archive_entry_filetype(ae));
assert(archive_entry_hardlink(ae) == NULL);
assertEqualInt(6, archive_entry_size(ae));
/* Second name for the same regular file (this happens to be
* returned second, so does get marked as a hardlink). */
assertEqualInt(0, archive_read_next_header(a, &ae));
- assertEqualString("long-joliet-file-name.textfile",
- archive_entry_pathname(ae));
+ assertEqualString("hardlink", archive_entry_pathname(ae));
assertEqualInt(AE_IFREG, archive_entry_filetype(ae));
- assertEqualString("hardlink", archive_entry_hardlink(ae));
+ assertEqualString("long-joliet-file-name.textfile",
+ archive_entry_hardlink(ae));
assert(!archive_entry_size_is_set(ae));
assertEqualInt(86401, archive_entry_mtime(ae));
assertEqualInt(86401, archive_entry_atime(ae));
assertEqualInt(2, archive_entry_stat(ae)->st_nlink);
assertEqualInt(1, archive_entry_uid(ae));
assertEqualInt(2, archive_entry_gid(ae));
- } else if (strcmp("file", archive_entry_pathname(ae)) == 0) {
+ } else if (strcmp("hardlink", archive_entry_pathname(ae)) == 0) {
/* A regular file. */
- assertEqualString("file", archive_entry_pathname(ae));
+ assertEqualString("hardlink", archive_entry_pathname(ae));
assertEqualInt(AE_IFREG, archive_entry_filetype(ae));
assertEqualInt(12345684, archive_entry_size(ae));
assertEqualInt(0,
assertEqualInt(2, archive_entry_stat(ae)->st_nlink);
assertEqualInt(1, archive_entry_uid(ae));
assertEqualInt(2, archive_entry_gid(ae));
- } else if (strcmp("hardlink", archive_entry_pathname(ae)) == 0) {
+ } else if (strcmp("file", archive_entry_pathname(ae)) == 0) {
/* A hardlink to the regular file. */
/* Note: If "hardlink" gets returned before "file",
* then "hardlink" will get returned as a regular file
* and "file" will get returned as the hardlink.
* This test should tolerate that, since it's a
* perfectly permissible thing for libarchive to do. */
- assertEqualString("hardlink", archive_entry_pathname(ae));
+ assertEqualString("file", archive_entry_pathname(ae));
assertEqualInt(AE_IFREG, archive_entry_filetype(ae));
- assertEqualString("file", archive_entry_hardlink(ae));
+ assertEqualString("hardlink", archive_entry_hardlink(ae));
assertEqualInt(0, archive_entry_size_is_set(ae));
assertEqualInt(0, archive_entry_size(ae));
assertEqualInt(86401, archive_entry_mtime(ae));
assertEqualInt(2, archive_entry_stat(ae)->st_nlink);
assertEqualInt(1, archive_entry_uid(ae));
assertEqualInt(2, archive_entry_gid(ae));
- } else if (strcmp("file", archive_entry_pathname(ae)) == 0) {
+ } else if (strcmp("hardlink", archive_entry_pathname(ae)) == 0) {
/* A regular file. */
- assertEqualString("file", archive_entry_pathname(ae));
+ assertEqualString("hardlink", archive_entry_pathname(ae));
assertEqualInt(AE_IFREG, archive_entry_filetype(ae));
assertEqualInt(12345684, archive_entry_size(ae));
assertEqualInt(0,
assertEqualInt(2, archive_entry_stat(ae)->st_nlink);
assertEqualInt(1, archive_entry_uid(ae));
assertEqualInt(2, archive_entry_gid(ae));
- } else if (strcmp("hardlink", archive_entry_pathname(ae)) == 0) {
+ } else if (strcmp("file", archive_entry_pathname(ae)) == 0) {
/* A hardlink to the regular file. */
/* Note: If "hardlink" gets returned before "file",
* then "hardlink" will get returned as a regular file
* and "file" will get returned as the hardlink.
* This test should tolerate that, since it's a
* perfectly permissible thing for libarchive to do. */
- assertEqualString("hardlink", archive_entry_pathname(ae));
+ assertEqualString("file", archive_entry_pathname(ae));
assertEqualInt(AE_IFREG, archive_entry_filetype(ae));
- assertEqualString("file", archive_entry_hardlink(ae));
+ assertEqualString("hardlink", archive_entry_hardlink(ae));
assertEqualInt(0, archive_entry_size_is_set(ae));
assertEqualInt(0, archive_entry_size(ae));
assertEqualInt(86401, archive_entry_mtime(ae));
--- /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"
+
+/*
+Execute the following command to rebuild the data for this program:
+ tail -n +32 test_read_format_isorr_rr_moved.c | /bin/sh
+
+dirname=/tmp/iso
+rm -rf $dirname
+mkdir -p $dirname/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9/dir10
+echo "hello" >$dirname/file
+dd if=/dev/zero count=1 bs=12345678 >>$dirname/file
+deepfile=$dirname/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9/dir10/deep
+echo "hello" >$deepfile
+dd if=/dev/zero count=1 bs=12345678 >>$deepfile
+time="197001020000.01"
+TZ=utc touch -afhm -t $time $deepfile
+TZ=utc touch -afhm -t $time $dirname/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9/dir10
+TZ=utc touch -afhm -t $time $dirname/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8/dir9
+TZ=utc touch -afhm -t $time $dirname/dir1/dir2/dir3/dir4/dir5/dir6/dir7/dir8
+TZ=utc touch -afhm -t $time $dirname/dir1/dir2/dir3/dir4/dir5/dir6/dir7
+TZ=utc touch -afhm -t $time $dirname/dir1/dir2/dir3/dir4/dir5/dir6
+TZ=utc touch -afhm -t $time $dirname/dir1/dir2/dir3/dir4/dir5
+TZ=utc touch -afhm -t $time $dirname/dir1/dir2/dir3/dir4
+TZ=utc touch -afhm -t $time $dirname/dir1/dir2/dir3
+TZ=utc touch -afhm -t $time $dirname/dir1/dir2
+TZ=utc touch -afhm -t $time $dirname/dir1
+TZ=utc touch -afhm -t $time $dirname/file
+TZ=utc touch -afhm -t $time $dirname
+F=test_read_format_isorr_rr_moved.iso.bz2
+mkhybrid -R -uid 1 -gid 2 $dirname | bzip2 > $F
+uuencode $F $F > $F.uu
+exit 1
+ */
+
+DEFINE_TEST(test_read_format_isorr_rr_moved)
+{
+ const char *refname = "test_read_format_isorr_rr_moved.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 8 files on the ISO image and
+ * verify that each one is what we expect. */
+ for (i = 0; i < 13; ++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));
+ /* Now, we read timestamp recorded by RRIP "TF". */
+ assertEqualInt(86401, archive_entry_mtime(ae));
+ assertEqualInt(0, archive_entry_mtime_nsec(ae));
+ /* Now, we read links recorded by RRIP "PX". */
+ assertEqualInt(3, 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("dir1", archive_entry_pathname(ae)) == 0) {
+ /* A directory. */
+ assertEqualString("dir1", archive_entry_pathname(ae));
+ assertEqualInt(AE_IFDIR, archive_entry_filetype(ae));
+ assertEqualInt(2048, archive_entry_size(ae));
+ assertEqualInt(86401, archive_entry_mtime(ae));
+ assertEqualInt(86401, archive_entry_atime(ae));
+ assertEqualInt(3, archive_entry_stat(ae)->st_nlink);
+ assertEqualInt(1, archive_entry_uid(ae));
+ assertEqualInt(2, archive_entry_gid(ae));
+ } else if (strcmp("dir1/dir2",
+ archive_entry_pathname(ae)) == 0) {
+ /* A directory. */
+ assertEqualString("dir1/dir2",
+ archive_entry_pathname(ae));
+ assertEqualInt(AE_IFDIR, archive_entry_filetype(ae));
+ assertEqualInt(2048, archive_entry_size(ae));
+ assertEqualInt(86401, archive_entry_mtime(ae));
+ assertEqualInt(86401, archive_entry_atime(ae));
+ assertEqualInt(3, archive_entry_stat(ae)->st_nlink);
+ assertEqualInt(1, archive_entry_uid(ae));
+ assertEqualInt(2, archive_entry_gid(ae));
+ } else if (strcmp("dir1/dir2/dir3",
+ archive_entry_pathname(ae)) == 0) {
+ /* A directory. */
+ assertEqualString("dir1/dir2/dir3",
+ archive_entry_pathname(ae));
+ assertEqualInt(AE_IFDIR, archive_entry_filetype(ae));
+ assertEqualInt(2048, archive_entry_size(ae));
+ assertEqualInt(86401, archive_entry_mtime(ae));
+ assertEqualInt(86401, archive_entry_atime(ae));
+ assertEqualInt(3, archive_entry_stat(ae)->st_nlink);
+ assertEqualInt(1, archive_entry_uid(ae));
+ assertEqualInt(2, archive_entry_gid(ae));
+ } else if (strcmp("dir1/dir2/dir3/dir4",
+ archive_entry_pathname(ae)) == 0) {
+ /* A directory. */
+ assertEqualString("dir1/dir2/dir3/dir4",
+ archive_entry_pathname(ae));
+ assertEqualInt(AE_IFDIR, archive_entry_filetype(ae));
+ assertEqualInt(2048, archive_entry_size(ae));
+ assertEqualInt(86401, archive_entry_mtime(ae));
+ assertEqualInt(86401, archive_entry_atime(ae));
+ assertEqualInt(3, archive_entry_stat(ae)->st_nlink);
+ assertEqualInt(1, archive_entry_uid(ae));
+ assertEqualInt(2, archive_entry_gid(ae));
+ } else if (strcmp("dir1/dir2/dir3/dir4/dir5",
+ archive_entry_pathname(ae)) == 0) {
+ /* A directory. */
+ assertEqualString("dir1/dir2/dir3/dir4/dir5",
+ archive_entry_pathname(ae));
+ assertEqualInt(AE_IFDIR, archive_entry_filetype(ae));
+ assertEqualInt(2048, archive_entry_size(ae));
+ assertEqualInt(86401, archive_entry_mtime(ae));
+ assertEqualInt(86401, archive_entry_atime(ae));
+ assertEqualInt(3, archive_entry_stat(ae)->st_nlink);
+ assertEqualInt(1, archive_entry_uid(ae));
+ assertEqualInt(2, archive_entry_gid(ae));
+ } else if (strcmp("dir1/dir2/dir3/dir4/dir5/dir6",
+ archive_entry_pathname(ae)) == 0) {
+ /* A directory. */
+ assertEqualString("dir1/dir2/dir3/dir4/dir5/dir6",
+ archive_entry_pathname(ae));
+ assertEqualInt(AE_IFDIR, archive_entry_filetype(ae));
+ assertEqualInt(2048, archive_entry_size(ae));
+ assertEqualInt(86401, archive_entry_mtime(ae));
+ assertEqualInt(86401, archive_entry_atime(ae));
+ assertEqualInt(3, archive_entry_stat(ae)->st_nlink);
+ assertEqualInt(1, archive_entry_uid(ae));
+ assertEqualInt(2, archive_entry_gid(ae));
+ } else if (strcmp("dir1/dir2/dir3/dir4/dir5/dir6/dir7",
+ archive_entry_pathname(ae)) == 0) {
+ /* A directory. */
+ assertEqualString("dir1/dir2/dir3/dir4/dir5/dir6/dir7",
+ archive_entry_pathname(ae));
+ assertEqualInt(AE_IFDIR, archive_entry_filetype(ae));
+ assertEqualInt(2048, archive_entry_size(ae));
+ assertEqualInt(86401, archive_entry_mtime(ae));
+ assertEqualInt(86401, archive_entry_atime(ae));
+ assertEqualInt(3, archive_entry_stat(ae)->st_nlink);
+ assertEqualInt(1, archive_entry_uid(ae));
+ assertEqualInt(2, archive_entry_gid(ae));
+ } else if (strcmp("dir1/dir2/dir3/dir4/dir5/dir6/dir7"
+ "/dir8",
+ archive_entry_pathname(ae)) == 0) {
+ /* A directory. */
+ assertEqualString("dir1/dir2/dir3/dir4/dir5/dir6/dir7"
+ "/dir8",
+ archive_entry_pathname(ae));
+ assertEqualInt(AE_IFDIR, archive_entry_filetype(ae));
+ assertEqualInt(2048, archive_entry_size(ae));
+ assertEqualInt(86401, archive_entry_mtime(ae));
+ assertEqualInt(86401, archive_entry_atime(ae));
+ assertEqualInt(3, archive_entry_stat(ae)->st_nlink);
+ assertEqualInt(1, archive_entry_uid(ae));
+ assertEqualInt(2, archive_entry_gid(ae));
+ } else if (strcmp("dir1/dir2/dir3/dir4/dir5/dir6/dir7"
+ "/dir8/dir9",
+ archive_entry_pathname(ae)) == 0) {
+ /* A directory. */
+ assertEqualString("dir1/dir2/dir3/dir4/dir5/dir6/dir7"
+ "/dir8/dir9",
+ archive_entry_pathname(ae));
+ assertEqualInt(AE_IFDIR, archive_entry_filetype(ae));
+ assertEqualInt(2048, archive_entry_size(ae));
+ assertEqualInt(86401, archive_entry_mtime(ae));
+ assertEqualInt(86401, archive_entry_atime(ae));
+ assertEqualInt(3, archive_entry_stat(ae)->st_nlink);
+ assertEqualInt(1, archive_entry_uid(ae));
+ assertEqualInt(2, archive_entry_gid(ae));
+ } else if (strcmp("dir1/dir2/dir3/dir4/dir5/dir6/dir7"
+ "/dir8/dir9/dir10",
+ archive_entry_pathname(ae)) == 0) {
+ /* A directory. */
+ assertEqualString("dir1/dir2/dir3/dir4/dir5/dir6/dir7"
+ "/dir8/dir9/dir10",
+ archive_entry_pathname(ae));
+ assertEqualInt(AE_IFDIR, archive_entry_filetype(ae));
+ assertEqualInt(2048, archive_entry_size(ae));
+ assertEqualInt(86401, archive_entry_mtime(ae));
+ assertEqualInt(86401, archive_entry_atime(ae));
+ assertEqualInt(2, archive_entry_stat(ae)->st_nlink);
+ assertEqualInt(1, archive_entry_uid(ae));
+ assertEqualInt(2, archive_entry_gid(ae));
+ } 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(12345684, archive_entry_size(ae));
+ assertEqualInt(0,
+ archive_read_data_block(a, &p, &size, &offset));
+ assertEqualInt(0, offset);
+ assertEqualMem(p, "hello\n", 6);
+ 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 if (strcmp("dir1/dir2/dir3/dir4/dir5/dir6/dir7"
+ "/dir8/dir9/dir10/deep",
+ archive_entry_pathname(ae)) == 0) {
+ /* A regular file. */
+ assertEqualString("dir1/dir2/dir3/dir4/dir5/dir6/dir7"
+ "/dir8/dir9/dir10/deep",
+ archive_entry_pathname(ae));
+ assertEqualInt(AE_IFREG, archive_entry_filetype(ae));
+ assertEqualInt(12345684, archive_entry_size(ae));
+ assertEqualInt(0,
+ archive_read_data_block(a, &p, &size, &offset));
+ assertEqualInt(0, offset);
+ assertEqualMem(p, "hello\n", 6);
+ 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_isorr_rr_moved.iso.bz2
+M0EIH.3%!62936>2O?C\``<!_____&__]9__X/__?8*_GWY<AJ$0P9%P@)2`@
+MA````L`(T`5^`V8.2:SEVTW,VX&BGZ4TFE/*>0F1Y$\4R>B:/4>34:>ID;2;
+M0"#!-!AJ,1IH]3U!IZ3(8`T),-$4\4]%/34!Z:(#0`T`T#0``&0&33#2````
+M$FJ2$])&30:;4:-J&0```#0``:`#0``T``'J`@P`$P`!,```````````````
+M`$2B*8333(4]HT&I-DT3)Z$&F@-#U!Z@``T#08@`&@'J>IZET$*:93.+D72Y
+MO@@AV2Z`E\!,\`+A?0R#K+KCE#8'9':';',/*'NTY>X?9Q<>*WF;((?]%DXX
+M"E&$03!`%UH(:F"L`J=&!\D1#JD4$3CB""(*IO0$40ERBX;KDRZV$`!T+NM5
+MRZ],NE0$,N6BH"``#M`!(PEZA`$@@#(@K_A$00``'%%$YJ(F+%554Q1Q3P))
+MC@8X8YCSX]L5A"NNN(555558"A[WO>^*R61SD"`J@D#@9^[S(YD^AL]MB+,\
+MD.)/VH$$/OD$$D@DD$D@DPA@S,22'+24!`'4;QU&-.I4.FR``0WJCF5`/'Y,
+M:KY/E=#@X#AOJZ#OB4R%,T0I(2%D4RP-N**JJJGW_N:N4@FP0$SR5.ZN6="B
+M"=RNA6VJE)TMJ*=;/+1&T&@H>HB)47Q=\4-TT+$1-.70?SIPFX"$-ZA00+YG
+M"AC!#.T"""U1$H%$(P8Q8P80(P8P6)&)&)&)$2*"_XI9F8,A+%0`.1D4QKNF
+MJQ\>V5UV:ZZZJZZ6S*,"5,C-2.62!52&72D@(;9$0YD*W41.N#Y!933!`PUS
+MH>-US<!`N6BAF!`\WI^%>XB)A"M"B$2,(]$(`RNJ4!$C&(S5$@,H(B"#$8Z&
+MDI&(D8Q$C&(D8RU2D:&U0Q<#UL'P^@K*@E"&9*,W=_+VH#-KR).I&BE[X1]S
+M:<RHKYQ:^.[:M:CO4\+B85J^S5G23R7T,6518L2[0HB/;"`)4E?00JP4YU*0
+M5D)0A1&-A1"BI(0D%)"&<X34%"FK##@IF-K-OV_.3VM3%?O8[Q8'3.\1Y-(P
+M@&"#R-`$$4!BE$&[+VI-,3R33,.=H!SR;#?)31MVEH5%)2KHX9.:TJ@-J`QA
+M&9/U(33$B(!$!"CB"PT9:VX,&F=0\00.>9.UO;,F?RJUU@0[9]>/G=H[IJ]I
+M[<G2Q$C4V5P*M#MAD,&];)XLJ)WUBKZ)'4<N6U,O!5QT3+1-R@[C"[#$@D](
+MT<,)59L+!;V37&N2BH=PHXM\(D3B:]O\6%_2L,:`=M';4BI"HH731V('4P9K
+MU2<[%J&L9R,MLK5N9S=HPL)KQ:-P8*``!,)HSI/*Z#Q*[+YAAQU0C;`1'K29
+M39;^7%*IT",.H^8`_WV0D<'-GM47$N);0!F#\M5#RW(=6=U4-L>EA/3%B/W"
+MI'46,VE:Q&3^U'ABINDR4R4WZ=-.$G,;:86(2!B7?<E(E+$DF'8L7#2["YHJ
+MK^U8LV35F^1555553#H`W*5([Q3'4XE1?!U7DR'4AH@8@Q3JQ@BFQIY`Q@?,
+M&;VM+!@P2U._[-7.O'/*4I2E*/H$80A!T7J?>*[6#%T\7#KZ#!K^.^X>.8$F
+M9`$0"[FP`E-"?8%01;0\,\!%X.*'$_@?=1_=_Q</#"B#,P;\P2Z8TDF!$DG-
+M$VQR>Q9/1^:93>O4_:JJKF7M$]/L:6FIM=:_7BY^;!:#JPLGZF14H63=E5)W
+M)V*\=2G"0HA9.J<G`5+9"<OXCI;H@6B!>Y(7)%%5553&]DY('GG_B[DBG"A(
+%<E>_'X``
+`
+end
assertEqualInt(2, archive_entry_stat(ae)->st_nlink);
assertEqualInt(1, archive_entry_uid(ae));
assertEqualInt(2, archive_entry_gid(ae));
- } else if (strcmp("file", archive_entry_pathname(ae)) == 0) {
+ } else if (strcmp("hardlink", archive_entry_pathname(ae)) == 0) {
/* A regular file. */
- assertEqualString("file", archive_entry_pathname(ae));
+ assertEqualString("hardlink", archive_entry_pathname(ae));
assertEqualInt(AE_IFREG, archive_entry_filetype(ae));
assertEqualInt(12345684, archive_entry_size(ae));
assertEqualInt(0,
assertEqualInt(0, offset);
assertEqualMem(p, "hello\n", 6);
assertEqualInt(86401, archive_entry_mtime(ae));
- assertEqualInt(86401, archive_entry_atime(ae));
assertEqualInt(2, archive_entry_stat(ae)->st_nlink);
assertEqualInt(1, archive_entry_uid(ae));
assertEqualInt(2, archive_entry_gid(ae));
- } else if (strcmp("hardlink", archive_entry_pathname(ae)) == 0) {
+ } else if (strcmp("file", archive_entry_pathname(ae)) == 0) {
/* A hardlink to the regular file. */
/* Note: If "hardlink" gets returned before "file",
* then "hardlink" will get returned as a regular file
* and "file" will get returned as the hardlink.
* This test should tolerate that, since it's a
* perfectly permissible thing for libarchive to do. */
- assertEqualString("hardlink", archive_entry_pathname(ae));
+ assertEqualString("file", archive_entry_pathname(ae));
assertEqualInt(AE_IFREG, archive_entry_filetype(ae));
- assertEqualString("file", archive_entry_hardlink(ae));
+ assertEqualString("hardlink", archive_entry_hardlink(ae));
assertEqualInt(0, archive_entry_size_is_set(ae));
assertEqualInt(0, archive_entry_size(ae));
assertEqualInt(86401, archive_entry_mtime(ae));
+ assertEqualInt(86401, archive_entry_atime(ae));
assertEqualInt(2, archive_entry_stat(ae)->st_nlink);
assertEqualInt(1, archive_entry_uid(ae));
assertEqualInt(2, archive_entry_gid(ae));