summaryrefslogtreecommitdiff
path: root/lib/tar
diff options
context:
space:
mode:
Diffstat (limited to 'lib/tar')
-rw-r--r--lib/tar/Makemodule.am5
-rw-r--r--lib/tar/internal.h8
-rw-r--r--lib/tar/pax_header.c2
-rw-r--r--lib/tar/read_header.c24
-rw-r--r--lib/tar/read_retry.c57
-rw-r--r--lib/tar/read_sparse_map_new.c20
-rw-r--r--lib/tar/read_sparse_map_old.c14
-rw-r--r--lib/tar/record_to_memory.c40
-rw-r--r--lib/tar/skip.c44
9 files changed, 92 insertions, 122 deletions
diff --git a/lib/tar/Makemodule.am b/lib/tar/Makemodule.am
index 7ba0454..414aca1 100644
--- a/lib/tar/Makemodule.am
+++ b/lib/tar/Makemodule.am
@@ -1,9 +1,10 @@
-libtar_a_SOURCES = lib/tar/read_header.c lib/tar/write_header.c lib/tar/skip.c
+libtar_a_SOURCES = lib/tar/read_header.c lib/tar/write_header.c
libtar_a_SOURCES += lib/tar/number.c lib/tar/checksum.c lib/tar/cleanup.c
libtar_a_SOURCES += lib/tar/read_sparse_map.c lib/tar/read_sparse_map_old.c
libtar_a_SOURCES += lib/tar/base64.c lib/tar/urldecode.c lib/tar/internal.h
-libtar_a_SOURCES += lib/tar/padd_file.c lib/tar/read_retry.c include/tar.h
+libtar_a_SOURCES += lib/tar/padd_file.c lib/tar/record_to_memory.c
libtar_a_SOURCES += lib/tar/pax_header.c lib/tar/read_sparse_map_new.c
+libtar_a_SOURCES += include/tar.h
libtar_a_CFLAGS = $(AM_CFLAGS)
libtar_a_CPPFLAGS = $(AM_CPPFLAGS)
diff --git a/lib/tar/internal.h b/lib/tar/internal.h
index bea863d..b7c4c34 100644
--- a/lib/tar/internal.h
+++ b/lib/tar/internal.h
@@ -59,9 +59,9 @@ bool is_checksum_valid(const tar_header_t *hdr);
sparse_map_t *read_sparse_map(const char *line);
-sparse_map_t *read_gnu_old_sparse(FILE *fp, tar_header_t *hdr);
+sparse_map_t *read_gnu_old_sparse(istream_t *fp, tar_header_t *hdr);
-sparse_map_t *read_gnu_new_sparse(FILE *fp, tar_header_decoded_t *out);
+sparse_map_t *read_gnu_new_sparse(istream_t *fp, tar_header_decoded_t *out);
void free_sparse_list(sparse_map_t *sparse);
@@ -69,9 +69,9 @@ size_t base64_decode(sqfs_u8 *out, const char *in, size_t len);
void urldecode(char *str);
-char *record_to_memory(FILE *fp, sqfs_u64 size);
+char *record_to_memory(istream_t *fp, size_t size);
-int read_pax_header(FILE *fp, sqfs_u64 entsize, unsigned int *set_by_pax,
+int read_pax_header(istream_t *fp, sqfs_u64 entsize, unsigned int *set_by_pax,
tar_header_decoded_t *out);
#endif /* INTERNAL_H */
diff --git a/lib/tar/pax_header.c b/lib/tar/pax_header.c
index 448976d..a96a32f 100644
--- a/lib/tar/pax_header.c
+++ b/lib/tar/pax_header.c
@@ -25,7 +25,7 @@ static tar_xattr_t *mkxattr(const char *key, size_t keylen,
return xattr;
}
-int read_pax_header(FILE *fp, sqfs_u64 entsize, unsigned int *set_by_pax,
+int read_pax_header(istream_t *fp, sqfs_u64 entsize, unsigned int *set_by_pax,
tar_header_decoded_t *out)
{
char *buffer, *line, *key, *ptr, *value, *end;
diff --git a/lib/tar/read_header.c b/lib/tar/read_header.c
index 14752ea..b332514 100644
--- a/lib/tar/read_header.c
+++ b/lib/tar/read_header.c
@@ -170,20 +170,24 @@ static int decode_header(const tar_header_t *hdr, unsigned int set_by_pax,
return 0;
}
-int read_header(FILE *fp, tar_header_decoded_t *out)
+int read_header(istream_t *fp, tar_header_decoded_t *out)
{
unsigned int set_by_pax = 0;
bool prev_was_zero = false;
sqfs_u64 pax_size;
tar_header_t hdr;
- int version;
+ int version, ret;
memset(out, 0, sizeof(*out));
for (;;) {
- if (read_retry("reading tar header", fp, &hdr, sizeof(hdr)))
+ ret = istream_read(fp, &hdr, sizeof(hdr));
+ if (ret < 0)
goto fail;
+ if ((size_t)ret < sizeof(hdr))
+ goto out_eof;
+
if (is_zero_block(&hdr)) {
if (prev_was_zero)
goto out_eof;
@@ -294,3 +298,17 @@ fail:
clear_header(out);
return -1;
}
+
+int skip_padding(istream_t *fp, sqfs_u64 size)
+{
+ size_t tail = size % 512;
+
+ return tail ? istream_skip(fp, 512 - tail) : 0;
+}
+
+int skip_entry(istream_t *fp, sqfs_u64 size)
+{
+ size_t tail = size % 512;
+
+ return istream_skip(fp, tail ? (size + 512 - tail) : size);
+}
diff --git a/lib/tar/read_retry.c b/lib/tar/read_retry.c
deleted file mode 100644
index 2a2f82c..0000000
--- a/lib/tar/read_retry.c
+++ /dev/null
@@ -1,57 +0,0 @@
-/* SPDX-License-Identifier: GPL-3.0-or-later */
-/*
- * read_retry.c
- *
- * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at>
- */
-#include "config.h"
-
-#include "tar.h"
-#include "internal.h"
-
-int read_retry(const char *errstr, FILE *fp, void *buffer, size_t size)
-{
- size_t ret;
-
- while (size > 0) {
- if (ferror(fp)) {
- fprintf(stderr, "%s: error reading from file\n",
- errstr);
- return -1;
- }
-
- if (feof(fp)) {
- fprintf(stderr, "%s: short read\n", errstr);
- return -1;
- }
-
- ret = fread(buffer, 1, size, fp);
- size -= ret;
- buffer = (char *)buffer + ret;
- }
-
- return 0;
-}
-
-char *record_to_memory(FILE *fp, sqfs_u64 size)
-{
- char *buffer = malloc(size + 1);
-
- if (buffer == NULL)
- goto fail_errno;
-
- if (read_retry("reading tar record", fp, buffer, size))
- goto fail;
-
- if (skip_padding(fp, size))
- goto fail;
-
- buffer[size] = '\0';
- return buffer;
-fail_errno:
- perror("reading tar record");
- goto fail;
-fail:
- free(buffer);
- return NULL;
-}
diff --git a/lib/tar/read_sparse_map_new.c b/lib/tar/read_sparse_map_new.c
index f4f0f92..d9f6c6e 100644
--- a/lib/tar/read_sparse_map_new.c
+++ b/lib/tar/read_sparse_map_new.c
@@ -28,7 +28,7 @@ static int decode(const char *str, size_t len, size_t *out)
return (*str == '\n') ? ((int)count + 1) : -1;
}
-sparse_map_t *read_gnu_new_sparse(FILE *fp, tar_header_decoded_t *out)
+sparse_map_t *read_gnu_new_sparse(istream_t *fp, tar_header_decoded_t *out)
{
sparse_map_t *last = NULL, *list = NULL, *ent = NULL;
size_t i, count, value;
@@ -38,8 +38,12 @@ sparse_map_t *read_gnu_new_sparse(FILE *fp, tar_header_decoded_t *out)
if (out->record_size < 512)
goto fail_format;
- if (read_retry("reading GNU sparse map", fp, buffer, 512))
- return NULL;
+ ret = istream_read(fp, buffer, 512);
+ if (ret < 0)
+ goto fail;
+
+ if (ret < 512)
+ goto fail_format;
diff = decode(buffer, 512, &count);
if (diff <= 0)
@@ -61,10 +65,12 @@ sparse_map_t *read_gnu_new_sparse(FILE *fp, tar_header_decoded_t *out)
if (out->record_size < 512)
goto fail_format;
- if (read_retry("reading GNU sparse map", fp,
- buffer + 512, 512)) {
- return NULL;
- }
+ ret = istream_read(fp, buffer + 512, 512);
+ if (ret < 0)
+ goto fail;
+
+ if (ret < 512)
+ goto fail_format;
ret = decode(buffer + diff, 1024 - diff, &value);
if (ret <= 0)
diff --git a/lib/tar/read_sparse_map_old.c b/lib/tar/read_sparse_map_old.c
index 84e1f9e..cd7177d 100644
--- a/lib/tar/read_sparse_map_old.c
+++ b/lib/tar/read_sparse_map_old.c
@@ -8,12 +8,12 @@
#include "internal.h"
-sparse_map_t *read_gnu_old_sparse(FILE *fp, tar_header_t *hdr)
+sparse_map_t *read_gnu_old_sparse(istream_t *fp, tar_header_t *hdr)
{
sparse_map_t *list = NULL, *end = NULL, *node;
gnu_sparse_t sph;
sqfs_u64 off, sz;
- int i;
+ int i, ret;
for (i = 0; i < 4; ++i) {
if (!isdigit(hdr->tail.gnu.sparse[i].offset[0]))
@@ -47,8 +47,14 @@ sparse_map_t *read_gnu_old_sparse(FILE *fp, tar_header_t *hdr)
return list;
do {
- if (read_retry("reading GNU sparse header",
- fp, &sph, sizeof(sph))) {
+ ret = istream_read(fp, &sph, sizeof(sph));
+ if (ret < 0)
+ goto fail;
+
+ if ((size_t)ret < sizeof(sph)) {
+ fputs("reading GNU sparse header: "
+ "unexpected end-of-file\n",
+ stderr);
goto fail;
}
diff --git a/lib/tar/record_to_memory.c b/lib/tar/record_to_memory.c
new file mode 100644
index 0000000..822608c
--- /dev/null
+++ b/lib/tar/record_to_memory.c
@@ -0,0 +1,40 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later */
+/*
+ * record_to_memory.c
+ *
+ * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at>
+ */
+#include "config.h"
+
+#include "tar.h"
+#include "internal.h"
+
+char *record_to_memory(istream_t *fp, size_t size)
+{
+ char *buffer = malloc(size + 1);
+ int ret;
+
+ if (buffer == NULL)
+ goto fail_errno;
+
+ ret = istream_read(fp, buffer, size);
+ if (ret < 0)
+ goto fail;
+
+ if ((size_t)ret < size) {
+ fputs("Reading tar record: unexpected end-of-file.\n", stderr);
+ goto fail;
+ }
+
+ if (skip_padding(fp, size))
+ goto fail;
+
+ buffer[size] = '\0';
+ return buffer;
+fail_errno:
+ perror("reading tar record");
+ goto fail;
+fail:
+ free(buffer);
+ return NULL;
+}
diff --git a/lib/tar/skip.c b/lib/tar/skip.c
deleted file mode 100644
index 36cd470..0000000
--- a/lib/tar/skip.c
+++ /dev/null
@@ -1,44 +0,0 @@
-/* SPDX-License-Identifier: GPL-3.0-or-later */
-/*
- * skip.c
- *
- * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at>
- */
-#include "config.h"
-
-#include "tar.h"
-
-#include <stdio.h>
-
-static int skip_bytes(FILE *fp, sqfs_u64 size)
-{
- unsigned char buffer[1024];
- size_t diff;
-
- while (size != 0) {
- diff = sizeof(buffer);
- if (diff > size)
- diff = size;
-
- if (read_retry("reading tar record padding", fp, buffer, diff))
- return -1;
-
- size -= diff;
- }
-
- return 0;
-}
-
-int skip_padding(FILE *fp, sqfs_u64 size)
-{
- size_t tail = size % 512;
-
- return tail ? skip_bytes(fp, 512 - tail) : 0;
-}
-
-int skip_entry(FILE *fp, sqfs_u64 size)
-{
- size_t tail = size % 512;
-
- return skip_bytes(fp, tail ? (size + 512 - tail) : size);
-}