From 42971331bdcb5900aba619c3163c0685f705f80d Mon Sep 17 00:00:00 2001 From: David Oberhollenzer Date: Sun, 12 Jan 2020 04:14:51 +0100 Subject: Implement 42.sqfs demo A play on the famous 42.zip Signed-off-by: David Oberhollenzer --- extras/Makemodule.am | 5 +- extras/mk42sqfs.c | 205 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 209 insertions(+), 1 deletion(-) create mode 100644 extras/mk42sqfs.c (limited to 'extras') 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 +#include +#include + +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; +} -- cgit v1.2.3