read tag and extent table in ec3_reader_create

This commit is contained in:
2025-02-04 12:57:55 +00:00
parent eabdc8777b
commit d94edfa8ee
2 changed files with 195 additions and 28 deletions

View File

@@ -1,34 +1,102 @@
#include "read.h" #include "read.h"
#include "bin.h" #include "bin.h"
#include "pipeline.h" #include "pipeline.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct ec3_reader { struct ec3_reader {
unsigned short r_version; struct ec3_container_info c_info;
unsigned short r_cluster_size; FILE *c_fp;
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;
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; struct ec3_pipeline *r_pipeline;
}; };
static void decode_header(const struct ec3_header *in, struct ec3_reader *out) static void decode_header(const struct ec3_header *in, struct ec3_reader *out)
{ {
out->r_version = b_i16_btoh(in->h_version); out->c_info.c_version = b_i16_btoh(in->h_version);
out->r_cluster_size = ec3_get_cluster_size(b_i16_btoh(in->h_cluster_size)); out->c_info.c_cluster_size
out->r_tag_table_offset = b_i64_btoh(in->h_tag_table_offset); = ec3_get_cluster_size(b_i16_btoh(in->h_cluster_size));
out->r_extent_table_offset = b_i64_btoh(in->h_extent_table_offset); out->c_info.c_tag_table_offset = b_i64_btoh(in->h_tag_table_offset);
out->r_cluster_table_offset = b_i64_btoh(in->h_cluster_table_offset); out->c_info.c_extent_table_offset
out->r_nr_tags = b_i32_btoh(in->h_tag_count); = b_i64_btoh(in->h_extent_table_offset);
out->r_nr_extents = b_i32_btoh(in->h_tag_count); out->c_info.c_cluster_table_offset
out->r_nr_cluster_groups = b_i32_btoh(in->h_cluster_group_count); = 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) 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); memset(reader, 0x0, sizeof *reader);
reader->c_fp = inp;
decode_header(&header, reader); decode_header(&header, reader);
unsigned short compression = b_i16_btoh(header.h_compression); unsigned short compression = b_i16_btoh(header.h_compression);
unsigned short encryption = b_i16_btoh(header.h_encryption); 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; stages[0].type = EC3_PIPELINE_FILE;
if (encryption != EC3_ENCRYPTION_NONE) { 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) { 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( enum ec3_status status = ec3_pipeline_create(
stages, stages,
sizeof stages / sizeof stages[0], sizeof stages / sizeof stages[0],
reader->r_cluster_size, reader->c_info.c_cluster_size,
&reader->r_pipeline); &reader->r_pipeline);
if (status != EC3_SUCCESS) { if (status != EC3_SUCCESS) {
@@ -80,20 +151,79 @@ enum ec3_status ec3_reader_create(FILE *inp, struct ec3_reader **out)
return status; 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; return EC3_SUCCESS;
} }
void ec3_reader_finish(struct ec3_reader *reader) 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) enum ec3_status ec3_tag_reader_close(struct ec3_tag_reader *tag)
{ {
return EC3_ERR_NOT_SUPPORTED;
} }

View File

@@ -3,17 +3,54 @@
#include "status.h" #include "status.h"
#include <stdio.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h>
struct ec3_reader; struct ec3_reader;
struct ec3_tag_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 enum ec3_status ec3_reader_create(FILE *inp, struct ec3_reader **out);
extern void ec3_reader_finish(struct ec3_reader *reader); 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); extern enum ec3_status ec3_tag_reader_close(struct ec3_tag_reader *tag);
#endif #endif