summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bin/rdsquashfs/Makemodule.am2
-rw-r--r--bin/rdsquashfs/fill_files.c30
-rw-r--r--bin/rdsquashfs/rdsquashfs.c14
-rw-r--r--bin/sqfs2tar/Makemodule.am5
-rw-r--r--bin/sqfs2tar/sqfs2tar.c21
-rw-r--r--bin/sqfs2tar/sqfs2tar.h2
-rw-r--r--bin/sqfs2tar/write_tree.c2
-rw-r--r--bin/sqfsdiff/Makemodule.am4
-rw-r--r--bin/sqfsdiff/extract.c13
-rw-r--r--include/common.h3
-rw-r--r--include/tar.h15
-rw-r--r--lib/common/data_reader_dump.c57
-rw-r--r--lib/tar/Makemodule.am3
-rw-r--r--lib/tar/padd_file.c6
-rw-r--r--lib/tar/write_header.c30
-rw-r--r--lib/tar/write_retry.c35
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;
-}