summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/data_writer.h93
-rw-r--r--include/highlevel.h36
-rw-r--r--lib/sqfshelper/Makemodule.am2
-rw-r--r--lib/sqfshelper/data_writer.c142
-rw-r--r--lib/sqfshelper/statistics.c57
-rw-r--r--mkfs/mkfs.c29
-rw-r--r--mkfs/mkfs.h1
-rw-r--r--tar/tar2sqfs.c35
8 files changed, 142 insertions, 253 deletions
diff --git a/include/data_writer.h b/include/data_writer.h
deleted file mode 100644
index cdf7a44..0000000
--- a/include/data_writer.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/* SPDX-License-Identifier: GPL-3.0-or-later */
-/*
- * data_writer.h
- *
- * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at>
- */
-#ifndef DATA_WRITER_H
-#define DATA_WRITER_H
-
-#include "config.h"
-
-#include "sqfs/compress.h"
-#include "sqfs/data.h"
-#include "fstree.h"
-#include "util.h"
-
-typedef struct data_writer_t data_writer_t;
-
-typedef struct {
- size_t file_count;
- size_t blocks_written;
- size_t frag_blocks_written;
- size_t duplicate_blocks;
- size_t sparse_blocks;
- size_t frag_count;
- size_t frag_dup;
- uint64_t bytes_written;
- uint64_t bytes_read;
-} data_writer_stats_t;
-
-enum {
- /* Don't generate fragments, always write the last block to disk as a
- block, even if it is incomplete. */
- DW_DONT_FRAGMENT = 0x01,
-
- /* Intentionally write all blocks uncompressed. */
- DW_DONT_COMPRESS = 0x02,
-
- /* Make sure the first block of a file is alligned to
- device block size */
- DW_ALLIGN_DEVBLK = 0x04,
-};
-
-/*
- Create a data writer. The pointer to the super block is kept internally and
- used to automatically update various counters when writing data.
-
- Returns NULL on failure and prints errors to stderr.
- */
-data_writer_t *data_writer_create(sqfs_super_t *super, sqfs_compressor_t *cmp,
- sqfs_file_t *file, size_t devblksize,
- unsigned int num_jobs, size_t max_backlog);
-
-void data_writer_destroy(data_writer_t *data);
-
-/*
- Write the finalfragment table to the underlying file.
-
- Returns 0 on success, prints errors to stderr.
-*/
-int data_writer_write_fragment_table(data_writer_t *data);
-
-/*
- Wait for everything to be written to disk. This also forces a currently
- pending fragment block to be compressed and wrtten.
-
- Returns 0 on success, prints errors to stderr.
-*/
-int data_writer_sync(data_writer_t *data);
-
-/*
- Read data from the given file descriptor, partition it into blocks and
- write them out (possibly compressed) to the underlying file. If the size
- is not a multiple of the block size, the last bit is kept in an internal
- fragment buffer which is written out if full.
-
- The file_info_t object is updated accordingly and used to determine the
- number of bytes to write and the input file name to report errors.
-
- Blocks or fragments that are all zero bytes automatically detected,
- not written out and the sparse file accounting updated accordingly.
-
- The flags argument is a combination of DW_* flags. After completion the
- data writer collects the 'fi' in an internal list it uses for deduplication.
-
- Returns 0 on success, prints errors to stderr.
-*/
-int write_data_from_file(data_writer_t *data, sqfs_inode_generic_t *inode,
- sqfs_file_t *file, int flags);
-
-data_writer_stats_t *data_writer_get_stats(data_writer_t *data);
-
-#endif /* DATA_WRITER_H */
diff --git a/include/highlevel.h b/include/highlevel.h
index bfc2d91..5bc4a96 100644
--- a/include/highlevel.h
+++ b/include/highlevel.h
@@ -15,20 +15,47 @@
#include "sqfs/data.h"
#include "sqfs/table.h"
#include "sqfs/meta_writer.h"
+#include "sqfs/data_reader.h"
+#include "sqfs/data_writer.h"
#include "sqfs/dir_writer.h"
#include "sqfs/dir_reader.h"
+#include "sqfs/block.h"
#include "sqfs/xattr.h"
#include "sqfs/dir.h"
#include "sqfs/io.h"
-#include "sqfs/data_reader.h"
-#include "data_writer.h"
#include "fstree.h"
+#include "util.h"
#include "tar.h"
#include <sys/stat.h>
#include <stdint.h>
#include <stddef.h>
+typedef struct {
+ size_t file_count;
+ size_t blocks_written;
+ size_t frag_blocks_written;
+ size_t duplicate_blocks;
+ size_t sparse_blocks;
+ size_t frag_count;
+ size_t frag_dup;
+ uint64_t bytes_written;
+ uint64_t bytes_read;
+} data_writer_stats_t;
+
+enum {
+ /* Don't generate fragments, always write the last block to disk as a
+ block, even if it is incomplete. */
+ DW_DONT_FRAGMENT = 0x01,
+
+ /* Intentionally write all blocks uncompressed. */
+ DW_DONT_COMPRESS = 0x02,
+
+ /* Make sure the first block of a file is alligned to
+ device block size */
+ DW_ALLIGN_DEVBLK = 0x04,
+};
+
/*
High level helper function to serialize an entire file system tree to
a squashfs inode table and directory table.
@@ -86,4 +113,9 @@ int sqfs_data_reader_dump(sqfs_data_reader_t *data,
sqfs_file_t *sqfs_get_stdin_file(const sparse_map_t *map, uint64_t size);
+void register_stat_hooks(sqfs_data_writer_t *data, data_writer_stats_t *stats);
+
+int write_data_from_file(sqfs_data_writer_t *data, sqfs_inode_generic_t *inode,
+ sqfs_file_t *file, size_t block_size, int flags);
+
#endif /* HIGHLEVEL_H */
diff --git a/lib/sqfshelper/Makemodule.am b/lib/sqfshelper/Makemodule.am
index 8a8deaa..896605a 100644
--- a/lib/sqfshelper/Makemodule.am
+++ b/lib/sqfshelper/Makemodule.am
@@ -6,7 +6,7 @@ libsqfshelper_a_SOURCES += lib/sqfshelper/print_version.c
libsqfshelper_a_SOURCES += lib/sqfshelper/inode_stat.c
libsqfshelper_a_SOURCES += lib/sqfshelper/data_reader_dump.c
libsqfshelper_a_SOURCES += lib/sqfshelper/compress.c lib/sqfshelper/comp_opt.c
-libsqfshelper_a_SOURCES += include/data_writer.h lib/sqfshelper/data_writer.c
+libsqfshelper_a_SOURCES += lib/sqfshelper/data_writer.c
libsqfshelper_a_SOURCES += lib/sqfshelper/write_xattr.c include/highlevel.h
libsqfshelper_a_SOURCES += lib/sqfshelper/get_path.c lib/sqfshelper/io_stdin.c
diff --git a/lib/sqfshelper/data_writer.c b/lib/sqfshelper/data_writer.c
index a365e6d..5c01cb8 100644
--- a/lib/sqfshelper/data_writer.c
+++ b/lib/sqfshelper/data_writer.c
@@ -6,10 +6,6 @@
*/
#include "config.h"
-#include "sqfs/data_writer.h"
-#include "sqfs/block.h"
-
-#include "data_writer.h"
#include "highlevel.h"
#include "util.h"
@@ -17,72 +13,14 @@
#include <string.h>
#include <unistd.h>
#include <stdio.h>
-#include <errno.h>
-#include <zlib.h>
-
-struct data_writer_t {
- sqfs_data_writer_t *proc;
- sqfs_compressor_t *cmp;
- sqfs_super_t *super;
-
- data_writer_stats_t stats;
-};
-
-
-static void post_block_write(void *user, const sqfs_block_t *block,
- sqfs_file_t *file)
-{
- data_writer_t *data = user;
- (void)file;
-
- if (block->flags & SQFS_BLK_FRAGMENT_BLOCK) {
- data->stats.frag_blocks_written += 1;
- } else {
- data->stats.blocks_written += 1;
- }
-
- data->stats.bytes_written += block->size;
-}
-
-static void pre_fragment_store(void *user, sqfs_block_t *block)
-{
- data_writer_t *data = user;
- (void)block;
-
- data->stats.frag_count += 1;
-}
-
-static void notify_blocks_erased(void *user, size_t count, uint64_t bytes)
-{
- data_writer_t *data = user;
- (void)bytes;
-
- data->stats.bytes_written -= bytes;
- data->stats.blocks_written -= count;
- data->stats.duplicate_blocks += count;
-}
-
-static void notify_fragment_discard(void *user, const sqfs_block_t *block)
-{
- data_writer_t *data = user;
- (void)block;
-
- data->stats.frag_dup += 1;
-}
-
-static const sqfs_block_hooks_t hooks = {
- .post_block_write = post_block_write,
- .pre_fragment_store = pre_fragment_store,
- .notify_blocks_erased = notify_blocks_erased,
- .notify_fragment_discard = notify_fragment_discard,
-};
static bool is_zero_block(unsigned char *ptr, size_t size)
{
return ptr[0] == 0 && memcmp(ptr, ptr + 1, size - 1) == 0;
}
-static int add_sentinel_block(data_writer_t *data, sqfs_inode_generic_t *inode,
+static int add_sentinel_block(sqfs_data_writer_t *data,
+ sqfs_inode_generic_t *inode,
uint32_t flags)
{
sqfs_block_t *blk = calloc(1, sizeof(*blk));
@@ -95,11 +33,11 @@ static int add_sentinel_block(data_writer_t *data, sqfs_inode_generic_t *inode,
blk->inode = inode;
blk->flags = flags;
- return sqfs_data_writer_enqueue(data->proc, blk);
+ return sqfs_data_writer_enqueue(data, blk);
}
-int write_data_from_file(data_writer_t *data, sqfs_inode_generic_t *inode,
- sqfs_file_t *file, int flags)
+int write_data_from_file(sqfs_data_writer_t *data, sqfs_inode_generic_t *inode,
+ sqfs_file_t *file, size_t block_size, int flags)
{
uint32_t blk_flags = SQFS_BLK_FIRST_BLOCK;
uint64_t filesz, offset;
@@ -116,8 +54,8 @@ int write_data_from_file(data_writer_t *data, sqfs_inode_generic_t *inode,
sqfs_inode_get_file_size(inode, &filesz);
for (offset = 0; offset < filesz; offset += diff) {
- if (filesz - offset > (uint64_t)data->super->block_size) {
- diff = data->super->block_size;
+ if (filesz - offset > (uint64_t)block_size) {
+ diff = block_size;
} else {
diff = filesz - offset;
}
@@ -131,8 +69,6 @@ int write_data_from_file(data_writer_t *data, sqfs_inode_generic_t *inode,
blk->index = i++;
if (is_zero_block(blk->data, blk->size)) {
- data->stats.sparse_blocks += 1;
-
sqfs_inode_make_extended(inode);
inode->data.file_ext.sparse += blk->size;
inode->num_file_blocks += 1;
@@ -142,8 +78,7 @@ int write_data_from_file(data_writer_t *data, sqfs_inode_generic_t *inode,
continue;
}
- if (diff < data->super->block_size &&
- !(flags & DW_DONT_FRAGMENT)) {
+ if (diff < block_size && !(flags & DW_DONT_FRAGMENT)) {
if (!(blk_flags & (SQFS_BLK_FIRST_BLOCK |
SQFS_BLK_LAST_BLOCK))) {
blk_flags |= SQFS_BLK_LAST_BLOCK;
@@ -157,10 +92,10 @@ int write_data_from_file(data_writer_t *data, sqfs_inode_generic_t *inode,
blk->flags |= SQFS_BLK_IS_FRAGMENT;
- if (sqfs_data_writer_enqueue(data->proc, blk))
+ if (sqfs_data_writer_enqueue(data, blk))
return -1;
} else {
- if (sqfs_data_writer_enqueue(data->proc, blk))
+ if (sqfs_data_writer_enqueue(data, blk))
return -1;
blk_flags &= ~SQFS_BLK_FIRST_BLOCK;
@@ -174,62 +109,5 @@ int write_data_from_file(data_writer_t *data, sqfs_inode_generic_t *inode,
if (add_sentinel_block(data, inode, blk_flags))
return -1;
}
-
- sqfs_inode_make_basic(inode);
-
- data->stats.bytes_read += filesz;
- data->stats.file_count += 1;
- return 0;
-}
-
-data_writer_t *data_writer_create(sqfs_super_t *super, sqfs_compressor_t *cmp,
- sqfs_file_t *file, size_t devblksize,
- unsigned int num_jobs, size_t max_backlog)
-{
- data_writer_t *data = calloc(1, sizeof(*data));
-
- if (data == NULL) {
- perror("creating data writer");
- return NULL;
- }
-
- data->proc = sqfs_data_writer_create(super->block_size, cmp,
- num_jobs, max_backlog,
- devblksize, file);
- if (data->proc == NULL) {
- perror("creating data block processor");
- free(data);
- return NULL;
- }
-
- sqfs_data_writer_set_hooks(data->proc, data, &hooks);
-
- data->cmp = cmp;
- data->super = super;
- return data;
-}
-
-void data_writer_destroy(data_writer_t *data)
-{
- sqfs_data_writer_destroy(data->proc);
- free(data);
-}
-
-int data_writer_write_fragment_table(data_writer_t *data)
-{
- if (sqfs_data_writer_write_fragment_table(data->proc, data->super)) {
- fputs("error storing fragment table\n", stderr);
- return -1;
- }
return 0;
}
-
-int data_writer_sync(data_writer_t *data)
-{
- return sqfs_data_writer_finish(data->proc);
-}
-
-data_writer_stats_t *data_writer_get_stats(data_writer_t *data)
-{
- return &data->stats;
-}
diff --git a/lib/sqfshelper/statistics.c b/lib/sqfshelper/statistics.c
index 87efc30..26c121f 100644
--- a/lib/sqfshelper/statistics.c
+++ b/lib/sqfshelper/statistics.c
@@ -7,8 +7,65 @@
#include "config.h"
#include "highlevel.h"
+#include "sqfs/block.h"
+
#include <stdio.h>
+static void post_block_write(void *user, const sqfs_block_t *block,
+ sqfs_file_t *file)
+{
+ data_writer_stats_t *stats = user;
+ (void)file;
+
+ if (block->size == 0)
+ return;
+
+ if (block->flags & SQFS_BLK_FRAGMENT_BLOCK) {
+ stats->frag_blocks_written += 1;
+ } else {
+ stats->blocks_written += 1;
+ }
+
+ stats->bytes_written += block->size;
+}
+
+static void pre_fragment_store(void *user, sqfs_block_t *block)
+{
+ data_writer_stats_t *stats = user;
+ (void)block;
+
+ stats->frag_count += 1;
+}
+
+static void notify_blocks_erased(void *user, size_t count, uint64_t bytes)
+{
+ data_writer_stats_t *stats = user;
+
+ stats->bytes_written -= bytes;
+ stats->blocks_written -= count;
+ stats->duplicate_blocks += count;
+}
+
+static void notify_fragment_discard(void *user, const sqfs_block_t *block)
+{
+ data_writer_stats_t *stats = user;
+ (void)block;
+
+ stats->frag_dup += 1;
+}
+
+static const sqfs_block_hooks_t hooks = {
+ .post_block_write = post_block_write,
+ .pre_fragment_store = pre_fragment_store,
+ .notify_blocks_erased = notify_blocks_erased,
+ .notify_fragment_discard = notify_fragment_discard,
+};
+
+void register_stat_hooks(sqfs_data_writer_t *data, data_writer_stats_t *stats)
+{
+ sqfs_data_writer_set_hooks(data, stats, &hooks);
+}
+
void sqfs_print_statistics(sqfs_super_t *super, data_writer_stats_t *stats)
{
size_t ratio;
diff --git a/mkfs/mkfs.c b/mkfs/mkfs.c
index acb3202..71e1863 100644
--- a/mkfs/mkfs.c
+++ b/mkfs/mkfs.c
@@ -28,7 +28,8 @@ static int restore_working_dir(options_t *opt)
return 0;
}
-static int pack_files(data_writer_t *data, fstree_t *fs, options_t *opt)
+static int pack_files(sqfs_data_writer_t *data, fstree_t *fs,
+ data_writer_stats_t *stats, options_t *opt)
{
sqfs_inode_generic_t *inode;
size_t max_blk_count;
@@ -72,14 +73,18 @@ static int pack_files(data_writer_t *data, fstree_t *fs, options_t *opt)
fi->user_ptr = inode;
- ret = write_data_from_file(data, inode, file, 0);
+ ret = write_data_from_file(data, inode, file,
+ fs->block_size, 0);
file->destroy(file);
if (ret)
return -1;
+
+ stats->file_count += 1;
+ stats->bytes_read += filesize;
}
- if (data_writer_sync(data))
+ if (sqfs_data_writer_finish(data))
return -1;
return restore_working_dir(opt);
@@ -118,10 +123,11 @@ int main(int argc, char **argv)
{
int status = EXIT_FAILURE, ret;
sqfs_compressor_config_t cfg;
+ data_writer_stats_t stats;
+ sqfs_data_writer_t *data;
sqfs_compressor_t *cmp;
sqfs_id_table_t *idtbl;
sqfs_file_t *outfile;
- data_writer_t *data;
sqfs_super_t super;
options_t opt;
fstree_t fs;
@@ -188,18 +194,21 @@ int main(int argc, char **argv)
if (ret > 0)
super.flags |= SQFS_FLAG_COMPRESSOR_OPTIONS;
- data = data_writer_create(&super, cmp, outfile,
- opt.devblksz, opt.num_jobs, opt.max_backlog);
+ data = sqfs_data_writer_create(super.block_size, cmp, opt.num_jobs,
+ opt.max_backlog, opt.devblksz, outfile);
if (data == NULL)
goto out_cmp;
- if (pack_files(data, &fs, &opt))
+ memset(&stats, 0, sizeof(stats));
+ register_stat_hooks(data, &stats);
+
+ if (pack_files(data, &fs, &stats, &opt))
goto out_data;
if (sqfs_serialize_fstree(outfile, &super, &fs, cmp, idtbl))
goto out_data;
- if (data_writer_write_fragment_table(data))
+ if (sqfs_data_writer_write_fragment_table(data, &super))
goto out_data;
if (opt.exportable) {
@@ -222,11 +231,11 @@ int main(int argc, char **argv)
goto out_data;
if (!opt.quiet)
- sqfs_print_statistics(&super, data_writer_get_stats(data));
+ sqfs_print_statistics(&super, &stats);
status = EXIT_SUCCESS;
out_data:
- data_writer_destroy(data);
+ sqfs_data_writer_destroy(data);
out_cmp:
cmp->destroy(cmp);
out_outfile:
diff --git a/mkfs/mkfs.h b/mkfs/mkfs.h
index 9d34d02..bbe5572 100644
--- a/mkfs/mkfs.h
+++ b/mkfs/mkfs.h
@@ -15,7 +15,6 @@
#include "sqfs/data.h"
#include "sqfs/io.h"
-#include "data_writer.h"
#include "highlevel.h"
#include "fstree.h"
#include "util.h"
diff --git a/tar/tar2sqfs.c b/tar/tar2sqfs.c
index 82720a8..4770810 100644
--- a/tar/tar2sqfs.c
+++ b/tar/tar2sqfs.c
@@ -12,7 +12,6 @@
#include "sqfs/data.h"
#include "sqfs/io.h"
-#include "data_writer.h"
#include "highlevel.h"
#include "fstree.h"
#include "util.h"
@@ -111,6 +110,8 @@ static bool dont_skip = false;
static bool no_xattr = false;
static bool exportable = false;
static bool keep_time = false;
+static data_writer_stats_t stats;
+static sqfs_super_t super;
static void process_args(int argc, char **argv)
{
@@ -223,7 +224,7 @@ fail_arg:
}
static int write_file(tar_header_decoded_t *hdr, file_info_t *fi,
- data_writer_t *data, uint64_t filesize)
+ sqfs_data_writer_t *data, uint64_t filesize)
{
const sparse_map_t *it;
sqfs_inode_generic_t *inode;
@@ -266,9 +267,12 @@ static int write_file(tar_header_decoded_t *hdr, file_info_t *fi,
}
}
- ret = write_data_from_file(data, inode, file, 0);
+ ret = write_data_from_file(data, inode, file, super.block_size, 0);
file->destroy(file);
+ stats.bytes_read += filesize;
+ stats.file_count += 1;
+
if (ret)
return -1;
@@ -302,7 +306,7 @@ static int copy_xattr(fstree_t *fs, tree_node_t *node,
}
static int create_node_and_repack_data(tar_header_decoded_t *hdr, fstree_t *fs,
- data_writer_t *data)
+ sqfs_data_writer_t *data)
{
tree_node_t *node;
@@ -333,7 +337,7 @@ fail_errno:
return -1;
}
-static int process_tar_ball(fstree_t *fs, data_writer_t *data)
+static int process_tar_ball(fstree_t *fs, sqfs_data_writer_t *data)
{
tar_header_decoded_t hdr;
uint64_t offset, count;
@@ -407,11 +411,10 @@ int main(int argc, char **argv)
{
sqfs_compressor_config_t cfg;
int status = EXIT_SUCCESS;
+ sqfs_data_writer_t *data;
sqfs_compressor_t *cmp;
sqfs_id_table_t *idtbl;
sqfs_file_t *outfile;
- data_writer_t *data;
- sqfs_super_t super;
fstree_t fs;
int ret;
@@ -450,10 +453,14 @@ int main(int argc, char **argv)
if (ret > 0)
super.flags |= SQFS_FLAG_COMPRESSOR_OPTIONS;
- data = data_writer_create(&super, cmp, outfile, devblksize,
- num_jobs, max_backlog);
- if (data == NULL)
+ data = sqfs_data_writer_create(super.block_size, cmp, num_jobs,
+ max_backlog, devblksize, outfile);
+ if (data == NULL) {
+ perror("creating data block processor");
goto out_cmp;
+ }
+
+ register_stat_hooks(data, &stats);
idtbl = sqfs_id_table_create();
if (idtbl == NULL)
@@ -462,7 +469,7 @@ int main(int argc, char **argv)
if (process_tar_ball(&fs, data))
goto out;
- if (data_writer_sync(data))
+ if (sqfs_data_writer_finish(data))
goto out;
tree_node_sort_recursive(fs.root);
@@ -476,7 +483,7 @@ int main(int argc, char **argv)
if (sqfs_serialize_fstree(outfile, &super, &fs, cmp, idtbl))
goto out;
- if (data_writer_write_fragment_table(data))
+ if (sqfs_data_writer_write_fragment_table(data, &super))
goto out;
if (exportable) {
@@ -499,13 +506,13 @@ int main(int argc, char **argv)
goto out;
if (!quiet)
- sqfs_print_statistics(&super, data_writer_get_stats(data));
+ sqfs_print_statistics(&super, &stats);
status = EXIT_SUCCESS;
out:
sqfs_id_table_destroy(idtbl);
out_data:
- data_writer_destroy(data);
+ sqfs_data_writer_destroy(data);
out_cmp:
cmp->destroy(cmp);
out_fs: