diff --git a/CMakeLists.txt b/CMakeLists.txt index d6ea4c943d..04f8d359e8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -109,7 +109,6 @@ IF (CMAKE_C_COMPILER_ID MATCHES "^GNU$" OR SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wunused") SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wshadow") SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wmissing-prototypes") - SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wcast-qual") # Ideally this will be a compile/link time check, yet there's no obvious way # how considering how old our minimum required cmake version is. The official # cmake.org side does not host the manual pages even. Normally we can use diff --git a/cat/CMakeLists.txt b/cat/CMakeLists.txt index 4fe6354b31..1b95de007a 100644 --- a/cat/CMakeLists.txt +++ b/cat/CMakeLists.txt @@ -21,13 +21,7 @@ IF(ENABLE_CAT) # How to build bsdcat ADD_EXECUTABLE(bsdcat ${bsdcat_SOURCES}) - IF(ENABLE_CAT_SHARED) - TARGET_LINK_LIBRARIES(bsdcat archive ${ADDITIONAL_LIBS}) - ELSE(ENABLE_CAT_SHARED) - TARGET_LINK_LIBRARIES(bsdcat archive_static ${ADDITIONAL_LIBS}) - SET_TARGET_PROPERTIES(bsdcat PROPERTIES COMPILE_DEFINITIONS - LIBARCHIVE_STATIC) - ENDIF(ENABLE_CAT_SHARED) + TARGET_LINK_LIBRARIES(bsdcat LibArchive::LibArchive ${ADDITIONAL_LIBS}) # Installation rules INSTALL(TARGETS bsdcat RUNTIME DESTINATION bin) diff --git a/cpio/CMakeLists.txt b/cpio/CMakeLists.txt index 85fda77828..7f42fb628d 100644 --- a/cpio/CMakeLists.txt +++ b/cpio/CMakeLists.txt @@ -30,13 +30,7 @@ IF(ENABLE_CPIO) # How to build bsdcpio ADD_EXECUTABLE(bsdcpio ${bsdcpio_SOURCES}) - IF(ENABLE_CPIO_SHARED) - TARGET_LINK_LIBRARIES(bsdcpio archive ${ADDITIONAL_LIBS}) - ELSE(ENABLE_CPIO_SHARED) - TARGET_LINK_LIBRARIES(bsdcpio archive_static ${ADDITIONAL_LIBS}) - SET_TARGET_PROPERTIES(bsdcpio PROPERTIES COMPILE_DEFINITIONS - LIBARCHIVE_STATIC) - ENDIF(ENABLE_CPIO_SHARED) + TARGET_LINK_LIBRARIES(bsdcpio LibArchive::LibArchive) # Installation rules INSTALL(TARGETS bsdcpio RUNTIME DESTINATION bin) diff --git a/libarchive/archive_options.c b/libarchive/archive_options.c index 6496025a5f..e486f7b552 100644 --- a/libarchive/archive_options.c +++ b/libarchive/archive_options.c @@ -177,7 +177,7 @@ parse_option(const char **s, const char **m, const char **o, const char **v) opt = *s; val = "1"; - p = strchr(opt, ','); + p = (char*)strchr(opt, ','); if (p != NULL) { *p = '\0'; @@ -192,14 +192,14 @@ parse_option(const char **s, const char **m, const char **o, const char **v) return end; } - p = strchr(opt, ':'); + p = (char *)strchr(opt, ':'); if (p != NULL) { *p = '\0'; mod = opt; opt = ++p; } - p = strchr(opt, '='); + p = (char*)strchr(opt, '='); if (p != NULL) { *p = '\0'; val = ++p; diff --git a/libarchive/archive_pack_dev.c b/libarchive/archive_pack_dev.c index d95444d979..6c03a4dddc 100644 --- a/libarchive/archive_pack_dev.c +++ b/libarchive/archive_pack_dev.c @@ -326,7 +326,7 @@ compare_format(const void *key, const void *element) pack_t * pack_find(const char *name) { - struct format *format; + const struct format *format; format = bsearch(name, formats, sizeof(formats)/sizeof(formats[0]), diff --git a/libarchive/archive_read_support_format_mtree.c b/libarchive/archive_read_support_format_mtree.c index a5fa30e3c2..088730fbf9 100644 --- a/libarchive/archive_read_support_format_mtree.c +++ b/libarchive/archive_read_support_format_mtree.c @@ -2094,7 +2094,7 @@ readline(struct archive_read *a, struct mtree *mtree, char **start, ssize_t total_size = 0; ssize_t find_off = 0; const void *t; - void *nl; + const void *nl; char *u; /* Accumulate line in a line buffer. */ diff --git a/libarchive/archive_read_support_format_tar.c b/libarchive/archive_read_support_format_tar.c index 04356f98ab..c50dd6aba0 100644 --- a/libarchive/archive_read_support_format_tar.c +++ b/libarchive/archive_read_support_format_tar.c @@ -133,6 +133,7 @@ struct tar { int pax_hdrcharset_binary; int header_recursion_depth; int64_t entry_bytes_remaining; + int64_t entry_data_start; int64_t entry_offset; int64_t entry_padding; int64_t entry_bytes_unconsumed; @@ -280,18 +281,6 @@ archive_read_support_format_tar(struct archive *_a) return (ARCHIVE_OK); } -static int64_t -client_seek_proxy(struct archive_read_filter *self, int64_t offset, int whence) -{ - if (self->archive->client.seeker == NULL) { - archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC, - "Current client reader does not support seeking a device"); - return (ARCHIVE_FAILED); - } - return (self->archive->client.seeker)(&self->archive->archive, - self->data, offset, whence); -} - static int archive_read_format_tar_read_header(struct archive_read *a, struct archive_entry *entry); @@ -300,42 +289,66 @@ static int64_t archive_read_format_tar_seek_data(struct archive_read *a, int64_t offset, int whence) { - struct tar *tar = (struct tar *)(a->format->data); - if (tar->entry_bytes_unconsumed) { - __archive_read_consume(a, tar->entry_bytes_unconsumed); - tar->entry_bytes_unconsumed = 0; - } - a->filter->avail = a->filter->client_avail = 0; - a->filter->next = a->filter->buffer; - a->filter->position = tar->entry_offset; - a->filter->end_of_file = 0; - (void)client_seek_proxy(a->filter, a->header_position, SEEK_SET); - archive_read_format_tar_read_header(a, a->entry); - int64_t client_offset; - (void)tar; - switch (whence) - { - case SEEK_CUR: - client_offset = a->archive.read_data_offset; - break; - case SEEK_END: - client_offset = a->header_position + tar->realsize; - break; - case SEEK_SET: - default: - client_offset = a->header_position; + struct tar *tar = (struct tar *)(a->format->data); + int64_t base_offset, target_offset, ret; + int sparse_count; + int64_t sparse_offset, sparse_length; + + /* + * For regular tar entries, random access is only safe when the + * entry data is a single contiguous block in the archive. + */ + sparse_count = archive_entry_sparse_count(a->entry); + if (sparse_count > 0) { + if (sparse_count != 1 || + archive_entry_sparse_reset(a->entry) != ARCHIVE_OK || + archive_entry_sparse_next(a->entry, &sparse_offset, + &sparse_length) != ARCHIVE_OK || + sparse_offset != 0 || sparse_length != tar->realsize) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Seeking of non-contiguous tar entries is unsupported"); + return (ARCHIVE_FAILED); + } + } + + switch (whence) { + case SEEK_CUR: + base_offset = a->archive.read_data_output_offset; + break; + case SEEK_END: + base_offset = tar->realsize; break; - } - client_offset += offset; - if (client_offset < a->header_position) { - client_offset = a->header_position; - } - else if (client_offset > tar->realsize + a->header_position) { - client_offset = tar->realsize + a->header_position; - } - int64_t ret_val = __archive_read_seek(a, client_offset + 512, SEEK_SET) - 512 - a->header_position; + case SEEK_SET: + default: + base_offset = 0; + break; + } + + target_offset = base_offset + offset; + if (target_offset < 0 || target_offset > tar->realsize) { + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, + "Attempt to seek past beginning or end of tar data block"); + return (ARCHIVE_FAILED); + } + + ret = __archive_read_seek( + a, tar->entry_data_start + target_offset, SEEK_SET); + if (ret < ARCHIVE_OK) + return (ret); + + gnu_clear_sparse_list(tar); + if (gnu_add_sparse_entry(a, tar, target_offset, + tar->realsize - target_offset) != ARCHIVE_OK) + return (ARCHIVE_FATAL); + tar->entry_offset = target_offset; + tar->entry_bytes_remaining = tar->realsize - target_offset; + tar->entry_padding = 0x1ff & (-tar->realsize); + tar->entry_bytes_unconsumed = 0; + __archive_reset_read_data(&a->archive); - return ret_val; + a->archive.read_data_output_offset = target_offset; + a->archive.read_data_offset = target_offset; + return (target_offset); } static int @@ -585,6 +598,7 @@ archive_read_format_tar_read_header(struct archive_read *a, } tar = (struct tar *)(a->format->data); + tar->entry_data_start = 0; tar->entry_offset = 0; gnu_clear_sparse_list(tar); tar->realsize = -1; /* Mark this as "unset" */ @@ -604,6 +618,7 @@ archive_read_format_tar_read_header(struct archive_read *a, r = tar_read_header(a, tar, entry, &unconsumed); tar_flush_unconsumed(a, &unconsumed); + tar->entry_data_start = a->filter->position; /* * "non-sparse" files are really just sparse files with @@ -2825,7 +2840,7 @@ readline(struct archive_read *a, struct tar *tar, const char **start, ssize_t total_size = 0; const void *t; const char *s; - void *p; + const void *p; tar_flush_unconsumed(a, unconsumed); diff --git a/libarchive/archive_write_set_format_iso9660.c b/libarchive/archive_write_set_format_iso9660.c index 2a3ae07fa2..58429a999c 100644 --- a/libarchive/archive_write_set_format_iso9660.c +++ b/libarchive/archive_write_set_format_iso9660.c @@ -5521,7 +5521,7 @@ isoent_setup_file_location(struct iso9660 *iso9660, int location) static int get_path_component(char *name, size_t n, const char *fn) { - char *p; + const char *p; size_t l; p = strchr(fn, '/'); diff --git a/libarchive/archive_write_set_format_mtree.c b/libarchive/archive_write_set_format_mtree.c index 619b7714ee..c75d55d507 100644 --- a/libarchive/archive_write_set_format_mtree.c +++ b/libarchive/archive_write_set_format_mtree.c @@ -1963,7 +1963,7 @@ mtree_entry_find_child(struct mtree_entry *parent, const char *child_name) static int get_path_component(char *name, size_t n, const char *fn) { - char *p; + const char *p; size_t l; p = strchr(fn, '/'); diff --git a/libarchive/archive_write_set_format_warc.c b/libarchive/archive_write_set_format_warc.c index 0ef003e2fc..ffe4cf3f7a 100644 --- a/libarchive/archive_write_set_format_warc.c +++ b/libarchive/archive_write_set_format_warc.c @@ -372,7 +372,7 @@ _popul_ehdr(struct archive_string *tgt, size_t tsz, warc_essential_hdr_t hdr) static const char _uri[] = ""; static const char _fil[] = "file://"; const char *u; - char *chk = strchr(hdr.tgturi, ':'); + const char *chk = strchr(hdr.tgturi, ':'); if (chk != NULL && chk[1U] == '/' && chk[2U] == '/') { /* yep, it's definitely a URI */ diff --git a/libarchive/archive_write_set_format_xar.c b/libarchive/archive_write_set_format_xar.c index 7307757d37..2c4446aab9 100644 --- a/libarchive/archive_write_set_format_xar.c +++ b/libarchive/archive_write_set_format_xar.c @@ -2227,7 +2227,7 @@ file_gen_utility_names(struct archive_write *a, struct file *file) static int get_path_component(char *name, int n, const char *fn) { - char *p; + const char *p; int l; p = strchr(fn, '/'); diff --git a/libarchive/test/CMakeLists.txt b/libarchive/test/CMakeLists.txt index 5e17d62fda..3453ee3f04 100644 --- a/libarchive/test/CMakeLists.txt +++ b/libarchive/test/CMakeLists.txt @@ -295,7 +295,7 @@ IF(ENABLE_TEST) # Register target # ADD_EXECUTABLE(libarchive_test ${libarchive_test_SOURCES}) - TARGET_LINK_LIBRARIES(libarchive_test archive_static ${ADDITIONAL_LIBS}) + TARGET_LINK_LIBRARIES(libarchive_test LibArchive::LibArchive ${ADDITIONAL_LIBS}) SET_PROPERTY(TARGET libarchive_test PROPERTY COMPILE_DEFINITIONS LIBARCHIVE_STATIC LIST_H) @@ -328,4 +328,3 @@ IF(ENABLE_TEST) COMMAND libarchive_test -r ${CMAKE_CURRENT_SOURCE_DIR} -vv) ADD_DEPENDENCIES(run_all_tests run_libarchive_test) ENDIF(ENABLE_TEST) - diff --git a/libarchive/test/test_read_format_tar.c b/libarchive/test/test_read_format_tar.c index 7c7cadd0a3..687cd950f0 100644 --- a/libarchive/test/test_read_format_tar.c +++ b/libarchive/test/test_read_format_tar.c @@ -452,6 +452,422 @@ static void verify(unsigned char *d, size_t s, free(buff); } +#define SMALL_ADVANCE 67 +static void +check_tar_seek(struct archive *a, const unsigned char *payload, + size_t payload_size, int64_t offset) +{ + unsigned char buff[SMALL_ADVANCE]; + size_t expected; + ssize_t bytes_read; + + expected = payload_size - (size_t)offset; + if (expected > sizeof(buff)) + expected = sizeof(buff); + + bytes_read = archive_read_data(a, buff, sizeof(buff)); + if (expected == 0) { + assertEqualInt(0, bytes_read); + return; + } + + assertEqualInt((int)expected, bytes_read); + assertEqualMem(buff, payload + offset, expected); +} + +static void +read_whole_tar_entry( + struct archive *a, unsigned char *payload, size_t payload_size) +{ + unsigned char dummy; + size_t total; + ssize_t bytes_read; + + total = 0; + while (total < payload_size) { + bytes_read = + archive_read_data(a, payload + total, payload_size - total); + assert(bytes_read >= 0); + total += bytes_read; + } + assertEqualInt((int)payload_size, (int)total); + assertEqualInt(0, archive_read_data(a, &dummy, 1)); +} + +static void +check_tar_sequential( + struct archive *a, const unsigned char *payload, size_t payload_size) +{ + unsigned char buff[4096]; + size_t total; + ssize_t bytes_read; + size_t remaining; + + total = 0; + while (1) { + bytes_read = archive_read_data(a, buff, sizeof(buff)); + assert(bytes_read >= 0); + if (bytes_read == 0) + break; + assert(total <= payload_size); + remaining = payload_size - total; + assert((size_t)bytes_read <= remaining); + assertEqualMem(buff, payload + total, (size_t)bytes_read); + total += (size_t)bytes_read; + } + assertEqualInt((int)payload_size, (int)total); +} + +struct synthetic_tar_entry { + const char *pathname; + const char *uname; + const char *gname; + int64_t size; + mode_t perm; + int64_t mtime; + long mtime_nsec; +}; + +struct test_rng { + uint32_t values[256]; + size_t next; +}; + +static void +test_rng_init(struct test_rng *rng) +{ + rng->next = sizeof(rng->values) / sizeof(rng->values[0]); +} + +static uint32_t +test_rng_next(struct test_rng *rng) +{ + if (rng->next >= sizeof(rng->values) / sizeof(rng->values[0])) { + fill_with_pseudorandom_data(rng->values, sizeof(rng->values)); + rng->next = 0; + } + return (rng->values[rng->next++]); +} + +static void +run_tar_seek_checks(struct archive *a, const unsigned char *payload, + size_t payload_size, struct test_rng *rng) +{ + int i; + + assertEqualInt(0, archive_seek_data(a, 0, SEEK_SET)); + check_tar_sequential(a, payload, payload_size); + assertEqualInt(0, archive_seek_data(a, 0, SEEK_SET)); + check_tar_sequential(a, payload, payload_size); + + assertEqualInt(0, archive_seek_data(a, 0, SEEK_SET)); + check_tar_seek(a, payload, payload_size, 0); + assertEqualInt((int)payload_size, archive_seek_data(a, 0, SEEK_END)); + check_tar_seek(a, payload, payload_size, payload_size); + + for (i = 0; i < 64; i++) { + int64_t current; + int64_t target; + int64_t delta; + + target = test_rng_next(rng) % (payload_size + 1); + assertEqualInt(target, archive_seek_data(a, target, SEEK_SET)); + check_tar_seek(a, payload, payload_size, target); + + current = target; + if (current < (int64_t)payload_size) { + size_t advanced = payload_size - (size_t)current; + if (advanced > SMALL_ADVANCE) + advanced = SMALL_ADVANCE; + current += advanced; + } + + delta = (test_rng_next(rng) % (payload_size + 1)) - current; + target = current + delta; + assertEqualInt(target, archive_seek_data(a, delta, SEEK_CUR)); + check_tar_seek(a, payload, payload_size, target); + + current = target; + if (current < (int64_t)payload_size) { + size_t advanced = payload_size - (size_t)current; + if (advanced > SMALL_ADVANCE) + advanced = SMALL_ADVANCE; + current += advanced; + } + + target = test_rng_next(rng) % (payload_size + 1); + assertEqualInt( + target, archive_seek_data( + a, target - (int64_t)payload_size, SEEK_END)); + check_tar_seek(a, payload, payload_size, target); + } +} +#undef SMALL_ADVANCE + +DEFINE_TEST(test_read_format_tar_seek_data) +{ + static const struct synthetic_tar_entry entries[] = { + { "seek/empty.bin", "reader", "archive", 0, 0644, 1712836001, 0 }, + { "seek/small.bin", "reader", "archive", 38, 0600, 1712836002, 111111111 }, + { "seek/block-minus-one.bin", "reader", "archive", 511, 0640, 1712836003, 222222222 }, + { "seek/block.bin", "reader-with-a-deliberately-long-name", "group", 512, 0644, 1712836004, 333333333 }, + { "seek/block-plus-one.bin", "user", "group-with-a-deliberately-long-name", 513, 0664, 1712836005, 444444444 }, + { "seek/abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_abcdefghijklmnopqrstuvwxyz_tail.bin", "reader", "archive", 4269, 0644, 1712836006, 555555555 } + }; + struct archive *a; + struct archive *aw; + struct archive_entry *ae; + unsigned char *archive_buff; + unsigned char **dumped; + size_t archive_size, used; + struct test_rng rng; + size_t i; + + archive_size = 128 * 1024; + archive_buff = malloc(archive_size); + dumped = calloc(sizeof(entries) / sizeof(entries[0]), sizeof(*dumped)); + assert(archive_buff != NULL); + assert(dumped != NULL); + + assert((aw = archive_write_new()) != NULL); + assertEqualIntA(aw, ARCHIVE_OK, archive_write_add_filter_none(aw)); + assertEqualIntA(aw, ARCHIVE_OK, archive_write_set_format_pax(aw)); + assertEqualIntA(aw, ARCHIVE_OK, + archive_write_open_memory(aw, archive_buff, archive_size, &used)); + + for (i = 0; i < sizeof(entries) / sizeof(entries[0]); i++) { + assert((ae = archive_entry_new()) != NULL); + archive_entry_set_pathname(ae, entries[i].pathname); + archive_entry_set_filetype(ae, AE_IFREG); + archive_entry_set_perm(ae, entries[i].perm); + archive_entry_set_size(ae, entries[i].size); + archive_entry_set_uid(ae, 1000 + (int)i); + archive_entry_set_gid(ae, 2000 + (int)i); + archive_entry_set_uname(ae, entries[i].uname); + archive_entry_set_gname(ae, entries[i].gname); + archive_entry_set_mtime( + ae, entries[i].mtime, entries[i].mtime_nsec); + if (entries[i].size > 0) { + dumped[i] = malloc((size_t)entries[i].size); + assert(dumped[i] != NULL); + fill_with_pseudorandom_data( + dumped[i], (size_t)entries[i].size); + } + assertEqualIntA(aw, ARCHIVE_OK, archive_write_header(aw, ae)); + if (entries[i].size > 0) { + assertEqualIntA(aw, (int)entries[i].size, + archive_write_data( + aw, dumped[i], (size_t)entries[i].size)); + } + archive_entry_free(ae); + } + assertEqualIntA(aw, ARCHIVE_OK, archive_write_close(aw)); + assertEqualInt(ARCHIVE_OK, archive_write_free(aw)); + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA( + a, ARCHIVE_OK, read_open_memory_seek(a, archive_buff, used, 113)); + + test_rng_init(&rng); + for (i = 0; i < sizeof(entries) / sizeof(entries[0]); i++) { + static const unsigned char empty_payload[1]; + const unsigned char *payload = dumped[i]; + + assertEqualIntA( + a, ARCHIVE_OK, archive_read_next_header(a, &ae)); + assertEqualString( + entries[i].pathname, archive_entry_pathname(ae)); + assertEqualInt((int)entries[i].size, archive_entry_size(ae)); + + if (payload == NULL) + payload = empty_payload; + read_whole_tar_entry(a, dumped[i], (size_t)entries[i].size); + run_tar_seek_checks(a, payload, (size_t)entries[i].size, &rng); + assertEqualIntA(a, ARCHIVE_OK, archive_read_data_skip(a)); + } + assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); + + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); + for (i = 0; i < sizeof(entries) / sizeof(entries[0]); i++) + free(dumped[i]); + free(dumped); + free(archive_buff); +} + +static void +dump_tar_entry(struct archive *a, int fd, int64_t entry_size) +{ + char buff[65536]; + int64_t remaining; + ssize_t bytes_read; + ssize_t bytes_written; + size_t to_read; + + remaining = entry_size; + while (remaining > 0) { + to_read = (size_t)remaining; + if (to_read > sizeof(buff)) + to_read = sizeof(buff); + bytes_read = archive_read_data(a, buff, to_read); + assert(bytes_read >= 0); + assert(bytes_read > 0); + bytes_written = write(fd, buff, bytes_read); + assertEqualInt((int)bytes_read, bytes_written); + remaining -= bytes_read; + } + assertEqualInt(0, archive_read_data(a, buff, 1)); +} + +static void +check_tar_seek_dump( + struct archive *a, int fd, int64_t entry_size, int64_t offset) +{ + char actual[4096]; + char expected[4096]; + size_t to_read; + ssize_t actual_read, expected_read; + + to_read = (size_t)(entry_size - offset); + if (to_read > sizeof(actual)) + to_read = sizeof(actual); + + actual_read = archive_read_data(a, actual, to_read); + if (to_read == 0) { + assertEqualInt(0, actual_read); + return; + } + assertEqualInt((int)to_read, actual_read); + + expected_read = pread(fd, expected, to_read, offset); + assertEqualInt((int)to_read, expected_read); + assertEqualMem(actual, expected, to_read); +} + +static void +check_tar_sequential_matches_dump(struct archive *a, int fd, int64_t entry_size) +{ + char actual[4096]; + char expected[4096]; + int64_t total; + ssize_t actual_read, expected_read; + size_t to_read; + + total = 0; + while (1) { + actual_read = archive_read_data(a, actual, sizeof(actual)); + assert(actual_read >= 0); + if (actual_read == 0) + break; + to_read = (size_t)actual_read; + expected_read = pread(fd, expected, to_read, total); + assertEqualInt((int)to_read, expected_read); + assertEqualMem(actual, expected, to_read); + total += actual_read; + } + assertEqualInt(entry_size, total); +} + +DEFINE_TEST(test_read_format_tar_seek_data_h264_archive) +{ + const char *pathname; + struct archive *a; + struct archive_entry *ae; + int dumpfd; + int files_tested; + struct test_rng rng; + + pathname = getenv("TAR_SEEK_ARCHIVE_PATH"); + if (pathname == NULL || pathname[0] == '\0') { + skipping("no env variable defined, skipping the test"); + return; + } + + assert((a = archive_read_new()) != NULL); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); + assertEqualIntA( + a, ARCHIVE_OK, archive_read_open_filename(a, pathname, 10240)); + + files_tested = 0; + test_rng_init(&rng); + while (archive_read_next_header(a, &ae) == ARCHIVE_OK) { + char dumpname[64]; + int64_t entry_size; + int i; + + if (archive_entry_filetype(ae) != AE_IFREG) { + assertEqualIntA( + a, ARCHIVE_OK, archive_read_data_skip(a)); + continue; + } + + entry_size = archive_entry_size(ae); + files_tested++; + snprintf(dumpname, sizeof(dumpname), "tar-seek-dump-%d.bin", + files_tested); + dumpfd = + open(dumpname, O_CREAT | O_TRUNC | O_RDWR | O_BINARY, 0644); + assert(dumpfd >= 0); + + dump_tar_entry(a, dumpfd, entry_size); + + assertEqualInt(0, archive_seek_data(a, 0, SEEK_SET)); + check_tar_sequential_matches_dump(a, dumpfd, entry_size); + assertEqualInt(0, archive_seek_data(a, 0, SEEK_SET)); + check_tar_sequential_matches_dump(a, dumpfd, entry_size); + + assertEqualInt(0, archive_seek_data(a, 0, SEEK_SET)); + check_tar_seek_dump(a, dumpfd, entry_size, 0); + + assertEqualInt(entry_size, archive_seek_data(a, 0, SEEK_END)); + check_tar_seek_dump(a, dumpfd, entry_size, entry_size); + + for (i = 0; i < 8; i++) { + int64_t target; + int64_t current; + int64_t delta; + + target = test_rng_next(&rng) % (entry_size + 1); + assertEqualInt( + target, archive_seek_data(a, target, SEEK_SET)); + check_tar_seek_dump(a, dumpfd, entry_size, target); + + current = target; + if (current < entry_size) { + size_t advanced = + (size_t)(entry_size - current); + if (advanced > 4096) + advanced = 4096; + current += advanced; + } + + delta = + (test_rng_next(&rng) % (entry_size + 1)) - current; + target = current + delta; + assertEqualInt( + target, archive_seek_data(a, delta, SEEK_CUR)); + check_tar_seek_dump(a, dumpfd, entry_size, target); + + target = test_rng_next(&rng) % (entry_size + 1); + assertEqualInt( + target, archive_seek_data( + a, target - entry_size, SEEK_END)); + check_tar_seek_dump(a, dumpfd, entry_size, target); + } + + assertEqualInt(0, close(dumpfd)); + assertEqualInt(0, unlink(dumpname)); + assertEqualIntA(a, ARCHIVE_OK, archive_read_data_skip(a)); + } + + assert(files_tested > 0); + assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); + assertEqualInt(ARCHIVE_OK, archive_read_free(a)); +} + DEFINE_TEST(test_read_format_tar) { verifyEmpty(); @@ -472,5 +888,3 @@ DEFINE_TEST(test_read_format_tar) verify(archivexL, sizeof(archivexL), verifyxL, ARCHIVE_FILTER_NONE, ARCHIVE_FORMAT_TAR_PAX_INTERCHANGE); } - - diff --git a/libarchive/test/test_write_format_mtree.c b/libarchive/test/test_write_format_mtree.c index 5109e0920b..c3c2c0d938 100644 --- a/libarchive/test/test_write_format_mtree.c +++ b/libarchive/test/test_write_format_mtree.c @@ -110,7 +110,7 @@ test_write_format_mtree_sub(int use_set, int dironly) assertEqualInt(ARCHIVE_OK, archive_write_free(a)); if (use_set) { - const char *p; + char *p; buff[used] = '\0'; assert(NULL != (p = strstr(buff, "\n/set "))); @@ -198,7 +198,7 @@ test_write_format_mtree_sub2(int use_set, int dironly) assertEqualInt(ARCHIVE_OK, archive_write_free(a)); if (use_set) { - const char *p; + char *p; buff[used] = '\0'; assert(NULL != (p = strstr(buff, "\n/set "))); diff --git a/tar/CMakeLists.txt b/tar/CMakeLists.txt index 6434791f78..acc6bdc10b 100644 --- a/tar/CMakeLists.txt +++ b/tar/CMakeLists.txt @@ -34,13 +34,7 @@ IF(ENABLE_TAR) # How to build bsdtar ADD_EXECUTABLE(bsdtar ${bsdtar_SOURCES}) - IF(ENABLE_TAR_SHARED) - TARGET_LINK_LIBRARIES(bsdtar archive ${ADDITIONAL_LIBS}) - ELSE(ENABLE_TAR_SHARED) - TARGET_LINK_LIBRARIES(bsdtar archive_static ${ADDITIONAL_LIBS}) - SET_TARGET_PROPERTIES(bsdtar PROPERTIES COMPILE_DEFINITIONS - LIBARCHIVE_STATIC) - ENDIF(ENABLE_TAR_SHARED) + TARGET_LINK_LIBRARIES(bsdtar archive LibArchive::LibArchive) # Installation rules INSTALL(TARGETS bsdtar RUNTIME DESTINATION bin) diff --git a/unzip/CMakeLists.txt b/unzip/CMakeLists.txt index 150eb2c6b0..04853fa4aa 100644 --- a/unzip/CMakeLists.txt +++ b/unzip/CMakeLists.txt @@ -25,13 +25,7 @@ IF(ENABLE_UNZIP) # How to build bsdunzip ADD_EXECUTABLE(bsdunzip ${bsdunzip_SOURCES}) - IF(ENABLE_UNZIP_SHARED) - TARGET_LINK_LIBRARIES(bsdunzip archive ${ADDITIONAL_LIBS}) - ELSE(ENABLE_UNZIP_SHARED) - TARGET_LINK_LIBRARIES(bsdunzip archive_static ${ADDITIONAL_LIBS}) - SET_TARGET_PROPERTIES(bsdunzip PROPERTIES COMPILE_DEFINITIONS - LIBARCHIVE_STATIC) - ENDIF(ENABLE_UNZIP_SHARED) + TARGET_LINK_LIBRARIES(bsdunzip LibArchive::LibArchive) # Installation rules INSTALL(TARGETS bsdunzip RUNTIME DESTINATION bin)