]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
RAR5 reader: add support for symlinks, hardlinks, owner and group data
authorMartin Matuska <martin@matuska.org>
Wed, 17 Apr 2019 16:52:27 +0000 (18:52 +0200)
committerMartin Matuska <martin@matuska.org>
Wed, 17 Apr 2019 23:04:02 +0000 (01:04 +0200)
Add missing test archives to Makefile.am

Makefile.am
libarchive/archive_read_support_format_rar5.c
libarchive/test/test_read_format_rar5.c
libarchive/test/test_read_format_rar5_hardlink.rar.uu [new file with mode: 0644]
libarchive/test/test_read_format_rar5_owner.rar.uu [new file with mode: 0644]
libarchive/test/test_read_format_rar5_symlink.rar.uu [new file with mode: 0644]

index 639936a64082998cb53417fca15982ac760ee3ef..b7a2a6bcaa78029e8c335a56befee07ef095e468 100644 (file)
@@ -825,6 +825,30 @@ libarchive_test_EXTRA_DIST=\
        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 \
@@ -837,6 +861,9 @@ libarchive_test_EXTRA_DIST=\
        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 \
@@ -850,6 +877,7 @@ libarchive_test_EXTRA_DIST=\
        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 \
@@ -859,6 +887,10 @@ libarchive_test_EXTRA_DIST=\
        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 \
@@ -868,6 +900,7 @@ libarchive_test_EXTRA_DIST=\
        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 \
index 159c3b61f5ff29b592c576aec93021408bd3a379..70796e358981d353875c48a1c9c3dfbe7cef0bff 100644 (file)
@@ -103,8 +103,39 @@ struct file_header {
     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. */
@@ -615,7 +646,7 @@ static int run_filter(struct archive_read* a, struct filter_info* flt) {
 
         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;
     }
 
@@ -797,6 +828,9 @@ static void reset_file_context(struct rar5* rar) {
     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);
 }
 
@@ -1135,7 +1169,7 @@ static int parse_file_extra_hash(struct archive_read* a, struct rar5* 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;
     }
 
@@ -1221,6 +1255,152 @@ static int parse_file_extra_htime(struct archive_read* a,
     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)
@@ -1230,11 +1410,6 @@ static int process_head_file_extra(struct archive_read* a,
     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;
@@ -1253,25 +1428,27 @@ static int process_head_file_extra(struct archive_read* a,
         }
 
         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;
         }
@@ -1406,7 +1583,7 @@ static int process_head_file(struct archive_read* a, struct rar5* rar,
     } 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;
     }
@@ -1453,7 +1630,8 @@ static int process_head_file(struct archive_read* a, struct rar5* rar,
 
     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) {
@@ -1596,7 +1774,7 @@ static int process_head_main(struct archive_read* a, struct rar5* rar,
             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;
     }
 
@@ -2217,7 +2395,7 @@ static int parse_block_header(struct archive_read* a, const uint8_t* p,
 
     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;
@@ -2570,7 +2748,7 @@ static int do_uncompress_block(struct archive_read* a, const uint8_t* p) {
 
         /* 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;
     }
@@ -3195,7 +3373,7 @@ static int do_unpack(struct archive_read* a, struct rar5* rar,
                 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;
index 0be9c45a5d49b7c6d95ebaf41fa9c91fac348839..e87e278f02a6f84d3a0696a445eb2fcb1f89dfb5 100644 (file)
@@ -768,3 +768,102 @@ DEFINE_TEST(test_read_format_rar5_block_by_block)
     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();
+}
diff --git a/libarchive/test/test_read_format_rar5_hardlink.rar.uu b/libarchive/test/test_read_format_rar5_hardlink.rar.uu
new file mode 100644 (file)
index 0000000..0ec085d
--- /dev/null
@@ -0,0 +1,6 @@
+begin 644 test_read_format_rar5_hardlink.rar
+M4F%R(1H'`0`SDK7E"@$%!@`%`0&`@`!KI,1X'@("A0`&A0"D@P(XC;=<(1>3
+M?8```0AF:6QE+G1X=#$R,S0*[8@"T2X"`PT`!@6D@P(XC;=<`````(```0QH
+@87)D;&EN:RYT>'0,!00`"&9I;&4N='AT'7=640,%!```
+`
+end
diff --git a/libarchive/test/test_read_format_rar5_owner.rar.uu b/libarchive/test/test_read_format_rar5_owner.rar.uu
new file mode 100644 (file)
index 0000000..285bdb9
--- /dev/null
@@ -0,0 +1,8 @@
+begin 644 test_read_format_rar5_owner.rar
+M4F%R(1H'`0`SDK7E"@$%!@`%`0&`@`!W:E-^+0(##H4`!H4`I(,"_8VW7"$7
+MDWV```$(<F]O="YT>'0-!@,$<F]O=`5W:&5E;#$R,S0*2J"P0S,"`Q*%``:%
+M`*2#`FZ-MUQFP<VL@``!"FYO8F]D>2YT>'01!@,&;F]B;V1Y!VYO9W)O=7`U
+M-C<X"L=81/8I`@,'A0`&A0"D@P)LD[=<>B#;(H```0MN=6UE<FEC+G1X=`8&
+2#(].N$4Y.3DY"AUW5E$#!00`
+`
+end
diff --git a/libarchive/test/test_read_format_rar5_symlink.rar.uu b/libarchive/test/test_read_format_rar5_symlink.rar.uu
new file mode 100644 (file)
index 0000000..f603e3c
--- /dev/null
@@ -0,0 +1,8 @@
+begin 644 test_read_format_rar5_symlink.rar
+M4F%R(1H'`0`SDK7E"@$%!@`%`0&`@`"$O8RN'@("A0`&A0"D@P(XC;=<(1>3
+M?8!``0AF:6QE+G1X=#$R,S0*8QI3.2T"`PT`!@CMPP)7C;=<`````(!``0MS
+M>6UL:6YK+G1X=`P%`0`(9FEL92YT>'2.NOQU)`(#"``&`^W#`DF6MUP`````
+M@$`!!V1I<FQI;FL'!0$!`V1I<J/_?\87`@(`!P#M@P%&EK=<`````(```0-D
+*:7(==U91`P4$````
+`
+end