From fd5c9f1259d0191af57b20f06dda35e62acb6275 Mon Sep 17 00:00:00 2001 From: David Oberhollenzer Date: Tue, 13 Jun 2023 23:44:19 +0200 Subject: Overhaul sqfs_istream_t/sqfs_ostream_t error handling Report an error number from the implementations, change the users to forward that error number (which also means libtar write header/link now returns an error code) and all subsequent binaries to use sqfs_perror() instead of relying on the function to print an error internally. Also, make sure to preserve errno/GetLastError() in the implementations and print out a stringified error in sqfs_perror() if the error code indicates an I/O error. Signed-off-by: David Oberhollenzer --- lib/tar/src/internal.h | 2 ++ lib/tar/src/iterator.c | 2 +- lib/tar/src/read_header.c | 12 +++++-- lib/tar/src/read_sparse_map_new.c | 9 ++++-- lib/tar/src/read_sparse_map_old.c | 5 ++- lib/tar/src/record_to_memory.c | 10 ++++-- lib/tar/src/write_header.c | 67 +++++++++++++++++++-------------------- 7 files changed, 64 insertions(+), 43 deletions(-) (limited to 'lib/tar/src') diff --git a/lib/tar/src/internal.h b/lib/tar/src/internal.h index 56613d3..4671f0b 100644 --- a/lib/tar/src/internal.h +++ b/lib/tar/src/internal.h @@ -12,6 +12,8 @@ #include "tar/tar.h" #include "tar/format.h" #include "util/util.h" +#include "sqfs/error.h" +#include "common.h" enum { PAX_SIZE = 0x001, diff --git a/lib/tar/src/iterator.c b/lib/tar/src/iterator.c index 93c931c..ed35b73 100644 --- a/lib/tar/src/iterator.c +++ b/lib/tar/src/iterator.c @@ -231,7 +231,7 @@ retry: return 0; fail: - tar->state = ret < 0 ? SQFS_ERROR_IO : 1; + tar->state = ret < 0 ? ret : 1; return tar->state; } diff --git a/lib/tar/src/read_header.c b/lib/tar/src/read_header.c index 16fc9d7..df2f56c 100644 --- a/lib/tar/src/read_header.c +++ b/lib/tar/src/read_header.c @@ -176,8 +176,11 @@ int read_header(sqfs_istream_t *fp, tar_header_decoded_t *out) for (;;) { ret = sqfs_istream_read(fp, &hdr, sizeof(hdr)); - if (ret < 0) + if (ret < 0) { + sqfs_perror(fp->get_filename(fp), + "reading raw tar header", ret); goto fail; + } if ((size_t)ret < sizeof(hdr)) goto out_eof; @@ -226,7 +229,12 @@ int read_header(sqfs_istream_t *fp, tar_header_decoded_t *out) goto fail; if (pax_size % 512) pax_size += 512 - (pax_size % 512); - sqfs_istream_skip(fp, pax_size); + ret = sqfs_istream_skip(fp, pax_size); + if (ret) { + sqfs_perror(fp->get_filename(fp), + "skipping padding", ret); + goto fail; + } continue; case TAR_TYPE_PAX: clear_header(out); diff --git a/lib/tar/src/read_sparse_map_new.c b/lib/tar/src/read_sparse_map_new.c index 4e317a8..e42466c 100644 --- a/lib/tar/src/read_sparse_map_new.c +++ b/lib/tar/src/read_sparse_map_new.c @@ -42,8 +42,10 @@ sparse_map_t *read_gnu_new_sparse(sqfs_istream_t *fp, tar_header_decoded_t *out) goto fail_format; ret = sqfs_istream_read(fp, buffer, 512); - if (ret < 0) + if (ret < 0) { + sqfs_perror(fp->get_filename(fp), "reading sparse list", ret); goto fail; + } if (ret < 512) goto fail_format; @@ -69,8 +71,11 @@ sparse_map_t *read_gnu_new_sparse(sqfs_istream_t *fp, tar_header_decoded_t *out) goto fail_format; ret = sqfs_istream_read(fp, buffer + 512, 512); - if (ret < 0) + if (ret < 0) { + sqfs_perror(fp->get_filename(fp), + "reading sparse list", ret); goto fail; + } if (ret < 512) goto fail_format; diff --git a/lib/tar/src/read_sparse_map_old.c b/lib/tar/src/read_sparse_map_old.c index 1794073..0915214 100644 --- a/lib/tar/src/read_sparse_map_old.c +++ b/lib/tar/src/read_sparse_map_old.c @@ -60,8 +60,11 @@ sparse_map_t *read_gnu_old_sparse(sqfs_istream_t *fp, tar_header_t *hdr) do { ret = sqfs_istream_read(fp, &sph, sizeof(sph)); - if (ret < 0) + if (ret < 0) { + sqfs_perror(fp->get_filename(fp), + "reading old GNU sparse list", ret); goto fail; + } if ((size_t)ret < sizeof(sph)) goto fail_eof; diff --git a/lib/tar/src/record_to_memory.c b/lib/tar/src/record_to_memory.c index 597d6f8..84beaa3 100644 --- a/lib/tar/src/record_to_memory.c +++ b/lib/tar/src/record_to_memory.c @@ -19,8 +19,10 @@ char *record_to_memory(sqfs_istream_t *fp, size_t size) goto fail_errno; ret = sqfs_istream_read(fp, buffer, size); - if (ret < 0) + if (ret < 0) { + sqfs_perror(fp->get_filename(fp), "reading tar record", ret); goto fail; + } if ((size_t)ret < size) { fputs("Reading tar record: unexpected end-of-file.\n", stderr); @@ -28,8 +30,12 @@ char *record_to_memory(sqfs_istream_t *fp, size_t size) } if (size % 512) { - if (sqfs_istream_skip(fp, 512 - (size % 512))) + ret = sqfs_istream_skip(fp, 512 - (size % 512)); + if (ret) { + sqfs_perror(fp->get_filename(fp), + "skipping tar padding", ret); goto fail; + } } buffer[size] = '\0'; diff --git a/lib/tar/src/write_header.c b/lib/tar/src/write_header.c index 1183c9a..dda98b7 100644 --- a/lib/tar/src/write_header.c +++ b/lib/tar/src/write_header.c @@ -8,6 +8,7 @@ #include "internal.h" #include "sqfs/xattr.h" +#include "sqfs/error.h" #include #include @@ -106,16 +107,19 @@ static int write_ext_header(sqfs_ostream_t *fp, const struct stat *orig, int type, const char *name) { struct stat sb; + int ret; sb = *orig; sb.st_mode = S_IFREG | 0644; sb.st_size = payload_len; - if (write_header(fp, &sb, name, NULL, type)) - return -1; + ret = write_header(fp, &sb, name, NULL, type); + if (ret) + return ret; - if (fp->append(fp, payload, payload_len)) - return -1; + ret = fp->append(fp, payload, payload_len); + if (ret) + return ret; return padd_file(fp, payload_len); } @@ -159,11 +163,8 @@ static int write_schily_xattr(sqfs_ostream_t *fp, const struct stat *orig, } buffer = calloc(1, total_size + 1); - if (buffer == NULL) { - fprintf(stderr, "%s: generating xattr header: " - "out-of-memory\n", name); - return -1; - } + if (buffer == NULL) + return SQFS_ERROR_ALLOC; ptr = buffer; @@ -188,15 +189,15 @@ int write_tar_header(sqfs_ostream_t *fp, const char *slink_target, const sqfs_xattr_t *xattr, unsigned int counter) { - const char *reason; char buffer[64]; - int type; + int type, ret; if (xattr != NULL) { sprintf(buffer, "pax/xattr%u", counter); - if (write_schily_xattr(fp, sb, buffer, xattr)) - return -1; + ret = write_schily_xattr(fp, sb, buffer, xattr); + if (ret) + return ret; } if (!S_ISLNK(sb->st_mode)) @@ -204,19 +205,20 @@ int write_tar_header(sqfs_ostream_t *fp, if (S_ISLNK(sb->st_mode) && sb->st_size >= 100) { sprintf(buffer, "gnu/target%u", counter); - if (write_ext_header(fp, sb, slink_target, sb->st_size, - TAR_TYPE_GNU_SLINK, buffer)) - return -1; + ret = write_ext_header(fp, sb, slink_target, sb->st_size, + TAR_TYPE_GNU_SLINK, buffer); + if (ret) + return ret; slink_target = NULL; } if (strlen(name) >= 100) { sprintf(buffer, "gnu/name%u", counter); - if (write_ext_header(fp, sb, name, strlen(name), - TAR_TYPE_GNU_PATH, buffer)) { - return -1; - } + ret = write_ext_header(fp, sb, name, strlen(name), + TAR_TYPE_GNU_PATH, buffer); + if (ret) + return ret; sprintf(buffer, "gnu/data%u", counter); name = buffer; @@ -229,18 +231,11 @@ int write_tar_header(sqfs_ostream_t *fp, case S_IFREG: type = TAR_TYPE_FILE; break; case S_IFDIR: type = TAR_TYPE_DIR; break; case S_IFIFO: type = TAR_TYPE_FIFO; break; - case S_IFSOCK: - reason = "cannot pack socket"; - goto out_skip; default: - reason = "unknown type"; - goto out_skip; + return SQFS_ERROR_UNSUPPORTED; } return write_header(fp, sb, name, slink_target, type); -out_skip: - fprintf(stderr, "WARNING: %s: %s\n", name, reason); - return 1; } int write_hard_link(sqfs_ostream_t *fp, const struct stat *sb, const char *name, @@ -249,15 +244,17 @@ int write_hard_link(sqfs_ostream_t *fp, const struct stat *sb, const char *name, tar_header_t hdr; char buffer[64]; size_t len; + int ret; memset(&hdr, 0, sizeof(hdr)); len = strlen(target); if (len >= 100) { sprintf(buffer, "gnu/target%u", counter); - if (write_ext_header(fp, sb, target, len, - TAR_TYPE_GNU_SLINK, buffer)) - return -1; + ret = write_ext_header(fp, sb, target, len, + TAR_TYPE_GNU_SLINK, buffer); + if (ret) + return ret; sprintf(hdr.linkname, "hardlink_%u", counter); } else { memcpy(hdr.linkname, target, len); @@ -266,10 +263,10 @@ int write_hard_link(sqfs_ostream_t *fp, const struct stat *sb, const char *name, len = strlen(name); if (len >= 100) { sprintf(buffer, "gnu/name%u", counter); - if (write_ext_header(fp, sb, name, len, - TAR_TYPE_GNU_PATH, buffer)) { - return -1; - } + ret = write_ext_header(fp, sb, name, len, + TAR_TYPE_GNU_PATH, buffer); + if (ret) + return ret; sprintf(hdr.name, "gnu/data%u", counter); } else { memcpy(hdr.name, name, len); -- cgit v1.2.3