diff --git a/src/capture.c b/src/capture.c index 4138360..fbb96f4 100644 --- a/src/capture.c +++ b/src/capture.c @@ -1,12 +1,9 @@ #include "bin.h" -#include "chunk-table.h" +#include "builder.h" #include "commands.h" -#include "fs-tree.h" #include "image.h" #include "misc.h" #include "status.h" -#include "string-table.h" -#include "volume.h" #include #include @@ -35,309 +32,6 @@ enum { OPT_VERBOSE, }; -struct capture_ctx { - struct fs_tree ctx_tree; - struct ec3_image_ioctx *ctx_image; - struct chunk_table ctx_chunks; - struct string_table ctx_strings; - struct ec3_volume *ctx_volume; -}; - -static enum ec3_status capture_file( - struct capture_ctx *ctx, - struct ec3_volume *vol, - b_directory *dir, - const char *filename, - const b_path *filepath, - ec3_chunk_id out_chunk) -{ - const struct ec3_image_info *image_info - = ec3_image_ioctx_get_info(ctx->ctx_image); - size_t key = string_table_get(&ctx->ctx_strings, filename); - size_t buf_len = image_info->img_cluster_size; - char *buf = malloc(buf_len); - - if (!buf) { - return EC3_ERR_NO_MEMORY; - } - - b_file *src = NULL; - b_status status = b_file_open( - dir, - filepath, - B_FILE_READ_ONLY | B_FILE_BINARY, - &src); - if (!B_OK(status)) { - free(buf); - return ec3_status_from_b_status(status, EC3_ERR_NO_ENTRY); - } - - enum ec3_status s2 = EC3_SUCCESS; - chunk_table_begin_chunk(&ctx->ctx_chunks); - - size_t chunk_size = 0; - - while (1) { - size_t nr_read = 0; - status = b_file_read( - src, - B_OFFSET_CURRENT, - buf_len, - buf, - &nr_read); - - if (!B_OK(status)) { - s2 = ec3_status_from_b_status( - status, - EC3_ERR_IO_FAILURE); - break; - } - - enum ec3_status s2 - = chunk_table_put(&ctx->ctx_chunks, buf, nr_read); - - if (s2 != EC3_SUCCESS) { - break; - } - - chunk_size += nr_read; - - if (nr_read < buf_len) { - break; - } - } - - s2 = chunk_table_end_chunk(&ctx->ctx_chunks, out_chunk); - - if (s2 != EC3_SUCCESS) { - return s2; - } - - char id_str[128]; - ec3_chunk_id_to_string(out_chunk, id_str, sizeof id_str); - // printf("wrote %zu byte chunk %s\n", chunk_size, id_str); - - free(buf); - b_file_release(src); - return s2; -} - -static int print_fs_tree_node( - struct fs_tree *tree, - struct fs_tree_node *node, - unsigned int depth, - int direction, - void *arg) -{ - if (direction == ITERATE_POSTORDER) { - depth = 0; - } - - for (unsigned int i = 0; i < depth; i++) { - fputs(" ", stdout); - } - - printf("%s ", node->n_name); - char id_str[128]; - - switch (node->n_type) { - case FS_TREE_FILE: - ec3_chunk_id_to_string(node->n_chunk, id_str, sizeof id_str); - printf("[%s]", id_str); - break; - case FS_TREE_DIR: - printf("[d]"); - break; - default: - break; - } - - printf("\n"); - - return 0; -} - -struct capture_directory_structure_args { - b_list *args_stack; - struct capture_ctx *args_ctx; -}; - -static int capture_directory_structure_callback( - struct fs_tree *tree, - struct fs_tree_node *node, - unsigned int depth, - int direction, - void *arg) -{ - if (direction != ITERATE_POSTORDER) { - return 0; - } - - struct capture_directory_structure_args *args = arg; - b_list *stack = args->args_stack; - struct capture_ctx *ctx = args->args_ctx; - - if (node->n_type == FS_TREE_FILE) { - b_list_push_back(stack, node); - return 0; - } - - size_t nr_children = fs_tree_node_get_nr_children(node); - struct ec3_directory_entry dent; - enum ec3_status status = EC3_SUCCESS; - - chunk_table_begin_chunk(&ctx->ctx_chunks); - for (size_t i = 0; i < nr_children; i++) { - struct fs_tree_node *child = b_list_pop_back(stack); - if (!child) { - return EC3_ERR_INTERNAL_FAILURE; - } - - dent.d_name = b_i32_htob( - string_table_get(&ctx->ctx_strings, child->n_name)); - dent.d_vnode = b_i32_htob(child->n_id); - - status = chunk_table_put(&ctx->ctx_chunks, &dent, sizeof dent); - } - - status = chunk_table_end_chunk(&ctx->ctx_chunks, node->n_chunk); - if (status != EC3_SUCCESS) { - return status; - } - - char id_str[128]; - ec3_chunk_id_to_string(node->n_chunk, id_str, sizeof id_str); - printf("[d %s / %zu] wrote %zu byte chunk %s\n", - node->n_name, - node->n_id, - nr_children * sizeof dent, - id_str); - - struct ec3_vnode vnode = { - .v_id = node->n_id, - .v_mode = EC3_V_DIR, - }; - - memcpy(vnode.v_data, node->n_chunk, sizeof vnode.v_data); - - ec3_volume_put_vnode(ctx->ctx_volume, &vnode); - - b_list_push_back(stack, node); - - return 0; -} - -static enum ec3_status capture_directory_structure(struct capture_ctx *ctx) -{ - b_list *stack = b_list_create(); - - struct capture_directory_structure_args args = { - .args_stack = stack, - .args_ctx = ctx, - }; - - fs_tree_iterate( - &ctx->ctx_tree, - capture_directory_structure_callback, - &args); - - return EC3_SUCCESS; -} - -static enum ec3_status capture_directory( - struct capture_ctx *ctx, - uint64_t id, - const char *cpath) -{ - b_path *path = b_path_create_from_cstr(cpath); - b_directory *dir; - b_status status = b_directory_open(NULL, path, &dir); - b_path_release(path); - - if (!B_OK(status)) { - return EC3_ERR_NO_ENTRY; - } - - struct ec3_tag_ioctx *volu; - enum ec3_status s2 = ec3_image_ioctx_create_tag( - ctx->ctx_image, - EC3_TAG_VOLU, - id, - EC3_TAG_IO_READ | EC3_TAG_IO_WRITE, - &volu); - if (s2 != EC3_SUCCESS) { - b_directory_release(dir); - return s2; - } - - struct ec3_volume *volume; - s2 = ec3_volume_create(ctx->ctx_image, volu, &volume); - - if (s2 != EC3_SUCCESS) { - ec3_tag_ioctx_close(volu); - b_directory_release(dir); - return s2; - } - - ctx->ctx_volume = volume; - - fs_tree_init(&ctx->ctx_tree); - - struct ec3_vnode vnode = {0}; - vnode.v_id = ctx->ctx_tree.fs_root->n_id; - ec3_volume_put_vnode(volume, &vnode); - - enum ec3_status status2 = EC3_SUCCESS; - b_directory_iterator it; - b_directory_iterator_begin(dir, &it, B_DIRECTORY_ITERATE_PARENT_LAST); - while (b_directory_iterator_is_valid(&it)) { - if (!b_directory_path_is_file(dir, it.filepath)) { - printf("dir: %s\n", b_path_ptr(it.filepath)); - b_directory_iterator_next(&it); - continue; - } - - ec3_vnode_from_file_info(&it.info, &vnode); - - printf("file: %s\n", b_path_ptr(it.filepath)); - - status2 = capture_file( - ctx, - volume, - dir, - it.filename, - it.filepath, - vnode.v_data); - - if (status2 != EC3_SUCCESS) { - b_err("failed to capture file '%s'", - b_path_ptr(it.filepath)); - b_i("error code: %s", ec3_status_to_string(status2)); - break; - } - - fs_tree_put( - &ctx->ctx_tree, - b_path_ptr(it.filepath), - &vnode.v_id, - vnode.v_data); - - ec3_volume_put_vnode(volume, &vnode); - - b_directory_iterator_next(&it); - } - - // fs_tree_iterate(&ctx->ctx_tree, print_fs_tree_node, NULL); - - capture_directory_structure(ctx); - fs_tree_fini(&ctx->ctx_tree); - - ec3_tag_ioctx_close(volu); - - b_directory_release(dir); - return status2; -} - static int capture( const b_command *self, const b_arglist *opt, @@ -360,74 +54,19 @@ static int capture( return -1; } - struct ec3_image_ioctx *image = NULL; + struct ec3_image_builder *image = NULL; struct ec3_parameters param = { .p_cluster_size = EC3_CLUSTER_16K, .p_compression_func = EC3_COMPRESSION_ZSTD, .p_ident = ident, }; - status = ec3_image_ioctx_open( - out_path, - ¶m, - EC3_IMAGE_IO_WRITE | EC3_IMAGE_IO_TRUNCATE, - &image); + status = ec3_image_builder_create(out_path, ¶m, &image); if (status != EC3_SUCCESS) { b_err("cannot initialise EC3 writer"); return -1; } - uint64_t ctab_id, cdat_id, stab_id; - ec3_identifier_from_string("_CHKTAB0", &ctab_id); - ec3_identifier_from_string("_CHKDAT0", &cdat_id); - ec3_identifier_from_string("_VOLSTR0", &stab_id); - - struct ec3_tag_ioctx *ctab, *cdat, *stab; - status = ec3_image_ioctx_create_tag( - image, - EC3_TAG_CTAB, - ctab_id, - EC3_TAG_IO_READ | EC3_TAG_IO_WRITE, - &ctab); - - if (status != EC3_SUCCESS) { - b_err("cannot create chunk table tag"); - b_i("error code: %s", ec3_status_to_string(status)); - return -1; - } - - status = ec3_image_ioctx_create_tag( - image, - EC3_TAG_CDAT, - cdat_id, - EC3_TAG_IO_READ | EC3_TAG_IO_WRITE, - &cdat); - - if (status != EC3_SUCCESS) { - b_err("cannot create chunk data tag"); - b_i("error code: %s", ec3_status_to_string(status)); - return -1; - } - - status = ec3_image_ioctx_create_tag( - image, - EC3_TAG_STAB, - stab_id, - EC3_TAG_IO_WRITE | EC3_TAG_IO_SEQUENTIAL, - &stab); - - if (status != EC3_SUCCESS) { - b_err("cannot create string table tag"); - b_i("error code: %s", ec3_status_to_string(status)); - return -1; - } - - struct capture_ctx ctx = {0}; - ctx.ctx_image = image; - chunk_table_init(ctab, cdat, param.p_cluster_size, &ctx.ctx_chunks); - chunk_table_init_empty_table(&ctx.ctx_chunks); - string_table_init(&ctx.ctx_strings); - uint64_t next_auto_id = 0; b_arglist_iterator it = {0}; @@ -435,8 +74,8 @@ static int capture( { printf("%s\n", it.value->val_str); - status = capture_directory( - &ctx, + status = ec3_image_builder_capture_directory( + image, next_auto_id, it.value->val_str); next_auto_id++; @@ -482,7 +121,10 @@ static int capture( return -1; } - status = capture_directory(&ctx, id, path->val_str); + status = ec3_image_builder_capture_directory( + image, + id, + path->val_str); if (status != EC3_SUCCESS) { b_err("an error occurred while writing to the " @@ -491,32 +133,7 @@ static int capture( } } - b_btree_iterator s_it; - b_btree_iterator_begin(&ctx.ctx_strings.s_offset_tree, &s_it); - while (b_btree_iterator_is_valid(&s_it)) { - struct string_table_entry *entry = b_unbox( - struct string_table_entry, - s_it.node, - e_offset_node); - - size_t len = strlen(entry->e_str) + 1; - size_t nr_written = 0; - status = ec3_tag_ioctx_write( - stab, - entry->e_str, - len, - &nr_written); - b_btree_iterator_next(&s_it); - } - - string_table_finish(&ctx.ctx_strings); - chunk_table_finish(&ctx.ctx_chunks); - - ec3_tag_ioctx_close(stab); - ec3_tag_ioctx_close(ctab); - ec3_tag_ioctx_close(cdat); - - ec3_image_ioctx_close(image); + ec3_image_builder_destroy(image); return 0; }