if (file->symlink.s != NULL)
archive_entry_copy_symlink(entry, file->symlink.s);
- /* If this entry points to the same data as the previous
- * entry, convert this into a hardlink to that entry.
- * But don't bother for zero-length files. */
+ /* Note: If the input isn't seekable, we can't rewind to
+ * return the same body again, so if the next entry refers to
+ * the same data, we have to return it as a hardlink to the
+ * original entry. */
+ /* TODO: We have enough information here to compute an
+ * accurate value for nlinks. We should do so and ignore
+ * nlinks from the RR extensions. */
if (file->offset == iso9660->previous_offset
&& file->size == iso9660->previous_size
&& file->size > 0) {
return (ARCHIVE_OK);
}
- /* If the offset is before our current position, we can't
- * seek backwards to extract it, so issue a warning. */
+ /* Except for the hardlink case above, if the offset of the
+ * next entry is before our current position, we can't seek
+ * backwards to extract it, so issue a warning. Note that
+ * this can only happen if this entry was added to the heap
+ * after we passed this offset, that is, only if the directory
+ * mentioning this entry is later than the body of the entry.
+ * Such layouts are very unusual; most ISO9660 writers lay out
+ * and record all directory information first, then store
+ * all file bodies. */
+ /* TODO: Someday, libarchive's I/O core will support optional
+ * seeking. When that day comes, this code should attempt to
+ * seek and only return the error if the seek fails. That
+ * 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) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
"Ignoring out-of-order file @%x (%s) %jd < %jd",
struct file_info *child;
/* N.B.: these special directory identifiers
- * are 8 bit "values" even on a
+ * are 8 bit "values" even on a
* Joliet CD with UCS-2 (16bit) encoding.
*/
assertEqualInt(2, archive_entry_gid(ae));
}
- /* A regular file with a hardlink. */
+ /* 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));
assertEqualInt(AE_IFREG, archive_entry_filetype(ae));
+ assert(archive_entry_hardlink(ae) == NULL);
assertEqualInt(6, archive_entry_size(ae));
assertEqualInt(0, archive_read_data_block(a, &p, &size, &offset));
assertEqualInt(6, (int)size);
if (withrr) {
assertEqualInt(86401, archive_entry_mtime(ae));
assertEqualInt(86401, archive_entry_atime(ae));
- assertEqualInt(2, archive_entry_stat(ae)->st_nlink);
+ /* TODO: Actually, libarchive should be able to
+ * compute nlinks correctly even without RR
+ * extensions. See comments in libarchive source. */
+ assertEqualInt(2, archive_entry_nlink(ae));
assertEqualInt(1, archive_entry_uid(ae));
assertEqualInt(2, archive_entry_gid(ae));
}
- /* Another link to the regular file. */
+ /* 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("long-joliet-file-name.textfile",
+ archive_entry_pathname(ae));
assertEqualInt(AE_IFREG, archive_entry_filetype(ae));
- assertEqualInt(0, archive_entry_size(ae));
+ assertEqualString("hardlink", archive_entry_hardlink(ae));
+ assert(!archive_entry_size_is_set(ae));
if (withrr) {
assertEqualInt(86401, archive_entry_mtime(ae));
assertEqualInt(86401, archive_entry_atime(ae));
- assertEqualInt(2, archive_entry_stat(ae)->st_nlink);
+ /* TODO: See above. */
+ assertEqualInt(2, archive_entry_nlink(ae));
assertEqualInt(1, archive_entry_uid(ae));
assertEqualInt(2, archive_entry_gid(ae));
}
assertEqualInt(172802, archive_entry_mtime(ae));
assertEqualInt(172802, archive_entry_atime(ae));
if (withrr) {
- assertEqualInt(1, archive_entry_stat(ae)->st_nlink);
+ assertEqualInt(1, archive_entry_nlink(ae));
assertEqualInt(1, archive_entry_uid(ae));
assertEqualInt(2, archive_entry_gid(ae));
}