summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2020-09-13 13:37:42 +0200
committerDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2020-09-16 09:34:35 +0200
commitf757737060d4daebb24a32e90d912661428708a8 (patch)
treea6e96145d4fc540e435c13a69c924329db2edb6d /lib
parentc1a2cb729bd5bb5fdadf00cb3968bbc541f79750 (diff)
Remodel libtar/tar2sqfs to read data from an istream_t
Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
Diffstat (limited to 'lib')
-rw-r--r--lib/common/Makemodule.am4
-rw-r--r--lib/common/io_stdin.c182
-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
11 files changed, 94 insertions, 306 deletions
diff --git a/lib/common/Makemodule.am b/lib/common/Makemodule.am
index df08894..e191e29 100644
--- a/lib/common/Makemodule.am
+++ b/lib/common/Makemodule.am
@@ -3,10 +3,10 @@ libcommon_a_SOURCES += lib/common/inode_stat.c lib/common/hardlink.c
libcommon_a_SOURCES += lib/common/print_version.c lib/common/data_reader_dump.c
libcommon_a_SOURCES += lib/common/compress.c lib/common/comp_opt.c
libcommon_a_SOURCES += lib/common/data_writer.c include/common.h
-libcommon_a_SOURCES += lib/common/get_path.c lib/common/io_stdin.c
+libcommon_a_SOURCES += lib/common/get_path.c lib/common/data_writer_ostream.c
libcommon_a_SOURCES += lib/common/writer.c lib/common/perror.c
libcommon_a_SOURCES += lib/common/mkdir_p.c lib/common/parse_size.c
-libcommon_a_SOURCES += lib/common/print_size.c lib/common/data_writer_ostream.c
+libcommon_a_SOURCES += lib/common/print_size.c
libcommon_a_CFLAGS = $(AM_CFLAGS) $(LZO_CFLAGS)
if WITH_LZO
diff --git a/lib/common/io_stdin.c b/lib/common/io_stdin.c
deleted file mode 100644
index 4694989..0000000
--- a/lib/common/io_stdin.c
+++ /dev/null
@@ -1,182 +0,0 @@
-/* SPDX-License-Identifier: GPL-3.0-or-later */
-/*
- * io_stdin.c
- *
- * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at>
- */
-#include "common.h"
-
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-
-
-typedef struct {
- sqfs_file_t base;
-
- const sparse_map_t *map;
- sqfs_u64 offset;
- sqfs_u64 real_size;
- sqfs_u64 apparent_size;
- FILE *fp;
-} sqfs_file_stdinout_t;
-
-
-static void stdinout_destroy(sqfs_object_t *base)
-{
- free(base);
-}
-
-static sqfs_u64 stdinout_get_size(const sqfs_file_t *base)
-{
- return ((const sqfs_file_stdinout_t *)base)->apparent_size;
-}
-
-static int stdinout_truncate(sqfs_file_t *base, sqfs_u64 size)
-{
- (void)base; (void)size;
- return SQFS_ERROR_IO;
-}
-
-static int stdin_read_at(sqfs_file_t *base, sqfs_u64 offset,
- void *buffer, size_t size)
-{
- sqfs_file_stdinout_t *file = (sqfs_file_stdinout_t *)base;
- size_t temp_size = 0;
- sqfs_u8 *temp = NULL;
- sqfs_u64 diff;
- size_t ret;
-
- if (offset < file->offset)
- return SQFS_ERROR_IO;
-
- if (offset > file->offset) {
- temp_size = 1024;
- temp = alloca(temp_size);
- }
-
- if (offset >= file->real_size || (offset + size) > file->real_size)
- return SQFS_ERROR_OUT_OF_BOUNDS;
-
- while (size > 0) {
- if (ferror(file->fp))
- return SQFS_ERROR_IO;
-
- if (feof(file->fp))
- return SQFS_ERROR_OUT_OF_BOUNDS;
-
- if (offset > file->offset) {
- diff = file->offset - offset;
- diff = diff > (sqfs_u64)temp_size ? temp_size : diff;
-
- ret = fread(temp, 1, diff, file->fp);
- } else {
- ret = fread(buffer, 1, size, file->fp);
- }
-
- if (offset <= file->offset) {
- buffer = (char *)buffer + ret;
- size -= ret;
- offset += ret;
- }
-
- file->offset += ret;
- }
-
- return 0;
-}
-
-static int stdin_read_condensed(sqfs_file_t *base, sqfs_u64 offset,
- void *buffer, size_t size)
-{
- sqfs_file_stdinout_t *file = (sqfs_file_stdinout_t *)base;
- sqfs_u64 poffset = 0, src_start;
- size_t dst_start, diff, count;
- const sparse_map_t *it;
- int err;
-
- memset(buffer, 0, size);
-
- for (it = file->map; it != NULL; it = it->next) {
- if (it->offset + it->count <= offset) {
- poffset += it->count;
- continue;
- }
-
- if (it->offset >= offset + size) {
- poffset += it->count;
- continue;
- }
-
- count = size;
-
- if (offset + count >= it->offset + it->count)
- count = it->offset + it->count - offset;
-
- if (it->offset < offset) {
- diff = offset - it->offset;
-
- src_start = poffset + diff;
- dst_start = 0;
- count -= diff;
- } else if (it->offset > offset) {
- diff = it->offset - offset;
-
- src_start = poffset;
- dst_start = diff;
- } else {
- src_start = poffset;
- dst_start = 0;
- }
-
- err = stdin_read_at(base, src_start,
- (char *)buffer + dst_start, count);
- if (err)
- return err;
-
- poffset += it->count;
- }
-
- return 0;
-}
-
-static int stdin_write_at(sqfs_file_t *base, sqfs_u64 offset,
- const void *buffer, size_t size)
-{
- (void)base; (void)offset; (void)buffer; (void)size;
- return SQFS_ERROR_IO;
-}
-
-sqfs_file_t *sqfs_get_stdin_file(FILE *fp, const sparse_map_t *map,
- sqfs_u64 size)
-{
- sqfs_file_stdinout_t *file = calloc(1, sizeof(*file));
- sqfs_file_t *base = (sqfs_file_t *)file;
- const sparse_map_t *it;
-
- if (file == NULL)
- return NULL;
-
- file->apparent_size = size;
- file->map = map;
- file->fp = fp;
-
- if (map != NULL) {
- for (it = map; it != NULL; it = it->next)
- file->real_size += map->count;
- } else {
- file->real_size = size;
- }
-
- ((sqfs_object_t *)base)->destroy = stdinout_destroy;
- base->write_at = stdin_write_at;
- base->get_size = stdinout_get_size;
- base->truncate = stdinout_truncate;
-
- if (map == NULL) {
- base->read_at = stdin_read_at;
- } else {
- base->read_at = stdin_read_condensed;
- }
- return base;
-}
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);
-}