summaryrefslogtreecommitdiffstats
path: root/lib/libarchive/archive_read_data_into_fd.c
diff options
context:
space:
mode:
authorkientzle <kientzle@FreeBSD.org>2004-06-02 08:14:43 +0000
committerkientzle <kientzle@FreeBSD.org>2004-06-02 08:14:43 +0000
commitd5f7a83e1b2d795a41b6ee882323609891e65aeb (patch)
treeff12dd5c58d3d34186f2f2fd2f6c027221d2ebd8 /lib/libarchive/archive_read_data_into_fd.c
parent80d36400edd04b536fd6cab0dae30c9e678e6598 (diff)
downloadFreeBSD-src-d5f7a83e1b2d795a41b6ee882323609891e65aeb.zip
FreeBSD-src-d5f7a83e1b2d795a41b6ee882323609891e65aeb.tar.gz
Refactor read_data:
* New read_data_block is both sparse-file aware and uses zero-copy semantics * Push read_data_block down into specific formats (opens door to various encoded entry bodies, such as zip or gtar -S) * Reimplement read_data, read_data_skip, read_data_into_fd in terms of new read_data_block. * Update documentation It's unfortunate that I couldn't just call the new interface archive_read_data, but didn't want to upset the API that much.
Diffstat (limited to 'lib/libarchive/archive_read_data_into_fd.c')
-rw-r--r--lib/libarchive/archive_read_data_into_fd.c55
1 files changed, 34 insertions, 21 deletions
diff --git a/lib/libarchive/archive_read_data_into_fd.c b/lib/libarchive/archive_read_data_into_fd.c
index 9bdad4d..85ba98d 100644
--- a/lib/libarchive/archive_read_data_into_fd.c
+++ b/lib/libarchive/archive_read_data_into_fd.c
@@ -33,36 +33,49 @@ __FBSDID("$FreeBSD$");
#include "archive.h"
#include "archive_private.h"
+/* Maximum amount of data to write at one time. */
+#define MAX_WRITE (1024 * 1024)
+
/*
- * This implementation minimizes copying of data.
+ * This implementation minimizes copying of data and is sparse-file aware.
*/
ssize_t
archive_read_data_into_fd(struct archive *a, int fd)
{
- ssize_t bytes_read, bytes_written, total_written;
+ int r;
const void *buff;
+ ssize_t size, bytes_to_write;
+ ssize_t bytes_written, total_written;
+ off_t offset;
+ off_t output_offset;
+
+ archive_check_magic(a, ARCHIVE_READ_MAGIC, ARCHIVE_STATE_DATA);
total_written = 0;
- while (a->entry_bytes_remaining > 0) {
- /* Remember: '1' here is minimum, not maximum. */
- /* Read-ahead function will return as much as is convenient. */
- bytes_read = (a->compression_read_ahead)(a, &buff, 1);
- if (bytes_read < 0)
- return (-1);
- if (bytes_read > a->entry_bytes_remaining)
- bytes_read = (ssize_t)a->entry_bytes_remaining;
- /* Don't copy more than 1 megabyte at a time. */
- if (bytes_read > (1024*1024))
- bytes_read = 1024*1024;
+ output_offset = 0;
- bytes_written = write(fd, buff, bytes_read);
- if (bytes_written < 0)
- return (-1);
- (a->compression_read_consume)(a, bytes_written);
- total_written += bytes_written;
- a->entry_bytes_remaining -= bytes_written;
- if (a->extract_progress != NULL)
- (*a->extract_progress)(a->extract_progress_user_data);
+ while ((r = archive_read_data_block(a, &buff, &size, &offset)) ==
+ ARCHIVE_OK) {
+ if (offset > output_offset) {
+ lseek(fd, offset - output_offset, SEEK_CUR);
+ output_offset = offset;
+ }
+ while (size > 0) {
+ bytes_to_write = size;
+ if (bytes_to_write > MAX_WRITE)
+ bytes_to_write = MAX_WRITE;
+ bytes_written = write(fd, buff, bytes_to_write);
+ if (bytes_written < 0)
+ return (-1);
+ output_offset += bytes_written;
+ total_written += bytes_written;
+ size -= bytes_written;
+ if (a->extract_progress != NULL)
+ (*a->extract_progress)(a->extract_progress_user_data);
+ }
}
+
+ if (r != ARCHIVE_EOF)
+ return (-1);
return (total_written);
}
OpenPOWER on IntegriCloud