svn commit: r201156 - head/lib/libarchive

Tim Kientzle kientzle at FreeBSD.org
Tue Dec 29 05:28:29 UTC 2009


Author: kientzle
Date: Tue Dec 29 05:28:28 2009
New Revision: 201156
URL: http://svn.freebsd.org/changeset/base/201156

Log:
  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

Modified:
  head/lib/libarchive/archive_read.c

Modified: head/lib/libarchive/archive_read.c
==============================================================================
--- head/lib/libarchive/archive_read.c	Tue Dec 29 05:20:12 2009	(r201155)
+++ head/lib/libarchive/archive_read.c	Tue Dec 29 05:28:28 2009	(r201156)
@@ -121,6 +121,9 @@ archive_read_set_format_options(struct a
 	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 a
 	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 
 {
 	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_fi
 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, v
 
 	__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 
 	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 archi
 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 archiv
 		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 archiv
 	 * 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) {


More information about the svn-src-all mailing list