diff --git a/tools/include/sqshtools_common.h b/tools/include/sqshtools_common.h index faf29379..b7bbfcb3 100644 --- a/tools/include/sqshtools_common.h +++ b/tools/include/sqshtools_common.h @@ -54,4 +54,17 @@ void print_raw(const char *segment, size_t segment_size); void print_escaped(const char *segment, size_t segment_size); +void locked_perror(const char *msg); + +void locked_sqsh_perror(int error_code, const char *msg); + +void locked_perror(const char *msg); + +__attribute__((__format__(__printf__, 2, 0))) void +locked_fprintf(FILE *stream, const char *format, ...); + +void locked_fputs(const char *s, FILE *stream); + +int locked_fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream); + #endif /* TOOLS_COMMON_H */ diff --git a/tools/src/common.c b/tools/src/common.c index c1cbd799..44f52f59 100644 --- a/tools/src/common.c +++ b/tools/src/common.c @@ -32,7 +32,52 @@ * @created Wednesday Jun 07, 2023 15:41:30 CEST */ +#include "sqsh_error.h" +#include #include +#include + +pthread_mutex_t output_lock = PTHREAD_MUTEX_INITIALIZER; + +void +locked_perror(const char *msg) { + pthread_mutex_lock(&output_lock); + perror(msg); + pthread_mutex_unlock(&output_lock); +} + +void +locked_fprintf(FILE *stream, const char *format, ...) { + va_list args; + va_start(args, format); + pthread_mutex_lock(&output_lock); + vfprintf(stream, format, args); + pthread_mutex_unlock(&output_lock); + va_end(args); +} + +void +locked_fputs(const char *s, FILE *stream) { + pthread_mutex_lock(&output_lock); + fputs(s, stream); + pthread_mutex_unlock(&output_lock); +} + +int +locked_fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) { + int ret; + pthread_mutex_lock(&output_lock); + ret = fwrite(ptr, size, nmemb, stream); + pthread_mutex_unlock(&output_lock); + return ret; +} + +void +locked_sqsh_perror(int error_code, const char *msg) { + pthread_mutex_lock(&output_lock); + sqsh_perror(error_code, msg); + pthread_mutex_unlock(&output_lock); +} struct SqshArchive * open_archive(const char *image_path, uint64_t offset, int *err) { @@ -55,7 +100,7 @@ open_archive(const char *image_path, uint64_t offset, int *err) { void print_raw(const char *segment, size_t segment_size) { - fwrite(segment, 1, segment_size, stdout); + locked_fwrite(segment, 1, segment_size, stdout); } void @@ -63,19 +108,19 @@ print_escaped(const char *segment, size_t segment_size) { for (size_t i = 0; i < segment_size; i++) { switch (segment[i]) { case '\n': - fputs("\\n", stdout); + locked_fputs("\\n", stdout); break; case '\r': - fputs("\\r", stdout); + locked_fputs("\\r", stdout); break; case '\t': - fputs("\\t", stdout); + locked_fputs("\\t", stdout); break; case '\\': - fputs("\\\\", stdout); + locked_fputs("\\\\", stdout); break; case '\x1b': - fputs("\\e", stdout); + locked_fputs("\\e", stdout); break; case 0x01: case 0x02: @@ -106,10 +151,10 @@ print_escaped(const char *segment, size_t segment_size) { case 0x1f: case 0x20: case 0x7f: - printf("\\x%02x", segment[i]); + locked_fprintf(stdout, "\\x%02x", segment[i]); break; default: - putchar(segment[i]); + locked_fputs((char[2]){segment[i], 0}, stdout); break; } } diff --git a/tools/src/unpack.c b/tools/src/unpack.c index 693323a9..d057cd93 100644 --- a/tools/src/unpack.c +++ b/tools/src/unpack.c @@ -37,7 +37,6 @@ #include #include #include -#include #include #include #include @@ -88,14 +87,14 @@ update_metadata(const char *path, const struct SqshFile *file) { times[0].tv_sec = times[1].tv_sec = sqsh_file_modified_time(file); rv = utimensat(AT_FDCWD, path, times, AT_SYMLINK_NOFOLLOW); if (rv < 0) { - perror(path); + locked_perror(path); goto out; } uint16_t mode = sqsh_file_permission(file); rv = fchmodat(AT_FDCWD, path, mode, AT_SYMLINK_NOFOLLOW); if (rv < 0) { - perror(path); + locked_perror(path); goto out; } @@ -105,7 +104,7 @@ update_metadata(const char *path, const struct SqshFile *file) { rv = chown(path, uid, gid); if (rv < 0) { - perror(path); + locked_perror(path); goto out; } } @@ -122,17 +121,17 @@ extract_dir(const char *path) { struct stat st; rv = stat(path, &st); if (rv < 0) { - perror(path); + locked_perror(path); goto out; } if (!S_ISDIR(st.st_mode)) { errno = EEXIST; - perror(path); + locked_perror(path); goto out; } } else if (rv < 0) { - perror(path); + locked_perror(path); goto out; } @@ -147,7 +146,7 @@ update_metadata_dir(const char *path, const struct SqshFile *file) { int rv = 0; rv = chmod(path, sqsh_file_permission(file)); if (rv < 0) { - perror(path); + locked_perror(path); goto out; } @@ -180,7 +179,7 @@ extract_file_after( int rv = 0; struct ExtractFileData *data = d; if (err < 0) { - sqsh_perror(err, data->path); + locked_sqsh_perror(err, data->path); } rv = rename(data->tmp_filename, data->path); @@ -194,7 +193,7 @@ extract_file_after( out: cx_semaphore_post(&file_descriptor_sem); if (rv < 0) { - sqsh_perror(rv, data->path); + locked_sqsh_perror(rv, data->path); } extract_file_cleanup(data, NULL); } @@ -261,7 +260,7 @@ extract_file(const char *path, const struct SqshFile *file) { } out: if (rv < 0) { - sqsh_perror(rv, path); + locked_sqsh_perror(rv, path); extract_file_cleanup(data, stream); if (fd > 0) { close(fd); @@ -389,7 +388,7 @@ extract_from_traversal( } else { file = sqsh_tree_traversal_open_file(iter, &rv); if (rv < 0) { - sqsh_perror(rv, path); + locked_sqsh_perror(rv, path); goto out; } @@ -423,14 +422,14 @@ extract_all( iter = sqsh_tree_traversal_new(base, &rv); if (rv < 0) { - sqsh_perror(rv, image_path); + locked_sqsh_perror(rv, image_path); goto out; } bool has_next = sqsh_tree_traversal_next(iter, &rv); if (!has_next) { rv = -SQSH_ERROR_INTERNAL; - sqsh_perror(rv, image_path); + locked_sqsh_perror(rv, image_path); goto out; } @@ -441,7 +440,7 @@ extract_all( } } if (rv < 0) { - sqsh_perror(rv, image_path); + locked_sqsh_perror(rv, image_path); goto out; } @@ -505,7 +504,7 @@ main(int argc, char *argv[]) { sqsh = open_archive(image_path, offset, &rv); if (rv < 0) { - sqsh_perror(rv, image_path); + locked_sqsh_perror(rv, image_path); rv = EXIT_FAILURE; goto out; } @@ -528,7 +527,7 @@ main(int argc, char *argv[]) { src_root = sqsh_lopen(sqsh, src_path, &rv); if (rv < 0) { - sqsh_perror(rv, src_path); + locked_sqsh_perror(rv, src_path); rv = EXIT_FAILURE; goto out; }