#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->payload_bytes_used = sizeof(sqfs_u32);
inode->payload_bytes_available = sizeof(sqfs_u32);
inode->extra[0] = (1 << 24) | inode->data.file.file_size;
return inode;
}
int main(void)
{
sqfs_meta_writer_t *inode_m, *dir_m;
int ret, status = EXIT_FAILURE;
sqfs_compressor_config_t cfg;
sqfs_inode_generic_t *inode;
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);
ret = sqfs_compressor_create(&cfg, &cmp);
if (ret != 0) {
fprintf(stderr, "Error creating compressor: %d.\n", ret);
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(0);
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_destroy(idtbl);
out_dirwr:
sqfs_destroy(dirwr);
out_dm:
sqfs_destroy(dir_m);
out_im:
sqfs_destroy(inode_m);
out_cmp:
sqfs_destroy(cmp);
out_file:
sqfs_destroy(file);
return status;
}