From 60064dd0412a149fe00cfc4e2f2361c22656db57 Mon Sep 17 00:00:00 2001 From: David Oberhollenzer Date: Sat, 7 Sep 2019 20:19:05 +0200 Subject: Remove printing to stderr in libsquashfs with returning error numbers Signed-off-by: David Oberhollenzer --- include/sqfs/error.h | 25 +++++ include/sqfs/meta_reader.h | 10 +- include/sqfs/table.h | 7 +- include/sqfs/xattr.h | 10 +- lib/Makemodule.am | 2 + lib/sqfs/block_processor.c | 20 ++-- lib/sqfs/block_processor_parallel.c | 42 +++----- lib/sqfs/comp/compressor.c | 12 +-- lib/sqfs/comp/gzip.c | 84 +++++----------- lib/sqfs/comp/internal.h | 1 + lib/sqfs/comp/lz4.c | 36 +++---- lib/sqfs/comp/lzo.c | 53 +++------- lib/sqfs/comp/xz.c | 52 ++++------ lib/sqfs/comp/zstd.c | 45 +++------ lib/sqfs/dir_writer.c | 75 +++++++------- lib/sqfs/id_table.c | 47 ++++----- lib/sqfs/meta_reader.c | 46 +++------ lib/sqfs/meta_writer.c | 28 +++--- lib/sqfs/process_block.c | 2 +- lib/sqfs/read_inode.c | 188 +++++++++++++++++++----------------- lib/sqfs/read_super.c | 57 ++++------- lib/sqfs/read_table.c | 37 ++++--- lib/sqfs/readdir.c | 43 ++++----- lib/sqfs/super.c | 23 ++--- lib/sqfs/write_inode.c | 37 ++++--- lib/sqfs/write_table.c | 29 +++--- lib/sqfs/xattr_reader.c | 168 +++++++++++++++----------------- lib/sqfshelper/data_reader.c | 14 ++- lib/sqfshelper/deserialize_fstree.c | 20 ++-- lib/sqfshelper/xattr_reader.c | 6 +- 30 files changed, 554 insertions(+), 665 deletions(-) create mode 100644 include/sqfs/error.h diff --git a/include/sqfs/error.h b/include/sqfs/error.h new file mode 100644 index 0000000..5bbf26c --- /dev/null +++ b/include/sqfs/error.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * error.h + * + * Copyright (C) 2019 David Oberhollenzer + */ +#ifndef SQFS_ERROR_H +#define SQFS_ERROR_H + +typedef enum { + SQFS_ERROR_ALLOC = -1, + SQFS_ERROR_IO = -2, + SQFS_ERROR_COMRPESSOR = -3, + SQFS_ERROR_INTERNAL = -4, + SQFS_ERROR_CORRUPTED = -5, + SQFS_ERROR_UNSUPPORTED = -6, + SQFS_ERROR_OVERFLOW = -7, + SQFS_ERROR_OUT_OF_BOUNDS = -8, + + SFQS_ERROR_SUPER_MAGIC = -9, + SFQS_ERROR_SUPER_VERSION = -10, + SQFS_ERROR_SUPER_BLOCK_SIZE = -11, +} E_SQFS_ERROR; + +#endif /* SQFS_ERROR_H */ diff --git a/include/sqfs/meta_reader.h b/include/sqfs/meta_reader.h index a529dba..f5008d4 100644 --- a/include/sqfs/meta_reader.h +++ b/include/sqfs/meta_reader.h @@ -44,15 +44,15 @@ SQFS_API int sqfs_meta_reader_read_dir_header(sqfs_meta_reader_t *m, /* Entry can be freed with a single free() call. The function internally prints to stderr on failure */ -SQFS_API sqfs_dir_entry_t *sqfs_meta_reader_read_dir_ent(sqfs_meta_reader_t *m); +SQFS_API int sqfs_meta_reader_read_dir_ent(sqfs_meta_reader_t *m, + sqfs_dir_entry_t **ent); /* Inode can be freed with a single free() call. The function internally prints error message to stderr on failure. */ SQFS_API -sqfs_inode_generic_t *sqfs_meta_reader_read_inode(sqfs_meta_reader_t *ir, - sqfs_super_t *super, - uint64_t block_start, - size_t offset); +int sqfs_meta_reader_read_inode(sqfs_meta_reader_t *ir, sqfs_super_t *super, + uint64_t block_start, size_t offset, + sqfs_inode_generic_t **out); #ifdef __cplusplus } diff --git a/include/sqfs/table.h b/include/sqfs/table.h index 70bb437..f837f6b 100644 --- a/include/sqfs/table.h +++ b/include/sqfs/table.h @@ -29,9 +29,10 @@ SQFS_API int sqfs_write_table(int outfd, sqfs_super_t *super, const void *data, size_t table_size, uint64_t *start); -SQFS_API void *sqfs_read_table(int fd, sqfs_compressor_t *cmp, - size_t table_size, uint64_t location, - uint64_t lower_limit, uint64_t upper_limit); +SQFS_API int sqfs_read_table(int fd, sqfs_compressor_t *cmp, + size_t table_size, uint64_t location, + uint64_t lower_limit, uint64_t upper_limit, + void **out); #ifdef __cplusplus } diff --git a/include/sqfs/xattr.h b/include/sqfs/xattr.h index 11976d0..0f9cf32 100644 --- a/include/sqfs/xattr.h +++ b/include/sqfs/xattr.h @@ -54,6 +54,8 @@ SQFS_API int sqfs_get_xattr_prefix_id(const char *key); /* Check if a given xattr key can be encoded in squashfs at all. */ SQFS_API bool sqfs_has_xattr(const char *key); +SQFS_API int sqfs_xattr_reader_load_locations(sqfs_xattr_reader_t *xr); + SQFS_API void sqfs_xattr_reader_destroy(sqfs_xattr_reader_t *xr); SQFS_API sqfs_xattr_reader_t *sqfs_xattr_reader_create(int sqfsfd, @@ -67,11 +69,13 @@ SQFS_API int sqfs_xattr_reader_seek_kv(sqfs_xattr_reader_t *xr, const sqfs_xattr_id_t *desc); SQFS_API -sqfs_xattr_value_t *sqfs_xattr_reader_read_value(sqfs_xattr_reader_t *xr, - const sqfs_xattr_entry_t *key); +int sqfs_xattr_reader_read_value(sqfs_xattr_reader_t *xr, + const sqfs_xattr_entry_t *key, + sqfs_xattr_value_t **val_out); SQFS_API -sqfs_xattr_entry_t *sqfs_xattr_reader_read_key(sqfs_xattr_reader_t *xr); +int sqfs_xattr_reader_read_key(sqfs_xattr_reader_t *xr, + sqfs_xattr_entry_t **key_out); #ifdef __cplusplus } diff --git a/lib/Makemodule.am b/lib/Makemodule.am index c71c1f8..e071fd0 100644 --- a/lib/Makemodule.am +++ b/lib/Makemodule.am @@ -48,6 +48,7 @@ libsquashfs_la_SOURCES += include/sqfs/compress.h include/sqfs/block_processor.h libsquashfs_la_SOURCES += include/sqfs/super.h include/sqfs/inode.h libsquashfs_la_SOURCES += include/sqfs/dir.h include/sqfs/xattr.h libsquashfs_la_SOURCES += include/sqfs/table.h include/sqfs/predef.h +libsquashfs_la_SOURCES += include/sqfs/error.h libsquashfs_la_SOURCES += lib/sqfs/meta_writer.c lib/sqfs/super.c libsquashfs_la_SOURCES += lib/sqfs/id_table.c lib/sqfs/dir_writer.c libsquashfs_la_SOURCES += lib/sqfs/write_table.c include/highlevel.h @@ -111,6 +112,7 @@ sqfsinclude_HEADERS += include/sqfs/compress.h include/sqfs/block_processor.h sqfsinclude_HEADERS += include/sqfs/super.h include/sqfs/inode.h sqfsinclude_HEADERS += include/sqfs/dir.h include/sqfs/xattr.h sqfsinclude_HEADERS += include/sqfs/table.h include/sqfs/predef.h +sqfsinclude_HEADERS += include/sqfs/error.h noinst_LIBRARIES += libfstree.a libtar.a libsqfshelper.a noinst_LTLIBRARIES += libutil.la diff --git a/lib/sqfs/block_processor.c b/lib/sqfs/block_processor.c index 3a57d14..649e97f 100644 --- a/lib/sqfs/block_processor.c +++ b/lib/sqfs/block_processor.c @@ -8,11 +8,11 @@ #include "config.h" #include "sqfs/block_processor.h" +#include "sqfs/error.h" #include "util.h" #include #include -#include struct sqfs_block_processor_t { size_t max_block_size; @@ -35,10 +35,8 @@ sqfs_block_processor_t *sqfs_block_processor_create(size_t max_block_size, proc = alloc_flex(sizeof(*proc), 1, max_block_size); - if (proc == NULL) { - perror("Creating block processor"); + if (proc == NULL) return NULL; - } proc->max_block_size = max_block_size; proc->cmp = cmp; @@ -55,19 +53,23 @@ void sqfs_block_processor_destroy(sqfs_block_processor_t *proc) int sqfs_block_processor_enqueue(sqfs_block_processor_t *proc, sqfs_block_t *block) { - if (sqfs_block_process(block, proc->cmp, - proc->scratch, proc->max_block_size)) + int ret; + + ret = sqfs_block_process(block, proc->cmp, + proc->scratch, proc->max_block_size); + if (ret) goto fail; - if (proc->cb(proc->user, block)) + ret = proc->cb(proc->user, block); + if (ret) goto fail; free(block); return 0; fail: free(block); - proc->status = -1; - return -1; + proc->status = ret; + return ret; } int sqfs_block_processor_finish(sqfs_block_processor_t *proc) diff --git a/lib/sqfs/block_processor_parallel.c b/lib/sqfs/block_processor_parallel.c index 3184d8b..b9a14c6 100644 --- a/lib/sqfs/block_processor_parallel.c +++ b/lib/sqfs/block_processor_parallel.c @@ -9,12 +9,12 @@ #include "sqfs/block_processor.h" #include "sqfs/compress.h" +#include "sqfs/error.h" #include "util.h" #include #include #include -#include #define MAX_BACKLOG_FACTOR (10) @@ -129,39 +129,29 @@ sqfs_block_processor_t *sqfs_block_processor_create(size_t max_block_size, proc = alloc_flex(sizeof(*proc), sizeof(proc->workers[0]), num_workers); - if (proc == NULL) { - perror("Creating block processor"); + if (proc == NULL) return NULL; - } proc->max_block_size = max_block_size; proc->cb = callback; proc->user = user; proc->num_workers = num_workers; - if (pthread_mutex_init(&proc->mtx, NULL)) { - perror("Creating block processor mutex"); + if (pthread_mutex_init(&proc->mtx, NULL)) goto fail_free; - } - if (pthread_cond_init(&proc->queue_cond, NULL)) { - perror("Creating block processor conditional"); + if (pthread_cond_init(&proc->queue_cond, NULL)) goto fail_mtx; - } - if (pthread_cond_init(&proc->done_cond, NULL)) { - perror("Creating block processor completion conditional"); + if (pthread_cond_init(&proc->done_cond, NULL)) goto fail_cond; - } for (i = 0; i < num_workers; ++i) { proc->workers[i] = alloc_flex(sizeof(compress_worker_t), 1, max_block_size); - if (proc->workers[i] == NULL) { - perror("Creating block worker data"); + if (proc->workers[i] == NULL) goto fail_init; - } proc->workers[i]->shared = proc; proc->workers[i]->cmp = cmp->create_copy(cmp); @@ -174,10 +164,8 @@ sqfs_block_processor_t *sqfs_block_processor_create(size_t max_block_size, ret = pthread_create(&proc->workers[i]->thread, NULL, worker_proc, proc->workers[i]); - if (ret != 0) { - perror("Creating block processor thread"); + if (ret != 0) goto fail_thread; - } } return proc; @@ -253,16 +241,18 @@ static int process_completed_blocks(sqfs_block_processor_t *proc, sqfs_block_t *queue) { sqfs_block_t *it; + int ret; while (queue != NULL) { it = queue; queue = queue->next; if (it->flags & SQFS_BLK_COMPRESS_ERROR) { - proc->status = -1; + proc->status = SQFS_ERROR_COMRPESSOR; } else { - if (proc->cb(proc->user, it)) - proc->status = -1; + ret = proc->cb(proc->user, it); + if (ret) + proc->status = ret; } free(it); @@ -329,7 +319,9 @@ int sqfs_block_processor_finish(sqfs_block_processor_t *proc) for (it = proc->done; it != NULL; it = it->next) { if (it->sequence_number != proc->dequeue_id++) { pthread_mutex_unlock(&proc->mtx); - goto bug_seqnum; + + /* XXX: this would actually be a BUG */ + return SQFS_ERROR_INTERNAL; } } @@ -338,8 +330,4 @@ int sqfs_block_processor_finish(sqfs_block_processor_t *proc) pthread_mutex_unlock(&proc->mtx); return process_completed_blocks(proc, queue); -bug_seqnum: - fputs("[BUG][parallel block processor] " - "gap in sequence numbers!\n", stderr); - return -1; } diff --git a/lib/sqfs/comp/compressor.c b/lib/sqfs/comp/compressor.c index 005dbd4..4d073f2 100644 --- a/lib/sqfs/comp/compressor.c +++ b/lib/sqfs/comp/compressor.c @@ -9,7 +9,6 @@ #include #include -#include #include "internal.h" #include "util.h" @@ -53,7 +52,7 @@ int sqfs_generic_write_options(int fd, const void *data, size_t size) if (write_data("writing compressor options", fd, buffer, sizeof(buffer))) { - return -1; + return SQFS_ERROR_IO; } return sizeof(buffer); @@ -65,14 +64,11 @@ int sqfs_generic_read_options(int fd, void *data, size_t size) if (read_data_at("reading compressor options", sizeof(sqfs_super_t), fd, buffer, sizeof(buffer))) { - return -1; + return SQFS_ERROR_IO; } - if (le16toh(*((uint16_t *)buffer)) != (0x8000 | size)) { - fputs("reading compressor options: invalid meta data header\n", - stderr); - return -1; - } + if (le16toh(*((uint16_t *)buffer)) != (0x8000 | size)) + return SQFS_ERROR_CORRUPTED; memcpy(data, buffer + 2, size); return 0; diff --git a/lib/sqfs/comp/gzip.c b/lib/sqfs/comp/gzip.c index e80073d..484901a 100644 --- a/lib/sqfs/comp/gzip.c +++ b/lib/sqfs/comp/gzip.c @@ -10,7 +10,6 @@ #include #include #include -#include #include #include @@ -67,30 +66,24 @@ static int gzip_read_options(sqfs_compressor_t *base, int fd) { gzip_compressor_t *gzip = (gzip_compressor_t *)base; gzip_options_t opt; + int ret; - if (sqfs_generic_read_options(fd, &opt, sizeof(opt))) - return -1; + ret = sqfs_generic_read_options(fd, &opt, sizeof(opt)); + if (ret) + return ret; gzip->opt.level = le32toh(opt.level); gzip->opt.window = le16toh(opt.window); gzip->opt.strategies = le16toh(opt.strategies); - if (gzip->opt.level < 1 || gzip->opt.level > 9) { - fprintf(stderr, "Invalid gzip compression level '%d'.\n", - gzip->opt.level); - return -1; - } + if (gzip->opt.level < 1 || gzip->opt.level > 9) + return SQFS_ERROR_UNSUPPORTED; - if (gzip->opt.window < 8 || gzip->opt.window > 15) { - fprintf(stderr, "Invalid gzip window size '%d'.\n", - gzip->opt.window); - return -1; - } + if (gzip->opt.window < 8 || gzip->opt.window > 15) + return SQFS_ERROR_UNSUPPORTED; - if (gzip->opt.strategies & ~SQFS_COMP_FLAG_GZIP_ALL) { - fputs("Unknown gzip strategies selected.\n", stderr); - return -1; - } + if (gzip->opt.strategies & ~SQFS_COMP_FLAG_GZIP_ALL) + return SQFS_ERROR_UNSUPPORTED; return 0; } @@ -124,11 +117,8 @@ static int find_strategy(gzip_compressor_t *gzip, const uint8_t *in, continue; ret = deflateReset(&gzip->strm); - if (ret != Z_OK) { - fputs("resetting zlib stream failed\n", - stderr); - return -1; - } + if (ret != Z_OK) + return SQFS_ERROR_COMRPESSOR; strategy = flag_to_zlib_strategy(i); @@ -138,11 +128,8 @@ static int find_strategy(gzip_compressor_t *gzip, const uint8_t *in, gzip->strm.avail_out = outsize; ret = deflateParams(&gzip->strm, gzip->opt.level, strategy); - if (ret != Z_OK) { - fputs("setting deflate parameters failed\n", - stderr); - return -1; - } + if (ret != Z_OK) + return SQFS_ERROR_COMRPESSOR; ret = deflate(&gzip->strm, Z_FINISH); @@ -154,8 +141,7 @@ static int find_strategy(gzip_compressor_t *gzip, const uint8_t *in, selected = strategy; } } else if (ret != Z_OK && ret != Z_BUF_ERROR) { - fputs("gzip block processing failed\n", stderr); - return -1; + return SQFS_ERROR_COMRPESSOR; } } @@ -172,7 +158,7 @@ static ssize_t gzip_do_block(sqfs_compressor_t *base, const uint8_t *in, if (gzip->compress && gzip->opt.strategies != 0) { strategy = find_strategy(gzip, in, size, out, outsize); if (strategy < 0) - return -1; + return strategy; } if (gzip->compress) { @@ -181,10 +167,8 @@ static ssize_t gzip_do_block(sqfs_compressor_t *base, const uint8_t *in, ret = inflateReset(&gzip->strm); } - if (ret != Z_OK) { - fputs("resetting zlib stream failed\n", stderr); - return -1; - } + if (ret != Z_OK) + return SQFS_ERROR_COMRPESSOR; gzip->strm.next_in = (void *)in; gzip->strm.avail_in = size; @@ -193,11 +177,8 @@ static ssize_t gzip_do_block(sqfs_compressor_t *base, const uint8_t *in, if (gzip->compress && gzip->opt.strategies != 0) { ret = deflateParams(&gzip->strm, gzip->opt.level, strategy); - if (ret != Z_OK) { - fputs("setting selcted deflate parameters failed\n", - stderr); - return -1; - } + if (ret != Z_OK) + return SQFS_ERROR_COMRPESSOR; } if (gzip->compress) { @@ -215,10 +196,8 @@ static ssize_t gzip_do_block(sqfs_compressor_t *base, const uint8_t *in, return (ssize_t)written; } - if (ret != Z_OK && ret != Z_BUF_ERROR) { - fputs("gzip block processing failed\n", stderr); - return -1; - } + if (ret != Z_OK && ret != Z_BUF_ERROR) + return SQFS_ERROR_COMRPESSOR; return 0; } @@ -228,10 +207,8 @@ static sqfs_compressor_t *gzip_create_copy(sqfs_compressor_t *cmp) gzip_compressor_t *gzip = malloc(sizeof(*gzip)); int ret; - if (gzip == NULL) { - perror("creating additional gzip compressor"); + if (gzip == NULL) return NULL; - } memcpy(gzip, cmp, sizeof(*gzip)); memset(&gzip->strm, 0, sizeof(gzip->strm)); @@ -244,8 +221,6 @@ static sqfs_compressor_t *gzip_create_copy(sqfs_compressor_t *cmp) } if (ret != Z_OK) { - fputs("internal error creating additional zlib stream\n", - stderr); free(gzip); return NULL; } @@ -261,34 +236,24 @@ sqfs_compressor_t *gzip_compressor_create(const sqfs_compressor_config_t *cfg) if (cfg->flags & ~(SQFS_COMP_FLAG_GZIP_ALL | SQFS_COMP_FLAG_GENERIC_ALL)) { - fputs("creating gzip compressor: unknown compressor flags\n", - stderr); return NULL; } if (cfg->opt.gzip.level < SQFS_GZIP_MIN_LEVEL || cfg->opt.gzip.level > SQFS_GZIP_MAX_LEVEL) { - fprintf(stderr, "creating gzip compressor: compression level" - "must be between %d and %d inclusive\n", - SQFS_GZIP_MIN_LEVEL, SQFS_GZIP_MAX_LEVEL); return NULL; } if (cfg->opt.gzip.window_size < SQFS_GZIP_MIN_WINDOW || cfg->opt.gzip.window_size > SQFS_GZIP_MAX_WINDOW) { - fprintf(stderr, "creating gzip compressor: window size" - "must be between %d and %d inclusive\n", - SQFS_GZIP_MIN_WINDOW, SQFS_GZIP_MAX_WINDOW); return NULL; } gzip = calloc(1, sizeof(*gzip)); base = (sqfs_compressor_t *)gzip; - if (gzip == NULL) { - perror("creating gzip compressor"); + if (gzip == NULL) return NULL; - } gzip->opt.level = cfg->opt.gzip.level; gzip->opt.window = cfg->opt.gzip.window_size; @@ -310,7 +275,6 @@ sqfs_compressor_t *gzip_compressor_create(const sqfs_compressor_config_t *cfg) } if (ret != Z_OK) { - fputs("internal error creating zlib stream\n", stderr); free(gzip); return NULL; } diff --git a/lib/sqfs/comp/internal.h b/lib/sqfs/comp/internal.h index 117bb82..d2410fc 100644 --- a/lib/sqfs/comp/internal.h +++ b/lib/sqfs/comp/internal.h @@ -11,6 +11,7 @@ #include "sqfs/predef.h" #include "sqfs/compress.h" +#include "sqfs/error.h" #include "util.h" SQFS_INTERNAL diff --git a/lib/sqfs/comp/lz4.c b/lib/sqfs/comp/lz4.c index 0893b34..446b83e 100644 --- a/lib/sqfs/comp/lz4.c +++ b/lib/sqfs/comp/lz4.c @@ -10,7 +10,6 @@ #include #include #include -#include #include #include @@ -44,18 +43,18 @@ static int lz4_write_options(sqfs_compressor_t *base, int fd) static int lz4_read_options(sqfs_compressor_t *base, int fd) { lz4_options opt; + int ret; (void)base; - if (sqfs_generic_read_options(fd, &opt, sizeof(opt))) - return -1; + ret = sqfs_generic_read_options(fd, &opt, sizeof(opt)); + if (ret) + return ret; opt.version = le32toh(opt.version); opt.flags = le32toh(opt.flags); - if (opt.version != LZ4LEGACY) { - fprintf(stderr, "unsupported lz4 version '%d'\n", opt.version); - return -1; - } + if (opt.version != LZ4LEGACY) + return SQFS_ERROR_UNSUPPORTED; return 0; } @@ -74,10 +73,8 @@ static ssize_t lz4_comp_block(sqfs_compressor_t *base, const uint8_t *in, size, outsize); } - if (ret < 0) { - fputs("internal error in lz4 compressor\n", stderr); - return -1; - } + if (ret < 0) + return SQFS_ERROR_COMRPESSOR; return ret; } @@ -90,10 +87,8 @@ static ssize_t lz4_uncomp_block(sqfs_compressor_t *base, const uint8_t *in, ret = LZ4_decompress_safe((void *)in, (void *)out, size, outsize); - if (ret < 0) { - fputs("internal error in lz4 decompressor\n", stderr); - return -1; - } + if (ret < 0) + return SQFS_ERROR_COMRPESSOR; return ret; } @@ -102,10 +97,8 @@ static sqfs_compressor_t *lz4_create_copy(sqfs_compressor_t *cmp) { lz4_compressor_t *lz4 = malloc(sizeof(*lz4)); - if (lz4 == NULL) { - perror("creating additional lz4 compressor"); + if (lz4 == NULL) return NULL; - } memcpy(lz4, cmp, sizeof(*lz4)); return (sqfs_compressor_t *)lz4; @@ -123,16 +116,13 @@ sqfs_compressor_t *lz4_compressor_create(const sqfs_compressor_config_t *cfg) if (cfg->flags & ~(SQFS_COMP_FLAG_LZ4_ALL | SQFS_COMP_FLAG_GENERIC_ALL)) { - fputs("creating lz4 compressor: unknown compressor flags\n", - stderr); + return NULL; } lz4 = calloc(1, sizeof(*lz4)); base = (sqfs_compressor_t *)lz4; - if (lz4 == NULL) { - perror("creating lz4 compressor"); + if (lz4 == NULL) return NULL; - } lz4->high_compression = (cfg->flags & SQFS_COMP_FLAG_LZ4_HC) != 0; diff --git a/lib/sqfs/comp/lzo.c b/lib/sqfs/comp/lzo.c index b01bf20..b4cfebf 100644 --- a/lib/sqfs/comp/lzo.c +++ b/lib/sqfs/comp/lzo.c @@ -10,8 +10,6 @@ #include #include #include -#include -#include #include @@ -86,9 +84,11 @@ static int lzo_read_options(sqfs_compressor_t *base, int fd) { lzo_compressor_t *lzo = (lzo_compressor_t *)base; lzo_options_t opt; + int ret; - if (sqfs_generic_read_options(fd, &opt, sizeof(opt))) - return -1; + ret = sqfs_generic_read_options(fd, &opt, sizeof(opt)); + if (ret) + return ret; lzo->algorithm = le32toh(opt.algorithm); lzo->level = le32toh(opt.level); @@ -99,21 +99,17 @@ static int lzo_read_options(sqfs_compressor_t *base, int fd) case SQFS_LZO1X_1_12: case SQFS_LZO1X_1_15: if (lzo->level != 0) - goto fail_level; + return SQFS_ERROR_UNSUPPORTED; break; case SQFS_LZO1X_999: if (lzo->level < 1 || lzo->level > 9) - goto fail_level; + return SQFS_ERROR_UNSUPPORTED; break; default: - fputs("Unsupported LZO variant specified.\n", stderr); - return -1; + return SQFS_ERROR_UNSUPPORTED; } return 0; -fail_level: - fputs("Unsupported LZO compression level specified.\n", stderr); - return -1; } static ssize_t lzo_comp_block(sqfs_compressor_t *base, const uint8_t *in, @@ -133,10 +129,8 @@ static ssize_t lzo_comp_block(sqfs_compressor_t *base, const uint8_t *in, &len, lzo->buffer); } - if (ret != LZO_E_OK) { - fputs("LZO compression failed.\n", stderr); - return -1; - } + if (ret != LZO_E_OK) + return SQFS_ERROR_COMRPESSOR; if (len < size) return len; @@ -153,10 +147,8 @@ static ssize_t lzo_uncomp_block(sqfs_compressor_t *base, const uint8_t *in, ret = lzo1x_decompress_safe(in, size, out, &len, lzo->buffer); - if (ret != LZO_E_OK) { - fputs("lzo decompress: input data is corrupted\n", stderr); - return -1; - } + if (ret != LZO_E_OK) + return SQFS_ERROR_COMRPESSOR; return len; } @@ -167,11 +159,8 @@ static sqfs_compressor_t *lzo_create_copy(sqfs_compressor_t *cmp) lzo_compressor_t *lzo; lzo = alloc_flex(sizeof(*lzo), 1, lzo_algs[other->algorithm].bufsize); - - if (lzo == NULL) { - perror("creating additional lzo compressor"); + if (lzo == NULL) return NULL; - } memcpy(lzo, other, sizeof(*lzo)); return (sqfs_compressor_t *)lzo; @@ -187,28 +176,18 @@ sqfs_compressor_t *lzo_compressor_create(const sqfs_compressor_config_t *cfg) sqfs_compressor_t *base; lzo_compressor_t *lzo; - if (cfg->flags & ~SQFS_COMP_FLAG_GENERIC_ALL) { - fputs("creating lzo compressor: unknown compressor flags\n", - stderr); + if (cfg->flags & ~SQFS_COMP_FLAG_GENERIC_ALL) return NULL; - } if (cfg->opt.lzo.algorithm > LZO_NUM_ALGS || lzo_algs[cfg->opt.lzo.algorithm].compress == NULL) { - fputs("creating lzo compressor: unknown LZO variant\n", - stderr); return NULL; } if (cfg->opt.lzo.algorithm == SQFS_LZO1X_999) { - if (cfg->opt.lzo.level > SQFS_LZO_MAX_LEVEL) { - fputs("creating lzo compressor: compression level " - "must be between 0 and 9 inclusive\n", stderr); + if (cfg->opt.lzo.level > SQFS_LZO_MAX_LEVEL) return NULL; - } } else if (cfg->opt.lzo.level != 0) { - fputs("creating lzo compressor: level argument " - "only supported by lzo1x 999\n", stderr); return NULL; } @@ -216,10 +195,8 @@ sqfs_compressor_t *lzo_compressor_create(const sqfs_compressor_config_t *cfg) lzo_algs[cfg->opt.lzo.algorithm].bufsize); base = (sqfs_compressor_t *)lzo; - if (lzo == NULL) { - perror("creating lzo compressor"); + if (lzo == NULL) return NULL; - } lzo->algorithm = cfg->opt.lzo.algorithm; lzo->level = cfg->opt.lzo.level; diff --git a/lib/sqfs/comp/xz.c b/lib/sqfs/comp/xz.c index 1f98a25..c626f92 100644 --- a/lib/sqfs/comp/xz.c +++ b/lib/sqfs/comp/xz.c @@ -10,8 +10,6 @@ #include #include #include -#include -#include #include #include "internal.h" @@ -56,22 +54,20 @@ static int xz_read_options(sqfs_compressor_t *base, int fd) { xz_compressor_t *xz = (xz_compressor_t *)base; xz_options_t opt; + int ret; - if (sqfs_generic_read_options(fd, &opt, sizeof(opt))) - return -1; + ret = sqfs_generic_read_options(fd, &opt, sizeof(opt)); + if (ret) + return ret; opt.dict_size = le32toh(opt.dict_size); opt.flags = le32toh(opt.flags); - if (!is_dict_size_valid(opt.dict_size)) { - fputs("Invalid lzma dictionary size.\n", stderr); - return -1; - } + if (!is_dict_size_valid(opt.dict_size)) + return SQFS_ERROR_CORRUPTED; - if (opt.flags & ~SQFS_COMP_FLAG_XZ_ALL) { - fputs("Unknown BCJ filter used.\n", stderr); - return -1; - } + if (opt.flags & ~SQFS_COMP_FLAG_XZ_ALL) + return SQFS_ERROR_UNSUPPORTED; xz->flags = opt.flags; xz->dict_size = opt.dict_size; @@ -88,10 +84,8 @@ static ssize_t compress(xz_compressor_t *xz, lzma_vli filter, lzma_ret ret; int i = 0; - if (lzma_lzma_preset(&opt, LZMA_PRESET_DEFAULT)) { - fputs("error initializing xz options\n", stderr); - return -1; - } + if (lzma_lzma_preset(&opt, LZMA_PRESET_DEFAULT)) + return SQFS_ERROR_COMRPESSOR; opt.dict_size = xz->dict_size; @@ -115,10 +109,8 @@ static ssize_t compress(xz_compressor_t *xz, lzma_vli filter, if (ret == LZMA_OK) return (written >= size) ? 0 : written; - if (ret != LZMA_BUF_ERROR) { - fputs("xz block compress failed\n", stderr); - return -1; - } + if (ret != LZMA_BUF_ERROR) + return SQFS_ERROR_COMRPESSOR; return 0; } @@ -165,7 +157,7 @@ static ssize_t xz_comp_block(sqfs_compressor_t *base, const uint8_t *in, ret = compress(xz, filter, in, size, out, outsize); if (ret < 0) - return -1; + return ret; if (ret > 0 && (smallest == 0 || (size_t)ret < smallest)) { smallest = ret; @@ -195,18 +187,15 @@ static ssize_t xz_uncomp_block(sqfs_compressor_t *base, const uint8_t *in, if (ret == LZMA_OK && size == src_pos) return (ssize_t)dest_pos; - fputs("xz block extract failed\n", stderr); - return -1; + return SQFS_ERROR_COMRPESSOR; } static sqfs_compressor_t *xz_create_copy(sqfs_compressor_t *cmp) { xz_compressor_t *xz = malloc(sizeof(*xz)); - if (xz == NULL) { - perror("creating additional xz compressor"); + if (xz == NULL) return NULL; - } memcpy(xz, cmp, sizeof(*xz)); return (sqfs_compressor_t *)xz; @@ -224,23 +213,16 @@ sqfs_compressor_t *xz_compressor_create(const sqfs_compressor_config_t *cfg) if (cfg->flags & ~(SQFS_COMP_FLAG_GENERIC_ALL | SQFS_COMP_FLAG_XZ_ALL)) { - fputs("creating xz compressor: unknown compressor flags\n", - stderr); return NULL; } - if (!is_dict_size_valid(cfg->opt.xz.dict_size)) { - fputs("creating xz compressor: invalid dictionary size\n", - stderr); + if (!is_dict_size_valid(cfg->opt.xz.dict_size)) return NULL; - } xz = calloc(1, sizeof(*xz)); base = (sqfs_compressor_t *)xz; - if (xz == NULL) { - perror("creating xz compressor"); + if (xz == NULL) return NULL; - } xz->flags = cfg->flags; xz->dict_size = cfg->opt.xz.dict_size; diff --git a/lib/sqfs/comp/zstd.c b/lib/sqfs/comp/zstd.c index 8a1dbf3..dc2387d 100644 --- a/lib/sqfs/comp/zstd.c +++ b/lib/sqfs/comp/zstd.c @@ -10,8 +10,6 @@ #include #include #include -#include -#include #include @@ -43,10 +41,12 @@ static int zstd_write_options(sqfs_compressor_t *base, int fd) static int zstd_read_options(sqfs_compressor_t *base, int fd) { zstd_options_t opt; + int ret; (void)base; - if (sqfs_generic_read_options(fd, &opt, sizeof(opt))) - return -1; + ret = sqfs_generic_read_options(fd, &opt, sizeof(opt)); + if (ret) + return ret; opt.level = le32toh(opt.level); return 0; @@ -61,11 +61,8 @@ static ssize_t zstd_comp_block(sqfs_compressor_t *base, const uint8_t *in, ret = ZSTD_compressCCtx(zstd->zctx, out, outsize, in, size, zstd->level); - if (ZSTD_isError(ret)) { - fprintf(stderr, "internal error in ZSTD compressor: %s\n", - ZSTD_getErrorName(ret)); - return -1; - } + if (ZSTD_isError(ret)) + return SQFS_ERROR_COMRPESSOR; return ret < size ? ret : 0; } @@ -78,11 +75,8 @@ static ssize_t zstd_uncomp_block(sqfs_compressor_t *base, const uint8_t *in, ret = ZSTD_decompress(out, outsize, in, size); - if (ZSTD_isError(ret)) { - fprintf(stderr, "error uncompressing ZSTD compressed data: %s", - ZSTD_getErrorName(ret)); - return -1; - } + if (ZSTD_isError(ret)) + return SQFS_ERROR_COMRPESSOR; return ret; } @@ -91,18 +85,14 @@ static sqfs_compressor_t *zstd_create_copy(sqfs_compressor_t *cmp) { zstd_compressor_t *zstd = malloc(sizeof(*zstd)); - if (zstd == NULL) { - perror("creating additional zstd compressor"); + if (zstd == NULL) return NULL; - } memcpy(zstd, cmp, sizeof(*zstd)); zstd->zctx = ZSTD_createCCtx(); if (zstd->zctx == NULL) { - fputs("error creating addtional zstd compression context\n", - stderr); free(zstd); return NULL; } @@ -123,26 +113,21 @@ sqfs_compressor_t *zstd_compressor_create(const sqfs_compressor_config_t *cfg) zstd_compressor_t *zstd; sqfs_compressor_t *base; - if (cfg->flags & ~SQFS_COMP_FLAG_GENERIC_ALL) { - fputs("creating zstd compressor: unknown compressor flags\n", - stderr); - } + if (cfg->flags & ~SQFS_COMP_FLAG_GENERIC_ALL) + return NULL; if (cfg->opt.zstd.level < 1 || cfg->opt.zstd.level > ZSTD_maxCLevel()) { - goto fail_level; + return NULL; } zstd = calloc(1, sizeof(*zstd)); base = (sqfs_compressor_t *)zstd; - if (zstd == NULL) { - perror("creating zstd compressor"); + if (zstd == NULL) return NULL; - } zstd->zctx = ZSTD_createCCtx(); if (zstd->zctx == NULL) { - fputs("error creating zstd compression context\n", stderr); free(zstd); return NULL; } @@ -154,8 +139,4 @@ sqfs_compressor_t *zstd_compressor_create(const sqfs_compressor_config_t *cfg) base->read_options = zstd_read_options; base->create_copy = zstd_create_copy; return base; -fail_level: - fprintf(stderr, "zstd compression level must be a number in the range " - "1...%d\n", ZSTD_maxCLevel()); - return NULL; } diff --git a/lib/sqfs/dir_writer.c b/lib/sqfs/dir_writer.c index d6921e7..aab5479 100644 --- a/lib/sqfs/dir_writer.c +++ b/lib/sqfs/dir_writer.c @@ -9,6 +9,7 @@ #include "sqfs/meta_writer.h" #include "sqfs/inode.h" +#include "sqfs/error.h" #include "sqfs/data.h" #include "sqfs/dir.h" #include "util.h" @@ -17,8 +18,6 @@ #include #include #include -#include -#include typedef struct dir_entry_t { struct dir_entry_t *next; @@ -59,9 +58,9 @@ static int get_type(mode_t mode) case S_IFCHR: return SQFS_INODE_CDEV; case S_IFDIR: return SQFS_INODE_DIR; case S_IFREG: return SQFS_INODE_FILE; - default: - assert(0); } + + return SQFS_ERROR_UNSUPPORTED; } static void writer_reset(sqfs_dir_writer_t *writer) @@ -92,10 +91,8 @@ sqfs_dir_writer_t *sqfs_dir_writer_create(sqfs_meta_writer_t *dm) { sqfs_dir_writer_t *writer = calloc(1, sizeof(*writer)); - if (writer == NULL) { - perror("creating directory writer"); + if (writer == NULL) return NULL; - } writer->dm = dm; return writer; @@ -123,16 +120,20 @@ int sqfs_dir_writer_add_entry(sqfs_dir_writer_t *writer, const char *name, uint32_t inode_num, uint64_t inode_ref, mode_t mode) { - dir_entry_t *ent = alloc_flex(sizeof(*ent), 1, strlen(name)); + dir_entry_t *ent; + int type; - if (ent == NULL) { - perror("creating directory entry"); - return -1; - } + type = get_type(mode); + if (type < 0) + return type; + + ent = alloc_flex(sizeof(*ent), 1, strlen(name)); + if (ent == NULL) + return SQFS_ERROR_ALLOC; ent->inode_ref = inode_ref; ent->inode_num = inode_num; - ent->type = get_type(mode); + ent->type = type; ent->name_len = strlen(name); memcpy(ent->name, name, ent->name_len); @@ -183,19 +184,19 @@ static int add_header(sqfs_dir_writer_t *writer, size_t count, { sqfs_dir_header_t hdr; index_ent_t *idx; + int err; hdr.count = htole32(count - 1); hdr.start_block = htole32(ref->inode_ref >> 16); hdr.inode_number = htole32(ref->inode_num); - if (sqfs_meta_writer_append(writer->dm, &hdr, sizeof(hdr))) - return -1; + err = sqfs_meta_writer_append(writer->dm, &hdr, sizeof(hdr)); + if (err) + return err; idx = calloc(1, sizeof(*idx)); - if (idx == NULL) { - perror("creating directory index entry"); - return -1; - } + if (idx == NULL) + return SQFS_ERROR_ALLOC; idx->ent = ref; idx->block = block; @@ -221,13 +222,15 @@ int sqfs_dir_writer_end(sqfs_dir_writer_t *writer) size_t i, count; uint32_t offset; uint64_t block; + int err; for (it = writer->list; it != NULL; ) { sqfs_meta_writer_get_position(writer->dm, &block, &offset); count = get_conseq_entry_count(offset, it); - if (add_header(writer, count, it, block)) - return -1; + err = add_header(writer, count, it, block); + if (err) + return err; first = it; @@ -240,15 +243,15 @@ int sqfs_dir_writer_end(sqfs_dir_writer_t *writer) diff_u16 = (uint16_t *)&ent.inode_diff; *diff_u16 = htole16(*diff_u16); - if (sqfs_meta_writer_append(writer->dm, &ent, - sizeof(ent))) { - return -1; - } + err = sqfs_meta_writer_append(writer->dm, &ent, + sizeof(ent)); + if (err) + return err; - if (sqfs_meta_writer_append(writer->dm, it->name, - it->name_len)) { - return -1; - } + err = sqfs_meta_writer_append(writer->dm, it->name, + it->name_len); + if (err) + return err; it = it->next; } @@ -277,19 +280,21 @@ int sqfs_dir_writer_write_index(sqfs_dir_writer_t *writer, { sqfs_dir_index_t ent; index_ent_t *idx; + int err; for (idx = writer->idx; idx != NULL; idx = idx->next) { ent.start_block = htole32(idx->block); ent.index = htole32(idx->index); ent.size = htole32(idx->ent->name_len - 1); - if (sqfs_meta_writer_append(im, &ent, sizeof(ent))) - return -1; + err = sqfs_meta_writer_append(im, &ent, sizeof(ent)); + if (err) + return err; - if (sqfs_meta_writer_append(im, idx->ent->name, - idx->ent->name_len)) { - return -1; - } + err = sqfs_meta_writer_append(im, idx->ent->name, + idx->ent->name_len); + if (err) + return err; } return 0; diff --git a/lib/sqfs/id_table.c b/lib/sqfs/id_table.c index f7ffe2d..496049e 100644 --- a/lib/sqfs/id_table.c +++ b/lib/sqfs/id_table.c @@ -10,10 +10,10 @@ #include "sqfs/id_table.h" #include "sqfs/super.h" #include "sqfs/table.h" +#include "sqfs/error.h" #include #include -#include struct sqfs_id_table_t { uint32_t *ids; @@ -23,12 +23,7 @@ struct sqfs_id_table_t { sqfs_id_table_t *sqfs_id_table_create(void) { - sqfs_id_table_t *tbl = calloc(1, sizeof(*tbl)); - - if (tbl == NULL) - perror("Creating ID table"); - - return tbl; + return calloc(1, sizeof(sqfs_id_table_t)); } void sqfs_id_table_destroy(sqfs_id_table_t *tbl) @@ -49,19 +44,15 @@ int sqfs_id_table_id_to_index(sqfs_id_table_t *tbl, uint32_t id, uint16_t *out) } } - if (tbl->num_ids == 0x10000) { - fputs("Too many unique UIDs/GIDs (more than 64k)!\n", stderr); - return -1; - } + if (tbl->num_ids == 0x10000) + return SQFS_ERROR_OVERFLOW; if (tbl->num_ids == tbl->max_ids) { sz = (tbl->max_ids ? tbl->max_ids * 2 : 16); ptr = realloc(tbl->ids, sizeof(tbl->ids[0]) * sz); - if (ptr == NULL) { - perror("growing ID table"); - return -1; - } + if (ptr == NULL) + return SQFS_ERROR_ALLOC; tbl->ids = ptr; tbl->max_ids = sz; @@ -75,10 +66,8 @@ int sqfs_id_table_id_to_index(sqfs_id_table_t *tbl, uint32_t id, uint16_t *out) int sqfs_id_table_index_to_id(const sqfs_id_table_t *tbl, uint16_t index, uint32_t *out) { - if (index >= tbl->num_ids) { - fputs("attempted out of bounds ID table access\n", stderr); - return -1; - } + if (index >= tbl->num_ids) + return SQFS_ERROR_OUT_OF_BOUNDS; *out = tbl->ids[index]; return 0; @@ -88,7 +77,9 @@ int sqfs_id_table_read(sqfs_id_table_t *tbl, int fd, sqfs_super_t *super, sqfs_compressor_t *cmp) { uint64_t upper_limit, lower_limit; + void *raw_ids; size_t i; + int ret; if (tbl->ids != NULL) { free(tbl->ids); @@ -97,10 +88,8 @@ int sqfs_id_table_read(sqfs_id_table_t *tbl, int fd, sqfs_super_t *super, tbl->ids = NULL; } - if (!super->id_count || super->id_table_start >= super->bytes_used) { - fputs("ID table missing from file system\n", stderr); - return -1; - } + if (!super->id_count || super->id_table_start >= super->bytes_used) + return SQFS_ERROR_CORRUPTED; upper_limit = super->id_table_start; lower_limit = super->directory_table_start; @@ -117,11 +106,13 @@ int sqfs_id_table_read(sqfs_id_table_t *tbl, int fd, sqfs_super_t *super, tbl->num_ids = super->id_count; tbl->max_ids = super->id_count; - tbl->ids = sqfs_read_table(fd, cmp, tbl->num_ids * sizeof(uint32_t), - super->id_table_start, lower_limit, - upper_limit); - if (tbl->ids == NULL) - return -1; + ret = sqfs_read_table(fd, cmp, tbl->num_ids * sizeof(uint32_t), + super->id_table_start, lower_limit, + upper_limit, &raw_ids); + if (ret) + return ret; + + tbl->ids = raw_ids; for (i = 0; i < tbl->num_ids; ++i) tbl->ids[i] = le32toh(tbl->ids[i]); diff --git a/lib/sqfs/meta_reader.c b/lib/sqfs/meta_reader.c index 38aac7e..295d0de 100644 --- a/lib/sqfs/meta_reader.c +++ b/lib/sqfs/meta_reader.c @@ -9,13 +9,13 @@ #include "sqfs/meta_reader.h" #include "sqfs/compress.h" +#include "sqfs/error.h" #include "sqfs/data.h" #include "util.h" #include #include #include -#include struct sqfs_meta_reader_t { uint64_t start; @@ -49,10 +49,8 @@ sqfs_meta_reader_t *sqfs_meta_reader_create(int fd, sqfs_compressor_t *cmp, { sqfs_meta_reader_t *m = calloc(1, sizeof(*m)); - if (m == NULL) { - perror("creating meta data reader"); + if (m == NULL) return NULL; - } m->start = start; m->limit = limit; @@ -75,11 +73,11 @@ int sqfs_meta_reader_seek(sqfs_meta_reader_t *m, uint64_t block_start, size_t size; if (block_start < m->start || block_start >= m->limit) - goto fail_range; + return SQFS_ERROR_OUT_OF_BOUNDS; if (block_start == m->block_offset) { if (offset >= m->data_used) - goto fail_offset; + return SQFS_ERROR_OUT_OF_BOUNDS; m->offset = offset; return 0; @@ -87,7 +85,7 @@ int sqfs_meta_reader_seek(sqfs_meta_reader_t *m, uint64_t block_start, if (read_data_at("reading meta data header", block_start, m->fd, &header, 2)) { - return -1; + return SQFS_ERROR_IO; } header = le16toh(header); @@ -95,24 +93,22 @@ int sqfs_meta_reader_seek(sqfs_meta_reader_t *m, uint64_t block_start, size = header & 0x7FFF; if (size > sizeof(m->data)) - goto fail_too_large; + return SQFS_ERROR_CORRUPTED; if ((block_start + 2 + size) > m->limit) - goto fail_block_bounds; + return SQFS_ERROR_OUT_OF_BOUNDS; if (read_data_at("reading meta data block", block_start + 2, m->fd, m->data, size)) { - return -1; + return SQFS_ERROR_IO; } if (compressed) { ret = m->cmp->do_block(m->cmp, m->data, size, m->scratch, sizeof(m->scratch)); - if (ret <= 0) { - fputs("error uncompressing meta data block\n", stderr); - return -1; - } + if (ret < 0) + return ret; memcpy(m->data, m->scratch, ret); m->data_used = ret; @@ -121,26 +117,12 @@ int sqfs_meta_reader_seek(sqfs_meta_reader_t *m, uint64_t block_start, } if (offset >= m->data_used) - goto fail_offset; + return SQFS_ERROR_OUT_OF_BOUNDS; m->block_offset = block_start; m->next_block = block_start + size + 2; m->offset = offset; return 0; -fail_block_bounds: - fputs("found metadata block that exceeds filesystem bounds.\n", - stderr); - return -1; -fail_too_large: - fputs("found metadata block larger than maximum size.\n", stderr); - return -1; -fail_offset: - fputs("Tried to seek past end of metadata block.\n", stderr); - return -1; -fail_range: - fputs("Tried to read meta data block past filesystem bounds.\n", - stderr); - return -1; } void sqfs_meta_reader_get_position(sqfs_meta_reader_t *m, uint64_t *block_start, @@ -153,13 +135,15 @@ void sqfs_meta_reader_get_position(sqfs_meta_reader_t *m, uint64_t *block_start, int sqfs_meta_reader_read(sqfs_meta_reader_t *m, void *data, size_t size) { size_t diff; + int ret; while (size != 0) { diff = m->data_used - m->offset; if (diff == 0) { - if (sqfs_meta_reader_seek(m, m->next_block, 0)) - return -1; + ret = sqfs_meta_reader_seek(m, m->next_block, 0); + if (ret) + return ret; diff = m->data_used; } diff --git a/lib/sqfs/meta_writer.c b/lib/sqfs/meta_writer.c index fdeea2e..46f9618 100644 --- a/lib/sqfs/meta_writer.c +++ b/lib/sqfs/meta_writer.c @@ -9,13 +9,13 @@ #include "sqfs/meta_writer.h" #include "sqfs/compress.h" +#include "sqfs/error.h" #include "sqfs/data.h" #include "util.h" #include #include #include -#include typedef struct meta_block_t { struct meta_block_t *next; @@ -58,10 +58,8 @@ sqfs_meta_writer_t *sqfs_meta_writer_create(int fd, sqfs_compressor_t *cmp, { sqfs_meta_writer_t *m = calloc(1, sizeof(*m)); - if (m == NULL) { - perror("creating meta data writer"); + if (m == NULL) return NULL; - } m->cmp = cmp; m->outfd = fd; @@ -92,16 +90,14 @@ int sqfs_meta_writer_flush(sqfs_meta_writer_t *m) return 0; outblk = calloc(1, sizeof(*outblk)); - if (outblk == NULL) { - perror("generating meta data block"); - return -1; - } + if (outblk == NULL) + return SQFS_ERROR_ALLOC; ret = m->cmp->do_block(m->cmp, m->data, m->offset, outblk->data + 2, sizeof(outblk->data) - 2); if (ret < 0) { free(outblk); - return -1; + return ret; } if (ret > 0) { @@ -113,6 +109,8 @@ int sqfs_meta_writer_flush(sqfs_meta_writer_t *m) count = m->offset + 2; } + ret = 0; + if (m->keep_in_mem) { if (m->list == NULL) { m->list = outblk; @@ -120,9 +118,9 @@ int sqfs_meta_writer_flush(sqfs_meta_writer_t *m) m->list_end->next = outblk; } m->list_end = outblk; - ret = 0; } else { - ret = write_block(m->outfd, outblk); + if (write_block(m->outfd, outblk)) + ret = SQFS_ERROR_IO; free(outblk); } @@ -136,13 +134,15 @@ int sqfs_meta_writer_append(sqfs_meta_writer_t *m, const void *data, size_t size) { size_t diff; + int ret; while (size != 0) { diff = sizeof(m->data) - m->offset; if (diff == 0) { - if (sqfs_meta_writer_flush(m)) - return -1; + ret = sqfs_meta_writer_flush(m); + if (ret) + return ret; diff = sizeof(m->data); } @@ -183,7 +183,7 @@ int sqfs_meta_write_write_to_file(sqfs_meta_writer_t *m) blk = m->list; if (write_block(m->outfd, blk)) - return -1; + return SQFS_ERROR_IO; m->list = blk->next; free(blk); diff --git a/lib/sqfs/process_block.c b/lib/sqfs/process_block.c index 2658ee7..2c1395f 100644 --- a/lib/sqfs/process_block.c +++ b/lib/sqfs/process_block.c @@ -27,7 +27,7 @@ int sqfs_block_process(sqfs_block_t *block, sqfs_compressor_t *cmp, scratch, scratch_size); if (ret < 0) - return -1; + return ret; if (ret > 0) { memcpy(block->data, scratch, ret); diff --git a/lib/sqfs/read_inode.c b/lib/sqfs/read_inode.c index 70ed9f1..56ea6a4 100644 --- a/lib/sqfs/read_inode.c +++ b/lib/sqfs/read_inode.c @@ -8,13 +8,13 @@ #include "config.h" #include "sqfs/meta_reader.h" +#include "sqfs/error.h" #include "sqfs/super.h" #include "sqfs/inode.h" #include "util.h" #include #include -#include #include #define SWAB16(x) x = le16toh(x) @@ -55,8 +55,7 @@ static int set_mode(sqfs_inode_t *inode) inode->mode |= S_IFIFO; break; default: - fputs("Found inode with unknown file mode\n", stderr); - return -1; + return SQFS_ERROR_UNSUPPORTED; } return 0; @@ -75,16 +74,17 @@ static uint64_t get_block_count(uint64_t size, uint64_t block_size, return count; } -static sqfs_inode_generic_t *read_inode_file(sqfs_meta_reader_t *ir, - sqfs_inode_t *base, - size_t block_size) +static int read_inode_file(sqfs_meta_reader_t *ir, sqfs_inode_t *base, + size_t block_size, sqfs_inode_generic_t **result) { sqfs_inode_generic_t *out; sqfs_inode_file_t file; uint64_t i, count; + int err; - if (sqfs_meta_reader_read(ir, &file, sizeof(file))) - return NULL; + err = sqfs_meta_reader_read(ir, &file, sizeof(file)); + if (err) + return err; SWAB32(file.blocks_start); SWAB32(file.fragment_index); @@ -95,38 +95,39 @@ static sqfs_inode_generic_t *read_inode_file(sqfs_meta_reader_t *ir, file.fragment_index, file.fragment_offset); out = alloc_flex(sizeof(*out), sizeof(uint32_t), count); - if (out == NULL) { - perror("reading extended file inode"); - return NULL; - } + if (out == NULL) + return SQFS_ERROR_ALLOC; out->base = *base; out->data.file = file; out->block_sizes = (uint32_t *)out->extra; out->num_file_blocks = count; - if (sqfs_meta_reader_read(ir, out->block_sizes, - count * sizeof(uint32_t))) { + err = sqfs_meta_reader_read(ir, out->block_sizes, + count * sizeof(uint32_t)); + if (err) { free(out); - return NULL; + return err; } for (i = 0; i < count; ++i) SWAB32(out->block_sizes[i]); - return out; + *result = out; + return 0; } -static sqfs_inode_generic_t *read_inode_file_ext(sqfs_meta_reader_t *ir, - sqfs_inode_t *base, - size_t block_size) +static int read_inode_file_ext(sqfs_meta_reader_t *ir, sqfs_inode_t *base, + size_t block_size, sqfs_inode_generic_t **result) { sqfs_inode_file_ext_t file; sqfs_inode_generic_t *out; uint64_t i, count; + int err; - if (sqfs_meta_reader_read(ir, &file, sizeof(file))) - return NULL; + err = sqfs_meta_reader_read(ir, &file, sizeof(file)); + if (err) + return err; SWAB64(file.blocks_start); SWAB64(file.file_size); @@ -141,8 +142,8 @@ static sqfs_inode_generic_t *read_inode_file_ext(sqfs_meta_reader_t *ir, out = alloc_flex(sizeof(*out), sizeof(uint32_t), count); if (out == NULL) { - perror("reading extended file inode"); - return NULL; + return errno == EOVERFLOW ? SQFS_ERROR_OVERFLOW : + SQFS_ERROR_ALLOC; } out->base = *base; @@ -150,90 +151,96 @@ static sqfs_inode_generic_t *read_inode_file_ext(sqfs_meta_reader_t *ir, out->block_sizes = (uint32_t *)out->extra; out->num_file_blocks = count; - if (sqfs_meta_reader_read(ir, out->block_sizes, - count * sizeof(uint32_t))) { + err = sqfs_meta_reader_read(ir, out->block_sizes, + count * sizeof(uint32_t)); + if (err) { free(out); - return NULL; + return err; } for (i = 0; i < count; ++i) SWAB32(out->block_sizes[i]); - return out; + *result = out; + return 0; } -static sqfs_inode_generic_t *read_inode_slink(sqfs_meta_reader_t *ir, - sqfs_inode_t *base) +static int read_inode_slink(sqfs_meta_reader_t *ir, sqfs_inode_t *base, + sqfs_inode_generic_t **result) { sqfs_inode_generic_t *out; sqfs_inode_slink_t slink; size_t size; + int err; - if (sqfs_meta_reader_read(ir, &slink, sizeof(slink))) - return NULL; + err = sqfs_meta_reader_read(ir, &slink, sizeof(slink)); + if (err) + return err; SWAB32(slink.nlink); SWAB32(slink.target_size); if (SZ_ADD_OV(slink.target_size, 1, &size) || SZ_ADD_OV(sizeof(*out), size, &size)) { - errno = EOVERFLOW; - goto fail; + return SQFS_ERROR_OVERFLOW; } out = calloc(1, size); if (out == NULL) - goto fail; + return SQFS_ERROR_ALLOC; out->slink_target = (char *)out->extra; out->base = *base; out->data.slink = slink; - if (sqfs_meta_reader_read(ir, out->slink_target, slink.target_size)) { + err = sqfs_meta_reader_read(ir, out->slink_target, slink.target_size); + if (err) { free(out); - return NULL; + return err; } - return out; -fail: - perror("reading symlink inode"); - return NULL; + *result = out; + return 0; } -static sqfs_inode_generic_t *read_inode_slink_ext(sqfs_meta_reader_t *ir, - sqfs_inode_t *base) +static int read_inode_slink_ext(sqfs_meta_reader_t *ir, sqfs_inode_t *base, + sqfs_inode_generic_t **result) { - sqfs_inode_generic_t *out = read_inode_slink(ir, base); uint32_t xattr; + int err; - if (out != NULL) { - if (sqfs_meta_reader_read(ir, &xattr, sizeof(xattr))) { - free(out); - return NULL; - } + err = read_inode_slink(ir, base, result); + if (err) + return err; - out->data.slink_ext.xattr_idx = le32toh(xattr); + err = sqfs_meta_reader_read(ir, &xattr, sizeof(xattr)); + if (err) { + free(*result); + return err; } - return out; + (*result)->data.slink_ext.xattr_idx = le32toh(xattr); + return 0; } -sqfs_inode_generic_t *sqfs_meta_reader_read_inode(sqfs_meta_reader_t *ir, - sqfs_super_t *super, - uint64_t block_start, - size_t offset) +int sqfs_meta_reader_read_inode(sqfs_meta_reader_t *ir, sqfs_super_t *super, + uint64_t block_start, size_t offset, + sqfs_inode_generic_t **result) { sqfs_inode_generic_t *out; sqfs_inode_t inode; + int err; /* read base inode */ block_start += super->inode_table_start; - if (sqfs_meta_reader_seek(ir, block_start, offset)) - return NULL; + err = sqfs_meta_reader_seek(ir, block_start, offset); + if (err) + return err; - if (sqfs_meta_reader_read(ir, &inode, sizeof(inode))) - return NULL; + err = sqfs_meta_reader_read(ir, &inode, sizeof(inode)); + if (err) + return err; SWAB16(inode.type); SWAB16(inode.mode); @@ -242,38 +249,39 @@ sqfs_inode_generic_t *sqfs_meta_reader_read_inode(sqfs_meta_reader_t *ir, SWAB32(inode.mod_time); SWAB32(inode.inode_number); - if (set_mode(&inode)) - return NULL; + err = set_mode(&inode); + if (err) + return err; /* inode types where the size is variable */ switch (inode.type) { case SQFS_INODE_FILE: - return read_inode_file(ir, &inode, super->block_size); + return read_inode_file(ir, &inode, super->block_size, result); case SQFS_INODE_SLINK: - return read_inode_slink(ir, &inode); + return read_inode_slink(ir, &inode, result); case SQFS_INODE_EXT_FILE: - return read_inode_file_ext(ir, &inode, super->block_size); + return read_inode_file_ext(ir, &inode, super->block_size, + result); case SQFS_INODE_EXT_SLINK: - return read_inode_slink_ext(ir, &inode); + return read_inode_slink_ext(ir, &inode, result); default: break; } /* everything else */ out = calloc(1, sizeof(*out)); - if (out == NULL) { - perror("reading symlink inode"); - return NULL; - } + if (out == NULL) + return SQFS_ERROR_ALLOC; out->base = inode; switch (inode.type) { case SQFS_INODE_DIR: - if (sqfs_meta_reader_read(ir, &out->data.dir, - sizeof(out->data.dir))) { + err = sqfs_meta_reader_read(ir, &out->data.dir, + sizeof(out->data.dir)); + if (err) goto fail_free; - } + SWAB32(out->data.dir.start_block); SWAB32(out->data.dir.nlink); SWAB16(out->data.dir.size); @@ -282,26 +290,26 @@ sqfs_inode_generic_t *sqfs_meta_reader_read_inode(sqfs_meta_reader_t *ir, break; case SQFS_INODE_BDEV: case SQFS_INODE_CDEV: - if (sqfs_meta_reader_read(ir, &out->data.dev, - sizeof(out->data.dev))) { + err = sqfs_meta_reader_read(ir, &out->data.dev, + sizeof(out->data.dev)); + if (err) goto fail_free; - } SWAB32(out->data.dev.nlink); SWAB32(out->data.dev.devno); break; case SQFS_INODE_FIFO: case SQFS_INODE_SOCKET: - if (sqfs_meta_reader_read(ir, &out->data.ipc, - sizeof(out->data.ipc))) { + err = sqfs_meta_reader_read(ir, &out->data.ipc, + sizeof(out->data.ipc)); + if (err) goto fail_free; - } SWAB32(out->data.ipc.nlink); break; case SQFS_INODE_EXT_DIR: - if (sqfs_meta_reader_read(ir, &out->data.dir_ext, - sizeof(out->data.dir_ext))) { + err = sqfs_meta_reader_read(ir, &out->data.dir_ext, + sizeof(out->data.dir_ext)); + if (err) goto fail_free; - } SWAB32(out->data.dir_ext.nlink); SWAB32(out->data.dir_ext.size); SWAB32(out->data.dir_ext.start_block); @@ -312,30 +320,30 @@ sqfs_inode_generic_t *sqfs_meta_reader_read_inode(sqfs_meta_reader_t *ir, break; case SQFS_INODE_EXT_BDEV: case SQFS_INODE_EXT_CDEV: - if (sqfs_meta_reader_read(ir, &out->data.dev_ext, - sizeof(out->data.dev_ext))) { + err = sqfs_meta_reader_read(ir, &out->data.dev_ext, + sizeof(out->data.dev_ext)); + if (err) goto fail_free; - } SWAB32(out->data.dev_ext.nlink); SWAB32(out->data.dev_ext.devno); SWAB32(out->data.dev_ext.xattr_idx); break; case SQFS_INODE_EXT_FIFO: case SQFS_INODE_EXT_SOCKET: - if (sqfs_meta_reader_read(ir, &out->data.ipc_ext, - sizeof(out->data.ipc_ext))) { + err = sqfs_meta_reader_read(ir, &out->data.ipc_ext, + sizeof(out->data.ipc_ext)); + if (err) goto fail_free; - } SWAB32(out->data.ipc_ext.nlink); SWAB32(out->data.ipc_ext.xattr_idx); break; default: - fputs("Unknown inode type found\n", stderr); - goto fail_free; + return SQFS_ERROR_UNSUPPORTED; } - return out; + *result = out; + return 0; fail_free: free(out); - return NULL; + return err; } diff --git a/lib/sqfs/read_super.c b/lib/sqfs/read_super.c index 5bd5e50..9f7425c 100644 --- a/lib/sqfs/read_super.c +++ b/lib/sqfs/read_super.c @@ -8,12 +8,11 @@ #include "config.h" #include "sqfs/super.h" +#include "sqfs/error.h" #include "util.h" #include #include -#include -#include int sqfs_super_read(sqfs_super_t *super, int fd) { @@ -22,7 +21,7 @@ int sqfs_super_read(sqfs_super_t *super, int fd) int i; if (read_data_at("reading super block", 0, fd, &temp, sizeof(temp))) - return -1; + return SQFS_ERROR_IO; temp.magic = le32toh(temp.magic); temp.inode_count = le32toh(temp.inode_count); @@ -44,33 +43,21 @@ int sqfs_super_read(sqfs_super_t *super, int fd) temp.fragment_table_start = le64toh(temp.fragment_table_start); temp.export_table_start = le64toh(temp.export_table_start); - if (temp.magic != SQFS_MAGIC) { - fputs("Magic number missing. Not a squashfs image.\n", stderr); - return -1; - } + if (temp.magic != SQFS_MAGIC) + return SFQS_ERROR_SUPER_MAGIC; if ((temp.version_major != SQFS_VERSION_MAJOR) || - (temp.version_minor != SQFS_VERSION_MINOR)) { - fprintf(stderr, - "The squashfs image uses squashfs version %d.%d\n" - "This tool currently only supports version %d.%d.\n", - temp.version_major, temp.version_minor, - SQFS_VERSION_MAJOR, SQFS_VERSION_MINOR); - return -1; - } - - if ((temp.block_size - 1) & temp.block_size) { - fputs("Block size in image is not a power of 2!\n", stderr); - return -1; - } - - if (temp.block_size < 4096 || temp.block_size >= (1 << 20)) { - fputs("Block size in iamge not between 4k and 1M\n", stderr); - return -1; - } + (temp.version_minor != SQFS_VERSION_MINOR)) + return SFQS_ERROR_SUPER_VERSION; + + if ((temp.block_size - 1) & temp.block_size) + return SQFS_ERROR_SUPER_BLOCK_SIZE; + + if (temp.block_size < 4096 || temp.block_size >= (1 << 20)) + return SQFS_ERROR_SUPER_BLOCK_SIZE; if (temp.block_log < 12 || temp.block_log > 20) - goto fail_block_log; + return SQFS_ERROR_CORRUPTED; block_size = 1; @@ -78,23 +65,15 @@ int sqfs_super_read(sqfs_super_t *super, int fd) block_size <<= 1; if (temp.block_size != block_size) - goto fail_block_log; + return SQFS_ERROR_CORRUPTED; if (temp.compression_id < SQFS_COMP_MIN || - temp.compression_id > SQFS_COMP_MAX) { - fputs("Image uses an unsupported compressor\n", stderr); - return -1; - } + temp.compression_id > SQFS_COMP_MAX) + return SQFS_ERROR_UNSUPPORTED; - if (temp.id_count == 0) { - fputs("ID table in squashfs image is empty.\n", stderr); - return -1; - } + if (temp.id_count == 0) + return SQFS_ERROR_CORRUPTED; memcpy(super, &temp, sizeof(temp)); return 0; -fail_block_log: - fputs("Mismatch between block size and block log\n", stderr); - fputs("Filesystem probably currupted.\n", stderr); - return -1; } diff --git a/lib/sqfs/read_table.c b/lib/sqfs/read_table.c index d2664d4..843247e 100644 --- a/lib/sqfs/read_table.c +++ b/lib/sqfs/read_table.c @@ -8,27 +8,27 @@ #include "config.h" #include "sqfs/meta_reader.h" -#include "highlevel.h" +#include "sqfs/error.h" +#include "sqfs/table.h" +#include "sqfs/data.h" #include "util.h" #include #include -#include -void *sqfs_read_table(int fd, sqfs_compressor_t *cmp, size_t table_size, - uint64_t location, uint64_t lower_limit, - uint64_t upper_limit) +int sqfs_read_table(int fd, sqfs_compressor_t *cmp, size_t table_size, + uint64_t location, uint64_t lower_limit, + uint64_t upper_limit, void **out) { size_t diff, block_count, blk_idx = 0; uint64_t start, *locations; sqfs_meta_reader_t *m; void *data, *ptr; + int err; data = malloc(table_size); - if (data == NULL) { - perror("reading table"); - return NULL; - } + if (data == NULL) + return SQFS_ERROR_ALLOC; /* restore list from image */ block_count = table_size / SQFS_META_BLOCK_SIZE; @@ -39,33 +39,38 @@ void *sqfs_read_table(int fd, sqfs_compressor_t *cmp, size_t table_size, locations = alloc_array(sizeof(uint64_t), block_count); if (locations == NULL) { - perror("allocation table location list"); + err = SQFS_ERROR_ALLOC; goto fail_data; } if (read_data_at("reading table locations", location, fd, locations, sizeof(uint64_t) * block_count)) { + err = SQFS_ERROR_IO; goto fail_idx; } /* Read the actual data */ m = sqfs_meta_reader_create(fd, cmp, lower_limit, upper_limit); - if (m == NULL) + if (m == NULL) { + err = SQFS_ERROR_ALLOC; goto fail_idx; + } ptr = data; while (table_size > 0) { start = le64toh(locations[blk_idx++]); - if (sqfs_meta_reader_seek(m, start, 0)) + err = sqfs_meta_reader_seek(m, start, 0); + if (err) goto fail; diff = SQFS_META_BLOCK_SIZE; if (diff > table_size) diff = table_size; - if (sqfs_meta_reader_read(m, ptr, diff)) + err = sqfs_meta_reader_read(m, ptr, diff); + if (err) goto fail; ptr = (char *)ptr + diff; @@ -74,12 +79,14 @@ void *sqfs_read_table(int fd, sqfs_compressor_t *cmp, size_t table_size, sqfs_meta_reader_destroy(m); free(locations); - return data; + *out = data; + return 0; fail: sqfs_meta_reader_destroy(m); fail_idx: free(locations); fail_data: free(data); - return NULL; + *out = NULL; + return err; } diff --git a/lib/sqfs/readdir.c b/lib/sqfs/readdir.c index e1712be..1323c36 100644 --- a/lib/sqfs/readdir.c +++ b/lib/sqfs/readdir.c @@ -8,38 +8,39 @@ #include "config.h" #include "sqfs/meta_reader.h" +#include "sqfs/error.h" #include "sqfs/dir.h" #include #include -#include int sqfs_meta_reader_read_dir_header(sqfs_meta_reader_t *m, sqfs_dir_header_t *hdr) { - if (sqfs_meta_reader_read(m, hdr, sizeof(*hdr))) - return -1; + int err = sqfs_meta_reader_read(m, hdr, sizeof(*hdr)); + if (err) + return err; hdr->count = le32toh(hdr->count); hdr->start_block = le32toh(hdr->start_block); hdr->inode_number = le32toh(hdr->inode_number); - if (hdr->count > (SQFS_MAX_DIR_ENT - 1)) { - fputs("Found a directory header with too many entries\n", - stderr); - return -1; - } + if (hdr->count > (SQFS_MAX_DIR_ENT - 1)) + return SQFS_ERROR_CORRUPTED; return 0; } -sqfs_dir_entry_t *sqfs_meta_reader_read_dir_ent(sqfs_meta_reader_t *m) +int sqfs_meta_reader_read_dir_ent(sqfs_meta_reader_t *m, + sqfs_dir_entry_t **result) { sqfs_dir_entry_t ent, *out; uint16_t *diff_u16; + int err; - if (sqfs_meta_reader_read(m, &ent, sizeof(ent))) - return NULL; + err = sqfs_meta_reader_read(m, &ent, sizeof(ent)); + if (err) + return err; diff_u16 = (uint16_t *)&ent.inode_diff; *diff_u16 = le16toh(*diff_u16); @@ -49,30 +50,28 @@ sqfs_dir_entry_t *sqfs_meta_reader_read_dir_ent(sqfs_meta_reader_t *m) ent.size = le16toh(ent.size); out = calloc(1, sizeof(*out) + ent.size + 2); - if (out == NULL) { - perror("reading dir entry"); - return NULL; - } + if (out == NULL) + return SQFS_ERROR_ALLOC; *out = ent; - if (sqfs_meta_reader_read(m, out->name, ent.size + 1)) { + err = sqfs_meta_reader_read(m, out->name, ent.size + 1); + if (err) { free(out); - return NULL; + return err; } if (strchr((char *)out->name, '/') != NULL || strchr((char *)out->name, '\\') != NULL) { - fputs("Found a file name that contains slashes\n", stderr); free(out); - return NULL; + return SQFS_ERROR_CORRUPTED; } if (strcmp((char *)out->name, "..") == 0 || strcmp((char *)out->name, ".") == 0) { - fputs("Found '..' or '.' in file names\n", stderr); free(out); - return NULL; + return SQFS_ERROR_CORRUPTED; } - return out; + *result = out; + return 0; } diff --git a/lib/sqfs/super.c b/lib/sqfs/super.c index 5541501..0489079 100644 --- a/lib/sqfs/super.c +++ b/lib/sqfs/super.c @@ -8,27 +8,23 @@ #include "config.h" #include "sqfs/super.h" +#include "sqfs/error.h" #include "util.h" #include #include #include -#include int sqfs_super_init(sqfs_super_t *super, size_t block_size, uint32_t mtime, E_SQFS_COMPRESSOR compressor) { unsigned int i; - if (block_size & (block_size - 1)) { - fputs("Block size must be a power of 2!\n", stderr); - return -1; - } + if (block_size & (block_size - 1)) + return SQFS_ERROR_SUPER_BLOCK_SIZE; - if (block_size < 4096 || block_size >= (1 << 20)) { - fputs("Block size must be between 4k and 1M\n", stderr); - return -1; - } + if (block_size < 4096 || block_size >= (1 << 20)) + return SQFS_ERROR_SUPER_BLOCK_SIZE; memset(super, 0, sizeof(*super)); super->magic = SQFS_MAGIC; @@ -77,16 +73,13 @@ int sqfs_super_write(sqfs_super_t *super, int fd) copy.export_table_start = htole64(super->export_table_start); if (lseek(fd, 0, SEEK_SET) == (off_t)-1) - goto fail_seek; + return SQFS_ERROR_IO; if (write_data("writing super block", fd, ©, sizeof(copy))) - return -1; + return SQFS_ERROR_IO; if (lseek(fd, 0, SEEK_END) == (off_t)-1) - goto fail_seek; + return SQFS_ERROR_IO; return 0; -fail_seek: - perror("squashfs writing super block: seek on output file"); - return -1; } diff --git a/lib/sqfs/write_inode.c b/lib/sqfs/write_inode.c index c51c1a3..42ec58f 100644 --- a/lib/sqfs/write_inode.c +++ b/lib/sqfs/write_inode.c @@ -8,6 +8,7 @@ #include "config.h" #include "sqfs/meta_writer.h" +#include "sqfs/error.h" #include "sqfs/inode.h" static int write_block_sizes(sqfs_meta_writer_t *ir, sqfs_inode_generic_t *n) @@ -26,6 +27,7 @@ int sqfs_meta_writer_write_inode(sqfs_meta_writer_t *ir, sqfs_inode_generic_t *n) { sqfs_inode_t base; + int ret; base.type = htole16(n->base.type); base.mode = htole16(n->base.mode); @@ -34,8 +36,9 @@ int sqfs_meta_writer_write_inode(sqfs_meta_writer_t *ir, base.mod_time = htole32(n->base.mod_time); base.inode_number = htole32(n->base.inode_number); - if (sqfs_meta_writer_append(ir, &base, sizeof(base))) - return -1; + ret = sqfs_meta_writer_append(ir, &base, sizeof(base)); + if (ret) + return ret; switch (n->base.type) { case SQFS_INODE_DIR: { @@ -56,8 +59,9 @@ int sqfs_meta_writer_write_inode(sqfs_meta_writer_t *ir, htole32(n->data.file.fragment_offset), .file_size = htole32(n->data.file.file_size), }; - if (sqfs_meta_writer_append(ir, &file, sizeof(file))) - return -1; + ret = sqfs_meta_writer_append(ir, &file, sizeof(file)); + if (ret) + return ret; return write_block_sizes(ir, n); } case SQFS_INODE_SLINK: { @@ -65,8 +69,9 @@ int sqfs_meta_writer_write_inode(sqfs_meta_writer_t *ir, .nlink = htole32(n->data.slink.nlink), .target_size = htole32(n->data.slink.target_size), }; - if (sqfs_meta_writer_append(ir, &slink, sizeof(slink))) - return -1; + ret = sqfs_meta_writer_append(ir, &slink, sizeof(slink)); + if (ret) + return ret; return sqfs_meta_writer_append(ir, n->slink_target, n->data.slink.target_size); } @@ -108,8 +113,9 @@ int sqfs_meta_writer_write_inode(sqfs_meta_writer_t *ir, htole32(n->data.file_ext.fragment_offset), .xattr_idx = htole32(n->data.file_ext.xattr_idx), }; - if (sqfs_meta_writer_append(ir, &file, sizeof(file))) - return -1; + ret = sqfs_meta_writer_append(ir, &file, sizeof(file)); + if (ret) + return ret; return write_block_sizes(ir, n); } case SQFS_INODE_EXT_SLINK: { @@ -119,12 +125,13 @@ int sqfs_meta_writer_write_inode(sqfs_meta_writer_t *ir, }; uint32_t xattr = htole32(n->data.slink_ext.xattr_idx); - if (sqfs_meta_writer_append(ir, &slink, sizeof(slink))) - return -1; - if (sqfs_meta_writer_append(ir, n->slink_target, - n->data.slink_ext.target_size)) { - return -1; - } + ret = sqfs_meta_writer_append(ir, &slink, sizeof(slink)); + if (ret) + return ret; + ret = sqfs_meta_writer_append(ir, n->slink_target, + n->data.slink_ext.target_size); + if (ret) + return ret; return sqfs_meta_writer_append(ir, &xattr, sizeof(xattr)); } case SQFS_INODE_EXT_BDEV: @@ -146,5 +153,5 @@ int sqfs_meta_writer_write_inode(sqfs_meta_writer_t *ir, } } - return -1; + return SQFS_ERROR_UNSUPPORTED; } diff --git a/lib/sqfs/write_table.c b/lib/sqfs/write_table.c index a5b4c69..c264ebd 100644 --- a/lib/sqfs/write_table.c +++ b/lib/sqfs/write_table.c @@ -8,12 +8,14 @@ #include "config.h" #include "sqfs/meta_writer.h" -#include "highlevel.h" +#include "sqfs/error.h" +#include "sqfs/super.h" +#include "sqfs/table.h" +#include "sqfs/data.h" #include "util.h" #include #include -#include int sqfs_write_table(int outfd, sqfs_super_t *super, sqfs_compressor_t *cmp, const void *data, size_t table_size, uint64_t *start) @@ -22,7 +24,7 @@ int sqfs_write_table(int outfd, sqfs_super_t *super, sqfs_compressor_t *cmp, uint64_t block, *locations; sqfs_meta_writer_t *m; uint32_t offset; - int ret = -1; + int ret; block_count = table_size / SQFS_META_BLOCK_SIZE; if ((table_size % SQFS_META_BLOCK_SIZE) != 0) @@ -30,15 +32,15 @@ int sqfs_write_table(int outfd, sqfs_super_t *super, sqfs_compressor_t *cmp, locations = alloc_array(sizeof(uint64_t), block_count); - if (locations == NULL) { - perror("writing table"); - return -1; - } + if (locations == NULL) + return SQFS_ERROR_ALLOC; /* Write actual data */ m = sqfs_meta_writer_create(outfd, cmp, false); - if (m == NULL) + if (m == NULL) { + ret = SQFS_ERROR_ALLOC; goto out_idx; + } while (table_size > 0) { sqfs_meta_writer_get_position(m, &block, &offset); @@ -48,14 +50,16 @@ int sqfs_write_table(int outfd, sqfs_super_t *super, sqfs_compressor_t *cmp, if (diff > table_size) diff = table_size; - if (sqfs_meta_writer_append(m, data, diff)) + ret = sqfs_meta_writer_append(m, data, diff); + if (ret) goto out; data = (const char *)data + diff; table_size -= diff; } - if (sqfs_meta_writer_flush(m)) + ret = sqfs_meta_writer_flush(m); + if (ret) goto out; sqfs_meta_writer_get_position(m, &block, &offset); @@ -65,8 +69,11 @@ int sqfs_write_table(int outfd, sqfs_super_t *super, sqfs_compressor_t *cmp, *start = super->bytes_used; list_size = sizeof(uint64_t) * block_count; - if (write_data("writing table locations", outfd, locations, list_size)) + if (write_data("writing table locations", outfd, + locations, list_size)) { + ret = SQFS_ERROR_IO; goto out; + } super->bytes_used += list_size; diff --git a/lib/sqfs/xattr_reader.c b/lib/sqfs/xattr_reader.c index aeee574..80731ba 100644 --- a/lib/sqfs/xattr_reader.c +++ b/lib/sqfs/xattr_reader.c @@ -10,12 +10,12 @@ #include "sqfs/meta_reader.h" #include "sqfs/super.h" #include "sqfs/xattr.h" +#include "sqfs/error.h" #include "sqfs/data.h" #include "util.h" #include #include -#include #include struct sqfs_xattr_reader_t { @@ -29,24 +29,28 @@ struct sqfs_xattr_reader_t { sqfs_meta_reader_t *idrd; sqfs_meta_reader_t *kvrd; sqfs_super_t *super; + int sqfsfd; }; -static int get_id_block_locations(sqfs_xattr_reader_t *xr, int sqfsfd, - sqfs_super_t *super) +int sqfs_xattr_reader_load_locations(sqfs_xattr_reader_t *xr) { sqfs_xattr_id_table_t idtbl; size_t i; + int err; - if (super->xattr_id_table_start >= super->bytes_used) { - fputs("xattr ID location table is after end of filesystem\n", - stderr); - return -1; - } + if (xr->super->flags & SQFS_FLAG_NO_XATTRS) + return 0; + + if (xr->super->xattr_id_table_start == 0xFFFFFFFFFFFFFFFF) + return 0; + + if (xr->super->xattr_id_table_start >= xr->super->bytes_used) + return SQFS_ERROR_OUT_OF_BOUNDS; if (read_data_at("reading xattr ID location table", - super->xattr_id_table_start, - sqfsfd, &idtbl, sizeof(idtbl))) { - return -1; + xr->super->xattr_id_table_start, + xr->sqfsfd, &idtbl, sizeof(idtbl))) { + return SQFS_ERROR_IO; } xr->xattr_start = le64toh(idtbl.xattr_table_start); @@ -59,23 +63,24 @@ static int get_id_block_locations(sqfs_xattr_reader_t *xr, int sqfsfd, xr->id_block_starts = alloc_array(sizeof(uint64_t), xr->num_id_blocks); if (xr->id_block_starts == NULL) { - perror("allocating xattr ID location table"); - return -1; + if (errno == EOVERFLOW) + return SQFS_ERROR_OVERFLOW; + return SQFS_ERROR_ALLOC; } if (read_data_at("reading xattr ID block locations", - super->xattr_id_table_start + sizeof(idtbl), - sqfsfd, xr->id_block_starts, + xr->super->xattr_id_table_start + sizeof(idtbl), + xr->sqfsfd, xr->id_block_starts, sizeof(uint64_t) * xr->num_id_blocks)) { + err = SQFS_ERROR_IO; goto fail; } for (i = 0; i < xr->num_id_blocks; ++i) { xr->id_block_starts[i] = le64toh(xr->id_block_starts[i]); - if (xr->id_block_starts[i] > super->bytes_used) { - fputs("found xattr ID block that is past " - "end of filesystem\n", stderr); + if (xr->id_block_starts[i] > xr->super->bytes_used) { + err = SQFS_ERROR_OUT_OF_BOUNDS; goto fail; } } @@ -84,119 +89,113 @@ static int get_id_block_locations(sqfs_xattr_reader_t *xr, int sqfsfd, fail: free(xr->id_block_starts); xr->id_block_starts = NULL; - return -1; + return err; } -sqfs_xattr_entry_t *sqfs_xattr_reader_read_key(sqfs_xattr_reader_t *xr) +int sqfs_xattr_reader_read_key(sqfs_xattr_reader_t *xr, + sqfs_xattr_entry_t **key_out) { sqfs_xattr_entry_t key, *out; const char *prefix; size_t plen, total; + int ret; - if (sqfs_meta_reader_read(xr->kvrd, &key, sizeof(key))) - return NULL; + ret = sqfs_meta_reader_read(xr->kvrd, &key, sizeof(key)); + if (ret) + return ret; key.type = le16toh(key.type); key.size = le16toh(key.size); prefix = sqfs_get_xattr_prefix(key.type & SQFS_XATTR_PREFIX_MASK); - if (prefix == NULL) { - fprintf(stderr, "found unknown xattr type %u\n", - key.type & SQFS_XATTR_PREFIX_MASK); - return NULL; - } + if (prefix == NULL) + return SQFS_ERROR_UNSUPPORTED; plen = strlen(prefix); if (SZ_ADD_OV(plen, key.size, &total) || SZ_ADD_OV(total, 1, &total) || SZ_ADD_OV(sizeof(*out), total, &total)) { - errno = EOVERFLOW; - goto fail_alloc; + return SQFS_ERROR_OVERFLOW; } out = calloc(1, total); - if (out == NULL) { - goto fail_alloc; - } + if (out == NULL) + return SQFS_ERROR_ALLOC; *out = key; memcpy(out->key, prefix, plen); - if (sqfs_meta_reader_read(xr->kvrd, out->key + plen, key.size)) { + ret = sqfs_meta_reader_read(xr->kvrd, out->key + plen, key.size); + if (ret) { free(out); - return NULL; + return ret; } - return out; -fail_alloc: - perror("allocating xattr key"); - return NULL; + *key_out = out; + return 0; } -sqfs_xattr_value_t *sqfs_xattr_reader_read_value(sqfs_xattr_reader_t *xr, - const sqfs_xattr_entry_t *key) +int sqfs_xattr_reader_read_value(sqfs_xattr_reader_t *xr, + const sqfs_xattr_entry_t *key, + sqfs_xattr_value_t **val_out) { size_t offset, new_offset, size; sqfs_xattr_value_t value, *out; uint64_t ref, start, new_start; + int ret; - if (sqfs_meta_reader_read(xr->kvrd, &value, sizeof(value))) - return NULL; + ret = sqfs_meta_reader_read(xr->kvrd, &value, sizeof(value)); + if (ret) + return ret; if (key->type & SQFS_XATTR_FLAG_OOL) { - if (sqfs_meta_reader_read(xr->kvrd, &ref, sizeof(ref))) - return NULL; + ret = sqfs_meta_reader_read(xr->kvrd, &ref, sizeof(ref)); + if (ret) + return ret; sqfs_meta_reader_get_position(xr->kvrd, &start, &offset); new_start = xr->xattr_start + (ref >> 16); - new_offset = ref & 0xFFFF; - - if (new_start > xr->super->bytes_used) { - fputs("OOL xattr reference points past end of " - "filesystem\n", stderr); - return NULL; - } + if (new_start >= xr->super->bytes_used) + return SQFS_ERROR_OUT_OF_BOUNDS; - if (new_offset >= SQFS_META_BLOCK_SIZE) { - fputs("OOL xattr reference points outside " - "metadata block\n", stderr); - return NULL; - } + new_offset = ref & 0xFFFF; + if (new_offset >= SQFS_META_BLOCK_SIZE) + return SQFS_ERROR_OUT_OF_BOUNDS; - if (sqfs_meta_reader_seek(xr->kvrd, new_start, new_offset)) - return NULL; + ret = sqfs_meta_reader_seek(xr->kvrd, new_start, new_offset); + if (ret) + return ret; } value.size = le32toh(value.size); if (SZ_ADD_OV(sizeof(*out), value.size, &size) || SZ_ADD_OV(size, 1, &size)) { - errno = EOVERFLOW; - goto fail_alloc; + return SQFS_ERROR_OVERFLOW; } out = calloc(1, size); if (out == NULL) - goto fail_alloc; + return SQFS_ERROR_ALLOC; *out = value; - if (sqfs_meta_reader_read(xr->kvrd, out->value, value.size)) + ret = sqfs_meta_reader_read(xr->kvrd, out->value, value.size); + if (ret) goto fail; if (key->type & SQFS_XATTR_FLAG_OOL) { - if (sqfs_meta_reader_seek(xr->kvrd, start, offset)) + ret = sqfs_meta_reader_seek(xr->kvrd, start, offset); + if (ret) goto fail; } - return out; -fail_alloc: - perror("allocating xattr value"); - return NULL; + *val_out = out; + return 0; fail: free(out); - return NULL; + return ret; } int sqfs_xattr_reader_seek_kv(sqfs_xattr_reader_t *xr, @@ -212,38 +211,35 @@ int sqfs_xattr_reader_get_desc(sqfs_xattr_reader_t *xr, uint32_t idx, sqfs_xattr_id_t *desc) { size_t block, offset; + int ret; memset(desc, 0, sizeof(*desc)); if (idx == 0xFFFFFFFF) return 0; - if (xr->kvrd == NULL || xr->idrd == NULL) { - if (idx != 0) - goto fail_bounds; - return 0; - } + if (xr->kvrd == NULL || xr->idrd == NULL) + return idx == 0 ? 0 : SQFS_ERROR_OUT_OF_BOUNDS; if (idx >= xr->num_ids) - goto fail_bounds; + return SQFS_ERROR_OUT_OF_BOUNDS; offset = (idx * sizeof(*desc)) % SQFS_META_BLOCK_SIZE; block = (idx * sizeof(*desc)) / SQFS_META_BLOCK_SIZE; - if (sqfs_meta_reader_seek(xr->idrd, xr->id_block_starts[block], offset)) - return -1; + ret = sqfs_meta_reader_seek(xr->idrd, xr->id_block_starts[block], + offset); + if (ret) + return ret; - if (sqfs_meta_reader_read(xr->idrd, desc, sizeof(*desc))) - return -1; + ret = sqfs_meta_reader_read(xr->idrd, desc, sizeof(*desc)); + if (ret) + return ret; desc->xattr = le64toh(desc->xattr); desc->count = le32toh(desc->count); desc->size = le32toh(desc->size); return 0; -fail_bounds: - fprintf(stderr, "Tried to access out of bounds " - "xattr index: 0x%08X\n", idx); - return -1; } void sqfs_xattr_reader_destroy(sqfs_xattr_reader_t *xr) @@ -263,10 +259,8 @@ sqfs_xattr_reader_t *sqfs_xattr_reader_create(int sqfsfd, sqfs_super_t *super, { sqfs_xattr_reader_t *xr = calloc(1, sizeof(*xr)); - if (xr == NULL) { - perror("creating xattr reader"); + if (xr == NULL) return NULL; - } if (super->flags & SQFS_FLAG_NO_XATTRS) return xr; @@ -274,9 +268,6 @@ sqfs_xattr_reader_t *sqfs_xattr_reader_create(int sqfsfd, sqfs_super_t *super, if (super->xattr_id_table_start == 0xFFFFFFFFFFFFFFFF) return xr; - if (get_id_block_locations(xr, sqfsfd, super)) - goto fail; - xr->idrd = sqfs_meta_reader_create(sqfsfd, cmp, super->id_table_start, super->bytes_used); @@ -289,6 +280,7 @@ sqfs_xattr_reader_t *sqfs_xattr_reader_create(int sqfsfd, sqfs_super_t *super, if (xr->kvrd == NULL) goto fail; + xr->sqfsfd = sqfsfd; xr->super = super; return xr; fail: diff --git a/lib/sqfshelper/data_reader.c b/lib/sqfshelper/data_reader.c index f7984b8..fc92e28 100644 --- a/lib/sqfshelper/data_reader.c +++ b/lib/sqfshelper/data_reader.c @@ -109,6 +109,8 @@ data_reader_t *data_reader_create(int fd, sqfs_super_t *super, { data_reader_t *data = alloc_flex(sizeof(*data), super->block_size, 3); size_t i, size; + void *raw_frag; + int ret; if (data == NULL) { perror("creating data reader"); @@ -142,15 +144,17 @@ data_reader_t *data_reader_create(int fd, sqfs_super_t *super, return NULL; } - data->frag = sqfs_read_table(fd, cmp, size, - super->fragment_table_start, - super->directory_table_start, - super->fragment_table_start); - if (data->frag == NULL) { + ret = sqfs_read_table(fd, cmp, size, super->fragment_table_start, + super->directory_table_start, + super->fragment_table_start, &raw_frag); + + if (ret) { free(data); return NULL; } + data->frag = raw_frag; + for (i = 0; i < data->num_fragments; ++i) { data->frag[i].size = le32toh(data->frag[i].size); data->frag[i].start_offset = diff --git a/lib/sqfshelper/deserialize_fstree.c b/lib/sqfshelper/deserialize_fstree.c index a3cf44d..1953f9b 100644 --- a/lib/sqfshelper/deserialize_fstree.c +++ b/lib/sqfshelper/deserialize_fstree.c @@ -90,6 +90,7 @@ static int fill_dir(sqfs_meta_reader_t *ir, sqfs_meta_reader_t *dr, uint64_t block_start; size_t size, diff; uint32_t i; + int err; size = root->data.dir->size; if (size <= sizeof(hdr)) @@ -110,8 +111,7 @@ static int fill_dir(sqfs_meta_reader_t *ir, sqfs_meta_reader_t *dr, size -= sizeof(hdr); for (i = 0; i <= hdr.count && size > sizeof(*ent); ++i) { - ent = sqfs_meta_reader_read_dir_ent(dr); - if (ent == NULL) + if (sqfs_meta_reader_read_dir_ent(dr, &ent)) return -1; diff = sizeof(*ent) + strlen((char *)ent->name); @@ -126,12 +126,12 @@ static int fill_dir(sqfs_meta_reader_t *ir, sqfs_meta_reader_t *dr, continue; } - inode = sqfs_meta_reader_read_inode(ir, super, - hdr.start_block, - ent->offset); - if (inode == NULL) { + err = sqfs_meta_reader_read_inode(ir, super, + hdr.start_block, + ent->offset, &inode); + if (err) { free(ent); - return -1; + return err; } n = tree_node_from_inode(inode, idtbl, @@ -240,10 +240,12 @@ int deserialize_fstree(fstree_t *out, sqfs_super_t *super, if (xr == NULL) goto out_id; + if (sqfs_xattr_reader_load_locations(xr)) + goto out_xr; + block_start = super->root_inode_ref >> 16; offset = super->root_inode_ref & 0xFFFF; - root = sqfs_meta_reader_read_inode(ir, super, block_start, offset); - if (root == NULL) + if (sqfs_meta_reader_read_inode(ir, super, block_start, offset, &root)) goto out_xr; if (root->base.type != SQFS_INODE_DIR && diff --git a/lib/sqfshelper/xattr_reader.c b/lib/sqfshelper/xattr_reader.c index a0dc6f6..376fdb2 100644 --- a/lib/sqfshelper/xattr_reader.c +++ b/lib/sqfshelper/xattr_reader.c @@ -24,12 +24,10 @@ static int restore_kv_pairs(sqfs_xattr_reader_t *xr, fstree_t *fs, int ret; for (i = 0; i < node->xattr->num_attr; ++i) { - key = sqfs_xattr_reader_read_key(xr); - if (key == NULL) + if (sqfs_xattr_reader_read_key(xr, &key)) return -1; - val = sqfs_xattr_reader_read_value(xr, key); - if (val == NULL) + if (sqfs_xattr_reader_read_value(xr, key, &val)) goto fail_key; ret = str_table_get_index(&fs->xattr_keys, -- cgit v1.2.3