aboutsummaryrefslogtreecommitdiff
path: root/extras
diff options
context:
space:
mode:
authorDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2020-01-12 04:14:51 +0100
committerDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2020-01-12 08:23:56 +0100
commit42971331bdcb5900aba619c3163c0685f705f80d (patch)
tree6907d064919d9616ad9c32fbc863ad4cadc5ead1 /extras
parentae3caba461401a32c23fb92569d3a22ca74c2bd0 (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.am5
-rw-r--r--extras/mk42sqfs.c205
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;
+}