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 "bin.h"
#include "pipeline.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
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,6 +120,7 @@ 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);
@@ -62,17 +131,19 @@ enum ec3_status ec3_reader_create(FILE *inp, struct ec3_reader **out)
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)
{
return EC3_ERR_NOT_SUPPORTED;
}

View File

@@ -3,16 +3,53 @@
#include "status.h"
#include <stdio.h>
#include <stdint.h>
#include <stdio.h>
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);