Commit 1a4788b3 authored by Petri Hintukainen's avatar Petri Hintukainen

Reduce inline file entry memory footprint

parent 7ab0d84e
...@@ -300,16 +300,16 @@ static struct file_entry *_decode_file_entry(const uint8_t *p, size_t size, ...@@ -300,16 +300,16 @@ static struct file_entry *_decode_file_entry(const uint8_t *p, size_t size,
fe->file_type = tag.file_type; fe->file_type = tag.file_type;
fe->length = _get_u64(p + 56); fe->length = _get_u64(p + 56);
fe->num_ad = num_ad;
fe->ad_type = tag.flags & 7; fe->ad_type = tag.flags & 7;
if (content_inline) { if (content_inline) {
/* data of small files can be embedded in file entry */ /* data of small files can be embedded in file entry */
/* copy embedded file data */ /* copy embedded file data */
fe->content_inline = 1; fe->content_inline = 1;
memcpy(fe->data.content, p + p_ad, l_ad); memcpy(fe->u.data.content, p + p_ad, l_ad);
} else { } else {
_decode_file_ads(p + p_ad, fe->ad_type, partition, &fe->data.ad[0], num_ad); fe->u.ads.num_ad = num_ad;
_decode_file_ads(p + p_ad, fe->ad_type, partition, &fe->u.ads.ad[0], num_ad);
} }
return fe; return fe;
...@@ -339,15 +339,15 @@ int decode_allocation_extent(struct file_entry **p_fe, const uint8_t *p, size_t ...@@ -339,15 +339,15 @@ int decode_allocation_extent(struct file_entry **p_fe, const uint8_t *p, size_t
return 0; return 0;
} }
fe = (struct file_entry *)realloc(fe, sizeof(struct file_entry) + sizeof(struct long_ad) * (fe->num_ad + num_ad)); fe = (struct file_entry *)realloc(fe, sizeof(struct file_entry) + sizeof(struct long_ad) * (fe->u.ads.num_ad + num_ad));
if (!fe) { if (!fe) {
return -1; return -1;
} }
*p_fe = fe; *p_fe = fe;
/* decode new allocation descriptors */ /* decode new allocation descriptors */
_decode_file_ads(p + 24, fe->ad_type, partition, &fe->data.ad[fe->num_ad], num_ad); _decode_file_ads(p + 24, fe->ad_type, partition, &fe->u.ads.ad[fe->u.ads.num_ad], num_ad);
fe->num_ad += num_ad; fe->u.ads.num_ad += num_ad;
return 0; return 0;
} }
......
...@@ -214,11 +214,18 @@ struct file_entry { ...@@ -214,11 +214,18 @@ struct file_entry {
uint8_t content_inline; /* 1 if file data is embedded in file entry */ uint8_t content_inline; /* 1 if file data is embedded in file entry */
uint8_t ad_type; /* from icb_flags; used when parsing allocation extents */ uint8_t ad_type; /* from icb_flags; used when parsing allocation extents */
uint32_t num_ad;
union { union {
struct long_ad ad[1]; /* Most files have only single extent, files in 3D BDs can have 100+. */ /* "normal" file */
uint8_t content[1]; /* content of small files is embedded here */ struct {
} data; uint32_t num_ad;
struct long_ad ad[1]; /* Most files have only single extent, files in 3D BDs can have 100+. */
} ads;
/* inline file */
struct {
uint8_t content[1]; /* content of small files is embedded here */
} data;
} u;
}; };
struct file_entry *decode_file_entry (const uint8_t *p, size_t size, uint16_t partition); struct file_entry *decode_file_entry (const uint8_t *p, size_t size, uint16_t partition);
......
...@@ -514,13 +514,13 @@ static int _map_metadata_partition(udfread_block_input *input, ...@@ -514,13 +514,13 @@ static int _map_metadata_partition(udfread_block_input *input,
if (fe->content_inline) { if (fe->content_inline) {
udf_error("invalid metadata file (content inline)\n"); udf_error("invalid metadata file (content inline)\n");
} else if (!fe->num_ad) { } else if (!fe->u.ads.num_ad) {
udf_error("invalid metadata file (no allocation descriptors)\n"); udf_error("invalid metadata file (no allocation descriptors)\n");
} else if (fe->file_type == UDF_FT_METADATA) { } else if (fe->file_type == UDF_FT_METADATA) {
part->p[1].lba = pd->start_block + fe->data.ad[0].lba; part->p[1].lba = pd->start_block + fe->u.ads.ad[0].lba;
udf_log("metadata file at lba %u\n", part->p[1].lba); udf_log("metadata file at lba %u\n", part->p[1].lba);
} else if (fe->file_type == UDF_FT_METADATA_MIRROR) { } else if (fe->file_type == UDF_FT_METADATA_MIRROR) {
part->p[1].mirror_lba = pd->start_block + fe->data.ad[0].lba; part->p[1].mirror_lba = pd->start_block + fe->u.ads.ad[0].lba;
udf_log("metadata mirror file at lba %u\n", part->p[1].mirror_lba); udf_log("metadata mirror file at lba %u\n", part->p[1].mirror_lba);
} else { } else {
udf_error("unknown metadata file type %u\n", fe->file_type); udf_error("unknown metadata file type %u\n", fe->file_type);
...@@ -839,13 +839,13 @@ static struct file_entry *_read_file_entry(udfread *udf, ...@@ -839,13 +839,13 @@ static struct file_entry *_read_file_entry(udfread *udf,
/* read possible additional allocation extents */ /* read possible additional allocation extents */
if (fe) { if (fe) {
while (fe->num_ad > 0 && while (fe->u.ads.num_ad > 0 &&
fe->data.ad[fe->num_ad - 1].extent_type == ECMA_AD_EXTENT_AD) { fe->u.ads.ad[fe->u.ads.num_ad - 1].extent_type == ECMA_AD_EXTENT_AD) {
/* drop pointer to this extent from the end of AD list */ /* drop pointer to this extent from the end of AD list */
fe->num_ad--; fe->u.ads.num_ad--;
icb = &fe->data.ad[fe->num_ad]; icb = &fe->u.ads.ad[fe->u.ads.num_ad];
udf_log("_read_file_entry: reading allocation extent @%u\n", icb->lba); udf_log("_read_file_entry: reading allocation extent @%u\n", icb->lba);
buf = _read_metadata(udf, icb, &tag_id); buf = _read_metadata(udf, icb, &tag_id);
...@@ -963,16 +963,16 @@ static struct udf_dir *_read_dir(udfread *udf, const struct long_ad *icb) ...@@ -963,16 +963,16 @@ static struct udf_dir *_read_dir(udfread *udf, const struct long_ad *icb)
if (fe->content_inline) { if (fe->content_inline) {
dir = (struct udf_dir *)calloc(1, sizeof(struct udf_dir)); dir = (struct udf_dir *)calloc(1, sizeof(struct udf_dir));
if (dir) { if (dir) {
if (_parse_dir(&fe->data.content[0], fe->length, dir) < 0) { if (_parse_dir(&fe->u.data.content[0], fe->length, dir) < 0) {
udf_error("failed parsing inline directory file\n"); udf_error("failed parsing inline directory file\n");
_free_dir(&dir); _free_dir(&dir);
} }
} }
} else if (fe->num_ad == 0) { } else if (fe->u.ads.num_ad == 0) {
udf_error("empty directory file"); udf_error("empty directory file");
} else { } else {
dir = _read_dir_file(udf, &fe->data.ad[0]); dir = _read_dir_file(udf, &fe->u.ads.ad[0]);
} }
free_file_entry(&fe); free_file_entry(&fe);
...@@ -1400,8 +1400,8 @@ static uint32_t _file_lba(UDFFILE *p, uint32_t file_block) ...@@ -1400,8 +1400,8 @@ static uint32_t _file_lba(UDFFILE *p, uint32_t file_block)
fe = p->fe; fe = p->fe;
for (i = 0; i < fe->num_ad; i++) { for (i = 0; i < fe->u.ads.num_ad; i++) {
const struct long_ad *ad = &fe->data.ad[0]; const struct long_ad *ad = &fe->u.ads.ad[0];
ad_size = (ad[i].length + UDF_BLOCK_SIZE - 1) / UDF_BLOCK_SIZE; ad_size = (ad[i].length + UDF_BLOCK_SIZE - 1) / UDF_BLOCK_SIZE;
if (file_block < ad_size) { if (file_block < ad_size) {
...@@ -1560,7 +1560,7 @@ ssize_t udfread_file_read(UDFFILE *p, void *buf, size_t bytes) ...@@ -1560,7 +1560,7 @@ ssize_t udfread_file_read(UDFFILE *p, void *buf, size_t bytes)
/* small files may be stored inline in file entry */ /* small files may be stored inline in file entry */
if (p->fe->content_inline) { if (p->fe->content_inline) {
memcpy(buf, &p->fe->data.content + p->pos, bytes); memcpy(buf, &p->fe->u.data.content + p->pos, bytes);
p->pos += bytes; p->pos += bytes;
return bytes; return bytes;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment