summaryrefslogtreecommitdiff
path: root/libarchive/archive_read_open_fd.c
diff options
context:
space:
mode:
authorTim Kientzle <kientzle@gmail.com>2010-05-31 15:01:37 -0400
committerTim Kientzle <kientzle@gmail.com>2010-05-31 15:01:37 -0400
commit1cc924729dab2d656141aaa3f220fde18aff8ba8 (patch)
tree91fc4714f8cfcbe379da10974fd71712be8a39c7 /libarchive/archive_read_open_fd.c
parente84527bd717961761e6025171ef49d4db1a97027 (diff)
downloadlibarchive-1cc924729dab2d656141aaa3f220fde18aff8ba8.tar.gz
Eliminate some more off_t usage; mark some that are okay because
they're only used on specific platforms where off_t is required. SVN-Revision: 2437
Diffstat (limited to 'libarchive/archive_read_open_fd.c')
-rw-r--r--libarchive/archive_read_open_fd.c55
1 files changed, 21 insertions, 34 deletions
diff --git a/libarchive/archive_read_open_fd.c b/libarchive/archive_read_open_fd.c
index bc547a57..4b9dba30 100644
--- a/libarchive/archive_read_open_fd.c
+++ b/libarchive/archive_read_open_fd.c
@@ -53,7 +53,7 @@ __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_open_fd.c 201103 2009-12-28
struct read_fd_data {
int fd;
size_t block_size;
- char can_skip;
+ char use_lseek;
void *buffer;
};
@@ -78,7 +78,7 @@ archive_read_open_fd(struct archive *a, int fd, size_t block_size)
return (ARCHIVE_FATAL);
}
- mine = (struct read_fd_data *)malloc(sizeof(*mine));
+ mine = (struct read_fd_data *)calloc(1, sizeof(*mine));
b = malloc(block_size);
if (mine == NULL || b == NULL) {
archive_set_error(a, ENOMEM, "No memory");
@@ -98,9 +98,8 @@ archive_read_open_fd(struct archive *a, int fd, size_t block_size)
*/
if (S_ISREG(st.st_mode)) {
archive_read_extract_set_skip_file(a, st.st_dev, st.st_ino);
- mine->can_skip = 1;
- } else
- mine->can_skip = 0;
+ mine->use_lseek = 1;
+ }
#if defined(__CYGWIN__) || defined(_WIN32)
setmode(mine->fd, O_BINARY);
#endif
@@ -138,7 +137,7 @@ file_skip(struct archive *a, void *client_data, int64_t request)
struct read_fd_data *mine = (struct read_fd_data *)client_data;
off_t old_offset, new_offset;
- if (!mine->can_skip)
+ if (!mine->use_lseek)
return (0);
/* Reduce request to the next smallest multiple of block_size */
@@ -146,36 +145,24 @@ file_skip(struct archive *a, void *client_data, int64_t request)
if (request == 0)
return (0);
+ if (((old_offset = lseek(mine->fd, 0, SEEK_CUR)) >= 0) &&
+ ((new_offset = lseek(mine->fd, request, SEEK_CUR)) >= 0))
+ return (new_offset - old_offset);
+
+ /* If seek failed once, it will probably fail again. */
+ mine->use_lseek = 0;
+
+ /* Let libarchive recover with read+discard. */
+ if (errno == ESPIPE)
+ return (0);
+
/*
- * Hurray for lazy evaluation: if the first lseek fails, the second
- * one will not be executed.
+ * There's been an error other than ESPIPE. This is most
+ * likely caused by a programmer error (too large request)
+ * or a corrupted archive file.
*/
- 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)
- {
- /*
- * Failure to lseek() can be caused by the file
- * descriptor pointing to a pipe, socket or FIFO.
- * Return 0 here, so the compression layer will use
- * read()s instead to advance the file descriptor.
- * It's slower of course, but works as well.
- */
- return (0);
- }
- /*
- * There's been an error other than ESPIPE. This is most
- * likely caused by a programmer error (too large request)
- * or a corrupted archive file.
- */
- archive_set_error(a, errno, "Error seeking");
- return (-1);
- }
- return (new_offset - old_offset);
+ archive_set_error(a, errno, "Error seeking");
+ return (-1);
}
static int