summaryrefslogtreecommitdiffstats
path: root/lib/libarchive/archive_read_support_format_cpio.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_support_format_cpio.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_support_format_cpio.c')
-rw-r--r--lib/libarchive/archive_read_support_format_cpio.c100
1 files changed, 72 insertions, 28 deletions
diff --git a/lib/libarchive/archive_read_support_format_cpio.c b/lib/libarchive/archive_read_support_format_cpio.c
index 830eafb..03af38f 100644
--- a/lib/libarchive/archive_read_support_format_cpio.c
+++ b/lib/libarchive/archive_read_support_format_cpio.c
@@ -97,27 +97,32 @@ struct links_entry {
#define CPIO_MAGIC 0x13141516
struct cpio {
int magic;
- int (*read_header)(struct archive *, struct stat *,
- size_t *, size_t *);
+ int (*read_header)(struct archive *, struct cpio *,
+ struct stat *, size_t *, size_t *);
struct links_entry *links_head;
struct archive_string entry_name;
struct archive_string entry_linkname;
+ off_t entry_bytes_remaining;
+ off_t entry_offset;
+ off_t entry_padding;
};
static int64_t atol16(const char *, unsigned);
static int64_t atol8(const char *, unsigned);
static int archive_read_format_cpio_bid(struct archive *);
static int archive_read_format_cpio_cleanup(struct archive *);
+static int archive_read_format_cpio_read_data(struct archive *,
+ const void **, size_t *, off_t *);
static int archive_read_format_cpio_read_header(struct archive *,
struct archive_entry *);
static int be4(const unsigned char *);
-static int header_bin_be(struct archive *, struct stat *,
+static int header_bin_be(struct archive *, struct cpio *, struct stat *,
size_t *, size_t *);
-static int header_bin_le(struct archive *, struct stat *,
+static int header_bin_le(struct archive *, struct cpio *, struct stat *,
size_t *, size_t *);
-static int header_newc(struct archive *, struct stat *,
+static int header_newc(struct archive *, struct cpio *, struct stat *,
size_t *, size_t *);
-static int header_odc(struct archive *, struct stat *,
+static int header_odc(struct archive *, struct cpio *, struct stat *,
size_t *, size_t *);
static int le4(const unsigned char *);
static void record_hardlink(struct cpio *cpio, struct archive_entry *entry,
@@ -137,6 +142,7 @@ archive_read_support_format_cpio(struct archive *a)
cpio,
archive_read_format_cpio_bid,
archive_read_format_cpio_read_header,
+ archive_read_format_cpio_read_data,
archive_read_format_cpio_cleanup);
if (r != ARCHIVE_OK)
@@ -216,7 +222,7 @@ archive_read_format_cpio_read_header(struct archive *a,
memset(&st, 0, sizeof(st));
cpio = *(a->pformat_data);
- r = (cpio->read_header(a, &st, &namelength, &name_pad));
+ r = (cpio->read_header(a, cpio, &st, &namelength, &name_pad));
if (r != ARCHIVE_OK)
return (r);
@@ -231,18 +237,19 @@ archive_read_format_cpio_read_header(struct archive *a,
(a->compression_read_consume)(a, namelength + name_pad);
archive_strncpy(&cpio->entry_name, h, namelength);
archive_entry_set_pathname(entry, cpio->entry_name.s);
+ cpio->entry_offset = 0;
/* If this is a symlink, read the link contents. */
if (S_ISLNK(st.st_mode)) {
bytes = (a->compression_read_ahead)(a, &h,
- a->entry_bytes_remaining);
- if ((off_t)bytes < a->entry_bytes_remaining)
+ cpio->entry_bytes_remaining);
+ if ((off_t)bytes < cpio->entry_bytes_remaining)
return (ARCHIVE_FATAL);
- (a->compression_read_consume)(a, a->entry_bytes_remaining);
+ (a->compression_read_consume)(a, cpio->entry_bytes_remaining);
archive_strncpy(&cpio->entry_linkname, h,
- a->entry_bytes_remaining);
+ cpio->entry_bytes_remaining);
archive_entry_set_symlink(entry, cpio->entry_linkname.s);
- a->entry_bytes_remaining = 0;
+ cpio->entry_bytes_remaining = 0;
}
/* Compare name to "TRAILER!!!" to test for end-of-archive. */
@@ -259,7 +266,44 @@ archive_read_format_cpio_read_header(struct archive *a,
}
static int
-header_newc(struct archive *a, struct stat *st,
+archive_read_format_cpio_read_data(struct archive *a,
+ const void **buff, size_t *size, off_t *offset)
+{
+ ssize_t bytes_read;
+ struct cpio *cpio;
+
+ cpio = *(a->pformat_data);
+ if (cpio->entry_bytes_remaining > 0) {
+ bytes_read = (a->compression_read_ahead)(a, buff, 1);
+ if (bytes_read <= 0)
+ return (ARCHIVE_FATAL);
+ if (bytes_read > cpio->entry_bytes_remaining)
+ bytes_read = cpio->entry_bytes_remaining;
+ *size = bytes_read;
+ *offset = cpio->entry_offset;
+ cpio->entry_offset += bytes_read;
+ cpio->entry_bytes_remaining -= bytes_read;
+ (a->compression_read_consume)(a, bytes_read);
+ return (ARCHIVE_OK);
+ } else {
+ while (cpio->entry_padding > 0) {
+ bytes_read = (a->compression_read_ahead)(a, buff, 1);
+ if (bytes_read <= 0)
+ return (ARCHIVE_FATAL);
+ if (bytes_read > cpio->entry_padding)
+ bytes_read = cpio->entry_padding;
+ (a->compression_read_consume)(a, bytes_read);
+ cpio->entry_padding -= bytes_read;
+ }
+ *buff = NULL;
+ *size = 0;
+ *offset = cpio->entry_offset;
+ return (ARCHIVE_EOF);
+ }
+}
+
+static int
+header_newc(struct archive *a, struct cpio *cpio, struct stat *st,
size_t *namelength, size_t *name_pad)
{
const void *h;
@@ -293,16 +337,16 @@ header_newc(struct archive *a, struct stat *st,
* size. struct stat.st_size may only be 32 bits, so
* assigning there first could lose information.
*/
- a->entry_bytes_remaining =
+ cpio->entry_bytes_remaining =
atol16(header->c_filesize, sizeof(header->c_filesize));
- st->st_size = a->entry_bytes_remaining;
+ st->st_size = cpio->entry_bytes_remaining;
/* Pad file contents to a multiple of 4. */
- a->entry_padding = 3 & -a->entry_bytes_remaining;
+ cpio->entry_padding = 3 & -cpio->entry_bytes_remaining;
return (ARCHIVE_OK);
}
static int
-header_odc(struct archive *a, struct stat *st,
+header_odc(struct archive *a, struct cpio *cpio, struct stat *st,
size_t *namelength, size_t *name_pad)
{
const void *h;
@@ -338,15 +382,15 @@ header_odc(struct archive *a, struct stat *st,
* size. struct stat.st_size may only be 32 bits, so
* assigning there first could lose information.
*/
- a->entry_bytes_remaining =
+ cpio->entry_bytes_remaining =
atol8(header->c_filesize, sizeof(header->c_filesize));
- st->st_size = a->entry_bytes_remaining;
- a->entry_padding = 0;
+ st->st_size = cpio->entry_bytes_remaining;
+ cpio->entry_padding = 0;
return (ARCHIVE_OK);
}
static int
-header_bin_le(struct archive *a, struct stat *st,
+header_bin_le(struct archive *a, struct cpio *cpio, struct stat *st,
size_t *namelength, size_t *name_pad)
{
const void *h;
@@ -376,14 +420,14 @@ header_bin_le(struct archive *a, struct stat *st,
*namelength = header->c_namesize[0] + header->c_namesize[1] * 256;
*name_pad = *namelength & 1; /* Pad to even. */
- a->entry_bytes_remaining = le4(header->c_filesize);
- st->st_size = a->entry_bytes_remaining;
- a->entry_padding = a->entry_bytes_remaining & 1; /* Pad to even. */
+ cpio->entry_bytes_remaining = le4(header->c_filesize);
+ st->st_size = cpio->entry_bytes_remaining;
+ cpio->entry_padding = cpio->entry_bytes_remaining & 1; /* Pad to even. */
return (ARCHIVE_OK);
}
static int
-header_bin_be(struct archive *a, struct stat *st,
+header_bin_be(struct archive *a, struct cpio *cpio, struct stat *st,
size_t *namelength, size_t *name_pad)
{
const void *h;
@@ -413,9 +457,9 @@ header_bin_be(struct archive *a, struct stat *st,
*namelength = header->c_namesize[0] * 256 + header->c_namesize[1];
*name_pad = *namelength & 1; /* Pad to even. */
- a->entry_bytes_remaining = be4(header->c_filesize);
- st->st_size = a->entry_bytes_remaining;
- a->entry_padding = a->entry_bytes_remaining & 1; /* Pad to even. */
+ cpio->entry_bytes_remaining = be4(header->c_filesize);
+ st->st_size = cpio->entry_bytes_remaining;
+ cpio->entry_padding = cpio->entry_bytes_remaining & 1; /* Pad to even. */
return (ARCHIVE_OK);
}
OpenPOWER on IntegriCloud