summaryrefslogtreecommitdiff
path: root/bin/tar2sqfs/process_tarball.c
diff options
context:
space:
mode:
Diffstat (limited to 'bin/tar2sqfs/process_tarball.c')
-rw-r--r--bin/tar2sqfs/process_tarball.c81
1 files changed, 64 insertions, 17 deletions
diff --git a/bin/tar2sqfs/process_tarball.c b/bin/tar2sqfs/process_tarball.c
index 415e362..4d7f0a1 100644
--- a/bin/tar2sqfs/process_tarball.c
+++ b/bin/tar2sqfs/process_tarball.c
@@ -6,28 +6,74 @@
*/
#include "tar2sqfs.h"
-static int write_file(FILE *input_file, sqfs_writer_t *sqfs,
+static int write_file(istream_t *input_file, sqfs_writer_t *sqfs,
const tar_header_decoded_t *hdr,
file_info_t *fi, sqfs_u64 filesize)
{
- sqfs_file_t *file;
- int flags;
- int ret;
+ const sparse_map_t *list;
+ int flags = 0, ret = 0;
+ sqfs_u64 offset, diff;
+ bool sparse_region;
+ ostream_t *out;
- file = sqfs_get_stdin_file(input_file, hdr->sparse, filesize);
- if (file == NULL) {
- perror("packing files");
- return -1;
- }
-
- flags = 0;
if (no_tail_pack && filesize > cfg.block_size)
flags |= SQFS_BLK_DONT_FRAGMENT;
- ret = write_data_from_file(hdr->name, sqfs->data,
- (sqfs_inode_generic_t **)&fi->user_ptr,
- file, flags);
- sqfs_destroy(file);
+ out = data_writer_ostream_create(hdr->name, sqfs->data,
+ (sqfs_inode_generic_t **)&fi->user_ptr,
+ flags);
+
+ if (out == NULL)
+ return -1;
+
+ list = hdr->sparse;
+
+ for (offset = 0; offset < filesize; offset += diff) {
+ if (hdr->sparse != NULL) {
+ if (list == NULL) {
+ sparse_region = true;
+ diff = filesize - offset;
+ } else if (offset < list->offset) {
+ sparse_region = true;
+ diff = list->offset - offset;
+ } else if (offset - list->offset >= list->count) {
+ list = list->next;
+ diff = 0;
+ continue;
+ } else {
+ sparse_region = false;
+ diff = list->count - (offset - list->offset);
+ }
+ } else {
+ sparse_region = false;
+ diff = filesize - offset;
+ }
+
+ if (sizeof(diff) > sizeof(size_t) && diff > 0x7FFFFFFFUL)
+ diff = 0x7FFFFFFFUL;
+
+ if (sparse_region) {
+ ret = ostream_append_sparse(out, diff);
+ } else {
+ ret = ostream_append_from_istream(out, input_file,
+ diff);
+
+ if (ret == 0) {
+ fprintf(stderr, "%s: unexpected end-of-file\n",
+ hdr->name);
+ ret = -1;
+ } else if (ret > 0) {
+ diff = ret;
+ ret = 0;
+ }
+ }
+
+ if (ret < 0)
+ break;
+ }
+
+ ostream_flush(out);
+ sqfs_destroy(out);
if (ret)
return -1;
@@ -78,7 +124,8 @@ static int copy_xattr(sqfs_writer_t *sqfs, tree_node_t *node,
return 0;
}
-static int create_node_and_repack_data(FILE *input_file, sqfs_writer_t *sqfs,
+static int create_node_and_repack_data(istream_t *input_file,
+ sqfs_writer_t *sqfs,
tar_header_decoded_t *hdr)
{
tree_node_t *node;
@@ -149,7 +196,7 @@ static int set_root_attribs(sqfs_writer_t *sqfs,
return 0;
}
-int process_tarball(FILE *input_file, sqfs_writer_t *sqfs)
+int process_tarball(istream_t *input_file, sqfs_writer_t *sqfs)
{
bool skip, is_root, is_prefixed;
tar_header_decoded_t hdr;