summaryrefslogtreecommitdiff
path: root/lib/common/data_reader_dump.c
diff options
context:
space:
mode:
authorDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2019-10-07 13:54:24 +0200
committerDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2019-10-07 13:54:24 +0200
commit1fad07ce86fc2a506c59501d7fb7c7d7481525f6 (patch)
tree6ba41c514e2ddc692cb95a0fb2070dd222897c7c /lib/common/data_reader_dump.c
parent5597dca9c6053cd19104e18d88edb199b32e3743 (diff)
Rename libsqfshelper to libcommon
That is IMO less confusing and express what it is (i.e. what it has become) more clearly, i.e. common code shared by the utilities. Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
Diffstat (limited to 'lib/common/data_reader_dump.c')
-rw-r--r--lib/common/data_reader_dump.c80
1 files changed, 80 insertions, 0 deletions
diff --git a/lib/common/data_reader_dump.c b/lib/common/data_reader_dump.c
new file mode 100644
index 0000000..140f527
--- /dev/null
+++ b/lib/common/data_reader_dump.c
@@ -0,0 +1,80 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later */
+/*
+ * data_reader_dump.c
+ *
+ * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at>
+ */
+#include "common.h"
+#include "util.h"
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdio.h>
+
+int sqfs_data_reader_dump(const char *name, sqfs_data_reader_t *data,
+ const sqfs_inode_generic_t *inode,
+ int outfd, size_t block_size, bool allow_sparse)
+{
+ sqfs_block_t *blk;
+ sqfs_u64 filesz;
+ size_t i, diff;
+ int err;
+
+ sqfs_inode_get_file_size(inode, &filesz);
+
+ if (allow_sparse && ftruncate(outfd, filesz))
+ goto fail_sparse;
+
+ for (i = 0; i < inode->num_file_blocks; ++i) {
+ if (SQFS_IS_SPARSE_BLOCK(inode->block_sizes[i]) &&
+ allow_sparse) {
+ if (filesz < block_size) {
+ diff = filesz;
+ filesz = 0;
+ } else {
+ diff = block_size;
+ filesz -= block_size;
+ }
+
+ if (lseek(outfd, diff, SEEK_CUR) == (off_t)-1)
+ goto fail_sparse;
+ } else {
+ err = sqfs_data_reader_get_block(data, inode, i, &blk);
+ if (err) {
+ sqfs_perror(name, "reading data block", err);
+ return -1;
+ }
+
+ if (write_data("writing uncompressed block",
+ outfd, blk->data, blk->size)) {
+ free(blk);
+ return -1;
+ }
+
+ filesz -= blk->size;
+ free(blk);
+ }
+ }
+
+ if (filesz > 0) {
+ err = sqfs_data_reader_get_fragment(data, inode, &blk);
+ if (err) {
+ sqfs_perror(name, "reading fragment block", err);
+ return -1;
+ }
+
+ if (write_data("writing uncompressed fragment", outfd,
+ blk->data, blk->size)) {
+ free(blk);
+ return -1;
+ }
+
+ free(blk);
+ }
+
+ return 0;
+fail_sparse:
+ perror("creating sparse output file");
+ return -1;
+}