diff options
author | kientzle <kientzle@FreeBSD.org> | 2009-12-29 05:28:28 +0000 |
---|---|---|
committer | kientzle <kientzle@FreeBSD.org> | 2009-12-29 05:28:28 +0000 |
commit | 8471ffeefd2b59c0313617b33083485ad84f505a (patch) | |
tree | 2b299224c8646e1b1705b4bf440bca2430324db7 /lib | |
parent | 7bdc19612bf4a5d7dcdd617e9bad41cbf1d4fe1c (diff) | |
download | FreeBSD-src-8471ffeefd2b59c0313617b33083485ad84f505a.zip FreeBSD-src-8471ffeefd2b59c0313617b33083485ad84f505a.tar.gz |
Various style and portability fixes, including:
* Enforce option interface can only be used before the archive is opened
* Correctly handle large skips on platforms with 32-bit off_t
* Use int64_t instead of off_t
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libarchive/archive_read.c | 47 |
1 files changed, 35 insertions, 12 deletions
diff --git a/lib/libarchive/archive_read.c b/lib/libarchive/archive_read.c index 648b1f9..bef2438 100644 --- a/lib/libarchive/archive_read.c +++ b/lib/libarchive/archive_read.c @@ -121,6 +121,9 @@ archive_read_set_format_options(struct archive *_a, const char *s) size_t i; int len, r; + __archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, + "archive_read_set_format_options"); + if (s == NULL || *s == '\0') return (ARCHIVE_OK); a = (struct archive_read *)_a; @@ -165,12 +168,14 @@ archive_read_set_filter_options(struct archive *_a, const char *s) char key[64], val[64]; int len, r; + __archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, + "archive_read_set_filter_options"); + if (s == NULL || *s == '\0') return (ARCHIVE_OK); a = (struct archive_read *)_a; __archive_check_magic(&a->archive, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, "archive_read_set_filter_options"); - filter = a->filter; len = 0; for (filter = a->filter; filter != NULL; filter = filter->upstream) { bidder = filter->bidder; @@ -206,6 +211,10 @@ archive_read_set_options(struct archive *_a, const char *s) { int r; + __archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, + "archive_read_set_options"); + archive_clear_error(_a); + r = archive_read_set_format_options(_a, s); if (r != ARCHIVE_OK) return (r); @@ -242,13 +251,26 @@ client_read_proxy(struct archive_read_filter *self, const void **buff) static int64_t client_skip_proxy(struct archive_read_filter *self, int64_t request) { - int64_t r; + int64_t ask, get, total; + /* Limit our maximum seek request to 1GB on platforms + * with 32-bit off_t (such as Windows). */ + int64_t skip_limit = ((int64_t)1) << (sizeof(off_t) * 8 - 2); + if (self->archive->client.skipper == NULL) return (0); - r = (self->archive->client.skipper)(&self->archive->archive, - self->data, request); - self->archive->archive.raw_position += r; - return (r); + total = 0; + for (;;) { + ask = request; + if (ask > skip_limit) + ask = skip_limit; + get = (self->archive->client.skipper)(&self->archive->archive, + self->data, ask); + if (get == 0) + return (total); + request -= get; + self->archive->archive.raw_position += get; + total += get; + } } static int @@ -277,6 +299,7 @@ archive_read_open2(struct archive *_a, void *client_data, __archive_check_magic(_a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_NEW, "archive_read_open"); + archive_clear_error(&a->archive); if (client_reader == NULL) __archive_errx(1, @@ -736,7 +759,7 @@ _archive_read_close(struct archive *_a) /* * Release memory and other resources. */ -int +static int _archive_read_finish(struct archive *_a) { struct archive_read *a = (struct archive_read *)_a; @@ -1121,6 +1144,8 @@ __archive_read_skip(struct archive_read *a, int64_t request) if (skipped == request) return (skipped); /* We hit EOF before we satisfied the skip request. */ + if (skipped < 0) // Map error code to 0 for error message below. + skipped = 0; archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Truncated input file (needed %jd bytes, only %jd available)", @@ -1140,7 +1165,7 @@ __archive_read_skip_lenient(struct archive_read *a, int64_t request) int64_t __archive_read_filter_skip(struct archive_read_filter *filter, int64_t request) { - off_t bytes_skipped, total_bytes_skipped = 0; + int64_t bytes_skipped, total_bytes_skipped = 0; size_t min; if (filter->fatal) @@ -1155,7 +1180,7 @@ __archive_read_filter_skip(struct archive_read_filter *filter, int64_t request) total_bytes_skipped += bytes_skipped; } if (filter->client_avail > 0) { - min = minimum(request, (off_t)filter->client_avail); + min = minimum(request, (int64_t)filter->client_avail); bytes_skipped = __archive_read_filter_consume(filter, min); request -= bytes_skipped; total_bytes_skipped += bytes_skipped; @@ -1189,10 +1214,8 @@ __archive_read_filter_skip(struct archive_read_filter *filter, int64_t request) * have to use ordinary reads to finish out the request. */ while (request > 0) { - const void* dummy_buffer; ssize_t bytes_read; - dummy_buffer = __archive_read_filter_ahead(filter, - 1, &bytes_read); + (void)__archive_read_filter_ahead(filter, 1, &bytes_read); if (bytes_read < 0) return (bytes_read); if (bytes_read == 0) { |