diff options
Diffstat (limited to 'lib/sqfshelper')
| -rw-r--r-- | lib/sqfshelper/Makemodule.am | 1 | ||||
| -rw-r--r-- | lib/sqfshelper/writer.c | 168 | 
2 files changed, 169 insertions, 0 deletions
diff --git a/lib/sqfshelper/Makemodule.am b/lib/sqfshelper/Makemodule.am index 62990fa..90a25d2 100644 --- a/lib/sqfshelper/Makemodule.am +++ b/lib/sqfshelper/Makemodule.am @@ -7,5 +7,6 @@ libsqfshelper_a_SOURCES += lib/sqfshelper/data_reader_dump.c  libsqfshelper_a_SOURCES += lib/sqfshelper/compress.c lib/sqfshelper/comp_opt.c  libsqfshelper_a_SOURCES += lib/sqfshelper/data_writer.c include/highlevel.h  libsqfshelper_a_SOURCES += lib/sqfshelper/get_path.c lib/sqfshelper/io_stdin.c +libsqfshelper_a_SOURCES += lib/sqfshelper/writer.c  noinst_LIBRARIES += libsqfshelper.a 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 <goliath@infraroot.at> + */ +#include "config.h" + +#include "highlevel.h" +#include "util.h" + +#include <string.h> + +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); +}  | 
