diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | extras/Makemodule.am | 4 | ||||
-rw-r--r-- | extras/mknastyfs.c | 184 |
3 files changed, 189 insertions, 0 deletions
@@ -43,3 +43,4 @@ m4/libtool.m4 m4/lt*.m4 Doxyfile tests/cantrbry.sh +mknastyfs diff --git a/extras/Makemodule.am b/extras/Makemodule.am index e69de29..83d9e8b 100644 --- a/extras/Makemodule.am +++ b/extras/Makemodule.am @@ -0,0 +1,4 @@ +mknastyfs_SOURCES = extras/mknastyfs.c +mknastyfs_LDADD = libsquashfs.la + +noinst_PROGRAMS += mknastyfs diff --git a/extras/mknastyfs.c b/extras/mknastyfs.c new file mode 100644 index 0000000..823bcf8 --- /dev/null +++ b/extras/mknastyfs.c @@ -0,0 +1,184 @@ +#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> + +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 = 1337; + 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; + int status = EXIT_FAILURE; + sqfs_dir_writer_t *dirwr; + sqfs_compressor_t *cmp; + sqfs_id_table_t *idtbl; + unsigned int inode_num; + sqfs_u64 block_start; + sqfs_super_t super; + sqfs_file_t *file; + sqfs_u32 offset; + + /* get a file object referring to our destination file */ + file = sqfs_open_file("nasty.sqfs", 0); + 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; + } + + /* 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); + + 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, "..", inode->base.inode_number, + (block_start << 16) | offset, + inode->base.mode); + free(inode); + + 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, "/etc/passwd", + inode->base.inode_number, + (block_start << 16) | offset, + inode->base.mode); + free(inode); + + sqfs_dir_writer_end(dirwr); + + 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 = file->get_size(file); + + 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; +} |