read tag and extent table in ec3_reader_create
This commit is contained in:
178
src/read.c
178
src/read.c
@@ -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,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)
|
||||
{
|
||||
|
||||
return EC3_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
41
src/read.h
41
src/read.h
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user