libarchive/test/test_read_format_rar_subblock.rar.uu \
libarchive/test/test_read_format_rar_unicode.rar.uu \
libarchive/test/test_read_format_rar_windows.rar.uu \
+ libarchive/test/test_read_format_rar5_arm.rar.uu \
+ libarchive/test/test_read_format_rar5_blake2.rar.uu \
+ libarchive/test/test_read_format_rar5_compressed.rar.uu \
+ libarchive/test/test_read_format_rar5_hardlink.rar.uu \
+ libarchive/test/test_read_format_rar5_multiarchive.part01.rar.uu \
+ libarchive/test/test_read_format_rar5_multiarchive.part02.rar.uu \
+ libarchive/test/test_read_format_rar5_multiarchive.part03.rar.uu \
+ libarchive/test/test_read_format_rar5_multiarchive.part04.rar.uu \
+ libarchive/test/test_read_format_rar5_multiarchive.part05.rar.uu \
+ libarchive/test/test_read_format_rar5_multiarchive.part06.rar.uu \
+ libarchive/test/test_read_format_rar5_multiarchive.part07.rar.uu \
+ libarchive/test/test_read_format_rar5_multiarchive.part08.rar.uu \
+ libarchive/test/test_read_format_rar5_multiarchive_solid.part01.rar.uu \
+ libarchive/test/test_read_format_rar5_multiarchive_solid.part02.rar.uu \
+ libarchive/test/test_read_format_rar5_multiarchive_solid.part03.rar.uu \
+ libarchive/test/test_read_format_rar5_multiarchive_solid.part04.rar.uu \
+ libarchive/test/test_read_format_rar5_multiple_files.rar.uu \
+ libarchive/test/test_read_format_rar5_multiple_files_solid.rar.uu \
+ libarchive/test/test_read_format_rar5_owner.rar.uu \
+ libarchive/test/test_read_format_rar5_solid.rar.uu \
+ libarchive/test/test_read_format_rar5_stored.rar.uu \
+ libarchive/test/test_read_format_rar5_stored_manyfiles.rar.uu \
+ libarchive/test/test_read_format_rar5_symlink.rar.uu \
+ libarchive/test/test_read_format_rar5_win32.rar.uu \
libarchive/test/test_read_format_raw.bufr.uu \
libarchive/test/test_read_format_raw.data.Z.uu \
libarchive/test/test_read_format_raw.data.uu \
libarchive/test/test_read_format_ustar_filename_koi8r.tar.Z.uu \
libarchive/test/test_read_format_warc.warc.uu \
libarchive/test/test_read_format_zip.zip.uu \
+ libarchive/test/test_read_format_zip_bz2_hang.zip.uu \
+ libarchive/test/test_read_format_zip_bzip2.zipx.uu \
+ libarchive/test/test_read_format_zip_bzip2_multi.zipx.uu \
libarchive/test/test_read_format_zip_comment_stored_1.zip.uu \
libarchive/test/test_read_format_zip_comment_stored_2.zip.uu \
libarchive/test/test_read_format_zip_encryption_data.zip.uu \
libarchive/test/test_read_format_zip_filename_utf8_ru2.zip.uu \
libarchive/test/test_read_format_zip_high_compression.zip.uu \
libarchive/test/test_read_format_zip_length_at_end.zip.uu \
+ libarchive/test/test_read_format_zip_lzma.zipx.uu \
libarchive/test/test_read_format_zip_jar.jar.uu \
libarchive/test/test_read_format_zip_mac_metadata.zip.uu \
libarchive/test/test_read_format_zip_malformed1.zip.uu \
libarchive/test/test_read_format_zip_padded1.zip.uu \
libarchive/test/test_read_format_zip_padded2.zip.uu \
libarchive/test/test_read_format_zip_padded3.zip.uu \
+ libarchive/test/test_read_format_zip_ppmd8.zipx.uu \
+ libarchive/test/test_read_format_zip_ppmd8_crash_1.zipx.uu \
+ libarchive/test/test_read_format_zip_ppmd8_crash_2.zipx.uu \
+ libarchive/test/test_read_format_zip_ppmd8_multi.zipx.uu \
libarchive/test/test_read_format_zip_sfx.uu \
libarchive/test/test_read_format_zip_symlink.zip.uu \
libarchive/test/test_read_format_zip_traditional_encryption_data.zip.uu \
libarchive/test/test_read_format_zip_winzip_aes256_large.zip.uu \
libarchive/test/test_read_format_zip_winzip_aes256_stored.zip.uu \
libarchive/test/test_read_format_zip_with_invalid_traditional_eocd.zip.uu \
+ libarchive/test/test_read_format_zip_xz_multi.zipx.uu \
libarchive/test/test_read_format_zip_zip64a.zip.uu \
libarchive/test/test_read_format_zip_zip64b.zip.uu \
libarchive/test/test_read_large_splitted_rar_aa.uu \
uint8_t blake2sp[32];
blake2sp_state b2state;
char has_blake2;
+
+ /* Optional redir fields */
+ uint64_t redir_type;
+ uint64_t redir_flags;
+};
+
+enum EXTRA {
+ EX_CRYPT = 0x01,
+ EX_HASH = 0x02,
+ EX_HTIME = 0x03,
+ EX_VERSION = 0x04,
+ EX_REDIR = 0x05,
+ EX_UOWNER = 0x06,
+ EX_SUBDATA = 0x07
};
+#define REDIR_SYMLINK_IS_DIR 1
+
+enum REDIR_TYPE {
+ REDIR_TYPE_NONE = 0,
+ REDIR_TYPE_UNIXSYMLINK = 1,
+ REDIR_TYPE_WINSYMLINK = 2,
+ REDIR_TYPE_JUNCTION = 3,
+ REDIR_TYPE_HARDLINK = 4,
+ REDIR_TYPE_FILECOPY = 5,
+};
+
+#define OWNER_USER_NAME 0x01
+#define OWNER_GROUP_NAME 0x02
+#define OWNER_USER_UID 0x04
+#define OWNER_GROUP_GID 0x08
+#define OWNER_MAXNAMELEN 256
+
enum FILTER_TYPE {
FILTER_DELTA = 0, /* Generic pattern. */
FILTER_E8 = 1, /* Intel x86 code. */
default:
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
- "Unsupported filter type: 0x%02x", flt->type);
+ "Unsupported filter type: 0x%x", flt->type);
return ARCHIVE_FATAL;
}
rar->cstate.last_write_ptr = 0;
rar->cstate.last_unstore_ptr = 0;
+ rar->file.redir_type = REDIR_TYPE_NONE;
+ rar->file.redir_flags = 0;
+
free_filters(rar);
}
*extra_data_size -= hash_size;
} else {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
- "Unsupported hash type (0x%02x)", (int) hash_type);
+ "Unsupported hash type (0x%x)", (int) hash_type);
return ARCHIVE_FATAL;
}
return ARCHIVE_OK;
}
+static int parse_file_extra_redir(struct archive_read* a,
+ struct archive_entry* e, struct rar5* rar,
+ ssize_t* extra_data_size)
+{
+ size_t value_len = 0;
+ char target_utf8_buf[2048 * 4];
+ const uint8_t* p;
+
+ if(!read_var_sized(a, &rar->file.redir_type, &value_len))
+ return ARCHIVE_EOF;
+ if(ARCHIVE_OK != consume(a, value_len))
+ return ARCHIVE_EOF;
+ *extra_data_size -= value_len;
+
+ if(!read_var_sized(a, &rar->file.redir_flags, &value_len))
+ return ARCHIVE_EOF;
+ if(ARCHIVE_OK != consume(a, value_len))
+ return ARCHIVE_EOF;
+ *extra_data_size -= value_len;
+
+ if(!read_var_sized(a, &value_len, NULL))
+ return ARCHIVE_EOF;
+ *extra_data_size -= value_len + 1;
+ if(!read_ahead(a, value_len, &p))
+ return ARCHIVE_EOF;
+
+ if(value_len > 2047) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ "Link target is too long");
+ return ARCHIVE_FATAL;
+ }
+ if(value_len == 0) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ "No link target specified");
+ return ARCHIVE_FATAL;
+ }
+ memcpy(target_utf8_buf, p, value_len);
+ target_utf8_buf[value_len] = 0;
+
+ if(ARCHIVE_OK != consume(a, value_len))
+ return ARCHIVE_EOF;
+
+ switch(rar->file.redir_type) {
+ case REDIR_TYPE_UNIXSYMLINK:
+ case REDIR_TYPE_WINSYMLINK:
+ archive_entry_set_filetype(e, AE_IFLNK);
+ archive_entry_update_symlink_utf8(e, target_utf8_buf);
+ if (rar->file.redir_flags & REDIR_SYMLINK_IS_DIR) {
+ archive_entry_set_symlink_type(e,
+ AE_SYMLINK_TYPE_DIRECTORY);
+ } else {
+ archive_entry_set_symlink_type(e,
+ AE_SYMLINK_TYPE_FILE);
+ }
+ break;
+
+ case REDIR_TYPE_HARDLINK:
+ archive_entry_set_filetype(e, AE_IFREG);
+ archive_entry_update_hardlink_utf8(e, target_utf8_buf);
+ break;
+
+ default:
+ /* Unknown redir type */
+ if(ARCHIVE_OK != consume(a, value_len))
+ return ARCHIVE_EOF;
+ archive_set_error(&a->archive,
+ ARCHIVE_ERRNO_FILE_FORMAT,
+ "Unsupported redir type: %ld",
+ rar->file.redir_type);
+ return ARCHIVE_FATAL;
+ break;
+ }
+ return ARCHIVE_OK;
+}
+
+static int parse_file_extra_owner(struct archive_read* a,
+ struct archive_entry* e, ssize_t* extra_data_size)
+{
+ uint64_t flags = 0;
+ size_t value_len = 0;
+ size_t name_len = 0;
+ size_t id = 0;
+ char namebuf[OWNER_MAXNAMELEN];
+ const uint8_t* p;
+
+ if(!read_var_sized(a, &flags, &value_len))
+ return ARCHIVE_EOF;
+ if(ARCHIVE_OK != consume(a, value_len))
+ return ARCHIVE_EOF;
+ *extra_data_size -= value_len;
+
+ if ((flags & OWNER_USER_NAME) != 0) {
+ if(!read_var_sized(a, &value_len, NULL))
+ return ARCHIVE_EOF;
+ *extra_data_size -= value_len + 1;
+ if(!read_ahead(a, value_len, &p))
+ return ARCHIVE_EOF;
+ if (value_len > OWNER_MAXNAMELEN)
+ name_len = OWNER_MAXNAMELEN;
+ else
+ name_len = value_len;
+ memcpy(namebuf, p, name_len);
+ namebuf[name_len] = 0;
+ if(ARCHIVE_OK != consume(a, value_len))
+ return ARCHIVE_EOF;
+
+ archive_entry_set_uname(e, namebuf);
+ }
+ if ((flags & OWNER_GROUP_NAME) != 0) {
+ if(!read_var_sized(a, &value_len, NULL))
+ return ARCHIVE_EOF;
+ *extra_data_size -= value_len + 1;
+ if(!read_ahead(a, value_len, &p))
+ return ARCHIVE_EOF;
+ if (value_len > OWNER_MAXNAMELEN)
+ name_len = OWNER_MAXNAMELEN;
+ else
+ name_len = value_len;
+ memcpy(namebuf, p, name_len);
+ namebuf[name_len] = 0;
+ if(ARCHIVE_OK != consume(a, value_len))
+ return ARCHIVE_EOF;
+
+ archive_entry_set_gname(e, namebuf);
+ }
+ if ((flags & OWNER_USER_UID) != 0) {
+ if(!read_var_sized(a, &id, &value_len))
+ return ARCHIVE_EOF;
+ if(ARCHIVE_OK != consume(a, value_len))
+ return ARCHIVE_EOF;
+ *extra_data_size -= value_len;
+
+ archive_entry_set_uid(e, id);
+ }
+ if ((flags & OWNER_GROUP_GID) != 0) {
+ if(!read_var_sized(a, &id, &value_len))
+ return ARCHIVE_EOF;
+ if(ARCHIVE_OK != consume(a, value_len))
+ return ARCHIVE_EOF;
+ *extra_data_size -= value_len;
+
+ archive_entry_set_gid(e, id);
+ }
+ return ARCHIVE_OK;
+}
+
static int process_head_file_extra(struct archive_read* a,
struct archive_entry* e, struct rar5* rar,
ssize_t extra_data_size)
int ret = ARCHIVE_FATAL;
size_t var_size;
- enum EXTRA {
- CRYPT = 0x01, HASH = 0x02, HTIME = 0x03, VERSION_ = 0x04,
- REDIR = 0x05, UOWNER = 0x06, SUBDATA = 0x07
- };
-
while(extra_data_size > 0) {
if(!read_var_sized(a, &extra_field_size, &var_size))
return ARCHIVE_EOF;
}
switch(extra_field_id) {
- case HASH:
+ case EX_HASH:
ret = parse_file_extra_hash(a, rar, &extra_data_size);
break;
- case HTIME:
+ case EX_HTIME:
ret = parse_file_extra_htime(a, e, rar, &extra_data_size);
break;
- case CRYPT:
- /* fallthrough */
- case VERSION_:
- /* fallthrough */
- case REDIR:
+ case EX_REDIR:
+ ret = parse_file_extra_redir(a, e, rar, &extra_data_size);
+ break;
+ case EX_UOWNER:
+ ret = parse_file_extra_owner(a, e, &extra_data_size);
+ break;
+ case EX_CRYPT:
/* fallthrough */
- case UOWNER:
+ case EX_VERSION:
/* fallthrough */
- case SUBDATA:
+ case EX_SUBDATA:
/* fallthrough */
default:
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
- "Unknown extra field in file/service block: 0x%02x",
+ "Unknown extra field in file/service block: 0x%x",
(int) extra_field_id);
return ARCHIVE_FATAL;
}
} else {
/* Unknown host OS */
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
- "Unsupported Host OS: 0x%02x", (int) host_os);
+ "Unsupported Host OS: 0x%x", (int) host_os);
return ARCHIVE_FATAL;
}
if((file_flags & UNKNOWN_UNPACKED_SIZE) == 0) {
rar->file.unpacked_size = (ssize_t) unpacked_size;
- archive_entry_set_size(entry, unpacked_size);
+ if(rar->file.redir_type == REDIR_TYPE_NONE)
+ archive_entry_set_size(entry, unpacked_size);
}
if(file_flags & UTIME) {
break;
default:
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
- "Unsupported extra type (0x%02x)", (int) extra_field_id);
+ "Unsupported extra type (0x%x)", (int) extra_field_id);
return ARCHIVE_FATAL;
}
if(calculated_cksum != hdr->block_cksum) {
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
- "Block checksum error: got 0x%02x, expected 0x%02x",
+ "Block checksum error: got 0x%x, expected 0x%x",
hdr->block_cksum, calculated_cksum);
return ARCHIVE_FATAL;
/* The program counter shouldn't reach here. */
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
- "Unsupported block code: 0x%02x", num);
+ "Unsupported block code: 0x%x", num);
return ARCHIVE_FATAL;
}
return uncompress_file(a);
default:
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
- "Compression method not supported: 0x%08x",
+ "Compression method not supported: 0x%x",
rar->cstate.method);
return ARCHIVE_FATAL;
assertEqualInt(computed_crc, 0x7CCA70CD);
EPILOGUE();
}
+
+DEFINE_TEST(test_read_format_rar5_owner)
+{
+ const int DATA_SIZE = 5;
+ uint8_t buff[5];
+
+ PROLOGUE("test_read_format_rar5_owner.rar");
+
+ assertA(0 == archive_read_next_header(a, &ae));
+ assertEqualString("root.txt", archive_entry_pathname(ae));
+ assertEqualString("root", archive_entry_uname(ae));
+ assertEqualString("wheel", archive_entry_gname(ae));
+ assertA((int) archive_entry_mtime(ae) > 0);
+ assertEqualInt(DATA_SIZE, archive_entry_size(ae));
+ assertA(DATA_SIZE == archive_read_data(a, buff, DATA_SIZE));
+
+ assertA(0 == archive_read_next_header(a, &ae));
+ assertEqualString("nobody.txt", archive_entry_pathname(ae));
+ assertEqualString("nobody", archive_entry_uname(ae));
+ assertEqualString("nogroup", archive_entry_gname(ae));
+ assertA((int) archive_entry_mtime(ae) > 0);
+ assertEqualInt(DATA_SIZE, archive_entry_size(ae));
+ assertA(DATA_SIZE == archive_read_data(a, buff, DATA_SIZE));
+
+ assertA(0 == archive_read_next_header(a, &ae));
+ assertEqualString("numeric.txt", archive_entry_pathname(ae));
+ assertEqualInt(9999, archive_entry_uid(ae));
+ assertEqualInt(8888, archive_entry_gid(ae));
+ assertA((int) archive_entry_mtime(ae) > 0);
+ assertEqualInt(DATA_SIZE, archive_entry_size(ae));
+ assertA(DATA_SIZE == archive_read_data(a, buff, DATA_SIZE));
+
+ assertA(ARCHIVE_EOF == archive_read_next_header(a, &ae));
+
+ EPILOGUE();
+}
+
+DEFINE_TEST(test_read_format_rar5_symlink)
+{
+ const int DATA_SIZE = 5;
+ uint8_t buff[5];
+
+ PROLOGUE("test_read_format_rar5_symlink.rar");
+
+ assertA(0 == archive_read_next_header(a, &ae));
+ assertEqualString("file.txt", archive_entry_pathname(ae));
+ assertEqualInt(AE_IFREG, archive_entry_filetype(ae));
+ assertA((int) archive_entry_mtime(ae) > 0);
+ assertEqualInt(DATA_SIZE, archive_entry_size(ae));
+ assertA(DATA_SIZE == archive_read_data(a, buff, DATA_SIZE));
+
+ assertA(0 == archive_read_next_header(a, &ae));
+ assertEqualString("symlink.txt", archive_entry_pathname(ae));
+ assertEqualInt(AE_IFLNK, archive_entry_filetype(ae));
+ assertEqualString("file.txt", archive_entry_symlink(ae));
+ assertEqualInt(AE_SYMLINK_TYPE_FILE, archive_entry_symlink_type(ae));
+ assertA(0 == archive_read_data(a, NULL, archive_entry_size(ae)));
+
+ assertA(0 == archive_read_next_header(a, &ae));
+ assertEqualString("dirlink", archive_entry_pathname(ae));
+ assertEqualInt(AE_IFLNK, archive_entry_filetype(ae));
+ assertEqualString("dir", archive_entry_symlink(ae));
+ assertEqualInt(AE_SYMLINK_TYPE_DIRECTORY, archive_entry_symlink_type(ae));
+ assertA(0 == archive_read_data(a, NULL, archive_entry_size(ae)));
+
+ assertA(0 == archive_read_next_header(a, &ae));
+ assertEqualString("dir", archive_entry_pathname(ae));
+ assertEqualInt(AE_IFDIR, archive_entry_filetype(ae));
+ assertA(0 == archive_read_data(a, NULL, archive_entry_size(ae)));
+
+ assertA(ARCHIVE_EOF == archive_read_next_header(a, &ae));
+
+ EPILOGUE();
+}
+
+DEFINE_TEST(test_read_format_rar5_hardlink)
+{
+ const int DATA_SIZE = 5;
+ uint8_t buff[5];
+
+ PROLOGUE("test_read_format_rar5_hardlink.rar");
+
+ assertA(0 == archive_read_next_header(a, &ae));
+ assertEqualString("file.txt", archive_entry_pathname(ae));
+ assertEqualInt(AE_IFREG, archive_entry_filetype(ae));
+ assertA((int) archive_entry_mtime(ae) > 0);
+ assertEqualInt(DATA_SIZE, archive_entry_size(ae));
+ assertA(DATA_SIZE == archive_read_data(a, buff, DATA_SIZE));
+
+ assertA(0 == archive_read_next_header(a, &ae));
+ assertEqualString("hardlink.txt", archive_entry_pathname(ae));
+ assertEqualInt(AE_IFREG, archive_entry_filetype(ae));
+ assertEqualString("file.txt", archive_entry_hardlink(ae));
+ assertA(0 == archive_read_data(a, NULL, archive_entry_size(ae)));
+
+ assertA(ARCHIVE_EOF == archive_read_next_header(a, &ae));
+
+ EPILOGUE();
+}