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
This commit is contained in:
Tim Kientzle 2009-12-29 05:28:28 +00:00
parent 081e9a983c
commit e2196d3e85

View File

@ -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) {