summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorkientzle <kientzle@FreeBSD.org>2007-06-18 00:36:54 +0000
committerkientzle <kientzle@FreeBSD.org>2007-06-18 00:36:54 +0000
commita5faebae4a45342f035681844764b46bc962865c (patch)
treed53bcc590f5c83dc15e7758522eca42ac348a135 /lib
parent85dbbe27811d719c4e6c770a2f8acd3dc9af6195 (diff)
downloadFreeBSD-src-a5faebae4a45342f035681844764b46bc962865c.zip
FreeBSD-src-a5faebae4a45342f035681844764b46bc962865c.tar.gz
Track whether the current read stream supports seek(). For now, we
assume yes unless seek has previously failed, but I fear I'll have to avoid seeks under other circumstances. (For instance, tape drives on FreeBSD seem to return garbage from lseek().) Also, optimize away zero-byte skips.
Diffstat (limited to 'lib')
-rw-r--r--lib/libarchive/archive_read_open_fd.c11
-rw-r--r--lib/libarchive/archive_read_open_filename.c11
2 files changed, 22 insertions, 0 deletions
diff --git a/lib/libarchive/archive_read_open_fd.c b/lib/libarchive/archive_read_open_fd.c
index 490b00b..0608fd6 100644
--- a/lib/libarchive/archive_read_open_fd.c
+++ b/lib/libarchive/archive_read_open_fd.c
@@ -47,6 +47,7 @@ __FBSDID("$FreeBSD$");
struct read_fd_data {
int fd;
size_t block_size;
+ char can_skip;
void *buffer;
};
@@ -77,6 +78,7 @@ archive_read_open_fd(struct archive *a, int fd, size_t block_size)
return (ARCHIVE_FATAL);
}
mine->fd = fd;
+ mine->can_skip = 1;
return (archive_read_open2(a, mine, file_open, file_read, file_skip, file_close));
}
@@ -121,8 +123,14 @@ file_skip(struct archive *a, void *client_data, off_t request)
struct read_fd_data *mine = (struct read_fd_data *)client_data;
off_t old_offset, new_offset;
+ if (!mine->can_skip)
+ return (0);
+
/* Reduce request to the next smallest multiple of block_size */
request = (request / mine->block_size) * mine->block_size;
+ if (request == 0)
+ return (0);
+
/*
* Hurray for lazy evaluation: if the first lseek fails, the second
* one will not be executed.
@@ -130,6 +138,9 @@ file_skip(struct archive *a, void *client_data, off_t request)
if (((old_offset = lseek(mine->fd, 0, SEEK_CUR)) < 0) ||
((new_offset = lseek(mine->fd, request, SEEK_CUR)) < 0))
{
+ /* If seek failed once, it will probably fail again. */
+ mine->can_skip = 0;
+
if (errno == ESPIPE)
{
/*
diff --git a/lib/libarchive/archive_read_open_filename.c b/lib/libarchive/archive_read_open_filename.c
index b4dd2e2..c95e787 100644
--- a/lib/libarchive/archive_read_open_filename.c
+++ b/lib/libarchive/archive_read_open_filename.c
@@ -52,6 +52,7 @@ struct read_file_data {
size_t block_size;
void *buffer;
mode_t st_mode; /* Mode bits for opened file. */
+ char can_skip; /* This file supports skipping. */
char filename[1]; /* Must be last! */
};
@@ -95,6 +96,7 @@ archive_read_open_filename(struct archive *a, const char *filename,
mine->block_size = block_size;
mine->buffer = NULL;
mine->fd = -1;
+ mine->can_skip = 1;
return (archive_read_open2(a, mine, file_open, file_read, file_skip, file_close));
}
@@ -165,8 +167,14 @@ file_skip(struct archive *a, void *client_data, off_t request)
struct read_file_data *mine = (struct read_file_data *)client_data;
off_t old_offset, new_offset;
+ if (!mine->can_skip) /* We can't skip, so ... */
+ return (0); /* ... skip zero bytes. */
+
/* Reduce request to the next smallest multiple of block_size */
request = (request / mine->block_size) * mine->block_size;
+ if (request == 0)
+ return (0);
+
/*
* Hurray for lazy evaluation: if the first lseek fails, the second
* one will not be executed.
@@ -174,6 +182,9 @@ file_skip(struct archive *a, void *client_data, off_t request)
if (((old_offset = lseek(mine->fd, 0, SEEK_CUR)) < 0) ||
((new_offset = lseek(mine->fd, request, SEEK_CUR)) < 0))
{
+ /* If skip failed once, it will probably fail again. */
+ mine->can_skip = 0;
+
if (errno == ESPIPE)
{
/*
OpenPOWER on IntegriCloud