|
Packit |
5e46da |
/*
|
|
Packit |
5e46da |
* This file is part of libudfread
|
|
Packit |
5e46da |
* Copyright (C) 2014-2015 VLC authors and VideoLAN
|
|
Packit |
5e46da |
*
|
|
Packit |
5e46da |
* Authors: Petri Hintukainen <phintuka@users.sourceforge.net>
|
|
Packit |
5e46da |
*
|
|
Packit |
5e46da |
* This library is free software; you can redistribute it and/or
|
|
Packit |
5e46da |
* modify it under the terms of the GNU Lesser General Public
|
|
Packit |
5e46da |
* License as published by the Free Software Foundation; either
|
|
Packit |
5e46da |
* version 2.1 of the License, or (at your option) any later version.
|
|
Packit |
5e46da |
*
|
|
Packit |
5e46da |
* This library is distributed in the hope that it will be useful,
|
|
Packit |
5e46da |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
5e46da |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
5e46da |
* Lesser General Public License for more details.
|
|
Packit |
5e46da |
*
|
|
Packit |
5e46da |
* You should have received a copy of the GNU Lesser General Public
|
|
Packit |
5e46da |
* License along with this library. If not, see
|
|
Packit |
5e46da |
* <http://www.gnu.org/licenses/>.
|
|
Packit |
5e46da |
*/
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
#if HAVE_CONFIG_H
|
|
Packit |
5e46da |
#include "config.h"
|
|
Packit |
5e46da |
#endif
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
#include "ecma167.h"
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
#include <stdint.h>
|
|
Packit |
5e46da |
#include <stdlib.h>
|
|
Packit |
5e46da |
#include <string.h>
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
#include <stdio.h>
|
|
Packit |
5e46da |
#define ecma_error(...) fprintf(stderr, "ecma: " __VA_ARGS__)
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
/*
|
|
Packit |
5e46da |
* Part 1: General
|
|
Packit |
5e46da |
*/
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
/* fixed-length dstring, ECMA 1/7.2.12 */
|
|
Packit |
5e46da |
static uint8_t _decode_dstring(const uint8_t *p, size_t field_length, uint8_t *str)
|
|
Packit |
5e46da |
{
|
|
Packit |
5e46da |
size_t length;
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
if (field_length < 1) {
|
|
Packit |
5e46da |
return 0;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
field_length--;
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
length = _get_u8(p + field_length);
|
|
Packit |
5e46da |
if (length > field_length) {
|
|
Packit |
5e46da |
length = field_length;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
memcpy(str, p, length);
|
|
Packit |
5e46da |
return (uint8_t)length;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
/* Extent Descriptor (ECMA 167, 3/7.1) */
|
|
Packit |
5e46da |
static void _decode_extent_ad(const uint8_t *p, struct extent_ad *ad)
|
|
Packit |
5e46da |
{
|
|
Packit |
5e46da |
ad->length = _get_u32(p + 0);
|
|
Packit |
5e46da |
ad->lba = _get_u32(p + 4);
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
/* Entity Identifier (ECMA 167, 1/7.4) */
|
|
Packit |
5e46da |
void decode_entity_id(const uint8_t *p, struct entity_id *eid)
|
|
Packit |
5e46da |
{
|
|
Packit |
5e46da |
memcpy(eid->identifier, p + 1, 23);
|
|
Packit |
5e46da |
memcpy(eid->identifier_suffix, p + 24, 8);
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
/*
|
|
Packit |
5e46da |
* Part 3: Volume Structure
|
|
Packit |
5e46da |
*/
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
/* Descriptor Tag (ECMA 167, 3/7.2) */
|
|
Packit |
5e46da |
enum tag_identifier decode_descriptor_tag(const uint8_t *buf)
|
|
Packit |
5e46da |
{
|
|
Packit |
5e46da |
uint16_t id;
|
|
Packit |
5e46da |
uint8_t checksum = 0;
|
|
Packit |
5e46da |
int i;
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
id = _get_u16(buf + 0);
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
/* descriptor tag is 16 bytes */
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
/* calculate tag checksum */
|
|
Packit |
5e46da |
for (i = 0; i < 4; i++) {
|
|
Packit |
5e46da |
checksum = (uint8_t)(checksum + buf[i]);
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
for (i = 5; i < 16; i++) {
|
|
Packit |
5e46da |
checksum = (uint8_t)(checksum + buf[i]);
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
if (checksum != buf[4]) {
|
|
Packit |
5e46da |
return ECMA_TAG_NONE;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
return (enum tag_identifier)id;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
/* Primary Volume Descriptor (ECMA 167, 3/10.1) */
|
|
Packit |
5e46da |
void decode_primary_volume(const uint8_t *p, struct primary_volume_descriptor *pvd)
|
|
Packit |
5e46da |
{
|
|
Packit |
5e46da |
pvd->volume_identifier_length = _decode_dstring(p + 24, 32, pvd->volume_identifier);
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
memcpy(pvd->volume_set_identifier, p + 72, 128);
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
/* Anchor Volume Descriptor Pointer (ECMA 167 3/10.2) */
|
|
Packit |
5e46da |
void decode_avdp(const uint8_t *p, struct anchor_volume_descriptor *avdp)
|
|
Packit |
5e46da |
{
|
|
Packit |
5e46da |
/* Main volume descriptor sequence extent */
|
|
Packit |
5e46da |
_decode_extent_ad(p + 16, &avdp->mvds);
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
/* Reserve (backup) volume descriptor sequence extent */
|
|
Packit |
5e46da |
_decode_extent_ad(p + 24, &avdp->rvds);
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
/* Volume Descriptor Pointer (ECMA 167 3/10.3) */
|
|
Packit |
5e46da |
void decode_vdp(const uint8_t *p, struct volume_descriptor_pointer *vdp)
|
|
Packit |
5e46da |
{
|
|
Packit |
5e46da |
_decode_extent_ad(p + 20, &vdp->next_extent);
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
/* Partition Descriptor (ECMA 167 3/10.5) */
|
|
Packit |
5e46da |
void decode_partition(const uint8_t *p, struct partition_descriptor *pd)
|
|
Packit |
5e46da |
{
|
|
Packit |
5e46da |
pd->number = _get_u16(p + 22);
|
|
Packit |
5e46da |
pd->start_block = _get_u32(p + 188);
|
|
Packit |
5e46da |
pd->num_blocks = _get_u32(p + 192);
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
/* Logical Volume Descriptor (ECMA 167 3/10.6) */
|
|
Packit |
5e46da |
void decode_logical_volume(const uint8_t *p, struct logical_volume_descriptor *lvd)
|
|
Packit |
5e46da |
{
|
|
Packit |
5e46da |
size_t map_size;
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
lvd->block_size = _get_u32(p + 212);
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
decode_entity_id(p + 216, &lvd->domain_id);
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
memcpy(lvd->contents_use, p + 248, 16);
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
lvd->partition_map_lable_length = _get_u32(p + 264);
|
|
Packit |
5e46da |
lvd->num_partition_maps = _get_u32(p + 268);
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
/* XXX cut long maps */
|
|
Packit |
5e46da |
map_size = lvd->partition_map_lable_length;
|
|
Packit |
5e46da |
if (map_size > sizeof(lvd->partition_map_table)) {
|
|
Packit |
5e46da |
map_size = sizeof(lvd->partition_map_table);
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
/* input size is one block (2048 bytes) */
|
|
Packit |
5e46da |
if (map_size > 2048 - 440) {
|
|
Packit |
5e46da |
map_size = 2048 - 440;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
memcpy(lvd->partition_map_table, p + 440, map_size);
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
/*
|
|
Packit |
5e46da |
* Part 4: File Structure
|
|
Packit |
5e46da |
*/
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
/* File Set Descriptor (ECMA 167 4/14.1) */
|
|
Packit |
5e46da |
void decode_file_set_descriptor(const uint8_t *p, struct file_set_descriptor *fsd)
|
|
Packit |
5e46da |
{
|
|
Packit |
5e46da |
decode_long_ad(p + 400, &fsd->root_icb);
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
/* File Identifier (ECMA 167 4/14.4) */
|
|
Packit |
5e46da |
size_t decode_file_identifier(const uint8_t *p, size_t size, struct file_identifier *fi)
|
|
Packit |
5e46da |
{
|
|
Packit |
5e46da |
size_t l_iu; /* length of implementation use field */
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
if (size < 38) {
|
|
Packit |
5e46da |
ecma_error("not enough data\n");
|
|
Packit |
5e46da |
return 0;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
fi->characteristic = _get_u8(p + 18);
|
|
Packit |
5e46da |
fi->filename_len = _get_u8(p + 19);
|
|
Packit |
5e46da |
decode_long_ad(p + 20, &fi->icb);
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
l_iu = _get_u16(p + 36);
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
if (size < 38 + l_iu + fi->filename_len) {
|
|
Packit |
5e46da |
ecma_error("not enough data\n");
|
|
Packit |
5e46da |
return 0;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
if (fi->filename_len) {
|
|
Packit |
5e46da |
memcpy(fi->filename, p + 38 + l_iu, fi->filename_len);
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
fi->filename[fi->filename_len] = 0;
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
/* ECMA 167, 4/14.4
|
|
Packit |
5e46da |
* padding size 4 * ip((L_FI+L_IU+38+3)/4) - (L_FI+L_IU+38)
|
|
Packit |
5e46da |
* => padded to dwords
|
|
Packit |
5e46da |
*/
|
|
Packit |
5e46da |
return 4 * ((38 + (size_t)fi->filename_len + l_iu + 3) / 4);
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
/* ICB Tag (ECMA 167 4/14.6) */
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
struct icb_tag {
|
|
Packit |
5e46da |
uint8_t file_type;
|
|
Packit |
5e46da |
uint16_t strategy_type;
|
|
Packit |
5e46da |
uint16_t flags;
|
|
Packit |
5e46da |
};
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
static void _decode_icb_tag(const uint8_t *p, struct icb_tag *tag)
|
|
Packit |
5e46da |
{
|
|
Packit |
5e46da |
tag->strategy_type = _get_u16(p + 4);
|
|
Packit |
5e46da |
tag->file_type = _get_u8 (p + 11);
|
|
Packit |
5e46da |
tag->flags = _get_u16(p + 18);
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
/* Allocation Descriptors */
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
#define AD_LENGTH_MASK 0x3fffffff
|
|
Packit |
5e46da |
#define AD_TYPE(length) ((length) >> 30)
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
/* Short Allocation Descriptor (ECMA 167, 4/14.14.1) */
|
|
Packit |
5e46da |
static void _decode_short_ad(const uint8_t *buf, uint16_t partition, struct long_ad *ad)
|
|
Packit |
5e46da |
{
|
|
Packit |
5e46da |
uint32_t u32 = _get_u32(buf + 0);
|
|
Packit |
5e46da |
ad->extent_type = AD_TYPE(u32);
|
|
Packit |
5e46da |
ad->length = u32 & AD_LENGTH_MASK;
|
|
Packit |
5e46da |
ad->lba = _get_u32(buf + 4);
|
|
Packit |
5e46da |
ad->partition = partition;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
/* Long Allocation Descriptor (ECMA 167, 4/14.14.2) */
|
|
Packit |
5e46da |
void decode_long_ad(const uint8_t *buf, struct long_ad *ad)
|
|
Packit |
5e46da |
{
|
|
Packit |
5e46da |
uint32_t u32 = _get_u32(buf + 0);
|
|
Packit |
5e46da |
ad->extent_type = AD_TYPE(u32);
|
|
Packit |
5e46da |
ad->length = u32 & AD_LENGTH_MASK;
|
|
Packit |
5e46da |
ad->lba = _get_u32(buf + 4);
|
|
Packit |
5e46da |
ad->partition = _get_u16(buf + 8);
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
/* Exrtended Allocation Descriptor (ECMA 167, 4/14.14.3) */
|
|
Packit |
5e46da |
static void _decode_extended_ad(const uint8_t *buf, struct long_ad *ad)
|
|
Packit |
5e46da |
{
|
|
Packit |
5e46da |
uint32_t u32 = _get_u32(buf + 0);
|
|
Packit |
5e46da |
ad->extent_type = AD_TYPE(u32);
|
|
Packit |
5e46da |
ad->length = u32 & AD_LENGTH_MASK;
|
|
Packit |
5e46da |
ad->lba = _get_u32(buf + 12);
|
|
Packit |
5e46da |
ad->partition = _get_u16(buf + 16);
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
/* File Entry */
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
static void _decode_file_ads(const uint8_t *p, int ad_type, uint16_t partition,
|
|
Packit |
5e46da |
struct long_ad *ad, unsigned num_ad)
|
|
Packit |
5e46da |
{
|
|
Packit |
5e46da |
uint32_t i;
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
for (i = 0; i < num_ad; i++) {
|
|
Packit |
5e46da |
switch (ad_type) {
|
|
Packit |
5e46da |
case 0:
|
|
Packit |
5e46da |
_decode_short_ad(p, partition, &ad[i]);
|
|
Packit |
5e46da |
p += 8;
|
|
Packit |
5e46da |
break;
|
|
Packit |
5e46da |
case 1:
|
|
Packit |
5e46da |
decode_long_ad(p, &ad[i]);
|
|
Packit |
5e46da |
p += 16;
|
|
Packit |
5e46da |
break;
|
|
Packit |
5e46da |
case 2:
|
|
Packit |
5e46da |
_decode_extended_ad(p, &ad[i]);
|
|
Packit |
5e46da |
p += 20;
|
|
Packit |
5e46da |
break;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
static struct file_entry *_decode_file_entry(const uint8_t *p, size_t size,
|
|
Packit |
5e46da |
uint16_t partition, uint32_t l_ad, uint32_t p_ad)
|
|
Packit |
5e46da |
{
|
|
Packit |
5e46da |
struct file_entry *fe;
|
|
Packit |
5e46da |
struct icb_tag tag;
|
|
Packit |
5e46da |
uint32_t num_ad;
|
|
Packit |
5e46da |
int content_inline = 0;
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
if (p_ad + l_ad > size) {
|
|
Packit |
5e46da |
ecma_error("not enough data in file entry\n");
|
|
Packit |
5e46da |
return NULL;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
_decode_icb_tag(p + 16, &tag;;
|
|
Packit |
5e46da |
if (tag.strategy_type != 4) {
|
|
Packit |
5e46da |
/* UDF (2.): only ICB strategy types 4 and 4096 shall be recorded */
|
|
Packit |
5e46da |
ecma_error("unsupported icb strategy type %d\n", tag.strategy_type);
|
|
Packit |
5e46da |
return NULL;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
switch (tag.flags & 7) {
|
|
Packit |
5e46da |
case 0: num_ad = l_ad / 8; break;
|
|
Packit |
5e46da |
case 1: num_ad = l_ad / 16; break;
|
|
Packit |
5e46da |
case 2: num_ad = l_ad / 20; break;
|
|
Packit |
5e46da |
case 3:
|
|
Packit |
5e46da |
num_ad = 0;
|
|
Packit |
5e46da |
content_inline = 1;
|
|
Packit |
5e46da |
break;
|
|
Packit |
5e46da |
default:
|
|
Packit |
5e46da |
ecma_error("unsupported icb flags: 0x%x\n", tag.flags);
|
|
Packit |
5e46da |
return NULL;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
if (num_ad < 1) {
|
|
Packit |
5e46da |
fe = (struct file_entry *)calloc(1, sizeof(struct file_entry) + l_ad);
|
|
Packit |
5e46da |
} else {
|
|
Packit |
5e46da |
fe = (struct file_entry *)calloc(1, sizeof(struct file_entry) + sizeof(struct long_ad) * (num_ad - 1));
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
if (!fe) {
|
|
Packit |
5e46da |
return NULL;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
fe->file_type = tag.file_type;
|
|
Packit |
5e46da |
fe->length = _get_u64(p + 56);
|
|
Packit |
5e46da |
fe->ad_type = tag.flags & 7;
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
if (content_inline) {
|
|
Packit |
5e46da |
/* data of small files can be embedded in file entry */
|
|
Packit |
5e46da |
/* copy embedded file data */
|
|
Packit |
5e46da |
fe->content_inline = 1;
|
|
Packit |
5e46da |
fe->u.data.information_length = l_ad;
|
|
Packit |
5e46da |
memcpy(fe->u.data.content, p + p_ad, l_ad);
|
|
Packit |
5e46da |
} else {
|
|
Packit |
5e46da |
fe->u.ads.num_ad = num_ad;
|
|
Packit |
5e46da |
_decode_file_ads(p + p_ad, fe->ad_type, partition, &fe->u.ads.ad[0], num_ad);
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
return fe;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
int decode_allocation_extent(struct file_entry **p_fe, const uint8_t *p, size_t size, uint16_t partition)
|
|
Packit |
5e46da |
{
|
|
Packit |
5e46da |
struct file_entry *fe = *p_fe;
|
|
Packit |
5e46da |
uint32_t l_ad, num_ad;
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
l_ad = _get_u32(p + 20);
|
|
Packit |
5e46da |
if (size < 24 || size - 24 < l_ad) {
|
|
Packit |
5e46da |
ecma_error("decode_allocation_extent: invalid allocation extent (l_ad)\n");
|
|
Packit |
5e46da |
return -1;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
switch (fe->ad_type) {
|
|
Packit |
5e46da |
case 0: num_ad = l_ad / 8; break;
|
|
Packit |
5e46da |
case 1: num_ad = l_ad / 16; break;
|
|
Packit |
5e46da |
case 2: num_ad = l_ad / 20; break;
|
|
Packit |
5e46da |
default:
|
|
Packit |
5e46da |
return -1;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
if (num_ad < 1) {
|
|
Packit |
5e46da |
ecma_error("decode_allocation_extent: empty allocation extent\n");
|
|
Packit |
5e46da |
return 0;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
fe = (struct file_entry *)realloc(*p_fe, sizeof(struct file_entry) + sizeof(struct long_ad) * (fe->u.ads.num_ad + num_ad));
|
|
Packit |
5e46da |
if (!fe) {
|
|
Packit |
5e46da |
return -1;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
*p_fe = fe;
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
/* decode new allocation descriptors */
|
|
Packit |
5e46da |
_decode_file_ads(p + 24, fe->ad_type, partition, &fe->u.ads.ad[fe->u.ads.num_ad], num_ad);
|
|
Packit |
5e46da |
fe->u.ads.num_ad += num_ad;
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
return 0;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
/* File Entry (ECMA 167, 4/14.9) */
|
|
Packit |
5e46da |
struct file_entry *decode_file_entry(const uint8_t *p, size_t size, uint16_t partition)
|
|
Packit |
5e46da |
{
|
|
Packit |
5e46da |
uint32_t l_ea, l_ad;
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
l_ea = _get_u32(p + 168);
|
|
Packit |
5e46da |
l_ad = _get_u32(p + 172);
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
/* check for integer overflow */
|
|
Packit |
5e46da |
if ((uint64_t)l_ea + (uint64_t)l_ad + (uint64_t)176 >= (uint64_t)1<<32) {
|
|
Packit |
5e46da |
ecma_error("invalid file entry\n");
|
|
Packit |
5e46da |
return NULL;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
return _decode_file_entry(p, size, partition, l_ad, 176 + l_ea);
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
/* Extended File Entry (ECMA 167, 4/14.17) */
|
|
Packit |
5e46da |
struct file_entry *decode_ext_file_entry(const uint8_t *p, size_t size, uint16_t partition)
|
|
Packit |
5e46da |
{
|
|
Packit |
5e46da |
uint32_t l_ea, l_ad;
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
l_ea = _get_u32(p + 208);
|
|
Packit |
5e46da |
l_ad = _get_u32(p + 212);
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
/* check for integer overflow */
|
|
Packit |
5e46da |
if ((uint64_t)l_ea + (uint64_t)l_ad + (uint64_t)216 >= (uint64_t)1<<32) {
|
|
Packit |
5e46da |
ecma_error("invalid file entry\n");
|
|
Packit |
5e46da |
return NULL;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
return _decode_file_entry(p, size, partition, l_ad, 216 + l_ea);
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
|
|
Packit |
5e46da |
void free_file_entry(struct file_entry **p_fe)
|
|
Packit |
5e46da |
{
|
|
Packit |
5e46da |
if (p_fe) {
|
|
Packit |
5e46da |
free(*p_fe);
|
|
Packit |
5e46da |
*p_fe = NULL;
|
|
Packit |
5e46da |
}
|
|
Packit |
5e46da |
}
|