diff --git a/src/query.c b/src/query.c index 0e3f329..5905134 100644 --- a/src/query.c +++ b/src/query.c @@ -1,17 +1,127 @@ #include "commands.h" +#include "misc.h" +#include "read.h" +#include "status.h" #include +#include +#include +#include enum { ARG_CONTAINER, OPT_VERBOSE, }; +static void tag_type_string(unsigned long in, char out[5]) +{ + b_i32 v = b_i32_htob(in); + out[0] = v.i_bytes[0]; + out[1] = v.i_bytes[1]; + out[2] = v.i_bytes[2]; + out[3] = v.i_bytes[3]; + out[4] = 0; +} + static int query( const b_command *self, const b_arglist *opt, const b_array *args) { + const char *in_path = NULL; + b_arglist_get_string( + opt, + B_COMMAND_INVALID_ID, + ARG_CONTAINER, + 0, + &in_path); + + FILE *fp = fopen(in_path, "rb"); + if (!fp) { + b_err("cannot open container '%s'", in_path); + b_i("reason: %s", strerror(errno)); + return -1; + } + + struct ec3_reader *reader = NULL; + enum ec3_status status = ec3_reader_create(fp, &reader); + if (status != EC3_SUCCESS) { + fclose(fp); + + b_err("cannot open container '%s'", in_path); + return -1; + } + + const struct ec3_container_info *c_info + = ec3_reader_get_container_info(reader); + + char container_id[32]; + ec3_identifier_to_string( + c_info->c_id, + container_id, + sizeof container_id); + + printf("container details:\n"); + printf(" %-20s: %04x\n", "format version", c_info->c_version); + printf(" %-20s: %s\n", "identifier", container_id); + printf(" %-20s: %u\n", "cluster size", c_info->c_cluster_size); + printf(" %-20s: 0x%zx\n", + "tag table offset", + c_info->c_tag_table_offset); + printf(" %-20s: 0x%zx\n", + "extent table offset", + c_info->c_extent_table_offset); + printf(" %-20s: 0x%zx\n", + "cluster table offset", + c_info->c_cluster_table_offset); + printf(" %-20s: %u\n", "tag count", c_info->c_nr_tags); + printf(" %-20s: %u\n", "extent count", c_info->c_nr_extents); + printf(" %-20s: %u\n", + "cluster group count", + c_info->c_nr_cluster_groups); + + printf("\ntags:\n"); + const struct ec3_tag_info *tags = ec3_reader_get_tags(reader); + for (unsigned int i = 0; i < c_info->c_nr_tags; i++) { + char tag_type[5]; + tag_type_string(tags[i].tag_type, tag_type); + + char tag_id[32]; + ec3_identifier_to_string( + tags[i].tag_ident, + tag_id, + sizeof tag_id); + + printf(" (%lx/%s) %s\n", tags[i].tag_type, tag_type, tag_id); + printf(" %-8s: %08lx\n", "flags", tags[i].tag_flags); + printf(" %-8s: %08lx\n", "checksum", tags[i].tag_checksum); + } + + printf("\nextents:\n"); + const struct ec3_extent_info *extents = ec3_reader_get_extents(reader); + for (unsigned int i = 0; i < c_info->c_nr_tags; i++) { + char tag_id[32]; + ec3_identifier_to_string( + extents[i].ex_owner, + tag_id, + sizeof tag_id); + + size_t physical_base = extents[i].ex_physical_cluster; + size_t physical_limit = physical_base + extents[i].ex_count - 1; + size_t logical_base = extents[i].ex_logical_cluster; + size_t logical_limit = logical_base + extents[i].ex_count - 1; + + printf(" (%16s) %lu clusters", tag_id, extents[i].ex_count); + printf(" [%05lx-%05lx] -> [%05lx-%05lx]\n", + logical_base, + logical_limit, + physical_base, + physical_limit); + } + + ec3_reader_finish(reader); + fclose(fp); + return 0; }