summaryrefslogtreecommitdiffstats
path: root/lib/libarchive
diff options
context:
space:
mode:
authorkientzle <kientzle@FreeBSD.org>2009-12-29 05:28:28 +0000
committerkientzle <kientzle@FreeBSD.org>2009-12-29 05:28:28 +0000
commit8471ffeefd2b59c0313617b33083485ad84f505a (patch)
tree2b299224c8646e1b1705b4bf440bca2430324db7 /lib/libarchive
parent7bdc19612bf4a5d7dcdd617e9bad41cbf1d4fe1c (diff)
downloadFreeBSD-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/libarchive')
-rw-r--r--lib/libarchive/archive_read.c47
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) {
OpenPOWER on IntegriCloud