From 41965bf9e02795168cced94985916c415064a04b Mon Sep 17 00:00:00 2001 From: Paul Harris Date: Tue, 30 Jun 2015 16:04:59 +0800 Subject: [PATCH] Add support for archive_read_data() for read_disk archives. Hoisted the relevant archive_read variables into the common archive struct. --- libarchive/archive_private.h | 19 ++++++++++++ libarchive/archive_read.c | 32 +++++++++++++++----- libarchive/archive_read_disk_posix.c | 2 ++ libarchive/archive_read_disk_windows.c | 2 ++ libarchive/archive_read_private.h | 17 ----------- libarchive/archive_read_support_format_rar.c | 10 +++--- 6 files changed, 52 insertions(+), 30 deletions(-) diff --git a/libarchive/archive_private.h b/libarchive/archive_private.h index 30d472fcd..4b4be9796 100644 --- a/libarchive/archive_private.h +++ b/libarchive/archive_private.h @@ -119,6 +119,23 @@ struct archive { unsigned current_codepage; /* Current ACP(ANSI CodePage). */ unsigned current_oemcp; /* Current OEMCP(OEM CodePage). */ struct archive_string_conv *sconv; + + /* + * Used by archive_read_data() to track blocks and copy + * data to client buffers, filling gaps with zero bytes. + */ + const char *read_data_block; + int64_t read_data_offset; + int64_t read_data_output_offset; + size_t read_data_remaining; + + /* + * Used by formats/filters to determine the amount of data + * requested from a call to archive_read_data(). This is only + * useful when the format/filter has seek support. + */ + char read_data_is_posix_read; + size_t read_data_requested; }; /* Check magic value and state; return(ARCHIVE_FATAL) if it isn't valid. */ @@ -139,6 +156,8 @@ int __archive_mktemp(const char *tmpdir); int __archive_clean(struct archive *); +void __archive_reset_read_data(struct archive *); + #define err_combine(a,b) ((a) < (b) ? (a) : (b)) #if defined(__BORLANDC__) || (defined(_MSC_VER) && _MSC_VER <= 1300) diff --git a/libarchive/archive_read.c b/libarchive/archive_read.c index 11f7a0b73..56dd8877b 100644 --- a/libarchive/archive_read.c +++ b/libarchive/archive_read.c @@ -667,10 +667,8 @@ _archive_read_next_header2(struct archive *_a, struct archive_entry *entry) break; } - a->read_data_output_offset = 0; - a->read_data_remaining = 0; - a->read_data_is_posix_read = 0; - a->read_data_requested = 0; + __archive_reset_read_data(&a->archive); + a->data_start_node = a->client.cursor; /* EOF always wins; otherwise return the worst error. */ return (r2 < r1 || r2 == ARCHIVE_EOF) ? r2 : r1; @@ -822,7 +820,7 @@ archive_read_format_capabilities(struct archive *_a) ssize_t archive_read_data(struct archive *_a, void *buff, size_t s) { - struct archive_read *a = (struct archive_read *)_a; + struct archive *a = (struct archive *)_a; char *dest; const void *read_buf; size_t bytes_read; @@ -837,7 +835,7 @@ archive_read_data(struct archive *_a, void *buff, size_t s) read_buf = a->read_data_block; a->read_data_is_posix_read = 1; a->read_data_requested = s; - r = _archive_read_data_block(&a->archive, &read_buf, + r = archive_read_data_block(a, &read_buf, &a->read_data_remaining, &a->read_data_offset); a->read_data_block = read_buf; if (r == ARCHIVE_EOF) @@ -852,7 +850,7 @@ archive_read_data(struct archive *_a, void *buff, size_t s) } if (a->read_data_offset < a->read_data_output_offset) { - archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, + archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT, "Encountered out-of-order sparse blocks"); return (ARCHIVE_RETRY); } @@ -895,6 +893,26 @@ archive_read_data(struct archive *_a, void *buff, size_t s) return (bytes_read); } + + + /* + * Reset the read_data_* variables, used for starting a new entry. + */ +void __archive_reset_read_data(struct archive * a) +{ + a->read_data_output_offset = 0; + a->read_data_remaining = 0; + a->read_data_is_posix_read = 0; + a->read_data_requested = 0; + + /* extra resets, from rar.c */ + a->read_data_block = NULL; + a->read_data_offset = 0; +} + + + + /* * Skip over all remaining data in this entry. */ diff --git a/libarchive/archive_read_disk_posix.c b/libarchive/archive_read_disk_posix.c index 7a5a159f6..0063ddd93 100644 --- a/libarchive/archive_read_disk_posix.c +++ b/libarchive/archive_read_disk_posix.c @@ -1152,6 +1152,8 @@ _archive_read_next_header2(struct archive *_a, struct archive_entry *entry) break; } + __archive_reset_read_data(&a->archive); + return (r); } diff --git a/libarchive/archive_read_disk_windows.c b/libarchive/archive_read_disk_windows.c index fb06f26fa..3fb6f15b1 100644 --- a/libarchive/archive_read_disk_windows.c +++ b/libarchive/archive_read_disk_windows.c @@ -1000,6 +1000,8 @@ _archive_read_next_header2(struct archive *_a, struct archive_entry *entry) break; } + __archive_reset_read_data(&a->archive); + return (r); } diff --git a/libarchive/archive_read_private.h b/libarchive/archive_read_private.h index 774db82b7..9b61a5380 100644 --- a/libarchive/archive_read_private.h +++ b/libarchive/archive_read_private.h @@ -166,23 +166,6 @@ struct archive_read { int64_t skip_file_dev; int64_t skip_file_ino; - /* - * Used by archive_read_data() to track blocks and copy - * data to client buffers, filling gaps with zero bytes. - */ - const char *read_data_block; - int64_t read_data_offset; - int64_t read_data_output_offset; - size_t read_data_remaining; - - /* - * Used by formats/filters to determine the amount of data - * requested from a call to archive_read_data(). This is only - * useful when the format/filter has seek support. - */ - char read_data_is_posix_read; - size_t read_data_requested; - /* Callbacks to open/read/write/close client archive streams. */ struct archive_read_client client; diff --git a/libarchive/archive_read_support_format_rar.c b/libarchive/archive_read_support_format_rar.c index ee8ce539f..88979bb4c 100644 --- a/libarchive/archive_read_support_format_rar.c +++ b/libarchive/archive_read_support_format_rar.c @@ -1203,10 +1203,8 @@ archive_read_format_rar_seek_data(struct archive_read *a, int64_t offset, ret -= rar->dbo[0].start_offset; /* Always restart reading the file after a seek */ - a->read_data_block = NULL; - a->read_data_offset = 0; - a->read_data_output_offset = 0; - a->read_data_remaining = 0; + __archive_reset_read_data(&a->archive); + rar->bytes_unconsumed = 0; rar->offset = 0; @@ -2907,8 +2905,8 @@ rar_read_ahead(struct archive_read *a, size_t min, ssize_t *avail) int ret; if (avail) { - if (a->read_data_is_posix_read && *avail > (ssize_t)a->read_data_requested) - *avail = a->read_data_requested; + if (a->archive.read_data_is_posix_read && *avail > (ssize_t)a->archive.read_data_requested) + *avail = a->archive.read_data_requested; if (*avail > rar->bytes_remaining) *avail = (ssize_t)rar->bytes_remaining; if (*avail < 0) -- 2.47.2