capture: implement directory structure capture
This commit is contained in:
175
src/capture.c
175
src/capture.c
@@ -1,13 +1,16 @@
|
||||
#include "bin.h"
|
||||
#include "chunk-table.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 <blue/cmd.h>
|
||||
#include <blue/io/directory.h>
|
||||
#include <blue/object/list.h>
|
||||
#include <blue/term/print.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
@@ -33,17 +36,20 @@ enum {
|
||||
};
|
||||
|
||||
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_tag_ioctx *vol,
|
||||
struct ec3_volume *vol,
|
||||
b_directory *dir,
|
||||
const char *filename,
|
||||
const b_path *filepath)
|
||||
const b_path *filepath,
|
||||
ec3_chunk_id out_chunk)
|
||||
{
|
||||
const struct ec3_image_info *image_info
|
||||
= ec3_image_ioctx_get_info(ctx->ctx_image);
|
||||
@@ -101,22 +107,143 @@ static enum ec3_status capture_file(
|
||||
}
|
||||
}
|
||||
|
||||
ec3_chunk_id id = {0};
|
||||
s2 = chunk_table_end_chunk(&ctx->ctx_chunks, id);
|
||||
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(id, id_str, sizeof id_str);
|
||||
printf("wrote %zu byte chunk %s\n", chunk_size, id_str);
|
||||
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,
|
||||
@@ -143,28 +270,43 @@ static enum ec3_status capture_directory(
|
||||
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);
|
||||
|
||||
b_directory_iterator it;
|
||||
b_directory_iterator_begin(dir, &it, B_DIRECTORY_ITERATE_PARENT_FIRST);
|
||||
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;
|
||||
}
|
||||
|
||||
printf("%s\n", b_path_ptr(it.filepath));
|
||||
ec3_vnode_from_file_info(&it.info, &vnode);
|
||||
|
||||
printf("file: %s\n", b_path_ptr(it.filepath));
|
||||
|
||||
enum ec3_status status2 = capture_file(
|
||||
ctx,
|
||||
volu,
|
||||
volume,
|
||||
dir,
|
||||
it.filename,
|
||||
it.filepath);
|
||||
it.filepath,
|
||||
vnode.v_data);
|
||||
|
||||
if (status2 != EC3_SUCCESS) {
|
||||
b_err("failed to capture file '%s'",
|
||||
@@ -173,9 +315,22 @@ static enum ec3_status capture_directory(
|
||||
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);
|
||||
|
||||
Reference in New Issue
Block a user