From d94edfa8ee35a03744c3b6c4599c4c28f0c73002 Mon Sep 17 00:00:00 2001 From: Max Wash Date: Tue, 4 Feb 2025 12:57:55 +0000 Subject: [PATCH] read tag and extent table in ec3_reader_create --- src/read.c | 180 +++++++++++++++++++++++++++++++++++++++++++++-------- src/read.h | 43 ++++++++++++- 2 files changed, 195 insertions(+), 28 deletions(-) diff --git a/src/read.c b/src/read.c index 3497a49..7a4fb82 100644 --- a/src/read.c +++ b/src/read.c @@ -1,34 +1,102 @@ #include "read.h" + #include "bin.h" #include "pipeline.h" #include +#include +#include struct ec3_reader { - unsigned short r_version; - unsigned short r_cluster_size; - size_t r_tag_table_offset; - size_t r_extent_table_offset; - size_t r_cluster_table_offset; - unsigned int r_nr_tags; - unsigned int r_nr_extents; - unsigned int r_nr_cluster_groups; + struct ec3_container_info c_info; + FILE *c_fp; - uint64_t r_id; + /* array of sizeo c_info.c_nr_tags */ + struct ec3_tag_info *c_tags; + /* array of sizeo c_info.c_nr_extents */ + struct ec3_extent_info *c_extents; struct ec3_pipeline *r_pipeline; }; static void decode_header(const struct ec3_header *in, struct ec3_reader *out) { - out->r_version = b_i16_btoh(in->h_version); - out->r_cluster_size = ec3_get_cluster_size(b_i16_btoh(in->h_cluster_size)); - out->r_tag_table_offset = b_i64_btoh(in->h_tag_table_offset); - out->r_extent_table_offset = b_i64_btoh(in->h_extent_table_offset); - out->r_cluster_table_offset = b_i64_btoh(in->h_cluster_table_offset); - out->r_nr_tags = b_i32_btoh(in->h_tag_count); - out->r_nr_extents = b_i32_btoh(in->h_tag_count); - out->r_nr_cluster_groups = b_i32_btoh(in->h_cluster_group_count); + out->c_info.c_version = b_i16_btoh(in->h_version); + out->c_info.c_cluster_size + = ec3_get_cluster_size(b_i16_btoh(in->h_cluster_size)); + out->c_info.c_tag_table_offset = b_i64_btoh(in->h_tag_table_offset); + out->c_info.c_extent_table_offset + = b_i64_btoh(in->h_extent_table_offset); + out->c_info.c_cluster_table_offset + = b_i64_btoh(in->h_cluster_table_offset); + out->c_info.c_nr_tags = b_i32_btoh(in->h_tag_count); + out->c_info.c_nr_extents = b_i32_btoh(in->h_tag_count); + out->c_info.c_nr_cluster_groups = b_i32_btoh(in->h_cluster_group_count); + out->c_info.c_id = b_i64_btoh(in->h_app_magic); +} + +static void decode_tag( + const struct ec3_tag_table_entry *in, + struct ec3_tag_info *out) +{ + out->tag_type = b_i32_btoh(in->tag_type); + out->tag_flags = b_i32_btoh(in->tag_flags); + out->tag_checksum = b_i32_btoh(in->tag_checksum); + out->tag_ident = b_i64_btoh(in->tag_ident); +} + +static void decode_extent( + const struct ec3_extent *in, + struct ec3_extent_info *out) +{ + out->ex_owner = b_i64_btoh(in->ex_owner); + out->ex_logical_cluster = b_i32_btoh(in->ex_logical_cluster); + out->ex_physical_cluster = b_i32_btoh(in->ex_physical_cluster); + out->ex_count = b_i32_btoh(in->ex_count); +} + +static enum ec3_status read_tag_table( + struct ec3_reader *reader, + struct ec3_tag_info *out) +{ + size_t offset = reader->c_info.c_tag_table_offset; + + for (unsigned int i = 0; i < reader->c_info.c_nr_tags; i++) { + fseek(reader->c_fp, offset, SEEK_SET); + struct ec3_tag_table_entry entry; + size_t r = fread(&entry, sizeof entry, 1, reader->c_fp); + if (r != 1) { + return ferror(reader->c_fp) ? EC3_ERR_IO_FAILURE + : EC3_ERR_BAD_FORMAT; + } + + decode_tag(&entry, &out[i]); + offset += sizeof entry; + } + + return EC3_SUCCESS; +} + +static enum ec3_status read_extent_table( + struct ec3_reader *reader, + struct ec3_extent_info *out) +{ + size_t offset = reader->c_info.c_extent_table_offset; + + for (unsigned int i = 0; i < reader->c_info.c_nr_extents; i++) { + fseek(reader->c_fp, offset, SEEK_SET); + struct ec3_extent entry; + size_t r = fread(&entry, sizeof entry, 1, reader->c_fp); + if (r != 1) { + return ferror(reader->c_fp) ? EC3_ERR_IO_FAILURE + : EC3_ERR_BAD_FORMAT; + } + + decode_extent(&entry, &out[i]); + offset += sizeof entry; + } + + return EC3_SUCCESS; } enum ec3_status ec3_reader_create(FILE *inp, struct ec3_reader **out) @@ -52,27 +120,30 @@ enum ec3_status ec3_reader_create(FILE *inp, struct ec3_reader **out) } memset(reader, 0x0, sizeof *reader); + reader->c_fp = inp; decode_header(&header, reader); unsigned short compression = b_i16_btoh(header.h_compression); unsigned short encryption = b_i16_btoh(header.h_encryption); - struct ec3_pipeline_stage_args stages[3] = { 0 }; + struct ec3_pipeline_stage_args stages[3] = {0}; stages[0].type = EC3_PIPELINE_FILE; if (encryption != EC3_ENCRYPTION_NONE) { - stages[1].type = ec3_get_pipeline_stage_for_encryption_func(encryption); + stages[1].type = ec3_get_pipeline_stage_for_encryption_func( + encryption); } if (compression != EC3_COMPRESSION_NONE) { - stages[2].type = ec3_get_pipeline_stage_for_compression_func(compression); + stages[2].type = ec3_get_pipeline_stage_for_compression_func( + compression); } enum ec3_status status = ec3_pipeline_create( stages, sizeof stages / sizeof stages[0], - reader->r_cluster_size, + reader->c_info.c_cluster_size, &reader->r_pipeline); if (status != EC3_SUCCESS) { @@ -80,20 +151,79 @@ enum ec3_status ec3_reader_create(FILE *inp, struct ec3_reader **out) return status; } + struct ec3_tag_info *tags + = calloc(reader->c_info.c_nr_tags, sizeof *tags); + + if (!tags) { + ec3_pipeline_destroy(reader->r_pipeline); + free(reader); + return EC3_ERR_NO_MEMORY; + } + + struct ec3_extent_info *extents + = calloc(reader->c_info.c_nr_extents, sizeof *extents); + if (!extents) { + free(tags); + ec3_pipeline_destroy(reader->r_pipeline); + free(reader); + return EC3_ERR_NO_MEMORY; + } + + status = read_tag_table(reader, tags); + if (status != EC3_SUCCESS) { + free(tags); + free(extents); + ec3_pipeline_destroy(reader->r_pipeline); + free(reader); + return status; + } + + status = read_extent_table(reader, extents); + if (status != EC3_SUCCESS) { + free(tags); + free(extents); + ec3_pipeline_destroy(reader->r_pipeline); + free(reader); + return status; + } + + reader->c_tags = tags; + reader->c_extents = extents; + + *out = reader; return EC3_SUCCESS; } void ec3_reader_finish(struct ec3_reader *reader) { - } -enum ec3_status ec3_reader_open_tag(struct ec3_reader *reader, uint64_t tag_ident, struct ec3_tag_reader **out) +const struct ec3_container_info *ec3_reader_get_container_info( + const struct ec3_reader *reader) { + return &reader->c_info; +} +const struct ec3_tag_info *ec3_reader_get_tags(const struct ec3_reader *reader) +{ + return reader->c_tags; +} + +const struct ec3_extent_info *ec3_reader_get_extents( + const struct ec3_reader *reader) +{ + return reader->c_extents; +} + +enum ec3_status ec3_reader_open_tag( + struct ec3_reader *reader, + uint64_t tag_ident, + struct ec3_tag_reader **out) +{ + return EC3_ERR_NOT_SUPPORTED; } enum ec3_status ec3_tag_reader_close(struct ec3_tag_reader *tag) { - -} \ No newline at end of file + return EC3_ERR_NOT_SUPPORTED; +} diff --git a/src/read.h b/src/read.h index 46df8ea..40b90d1 100644 --- a/src/read.h +++ b/src/read.h @@ -3,17 +3,54 @@ #include "status.h" -#include #include +#include struct ec3_reader; struct ec3_tag_reader; +struct ec3_container_info { + unsigned short c_version; + unsigned short c_cluster_size; + size_t c_tag_table_offset; + size_t c_extent_table_offset; + size_t c_cluster_table_offset; + unsigned int c_nr_tags; + unsigned int c_nr_extents; + unsigned int c_nr_cluster_groups; + + uint64_t c_id; +}; + +struct ec3_tag_info { + unsigned long tag_type; + unsigned long tag_flags; + unsigned long tag_checksum; + unsigned long long tag_ident; +}; + +struct ec3_extent_info { + unsigned long long ex_owner; + unsigned long ex_logical_cluster; + unsigned long ex_physical_cluster; + unsigned long ex_count; +}; + extern enum ec3_status ec3_reader_create(FILE *inp, struct ec3_reader **out); extern void ec3_reader_finish(struct ec3_reader *reader); -extern enum ec3_status ec3_reader_open_tag(struct ec3_reader *reader, uint64_t tag_ident, struct ec3_tag_reader **out); +extern const struct ec3_container_info *ec3_reader_get_container_info( + const struct ec3_reader *reader); +extern const struct ec3_tag_info *ec3_reader_get_tags( + const struct ec3_reader *reader); +extern const struct ec3_extent_info *ec3_reader_get_extents( + const struct ec3_reader *reader); + +extern enum ec3_status ec3_reader_open_tag( + struct ec3_reader *reader, + uint64_t tag_ident, + struct ec3_tag_reader **out); extern enum ec3_status ec3_tag_reader_close(struct ec3_tag_reader *tag); -#endif \ No newline at end of file +#endif