From 1e24f45ab120ea83a6faab2e4e14038547898f64 Mon Sep 17 00:00:00 2001 From: David Oberhollenzer Date: Sat, 5 Oct 2019 20:06:50 +0200 Subject: Merge all the common code for generating images Signed-off-by: David Oberhollenzer --- lib/sqfshelper/writer.c | 168 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 168 insertions(+) create mode 100644 lib/sqfshelper/writer.c (limited to 'lib/sqfshelper/writer.c') diff --git a/lib/sqfshelper/writer.c b/lib/sqfshelper/writer.c new file mode 100644 index 0000000..76a12fc --- /dev/null +++ b/lib/sqfshelper/writer.c @@ -0,0 +1,168 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * writer.c + * + * Copyright (C) 2019 David Oberhollenzer + */ +#include "config.h" + +#include "highlevel.h" +#include "util.h" + +#include + +void sqfs_writer_cfg_init(sqfs_writer_cfg_t *cfg) +{ + memset(cfg, 0, sizeof(*cfg)); + + cfg->num_jobs = 1; + cfg->block_size = SQFS_DEFAULT_BLOCK_SIZE; + cfg->devblksize = SQFS_DEVBLK_SIZE; + cfg->comp_id = compressor_get_default(); +} + +int sqfs_writer_init(sqfs_writer_t *sqfs, const sqfs_writer_cfg_t *wrcfg) +{ + sqfs_compressor_config_t cfg; + int ret; + + if (compressor_cfg_init_options(&cfg, wrcfg->comp_id, + wrcfg->block_size, + wrcfg->comp_extra)) { + return -1; + } + + sqfs->outfile = sqfs_open_file(wrcfg->filename, wrcfg->outmode); + if (sqfs->outfile == NULL) { + perror(wrcfg->filename); + return -1; + } + + if (fstree_init(&sqfs->fs, wrcfg->fs_defaults)) + goto fail_file; + + sqfs->cmp = sqfs_compressor_create(&cfg); + if (sqfs->cmp == NULL) { + fputs("Error creating compressor\n", stderr); + goto fail_fs; + } + + if (sqfs_super_init(&sqfs->super, wrcfg->block_size, + sqfs->fs.defaults.st_mtime, wrcfg->comp_id)) { + goto fail_cmp; + } + + if (sqfs_super_write(&sqfs->super, sqfs->outfile)) + goto fail_cmp; + + ret = sqfs->cmp->write_options(sqfs->cmp, sqfs->outfile); + if (ret < 0) + goto fail_cmp; + + if (ret > 0) + sqfs->super.flags |= SQFS_FLAG_COMPRESSOR_OPTIONS; + + sqfs->data = sqfs_data_writer_create(sqfs->super.block_size, + sqfs->cmp, wrcfg->num_jobs, + wrcfg->max_backlog, + wrcfg->devblksize, + sqfs->outfile); + if (sqfs->data == NULL) { + perror("creating data block processor"); + goto fail_cmp; + } + + register_stat_hooks(sqfs->data, &sqfs->stats); + + sqfs->idtbl = sqfs_id_table_create(); + if (sqfs->idtbl == NULL) + goto fail_data; + + if (!wrcfg->no_xattr) { + sqfs->xwr = sqfs_xattr_writer_create(); + + if (sqfs->xwr == NULL) { + perror("creating xattr writer"); + goto fail; + } + } + + return 0; +fail: + if (sqfs->xwr != NULL) + sqfs_xattr_writer_destroy(sqfs->xwr); + sqfs_id_table_destroy(sqfs->idtbl); +fail_data: + sqfs_data_writer_destroy(sqfs->data); +fail_cmp: + sqfs->cmp->destroy(sqfs->cmp); +fail_fs: + fstree_cleanup(&sqfs->fs); +fail_file: + sqfs->outfile->destroy(sqfs->outfile); + return -1; +} + +int sqfs_writer_finish(sqfs_writer_t *sqfs, const sqfs_writer_cfg_t *cfg) +{ + if (sqfs_data_writer_finish(sqfs->data)) + return -1; + + tree_node_sort_recursive(sqfs->fs.root); + if (fstree_gen_inode_table(&sqfs->fs)) + return -1; + + sqfs->super.inode_count = sqfs->fs.inode_tbl_size; + + if (sqfs_serialize_fstree(sqfs->outfile, &sqfs->super, + &sqfs->fs, sqfs->cmp, sqfs->idtbl)) { + return -1; + } + + if (sqfs_data_writer_write_fragment_table(sqfs->data, &sqfs->super)) + return -1; + + if (cfg->exportable) { + if (write_export_table(sqfs->outfile, &sqfs->fs, + &sqfs->super, sqfs->cmp)) { + return -1; + } + } + + if (sqfs_id_table_write(sqfs->idtbl, sqfs->outfile, + &sqfs->super, sqfs->cmp)) { + return -1; + } + + if (sqfs_xattr_writer_flush(sqfs->xwr, sqfs->outfile, + &sqfs->super, sqfs->cmp)) { + fputs("Error writing xattr table\n", stderr); + return -1; + } + + sqfs->super.bytes_used = sqfs->outfile->get_size(sqfs->outfile); + + if (sqfs_super_write(&sqfs->super, sqfs->outfile)) + return 0; + + if (padd_sqfs(sqfs->outfile, sqfs->super.bytes_used, + cfg->devblksize)) { + return -1; + } + + if (!cfg->quiet) + sqfs_print_statistics(&sqfs->super, &sqfs->stats); + + return 0; +} + +void sqfs_writer_cleanup(sqfs_writer_t *sqfs) +{ + if (sqfs->xwr != NULL) + sqfs_xattr_writer_destroy(sqfs->xwr); + sqfs_id_table_destroy(sqfs->idtbl); + sqfs_data_writer_destroy(sqfs->data); + sqfs->cmp->destroy(sqfs->cmp); + fstree_cleanup(&sqfs->fs); + sqfs->outfile->destroy(sqfs->outfile); +} -- cgit v1.2.3