aboutsummaryrefslogtreecommitdiff
path: root/extras/mknastyfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'extras/mknastyfs.c')
-rw-r--r--extras/mknastyfs.c184
1 files changed, 184 insertions, 0 deletions
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;
+}