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/io/src/get_line.c | 27 ++++++----- lib/io/src/unix/istream.c | 65 ++++++++++++------------- lib/io/src/unix/ostream.c | 110 +++++++++++++++++++++--------------------- lib/io/src/win32/istream.c | 59 ++++++++++++----------- lib/io/src/win32/ostream.c | 116 +++++++++++++++++++++------------------------ lib/io/src/xfrm/istream.c | 8 ++-- lib/io/src/xfrm/ostream.c | 33 +++++++------ 7 files changed, 209 insertions(+), 209 deletions(-) (limited to 'lib/io/src') diff --git a/lib/io/src/get_line.c b/lib/io/src/get_line.c index ad37be6..3178592 100644 --- a/lib/io/src/get_line.c +++ b/lib/io/src/get_line.c @@ -6,6 +6,7 @@ */ #include "internal.h" #include "sqfs/io.h" +#include "sqfs/error.h" static void ltrim(char *buffer) { @@ -44,17 +45,17 @@ int istream_get_line(sqfs_istream_t *strm, char **out, { char *line = NULL, *new; size_t line_len = 0; + int err; for (;;) { bool have_line = false; size_t i, count, avail; const sqfs_u8 *ptr; - int ret; - ret = strm->get_buffered_data(strm, &ptr, &avail, 0); - if (ret < 0) - goto fail_free; - if (ret > 0) { + err = strm->get_buffered_data(strm, &ptr, &avail, 0); + if (err < 0) + goto fail; + if (err > 0) { if (line_len == 0) goto out_eof; @@ -78,8 +79,10 @@ int istream_get_line(sqfs_istream_t *strm, char **out, } new = realloc(line, line_len + count + 1); - if (new == NULL) - goto fail_errno; + if (new == NULL) { + err = SQFS_ERROR_ALLOC; + goto fail; + } line = new; memcpy(line + line_len, ptr, count); @@ -108,13 +111,13 @@ int istream_get_line(sqfs_istream_t *strm, char **out, *out = line; return 0; -fail_errno: - fprintf(stderr, "%s: " PRI_SZ ": %s.\n", strm->get_filename(strm), - *line_num, strerror(errno)); -fail_free: +fail: { + int temp = errno; free(line); *out = NULL; - return -1; + errno = temp; + return err; +} out_eof: free(line); *out = NULL; diff --git a/lib/io/src/unix/istream.c b/lib/io/src/unix/istream.c index ca9a183..5005a69 100644 --- a/lib/io/src/unix/istream.c +++ b/lib/io/src/unix/istream.c @@ -6,6 +6,7 @@ */ #include "../internal.h" #include "sqfs/io.h" +#include "sqfs/error.h" typedef struct { sqfs_istream_t base; @@ -46,9 +47,7 @@ static int precache(sqfs_istream_t *strm) if (ret < 0) { if (errno == EINTR) continue; - - perror(file->path); - return -1; + return SQFS_ERROR_IO; } file->buffer_used += ret; @@ -90,76 +89,72 @@ static void file_advance_buffer(sqfs_istream_t *strm, size_t count) static const char *file_get_filename(sqfs_istream_t *strm) { - file_istream_t *file = (file_istream_t *)strm; - - return file->path; + return ((file_istream_t *)strm)->path; } static void file_destroy(sqfs_object_t *obj) { file_istream_t *file = (file_istream_t *)obj; - if (file->fd != STDIN_FILENO) - close(file->fd); - + close(file->fd); free(file->path); free(file); } -sqfs_istream_t *istream_open_handle(const char *path, int fd) +int istream_open_handle(sqfs_istream_t **out, const char *path, + sqfs_file_handle_t fd) { file_istream_t *file = calloc(1, sizeof(*file)); sqfs_istream_t *strm = (sqfs_istream_t *)file; - if (file == NULL) { - perror(path); - return NULL; - } + if (file == NULL) + return SQFS_ERROR_ALLOC; sqfs_object_init(file, file_destroy, NULL); file->path = strdup(path); if (file->path == NULL) { - perror(path); - goto fail_free; + int temp = errno; + free(file); + errno = temp; + return SQFS_ERROR_ALLOC; } file->fd = dup(fd); if (file->fd < 0) { - perror(path); - goto fail_path; + int temp = errno; + free(file->path); + free(file); + errno = temp; + return SQFS_ERROR_IO; } close(fd); strm->get_buffered_data = file_get_buffered_data; strm->advance_buffer = file_advance_buffer; strm->get_filename = file_get_filename; - return strm; -fail_path: - free(file->path); -fail_free: - free(file); - return NULL; + + *out = strm; + return 0; } -sqfs_istream_t *istream_open_file(const char *path) +int istream_open_file(sqfs_istream_t **out, const char *path) { sqfs_file_handle_t fd; - sqfs_istream_t *out; + int ret; - if (sqfs_open_native_file(&fd, path, SQFS_FILE_OPEN_READ_ONLY)) { - perror(path); - return NULL; - } + ret = sqfs_open_native_file(&fd, path, SQFS_FILE_OPEN_READ_ONLY); + if (ret) + return ret; - out = istream_open_handle(path, fd); - if (out == NULL) + ret = istream_open_handle(out, path, fd); + if (ret != 0) close(fd); - return out; + return ret; } -sqfs_istream_t *istream_open_stdin(void) +int istream_open_stdin(sqfs_istream_t **out) { - return istream_open_handle("stdin", STDIN_FILENO); + return istream_open_handle(out, "stdin", STDIN_FILENO); } diff --git a/lib/io/src/unix/ostream.c b/lib/io/src/unix/ostream.c index 52a566a..a97d8f3 100644 --- a/lib/io/src/unix/ostream.c +++ b/lib/io/src/unix/ostream.c @@ -6,6 +6,7 @@ */ #include "../internal.h" #include "sqfs/io.h" +#include "sqfs/error.h" typedef struct { sqfs_ostream_t base; @@ -23,15 +24,14 @@ static int write_all(file_ostream_t *file, const sqfs_u8 *data, size_t size) ssize_t ret = write(file->fd, data, size); if (ret == 0) { - fprintf(stderr, "%s: truncated write.\n", file->path); - return -1; + errno = EPIPE; + return SQFS_ERROR_IO; } if (ret < 0) { if (errno == EINTR) continue; - perror(file->path); - return -1; + return SQFS_ERROR_IO; } file->size += ret; @@ -46,6 +46,7 @@ static int realize_sparse(file_ostream_t *file) { unsigned char *buffer; size_t diff, bufsz; + int ret; if (file->sparse_count == 0) return 0; @@ -54,15 +55,18 @@ static int realize_sparse(file_ostream_t *file) bufsz = file->sparse_count > 1024 ? 1024 : file->sparse_count; buffer = calloc(1, bufsz); if (buffer == NULL) - goto fail; + return SQFS_ERROR_ALLOC; while (file->sparse_count > 0) { diff = file->sparse_count > (off_t)bufsz ? bufsz : (size_t)file->sparse_count; - if (write_all(file, buffer, diff)) { + ret = write_all(file, buffer, diff); + if (ret) { + int temp = errno; free(buffer); - return -1; + errno = temp; + return ret; } file->sparse_count -= diff; @@ -71,35 +75,31 @@ static int realize_sparse(file_ostream_t *file) free(buffer); } else { if (lseek(file->fd, file->sparse_count, SEEK_CUR) == (off_t)-1) - goto fail; + return SQFS_ERROR_IO; if (ftruncate(file->fd, file->size) != 0) - goto fail; + return SQFS_ERROR_IO; file->sparse_count = 0; } return 0; -fail: - perror(file->path); - return -1; } static int file_append(sqfs_ostream_t *strm, const void *data, size_t size) { file_ostream_t *file = (file_ostream_t *)strm; + int ret; - if (size == 0) - return 0; - - if (data == NULL) { + if (size == 0 || data == NULL) { file->sparse_count += size; file->size += size; return 0; } - if (realize_sparse(file)) - return -1; + ret = realize_sparse(file); + if (ret) + return ret; return write_all(file, data, size); } @@ -107,15 +107,15 @@ static int file_append(sqfs_ostream_t *strm, const void *data, size_t size) static int file_flush(sqfs_ostream_t *strm) { file_ostream_t *file = (file_ostream_t *)strm; + int ret; - if (realize_sparse(file)) - return -1; + ret = realize_sparse(file); + if (ret) + return ret; if (fsync(file->fd) != 0) { - if (errno == EINVAL) - return 0; - perror(file->path); - return -1; + if (errno != EINVAL) + return SQFS_ERROR_IO; } return 0; @@ -132,33 +132,36 @@ static void file_destroy(sqfs_object_t *obj) static const char *file_get_filename(sqfs_ostream_t *strm) { - file_ostream_t *file = (file_ostream_t *)strm; - - return file->path; + return ((file_ostream_t *)strm)->path; } -sqfs_ostream_t *ostream_open_handle(const char *path, int fd, int flags) +int ostream_open_handle(sqfs_ostream_t **out, const char *path, + sqfs_file_handle_t fd, int flags) { file_ostream_t *file = calloc(1, sizeof(*file)); sqfs_ostream_t *strm = (sqfs_ostream_t *)file; - if (file == NULL) { - perror(path); - return NULL; - } + *out = NULL; + if (file == NULL) + return SQFS_ERROR_ALLOC; sqfs_object_init(file, file_destroy, NULL); file->path = strdup(path); if (file->path == NULL) { - perror(path); - goto fail_free; + int temp = errno; + free(file); + errno = temp; + return SQFS_ERROR_ALLOC; } file->fd = dup(fd); if (file->fd < 0) { - perror(path); - goto fail_path; + int temp = errno; + free(file->path); + free(file); + errno = temp; + return SQFS_ERROR_IO; } close(fd); @@ -167,33 +170,34 @@ sqfs_ostream_t *ostream_open_handle(const char *path, int fd, int flags) strm->append = file_append; strm->flush = file_flush; strm->get_filename = file_get_filename; - return strm; -fail_path: - free(file->path); -fail_free: - free(file); - return NULL; + + *out = strm; + return 0; } -sqfs_ostream_t *ostream_open_file(const char *path, int flags) +int ostream_open_file(sqfs_ostream_t **out, const char *path, int flags) { sqfs_file_handle_t fd; - sqfs_ostream_t *out; + int ret; - if (sqfs_open_native_file(&fd, path, flags)) { - perror(path); - return NULL; - } + *out = NULL; + ret = sqfs_open_native_file(&fd, path, flags); + if (ret) + return ret; - out = ostream_open_handle(path, fd, flags); - if (out == NULL) + ret = ostream_open_handle(out, path, fd, flags); + if (ret) { + int temp = errno; close(fd); + errno = temp; + return ret; + } - return out; + return 0; } -sqfs_ostream_t *ostream_open_stdout(void) +int ostream_open_stdout(sqfs_ostream_t **out) { - return ostream_open_handle("stdout", STDOUT_FILENO, + return ostream_open_handle(out, "stdout", STDOUT_FILENO, SQFS_FILE_OPEN_NO_SPARSE); } diff --git a/lib/io/src/win32/istream.c b/lib/io/src/win32/istream.c index 7cc7144..1a4f4db 100644 --- a/lib/io/src/win32/istream.c +++ b/lib/io/src/win32/istream.c @@ -6,6 +6,7 @@ */ #include "../internal.h" #include "sqfs/io.h" +#include "sqfs/error.h" #define WIN32_LEAN_AND_MEAN #include @@ -52,8 +53,7 @@ static int precache(sqfs_istream_t *strm) } SetLastError(error); - w32_perror(file->path); - return -1; + return SQFS_ERROR_IO; } if (actual == 0) { @@ -112,31 +112,34 @@ static void file_destroy(sqfs_object_t *obj) free(file); } -sqfs_istream_t *istream_open_handle(const char *path, HANDLE hnd) +int istream_open_handle(sqfs_istream_t **out, const char *path, HANDLE hnd) { file_istream_t *file = calloc(1, sizeof(*file)); sqfs_istream_t *strm = (sqfs_istream_t *)file; BOOL ret; - if (file == NULL) { - perror(path); - return NULL; - } + if (file == NULL) + return SQFS_ERROR_ALLOC; sqfs_object_init(file, file_destroy, NULL); file->path = strdup(path); if (file->path == NULL) { - perror(path); - goto fail_free; + DWORD temp = GetLastError(); + free(file); + SetLastError(temp); + return SQFS_ERROR_ALLOC; } ret = DuplicateHandle(GetCurrentProcess(), hnd, GetCurrentProcess(), &file->hnd, 0, FALSE, DUPLICATE_SAME_ACCESS); if (!ret) { - w32_perror(path); - goto fail_path; + DWORD temp = GetLastError(); + free(file->path); + free(file); + SetLastError(temp); + return SQFS_ERROR_IO; } CloseHandle(hnd); @@ -144,34 +147,34 @@ sqfs_istream_t *istream_open_handle(const char *path, HANDLE hnd) strm->get_buffered_data = file_get_buffered_data; strm->advance_buffer = file_advance_buffer; strm->get_filename = file_get_filename; - return strm; -fail_path: - free(file->path); -fail_free: - free(file); - return NULL; + + *out = strm; + return 0; } -sqfs_istream_t *istream_open_file(const char *path) +int istream_open_file(sqfs_istream_t **out, const char *path) { sqfs_file_handle_t hnd; - sqfs_istream_t *out; + int ret; - if (sqfs_open_native_file(&hnd, path, SQFS_FILE_OPEN_READ_ONLY)) { - w32_perror(path); - return NULL; - } + ret = sqfs_open_native_file(&hnd, path, SQFS_FILE_OPEN_READ_ONLY); + if (ret) + return ret; - out = istream_open_handle(path, hnd); - if (out == NULL) + ret = istream_open_handle(out, path, hnd); + if (ret) { + DWORD temp = GetLastError(); CloseHandle(hnd); + SetLastError(temp); + return ret; + } - return out; + return 0; } -sqfs_istream_t *istream_open_stdin(void) +int istream_open_stdin(sqfs_istream_t **out) { HANDLE hnd = GetStdHandle(STD_INPUT_HANDLE); - return istream_open_handle("stdin", hnd); + return istream_open_handle(out, "stdin", hnd); } diff --git a/lib/io/src/win32/ostream.c b/lib/io/src/win32/ostream.c index 5b584e5..b2ba599 100644 --- a/lib/io/src/win32/ostream.c +++ b/lib/io/src/win32/ostream.c @@ -6,6 +6,7 @@ */ #include "../internal.h" #include "sqfs/io.h" +#include "sqfs/error.h" #define WIN32_LEAN_AND_MEAN #include @@ -23,10 +24,8 @@ static int write_data(file_ostream_t *file, const void *data, size_t size) DWORD diff; while (size > 0) { - if (!WriteFile(file->hnd, data, size, &diff, NULL)) { - w32_perror(file->path); - return -1; - } + if (!WriteFile(file->hnd, data, size, &diff, NULL)) + return SQFS_ERROR_IO; size -= diff; data = (const char *)data + diff; @@ -40,6 +39,7 @@ static int realize_sparse(file_ostream_t *file) size_t bufsz, diff; LARGE_INTEGER pos; void *buffer; + int ret; if (file->sparse_count == 0) return 0; @@ -48,18 +48,19 @@ static int realize_sparse(file_ostream_t *file) bufsz = file->sparse_count > 1024 ? 1024 : file->sparse_count; buffer = calloc(1, bufsz); - if (buffer == NULL) { - fputs("out-of-memory\n", stderr); - return -1; - } + if (buffer == NULL) + return SQFS_ERROR_ALLOC; while (file->sparse_count > 0) { diff = file->sparse_count > bufsz ? bufsz : file->sparse_count; - if (write_data(file, buffer, diff)) { + ret = write_data(file, buffer, diff); + if (ret) { + DWORD temp = GetLastError(); free(buffer); - return -1; + SetLastError(temp); + return ret; } file->sparse_count -= diff; @@ -70,34 +71,30 @@ static int realize_sparse(file_ostream_t *file) pos.QuadPart = file->sparse_count; if (!SetFilePointerEx(file->hnd, pos, NULL, FILE_CURRENT)) - goto fail; + return SQFS_ERROR_IO; if (!SetEndOfFile(file->hnd)) - goto fail; + return SQFS_ERROR_IO; file->sparse_count = 0; } return 0; -fail: - w32_perror(file->path); - return -1; } static int file_append(sqfs_ostream_t *strm, const void *data, size_t size) { file_ostream_t *file = (file_ostream_t *)strm; + int ret; - if (size == 0) - return 0; - - if (data == NULL) { + if (size == 0 || data == NULL) { file->sparse_count += size; return 0; } - if (realize_sparse(file)) - return -1; + ret = realize_sparse(file); + if (ret) + return ret; return write_data(file, data, size); } @@ -105,14 +102,14 @@ static int file_append(sqfs_ostream_t *strm, const void *data, size_t size) static int file_flush(sqfs_ostream_t *strm) { file_ostream_t *file = (file_ostream_t *)strm; + int ret; - if (realize_sparse(file)) - return -1; + ret = realize_sparse(file); + if (ret) + return ret; - if (!FlushFileBuffers(file->hnd)) { - w32_perror(file->path); - return -1; - } + if (!FlushFileBuffers(file->hnd)) + return SQFS_ERROR_IO; return 0; } @@ -128,36 +125,36 @@ static void file_destroy(sqfs_object_t *obj) static const char *file_get_filename(sqfs_ostream_t *strm) { - file_ostream_t *file = (file_ostream_t *)strm; - - return file->path; + return ((file_ostream_t *)strm)->path; } -sqfs_ostream_t *ostream_open_handle(const char *path, HANDLE hnd, int flags) +int ostream_open_handle(sqfs_ostream_t **out, const char *path, + sqfs_file_handle_t hnd, int flags) { file_ostream_t *file = calloc(1, sizeof(*file)); sqfs_ostream_t *strm = (sqfs_ostream_t *)file; BOOL ret; - if (file == NULL) { - perror(path); - return NULL; - } + if (file == NULL) + return SQFS_ERROR_ALLOC; sqfs_object_init(file, file_destroy, NULL); file->path = strdup(path); if (file->path == NULL) { - perror(path); - goto fail_free; + free(file); + return SQFS_ERROR_ALLOC; } ret = DuplicateHandle(GetCurrentProcess(), hnd, GetCurrentProcess(), &file->hnd, 0, FALSE, DUPLICATE_SAME_ACCESS); if (!ret) { - w32_perror(path); - goto fail_path; + DWORD temp = GetLastError(); + free(file->path); + free(file); + SetLastError(temp); + return SQFS_ERROR_IO; } CloseHandle(hnd); @@ -166,39 +163,36 @@ sqfs_ostream_t *ostream_open_handle(const char *path, HANDLE hnd, int flags) strm->append = file_append; strm->flush = file_flush; strm->get_filename = file_get_filename; - return strm; -fail_path: - free(file->path); -fail_free: - free(file); - return NULL; + + *out = strm; + return 0; } -sqfs_ostream_t *ostream_open_file(const char *path, int flags) +int ostream_open_file(sqfs_ostream_t **out, const char *path, int flags) { sqfs_file_handle_t hnd; - sqfs_ostream_t *out; - - if (sqfs_open_native_file(&hnd, path, flags)) { - w32_perror(path); - return NULL; - } + int ret; - if (hnd == INVALID_HANDLE_VALUE) { - w32_perror(path); - return NULL; - } + *out = NULL; + ret = sqfs_open_native_file(&hnd, path, flags); + if (ret) + return ret; - out = ostream_open_handle(path, hnd, flags); - if (out == NULL) + ret = ostream_open_handle(out, path, hnd, flags); + if (ret) { + DWORD temp = GetLastError(); CloseHandle(hnd); + SetLastError(temp); + return SQFS_ERROR_IO; + } - return out; + return 0; } -sqfs_ostream_t *ostream_open_stdout(void) +int ostream_open_stdout(sqfs_ostream_t **out) { HANDLE hnd = GetStdHandle(STD_OUTPUT_HANDLE); - return ostream_open_handle("stdout", hnd, SQFS_FILE_OPEN_NO_SPARSE); + return ostream_open_handle(out, "stdout", hnd, + SQFS_FILE_OPEN_NO_SPARSE); } diff --git a/lib/io/src/xfrm/istream.c b/lib/io/src/xfrm/istream.c index c499f6c..ee4b5bd 100644 --- a/lib/io/src/xfrm/istream.c +++ b/lib/io/src/xfrm/istream.c @@ -6,6 +6,7 @@ */ #include "../internal.h" #include "sqfs/io.h" +#include "sqfs/error.h" typedef struct istream_xfrm_t { sqfs_istream_t base; @@ -52,11 +53,8 @@ static int precache(sqfs_istream_t *base) BUFSZ - out_off, &in_off, &out_off, mode); - if (ret == XFRM_STREAM_ERROR) { - fprintf(stderr, "%s: internal error in decompressor.\n", - base->get_filename(base)); - return -1; - } + if (ret == XFRM_STREAM_ERROR) + return SQFS_ERROR_COMPRESSOR; xfrm->buffer_used = out_off; xfrm->wrapped->advance_buffer(xfrm->wrapped, in_off); diff --git a/lib/io/src/xfrm/ostream.c b/lib/io/src/xfrm/ostream.c index 4c77f42..c035f2a 100644 --- a/lib/io/src/xfrm/ostream.c +++ b/lib/io/src/xfrm/ostream.c @@ -6,6 +6,7 @@ */ #include "../internal.h" #include "sqfs/io.h" +#include "sqfs/error.h" typedef struct ostream_xfrm_t { sqfs_ostream_t base; @@ -26,7 +27,7 @@ static int flush_inbuf(ostream_xfrm_t *xfrm, bool finish) const int mode = finish ? XFRM_STREAM_FLUSH_FULL : XFRM_STREAM_FLUSH_NONE; sqfs_u32 off_in = 0, off_out = 0; - int ret; + int ret, ioret; while (finish || off_in < avail_in) { ret = xfrm->xfrm->process_data(xfrm->xfrm, @@ -36,15 +37,13 @@ static int flush_inbuf(ostream_xfrm_t *xfrm, bool finish) avail_out - off_out, &off_in, &off_out, mode); - if (ret == XFRM_STREAM_ERROR) { - fprintf(stderr, - "%s: internal error in compressor.\n", - xfrm->wrapped->get_filename(xfrm->wrapped)); - return -1; - } + if (ret == XFRM_STREAM_ERROR) + return SQFS_ERROR_COMPRESSOR; - if (xfrm->wrapped->append(xfrm->wrapped, xfrm->outbuf, off_out)) - return -1; + ioret = xfrm->wrapped->append(xfrm->wrapped, + xfrm->outbuf, off_out); + if (ioret) + return ioret; off_out = 0; @@ -53,8 +52,10 @@ static int flush_inbuf(ostream_xfrm_t *xfrm, bool finish) } if (off_out > 0) { - if (xfrm->wrapped->append(xfrm->wrapped, xfrm->outbuf, off_out)) - return -1; + ret = xfrm->wrapped->append(xfrm->wrapped, + xfrm->outbuf, off_out); + if (ret) + return ret; } if (off_in < avail_in) { @@ -74,8 +75,9 @@ static int xfrm_append(sqfs_ostream_t *strm, const void *data, size_t size) while (size > 0) { if (xfrm->inbuf_used >= BUFSZ) { - if (flush_inbuf(xfrm, false)) - return -1; + int ret = flush_inbuf(xfrm, false); + if (ret) + return ret; } diff = BUFSZ - xfrm->inbuf_used; @@ -102,8 +104,9 @@ static int xfrm_flush(sqfs_ostream_t *strm) ostream_xfrm_t *xfrm = (ostream_xfrm_t *)strm; if (xfrm->inbuf_used > 0) { - if (flush_inbuf(xfrm, true)) - return -1; + int ret = flush_inbuf(xfrm, true); + if (ret) + return ret; } return xfrm->wrapped->flush(xfrm->wrapped); -- cgit v1.2.3