diff options
-rw-r--r-- | bin/rdsquashfs/Makemodule.am | 2 | ||||
-rw-r--r-- | bin/rdsquashfs/fill_files.c | 30 | ||||
-rw-r--r-- | bin/rdsquashfs/rdsquashfs.c | 14 | ||||
-rw-r--r-- | bin/sqfs2tar/Makemodule.am | 5 | ||||
-rw-r--r-- | bin/sqfs2tar/sqfs2tar.c | 21 | ||||
-rw-r--r-- | bin/sqfs2tar/sqfs2tar.h | 2 | ||||
-rw-r--r-- | bin/sqfs2tar/write_tree.c | 2 | ||||
-rw-r--r-- | bin/sqfsdiff/Makemodule.am | 4 | ||||
-rw-r--r-- | bin/sqfsdiff/extract.c | 13 | ||||
-rw-r--r-- | include/common.h | 3 | ||||
-rw-r--r-- | include/tar.h | 15 | ||||
-rw-r--r-- | lib/common/data_reader_dump.c | 57 | ||||
-rw-r--r-- | lib/tar/Makemodule.am | 3 | ||||
-rw-r--r-- | lib/tar/padd_file.c | 6 | ||||
-rw-r--r-- | lib/tar/write_header.c | 30 | ||||
-rw-r--r-- | lib/tar/write_retry.c | 35 |
16 files changed, 86 insertions, 156 deletions
diff --git a/bin/rdsquashfs/Makemodule.am b/bin/rdsquashfs/Makemodule.am index e4f3b96..094771c 100644 --- a/bin/rdsquashfs/Makemodule.am +++ b/bin/rdsquashfs/Makemodule.am @@ -4,7 +4,7 @@ rdsquashfs_SOURCES += bin/rdsquashfs/restore_fstree.c bin/rdsquashfs/describe.c rdsquashfs_SOURCES += bin/rdsquashfs/fill_files.c bin/rdsquashfs/dump_xattrs.c rdsquashfs_SOURCES += bin/rdsquashfs/stat.c rdsquashfs_CFLAGS = $(AM_CFLAGS) $(PTHREAD_CFLAGS) -rdsquashfs_LDADD = libcommon.a libcompat.a libsquashfs.la +rdsquashfs_LDADD = libcommon.a libfstream.a libcompat.a libsquashfs.la rdsquashfs_LDADD += libfstree.a $(LZO_LIBS) $(PTHREAD_LIBS) dist_man1_MANS += bin/rdsquashfs/rdsquashfs.1 diff --git a/bin/rdsquashfs/fill_files.c b/bin/rdsquashfs/fill_files.c index b75afbf..63ad640 100644 --- a/bin/rdsquashfs/fill_files.c +++ b/bin/rdsquashfs/fill_files.c @@ -135,29 +135,31 @@ static int gen_file_list_dfs(const sqfs_tree_node_t *n) static int fill_files(sqfs_data_reader_t *data, int flags) { + int ret, openflags; + ostream_t *fp; size_t i; - FILE *fp; + + openflags = OSTREAM_OPEN_OVERWRITE; + + if (flags & UNPACK_NO_SPARSE) + openflags |= OSTREAM_OPEN_SPARSE; for (i = 0; i < num_files; ++i) { - fp = fopen(files[i].path, "wb"); - if (fp == NULL) { - fprintf(stderr, "unpacking %s: %s\n", - files[i].path, strerror(errno)); + fp = ostream_open_file(files[i].path, openflags); + if (fp == NULL) return -1; - } if (!(flags & UNPACK_QUIET)) printf("unpacking %s\n", files[i].path); - if (sqfs_data_reader_dump(files[i].path, data, files[i].inode, - fp, block_size, - (flags & UNPACK_NO_SPARSE) == 0)) { - fclose(fp); - return -1; - } + ret = sqfs_data_reader_dump(files[i].path, data, files[i].inode, + fp, block_size); + if (ret == 0) + ret = ostream_flush(fp); - fflush(fp); - fclose(fp); + sqfs_destroy(fp); + if (ret) + return -1; } return 0; diff --git a/bin/rdsquashfs/rdsquashfs.c b/bin/rdsquashfs/rdsquashfs.c index 1c11afa..5b6ce19 100644 --- a/bin/rdsquashfs/rdsquashfs.c +++ b/bin/rdsquashfs/rdsquashfs.c @@ -115,18 +115,28 @@ int main(int argc, char **argv) if (stat_file(n)) goto out; break; - case OP_CAT: + case OP_CAT: { + ostream_t *fp; + if (!S_ISREG(n->inode->base.mode)) { fprintf(stderr, "/%s: not a regular file\n", opt.cmdpath); goto out; } + fp = ostream_open_stdout(); + if (fp == NULL) + goto out; + if (sqfs_data_reader_dump(opt.cmdpath, data, n->inode, - stdout, super.block_size, false)) { + fp, super.block_size)) { + sqfs_destroy(fp); goto out; } + + sqfs_destroy(fp); break; + } case OP_UNPACK: if (opt.unpack_root != NULL) { if (mkdir_p(opt.unpack_root)) diff --git a/bin/sqfs2tar/Makemodule.am b/bin/sqfs2tar/Makemodule.am index f8d95cc..cd00508 100644 --- a/bin/sqfs2tar/Makemodule.am +++ b/bin/sqfs2tar/Makemodule.am @@ -2,8 +2,9 @@ sqfs2tar_SOURCES = bin/sqfs2tar/sqfs2tar.c bin/sqfs2tar/sqfs2tar.h sqfs2tar_SOURCES += bin/sqfs2tar/options.c bin/sqfs2tar/write_tree.c sqfs2tar_SOURCES += bin/sqfs2tar/xattr.c sqfs2tar_CFLAGS = $(AM_CFLAGS) $(PTHREAD_CFLAGS) -sqfs2tar_LDADD = libcommon.a libutil.a libsquashfs.la libtar.a libcompat.a -sqfs2tar_LDADD += libfstree.a $(LZO_LIBS) $(PTHREAD_LIBS) +sqfs2tar_LDADD = libcommon.a libutil.a libsquashfs.la libtar.a +sqfs2tar_LDADD += libfstream.a libcompat.a libfstree.a +sqfs2tar_LDADD += $(LZO_LIBS) $(PTHREAD_LIBS) dist_man1_MANS += bin/sqfs2tar/sqfs2tar.1 bin_PROGRAMS += sqfs2tar diff --git a/bin/sqfs2tar/sqfs2tar.c b/bin/sqfs2tar/sqfs2tar.c index 8c5f631..c5d1201 100644 --- a/bin/sqfs2tar/sqfs2tar.c +++ b/bin/sqfs2tar/sqfs2tar.c @@ -9,7 +9,7 @@ sqfs_xattr_reader_t *xr; sqfs_data_reader_t *data; sqfs_super_t super; -FILE *out_file = NULL; +ostream_t *out_file = NULL; static sqfs_file_t *file; @@ -63,8 +63,7 @@ static int terminate_archive(void) memset(buffer, '\0', sizeof(buffer)); - return write_retry("adding archive terminator", out_file, - buffer, sizeof(buffer)); + return ostream_append(out_file, buffer, sizeof(buffer)); } static sqfs_tree_node_t *tree_merge(sqfs_tree_node_t *lhs, @@ -118,13 +117,7 @@ int main(int argc, char **argv) process_args(argc, argv); -#ifdef _WIN32 - _setmode(_fileno(stdout), _O_BINARY); - out_file = stdout; -#else - out_file = freopen(NULL, "wb", stdout); -#endif - + out_file = ostream_open_stdout(); if (out_file == NULL) { perror("changing stdout to binary mode"); goto out_dirs; @@ -133,7 +126,7 @@ int main(int argc, char **argv) file = sqfs_open_file(filename, SQFS_FILE_OPEN_READ_ONLY); if (file == NULL) { perror(filename); - goto out_dirs; + goto out_ostrm; } ret = sqfs_super_read(&super, file); @@ -244,8 +237,10 @@ int main(int argc, char **argv) if (terminate_archive()) goto out; + if (ostream_flush(out_file)) + goto out; + status = EXIT_SUCCESS; - fflush(out_file); out: if (root != NULL) sqfs_dir_tree_destroy(root); @@ -262,6 +257,8 @@ out_cmp: sqfs_destroy(cmp); out_fd: sqfs_destroy(file); +out_ostrm: + sqfs_destroy(out_file); out_dirs: for (i = 0; i < num_subdirs; ++i) free(subdirs[i]); diff --git a/bin/sqfs2tar/sqfs2tar.h b/bin/sqfs2tar/sqfs2tar.h index 6eee2b1..70f51ef 100644 --- a/bin/sqfs2tar/sqfs2tar.h +++ b/bin/sqfs2tar/sqfs2tar.h @@ -37,7 +37,7 @@ void process_args(int argc, char **argv); extern sqfs_xattr_reader_t *xr; extern sqfs_data_reader_t *data; extern sqfs_super_t super; -extern FILE *out_file; +extern ostream_t *out_file; char *assemble_tar_path(char *name, bool is_dir); diff --git a/bin/sqfs2tar/write_tree.c b/bin/sqfs2tar/write_tree.c index 28e1cf0..e460481 100644 --- a/bin/sqfs2tar/write_tree.c +++ b/bin/sqfs2tar/write_tree.c @@ -105,7 +105,7 @@ static int write_tree_dfs(const sqfs_tree_node_t *n) if (S_ISREG(sb.st_mode)) { if (sqfs_data_reader_dump(name, data, n->inode, out_file, - super.block_size, false)) { + super.block_size)) { free(name); return -1; } diff --git a/bin/sqfsdiff/Makemodule.am b/bin/sqfsdiff/Makemodule.am index b5de502..8331f25 100644 --- a/bin/sqfsdiff/Makemodule.am +++ b/bin/sqfsdiff/Makemodule.am @@ -4,8 +4,8 @@ sqfsdiff_SOURCES += bin/sqfsdiff/compare_dir.c bin/sqfsdiff/node_compare.c sqfsdiff_SOURCES += bin/sqfsdiff/compare_files.c bin/sqfsdiff/super.c sqfsdiff_SOURCES += bin/sqfsdiff/extract.c sqfsdiff_CFLAGS = $(AM_CFLAGS) $(PTHREAD_CFLAGS) -sqfsdiff_LDADD = libcommon.a libsquashfs.la libcompat.a $(LZO_LIBS) libfstree.a -sqfsdiff_LDADD += $(PTHREAD_LIBS) +sqfsdiff_LDADD = libcommon.a libsquashfs.la libfstream.a libcompat.a +sqfsdiff_LDADD += $(LZO_LIBS) libfstree.a $(PTHREAD_LIBS) dist_man1_MANS += bin/sqfsdiff/sqfsdiff.1 bin_PROGRAMS += sqfsdiff diff --git a/bin/sqfsdiff/extract.c b/bin/sqfsdiff/extract.c index 979572a..0c68918 100644 --- a/bin/sqfsdiff/extract.c +++ b/bin/sqfsdiff/extract.c @@ -10,7 +10,7 @@ static int extract(sqfs_data_reader_t *data, const sqfs_inode_generic_t *inode, const char *prefix, const char *path, size_t block_size) { char *ptr, *temp; - FILE *fp; + ostream_t *fp; temp = alloca(strlen(prefix) + strlen(path) + 2); sprintf(temp, "%s/%s", prefix, path); @@ -21,19 +21,20 @@ static int extract(sqfs_data_reader_t *data, const sqfs_inode_generic_t *inode, return -1; *ptr = '/'; - fp = fopen(temp, "wb"); + fp = ostream_open_file(temp, OSTREAM_OPEN_OVERWRITE | + OSTREAM_OPEN_SPARSE); if (fp == NULL) { perror(temp); return -1; } - if (sqfs_data_reader_dump(path, data, inode, fp, block_size, true)) { - fclose(fp); + if (sqfs_data_reader_dump(path, data, inode, fp, block_size)) { + sqfs_destroy(fp); return -1; } - fflush(fp); - fclose(fp); + ostream_flush(fp); + sqfs_destroy(fp); return 0; } diff --git a/include/common.h b/include/common.h index 196f774..8639558 100644 --- a/include/common.h +++ b/include/common.h @@ -28,6 +28,7 @@ #include "sqfs/dir.h" #include "sqfs/io.h" +#include "fstream.h" #include "compat.h" #include "fstree.h" #include "tar.h" @@ -111,7 +112,7 @@ char *sqfs_tree_node_get_path(const sqfs_tree_node_t *node); int sqfs_data_reader_dump(const char *name, sqfs_data_reader_t *data, const sqfs_inode_generic_t *inode, - FILE *fp, size_t block_size, bool allow_sparse); + ostream_t *fp, size_t block_size); sqfs_file_t *sqfs_get_stdin_file(FILE *fp, const sparse_map_t *map, sqfs_u64 size); diff --git a/include/tar.h b/include/tar.h index f235d08..38ec656 100644 --- a/include/tar.h +++ b/include/tar.h @@ -9,6 +9,7 @@ #include "config.h" #include "compat.h" +#include "fstream.h" #include <stdbool.h> #include <stdint.h> @@ -122,11 +123,11 @@ typedef struct { The counter is an incremental record counter used if additional headers need to be generated. */ -int write_tar_header(FILE *fp, const struct stat *sb, const char *name, +int write_tar_header(ostream_t *fp, const struct stat *sb, const char *name, const char *slink_target, const tar_xattr_t *xattr, unsigned int counter); -int write_hard_link(FILE *fp, const struct stat *sb, const char *name, +int write_hard_link(ostream_t *fp, const struct stat *sb, const char *name, const char *target, unsigned int counter); /* calcuate and skip the zero padding */ @@ -145,7 +146,7 @@ void clear_header(tar_header_decoded_t *hdr); Write zero bytes to an output file to padd it to the tar record size. Returns 0 on success. On failure, prints error message to stderr. */ -int padd_file(FILE *fp, sqfs_u64 size); +int padd_file(ostream_t *fp, sqfs_u64 size); /* @@ -156,12 +157,4 @@ int padd_file(FILE *fp, sqfs_u64 size); */ int read_retry(const char *errstr, FILE *fp, void *buffer, size_t size); -/* - A wrapper around the write() system call. It retries the write if it is - interrupted by a signal or only part of the data was written. Returns 0 - on success. Writes to stderr on failure using 'errstr' as a perror style - error prefix. -*/ -int write_retry(const char *errstr, FILE *fp, const void *data, size_t size); - #endif /* TAR_H */ diff --git a/lib/common/data_reader_dump.c b/lib/common/data_reader_dump.c index d832388..7902c25 100644 --- a/lib/common/data_reader_dump.c +++ b/lib/common/data_reader_dump.c @@ -11,33 +11,9 @@ #include <stdio.h> #include <errno.h> -static int append_block(FILE *fp, const sqfs_u8 *data, size_t size) -{ - const sqfs_u8 *ptr = data; - size_t ret; - - while (size > 0) { - if (ferror(fp)) { - fputs("writing data block: error writing to file\n", - stderr); - } - - if (feof(fp)) { - fputs("writing data block: unexpected end of file\n", - stderr); - } - - ret = fwrite(ptr, 1, size, fp); - ptr += ret; - size -= ret; - } - - return 0; -} - int sqfs_data_reader_dump(const char *name, sqfs_data_reader_t *data, const sqfs_inode_generic_t *inode, - FILE *fp, size_t block_size, bool allow_sparse) + ostream_t *fp, size_t block_size) { size_t i, diff, chunk_size; sqfs_u64 filesz; @@ -46,23 +22,12 @@ int sqfs_data_reader_dump(const char *name, sqfs_data_reader_t *data, sqfs_inode_get_file_size(inode, &filesz); -#if defined(_POSIX_VERSION) && (_POSIX_VERSION >= 200112L) - if (allow_sparse) { - int fd = fileno(fp); - - if (ftruncate(fd, filesz)) - goto fail_sparse; - } -#else - allow_sparse = false; -#endif - for (i = 0; i < sqfs_inode_get_file_block_count(inode); ++i) { diff = (filesz < block_size) ? filesz : block_size; - if (SQFS_IS_SPARSE_BLOCK(inode->extra[i]) && allow_sparse) { - if (fseek(fp, diff, SEEK_CUR) < 0) - goto fail_sparse; + if (SQFS_IS_SPARSE_BLOCK(inode->extra[i])) { + if (ostream_append_sparse(fp, diff)) + return -1; } else { err = sqfs_data_reader_get_block(data, inode, i, &chunk_size, &chunk); @@ -71,7 +36,7 @@ int sqfs_data_reader_dump(const char *name, sqfs_data_reader_t *data, return -1; } - err = append_block(fp, chunk, chunk_size); + err = ostream_append(fp, chunk, chunk_size); free(chunk); if (err) @@ -89,16 +54,12 @@ int sqfs_data_reader_dump(const char *name, sqfs_data_reader_t *data, return -1; } - if (append_block(fp, chunk, chunk_size)) { - free(chunk); - return -1; - } - + err = ostream_append(fp, chunk, chunk_size); free(chunk); + + if (err) + return -1; } return 0; -fail_sparse: - perror("creating sparse output file"); - return -1; } diff --git a/lib/tar/Makemodule.am b/lib/tar/Makemodule.am index fe18895..7ba0454 100644 --- a/lib/tar/Makemodule.am +++ b/lib/tar/Makemodule.am @@ -3,8 +3,7 @@ libtar_a_SOURCES += lib/tar/number.c lib/tar/checksum.c lib/tar/cleanup.c libtar_a_SOURCES += lib/tar/read_sparse_map.c lib/tar/read_sparse_map_old.c libtar_a_SOURCES += lib/tar/base64.c lib/tar/urldecode.c lib/tar/internal.h libtar_a_SOURCES += lib/tar/padd_file.c lib/tar/read_retry.c include/tar.h -libtar_a_SOURCES += lib/tar/write_retry.c lib/tar/pax_header.c -libtar_a_SOURCES += lib/tar/read_sparse_map_new.c +libtar_a_SOURCES += lib/tar/pax_header.c lib/tar/read_sparse_map_new.c libtar_a_CFLAGS = $(AM_CFLAGS) libtar_a_CPPFLAGS = $(AM_CPPFLAGS) diff --git a/lib/tar/padd_file.c b/lib/tar/padd_file.c index dd945a3..1173096 100644 --- a/lib/tar/padd_file.c +++ b/lib/tar/padd_file.c @@ -10,7 +10,7 @@ #include <stdlib.h> #include <stdio.h> -int padd_file(FILE *fp, sqfs_u64 size) +int padd_file(ostream_t *fp, sqfs_u64 size) { size_t padd_sz = size % TAR_RECORD_SIZE; int status = -1; @@ -25,10 +25,8 @@ int padd_file(FILE *fp, sqfs_u64 size) if (buffer == NULL) goto fail_errno; - if (write_retry("padding output file to block size", - fp, buffer, padd_sz)) { + if (ostream_append(fp, buffer, padd_sz)) goto out; - } status = 0; out: diff --git a/lib/tar/write_header.c b/lib/tar/write_header.c index aaf9f08..3caa1b3 100644 --- a/lib/tar/write_header.c +++ b/lib/tar/write_header.c @@ -53,7 +53,7 @@ static void write_number_signed(char *dst, sqfs_s64 value, int digits) } } -static int write_header(FILE *fp, const struct stat *sb, const char *name, +static int write_header(ostream_t *fp, const struct stat *sb, const char *name, const char *slink_target, int type) { int maj = 0, min = 0; @@ -88,10 +88,10 @@ static int write_header(FILE *fp, const struct stat *sb, const char *name, update_checksum(&hdr); - return write_retry("writing tar header record", fp, &hdr, sizeof(hdr)); + return ostream_append(fp, &hdr, sizeof(hdr)); } -static int write_gnu_header(FILE *fp, const struct stat *orig, +static int write_gnu_header(ostream_t *fp, const struct stat *orig, const char *payload, size_t payload_len, int type, const char *name) { @@ -104,10 +104,8 @@ static int write_gnu_header(FILE *fp, const struct stat *orig, if (write_header(fp, &sb, name, NULL, type)) return -1; - if (write_retry("writing GNU extension header", - fp, payload, payload_len)) { + if (ostream_append(fp, payload, payload_len)) return -1; - } return padd_file(fp, payload_len); } @@ -136,7 +134,7 @@ static size_t prefix_digit_len(size_t len) return ndigit; } -static int write_schily_xattr(FILE *fp, const struct stat *orig, +static int write_schily_xattr(ostream_t *fp, const struct stat *orig, const char *name, const tar_xattr_t *xattr) { static const char *prefix = "SCHILY.xattr."; @@ -161,15 +159,20 @@ static int write_schily_xattr(FILE *fp, const struct stat *orig, len = strlen(prefix) + strlen(it->key) + it->value_len + 3; len += prefix_digit_len(len); - fprintf(fp, PRI_SZ " %s%s=", len, prefix, it->key); - fwrite(it->value, 1, it->value_len, fp); - fputc('\n', fp); + if (ostream_printf(fp, PRI_SZ " %s%s=", + len, prefix, it->key) < 0) { + return -1; + } + if (ostream_append(fp, it->value, it->value_len)) + return -1; + if (ostream_append(fp, "\n", 1)) + return -1; } return padd_file(fp, total_size); } -int write_tar_header(FILE *fp, const struct stat *sb, const char *name, +int write_tar_header(ostream_t *fp, const struct stat *sb, const char *name, const char *slink_target, const tar_xattr_t *xattr, unsigned int counter) { @@ -228,7 +231,7 @@ out_skip: return 1; } -int write_hard_link(FILE *fp, const struct stat *sb, const char *name, +int write_hard_link(ostream_t *fp, const struct stat *sb, const char *name, const char *target, unsigned int counter) { tar_header_t hdr; @@ -274,6 +277,5 @@ int write_hard_link(FILE *fp, const struct stat *sb, const char *name, write_number(hdr.devminor, 0, sizeof(hdr.devminor)); update_checksum(&hdr); - return write_retry("writing tar hard link record", - fp, &hdr, sizeof(hdr)); + return ostream_append(fp, &hdr, sizeof(hdr)); } diff --git a/lib/tar/write_retry.c b/lib/tar/write_retry.c deleted file mode 100644 index f4f3166..0000000 --- a/lib/tar/write_retry.c +++ /dev/null @@ -1,35 +0,0 @@ -/* SPDX-License-Identifier: LGPL-3.0-or-later */ -/* - * write_retry.c - * - * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at> - */ -#include "config.h" - -#include <errno.h> -#include <stdio.h> - -#include "tar.h" - -int write_retry(const char *errstr, FILE *fp, const void *data, size_t size) -{ - size_t ret; - - while (size > 0) { - if (feof(fp)) { - fprintf(stderr, "%s: write truncated\n", errstr); - return -1; - } - - if (ferror(fp)) { - fprintf(stderr, "%s: error writing to file\n", errstr); - return -1; - } - - ret = fwrite(data, 1, size, fp); - data = (const char *)data + ret; - size -= ret; - } - - return 0; -} |