diff options
| author | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2020-01-12 04:14:51 +0100 | 
|---|---|---|
| committer | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2020-01-12 08:23:56 +0100 | 
| commit | 42971331bdcb5900aba619c3163c0685f705f80d (patch) | |
| tree | 6907d064919d9616ad9c32fbc863ad4cadc5ead1 /extras | |
| parent | ae3caba461401a32c23fb92569d3a22ca74c2bd0 (diff) | |
Implement 42.sqfs demo
A play on the famous 42.zip
Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
Diffstat (limited to 'extras')
| -rw-r--r-- | extras/Makemodule.am | 5 | ||||
| -rw-r--r-- | extras/mk42sqfs.c | 205 | 
2 files changed, 209 insertions, 1 deletions
| diff --git a/extras/Makemodule.am b/extras/Makemodule.am index 83d9e8b..77d734e 100644 --- a/extras/Makemodule.am +++ b/extras/Makemodule.am @@ -1,4 +1,7 @@  mknastyfs_SOURCES = extras/mknastyfs.c  mknastyfs_LDADD = libsquashfs.la -noinst_PROGRAMS += mknastyfs +mk42sqfs_SOURCES = extras/mk42sqfs.c +mk42sqfs_LDADD = libsquashfs.la + +noinst_PROGRAMS += mknastyfs mk42sqfs diff --git a/extras/mk42sqfs.c b/extras/mk42sqfs.c new file mode 100644 index 0000000..25c9047 --- /dev/null +++ b/extras/mk42sqfs.c @@ -0,0 +1,205 @@ +#include "sqfs/meta_writer.h" +#include "sqfs/dir_writer.h" +#include "sqfs/compressor.h" +#include "sqfs/id_table.h" +#include "sqfs/inode.h" +#include "sqfs/super.h" +#include "sqfs/io.h" + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> + +const char *README = +"This SuqashFS image contains ITSELF 42 times. Do NOT try to recursively\n" +"scan or unpack it. You will end up with an infinite amount of data!\n"; + +static void add_padding(sqfs_file_t *file) +{ +	sqfs_u64 diff, size; + +	size = file->get_size(file); +	diff = size % 4096; + +	if (diff > 0) +		file->truncate(file, size + (4096 - diff)); +} + +static sqfs_inode_generic_t *create_file_inode(sqfs_id_table_t *idtbl, +					       unsigned int inode_num) +{ +	sqfs_inode_generic_t *inode; + +	inode = calloc(1, sizeof(*inode) + sizeof(sqfs_u32)); +	inode->base.type = SQFS_INODE_FILE; +	inode->base.mode = SQFS_INODE_MODE_REG | 0644; +	inode->base.inode_number = inode_num; + +	sqfs_id_table_id_to_index(idtbl, 0, &inode->base.uid_idx); +	sqfs_id_table_id_to_index(idtbl, 0, &inode->base.gid_idx); + +	inode->data.file.file_size = 4096; +	inode->data.file.fragment_index = 0xFFFFFFFF; + +	inode->num_file_blocks = 1; +	inode->block_sizes = (sqfs_u32 *)inode->extra; +	inode->block_sizes[0] = (1 << 24) | inode->data.file.file_size; +	return inode; +} + +int main(void) +{ +	sqfs_meta_writer_t *inode_m, *dir_m; +	sqfs_compressor_config_t cfg; +	sqfs_inode_generic_t *inode; +	unsigned int i, inode_num; +	int status = EXIT_FAILURE; +	sqfs_dir_writer_t *dirwr; +	sqfs_compressor_t *cmp; +	sqfs_id_table_t *idtbl; +	sqfs_u64 block_start; +	sqfs_super_t super; +	sqfs_file_t *file; +	sqfs_u32 offset; +	char buffer[32]; + +	/* get a file object referring to our destination file */ +	file = sqfs_open_file("42.sqfs", SQFS_FILE_OPEN_OVERWRITE); +	if (file == NULL) { +		fputs("Error opening output file.\n", stderr); +		return EXIT_FAILURE; +	} + +	/* initialize the super block with sane values */ +	sqfs_super_init(&super, 4096, 0, SQFS_COMP_GZIP); + +	if (sqfs_super_write(&super, file)) { +		fputs("Error witing super block.\n", stderr); +		goto out_file; +	} + +	/* write the file data for the readme */ +	if (file->write_at(file, sizeof(super), README, strlen(README))) { +		fputs("Error writing file data!\n", stderr); +		goto out_file; +	} + +	/* create a compressor */ +	sqfs_compressor_config_init(&cfg, super.compression_id, +				    super.block_size, 0); + +	cmp = sqfs_compressor_create(&cfg); +	if (cmp == NULL) { +		fputs("Error creating compressor.\n", stderr); +		goto out_file; +	} + +	/* create meta data writers for inodes and directories */ +	inode_m = sqfs_meta_writer_create(file, cmp, 0); +	if (inode_m == NULL) { +		fputs("Error creating inode meta data writer.\n", stderr); +		goto out_cmp; +	} + +	dir_m = sqfs_meta_writer_create(file, cmp, +					SQFS_META_WRITER_KEEP_IN_MEMORY); +	if (dir_m == NULL) { +		fputs("Error creating directory meta data writer.\n", stderr); +		goto out_im; +	} + +	/* create a higher level directory writer on top of the meta writer */ +	dirwr = sqfs_dir_writer_create(dir_m, 0); +	if (dirwr == NULL) { +		fputs("Error creating directory writer.\n", stderr); +		goto out_dm; +	} + +	/* create an ID table */ +	idtbl = sqfs_id_table_create(); +	if (idtbl == NULL) { +		fputs("Error creating ID table.\n", stderr); +		goto out_dirwr; +	} + +	/* generate inodes and directories */ +	super.inode_table_start = file->get_size(file); +	inode_num = 1; + +	sqfs_dir_writer_begin(dirwr, 0); + +	for (i = 0; i < 42; ++i) { +		sprintf(buffer, "%02u.sqfs", i + 1); + +		inode = create_file_inode(idtbl, inode_num++); +		sqfs_meta_writer_get_position(inode_m, &block_start, &offset); +		sqfs_meta_writer_write_inode(inode_m, inode); +		sqfs_dir_writer_add_entry(dirwr, buffer, +					  inode->base.inode_number, +					  (block_start << 16) | offset, +					  inode->base.mode); +		free(inode); +	} + +	inode = create_file_inode(idtbl, inode_num++); +	inode->data.file.blocks_start = sizeof(super); +	inode->data.file.file_size = strlen(README); +	inode->block_sizes[0] = (1 << 24) | inode->data.file.file_size; + +	sqfs_meta_writer_get_position(inode_m, &block_start, &offset); +	sqfs_meta_writer_write_inode(inode_m, inode); +	sqfs_dir_writer_add_entry(dirwr, "README.txt", +				  inode->base.inode_number, +				  (block_start << 16) | offset, +				  inode->base.mode); +	free(inode); + +	sqfs_dir_writer_end(dirwr); + +	/* create an inode for the root directory */ +	inode = sqfs_dir_writer_create_inode(dirwr, 0, 0xFFFFFFFF, 0); + +	inode->base.mode = SQFS_INODE_MODE_DIR | 0755; +	inode->base.inode_number = inode_num++; +	sqfs_id_table_id_to_index(idtbl, 0, &inode->base.uid_idx); +	sqfs_id_table_id_to_index(idtbl, 0, &inode->base.gid_idx); + +	sqfs_meta_writer_get_position(inode_m, &block_start, &offset); +	super.root_inode_ref = (block_start << 16) | offset; +	sqfs_meta_writer_write_inode(inode_m, inode); +	free(inode); + +	/* flush the meta data to the file */ +	sqfs_meta_writer_flush(inode_m); +	sqfs_meta_writer_flush(dir_m); + +	super.directory_table_start = file->get_size(file); +	sqfs_meta_write_write_to_file(dir_m); + +	sqfs_id_table_write(idtbl, file, &super, cmp); + +	super.inode_count = inode_num - 2; +	super.bytes_used = 4096; + +	if (sqfs_super_write(&super, file)) { +		fputs("Error update the final super block.\n", stderr); +		goto out_file; +	} + +	add_padding(file); + +	/* cleanup */ +	status = EXIT_SUCCESS; +	sqfs_id_table_destroy(idtbl); +out_dirwr: +	sqfs_dir_writer_destroy(dirwr); +out_dm: +	sqfs_meta_writer_destroy(dir_m); +out_im: +	sqfs_meta_writer_destroy(inode_m); +out_cmp: +	cmp->destroy(cmp); +out_file: +	file->destroy(file); +	return status; +} | 
