Blame contrib/libudfread/src/ecma167.h

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
#ifndef UDFREAD_ECMA167_H_
Packit 5e46da
#define UDFREAD_ECMA167_H_
Packit 5e46da
Packit 5e46da
#include <stdint.h> /* *int_t */
Packit 5e46da
#include <stddef.h> /* size_t */
Packit 5e46da
Packit 5e46da
/*
Packit 5e46da
 * Minimal implementation of ECMA-167:
Packit 5e46da
 * Volume and File Structure for Write-Once and Rewritable
Packit 5e46da
 * Media using Non-Sequential Recording for Information Interchange
Packit 5e46da
 *
Packit 5e46da
 * Based on 3rd Edition, June 1997
Packit 5e46da
 * http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-167.pdf
Packit 5e46da
 *
Packit 5e46da
 */
Packit 5e46da
Packit 5e46da
/*
Packit 5e46da
 * Part 1: General
Packit 5e46da
 */
Packit 5e46da
Packit 5e46da
/* Numerical Values (ECMA 167, 1/7.1) */
Packit 5e46da
Packit 5e46da
static inline uint32_t _get_u8(const uint8_t *p)
Packit 5e46da
{
Packit 5e46da
  return (uint32_t)p[0];
Packit 5e46da
}
Packit 5e46da
Packit 5e46da
static inline uint32_t _get_u16(const uint8_t *p)
Packit 5e46da
{
Packit 5e46da
    return _get_u8(p) | (_get_u8(p + 1) << 8);
Packit 5e46da
}
Packit 5e46da
Packit 5e46da
static inline uint32_t _get_u32(const uint8_t *p)
Packit 5e46da
{
Packit 5e46da
    return _get_u16(p) | (_get_u16(p + 2) << 16);
Packit 5e46da
}
Packit 5e46da
Packit 5e46da
static inline uint64_t _get_u64(const uint8_t *p)
Packit 5e46da
{
Packit 5e46da
    return (uint64_t)_get_u32(p) | ((uint64_t)_get_u32(p + 4) << 32);
Packit 5e46da
}
Packit 5e46da
Packit 5e46da
/* Entity Identifier (ECMA 167, 1/7.4) */
Packit 5e46da
Packit 5e46da
struct entity_id {
Packit 5e46da
    uint8_t identifier[23];
Packit 5e46da
    uint8_t identifier_suffix[8];
Packit 5e46da
};
Packit 5e46da
Packit 5e46da
void decode_entity_id(const uint8_t *p, struct entity_id *eid);
Packit 5e46da
Packit 5e46da
/*
Packit 5e46da
 * Part 3: Volume Structure
Packit 5e46da
 */
Packit 5e46da
Packit 5e46da
/* Extent Descriptor (ECMA 167, 3/7.1) */
Packit 5e46da
Packit 5e46da
struct extent_ad {
Packit 5e46da
    uint32_t lba;
Packit 5e46da
    uint32_t length; /* in bytes */
Packit 5e46da
};
Packit 5e46da
Packit 5e46da
/* Descriptor Tag (ECMA 167, 3/7.2) */
Packit 5e46da
Packit 5e46da
enum tag_identifier {
Packit 5e46da
    /* ECMA 167, 3/7.2.1) */
Packit 5e46da
    ECMA_PrimaryVolumeDescriptor              = 1,
Packit 5e46da
    ECMA_AnchorVolumeDescriptorPointer        = 2,
Packit 5e46da
    ECMA_VolumeDescriptorPointer              = 3,
Packit 5e46da
    ECMA_PartitionDescriptor                  = 5,
Packit 5e46da
    ECMA_LogicalVolumeDescriptor              = 6,
Packit 5e46da
    ECMA_TerminatingDescriptor                = 8,
Packit 5e46da
Packit 5e46da
    /* ECMA 167, 4/7.2.1 */
Packit 5e46da
    ECMA_FileSetDescriptor                    = 256,
Packit 5e46da
    ECMA_FileIdentifierDescriptor             = 257,
Packit 5e46da
    ECMA_AllocationExtentDescriptor           = 258,
Packit 5e46da
    ECMA_FileEntry                            = 261,
Packit 5e46da
    ECMA_ExtendedFileEntry                    = 266,
Packit 5e46da
Packit 5e46da
    ECMA_TAG_NONE                             = -1,
Packit 5e46da
};
Packit 5e46da
Packit 5e46da
enum tag_identifier decode_descriptor_tag(const uint8_t *buf);
Packit 5e46da
Packit 5e46da
/* Primary Volume Descriptor (ECMA 167, 3/10.1) */
Packit 5e46da
Packit 5e46da
struct primary_volume_descriptor {
Packit 5e46da
    uint8_t volume_identifier[31];
Packit 5e46da
    uint8_t volume_identifier_length;
Packit 5e46da
    uint8_t volume_set_identifier[128];
Packit 5e46da
};
Packit 5e46da
Packit 5e46da
void decode_primary_volume(const uint8_t *p, struct primary_volume_descriptor *pvd);
Packit 5e46da
Packit 5e46da
/* Anchor Volume Descriptor (ECMA 167, 3/10.2) */
Packit 5e46da
Packit 5e46da
struct anchor_volume_descriptor {
Packit 5e46da
    struct extent_ad mvds; /* Main Volume Descriptor Sequence extent */
Packit 5e46da
    struct extent_ad rvds; /* Reserve Volume Descriptor Sequence extent */
Packit 5e46da
};
Packit 5e46da
Packit 5e46da
void decode_avdp(const uint8_t *p, struct anchor_volume_descriptor *avdp);
Packit 5e46da
Packit 5e46da
/* Volume Descriptor Pointer (ECMA 167, 3/10.3) */
Packit 5e46da
Packit 5e46da
struct volume_descriptor_pointer {
Packit 5e46da
    struct extent_ad next_extent; /* Next Volume Descriptor Sequence Extent */
Packit 5e46da
};
Packit 5e46da
Packit 5e46da
void decode_vdp(const uint8_t *p, struct volume_descriptor_pointer *vdp);
Packit 5e46da
Packit 5e46da
/* Partition Descriptor (ECMA 167, 3/10.5) */
Packit 5e46da
Packit 5e46da
struct partition_descriptor {
Packit 5e46da
    uint16_t number;
Packit 5e46da
    uint32_t start_block;
Packit 5e46da
    uint32_t num_blocks;
Packit 5e46da
};
Packit 5e46da
Packit 5e46da
void decode_partition(const uint8_t *p, struct partition_descriptor *pd);
Packit 5e46da
Packit 5e46da
/* Logical Volume Descriptor (ECMA 167, 3/10.6) */
Packit 5e46da
Packit 5e46da
struct logical_volume_descriptor {
Packit 5e46da
    uint32_t         block_size;
Packit 5e46da
    struct entity_id domain_id;
Packit 5e46da
    uint8_t          contents_use[16];
Packit 5e46da
Packit 5e46da
    uint32_t num_partition_maps;
Packit 5e46da
    uint32_t partition_map_lable_length;
Packit 5e46da
    uint8_t  partition_map_table[2048];
Packit 5e46da
};
Packit 5e46da
Packit 5e46da
void decode_logical_volume(const uint8_t *p, struct logical_volume_descriptor *lvd);
Packit 5e46da
Packit 5e46da
/*
Packit 5e46da
 * Part 4: File Structure
Packit 5e46da
 */
Packit 5e46da
Packit 5e46da
enum {
Packit 5e46da
    ECMA_AD_EXTENT_NORMAL = 0,        /* allocated and recorded file data */
Packit 5e46da
    ECMA_AD_EXTENT_NOT_RECORDED = 1,
Packit 5e46da
    ECMA_AD_EXTENT_NOT_ALLOCATED = 2,
Packit 5e46da
    ECMA_AD_EXTENT_AD = 3,            /* pointer to next extent of allocation descriptors */
Packit 5e46da
};
Packit 5e46da
Packit 5e46da
Packit 5e46da
/* Short/Long/Extended Allocation Descriptor (ECMA 167, 4/14.14.[1,2,3]) */
Packit 5e46da
Packit 5e46da
struct long_ad {
Packit 5e46da
    uint32_t lba;    /* start block, relative to partition start */
Packit 5e46da
    uint32_t length; /* in bytes */
Packit 5e46da
    uint16_t partition;
Packit 5e46da
    uint8_t  extent_type;
Packit 5e46da
};
Packit 5e46da
Packit 5e46da
void decode_long_ad(const uint8_t *p, struct long_ad *ad);
Packit 5e46da
Packit 5e46da
/* File Set Descriptor (ECMA 167 4/14.1) */
Packit 5e46da
Packit 5e46da
struct  file_set_descriptor {
Packit 5e46da
    struct long_ad root_icb;
Packit 5e46da
};
Packit 5e46da
Packit 5e46da
void decode_file_set_descriptor(const uint8_t *p, struct file_set_descriptor *fsd);
Packit 5e46da
Packit 5e46da
/* File Identifier (ECMA 167 4/14.4) */
Packit 5e46da
Packit 5e46da
enum {
Packit 5e46da
    CHAR_FLAG_HIDDEN  = 0x01,
Packit 5e46da
    CHAR_FLAG_DIR     = 0x02,
Packit 5e46da
    CHAR_FLAG_DELETED = 0x04,
Packit 5e46da
    CHAR_FLAG_PARENT  = 0x08,
Packit 5e46da
};
Packit 5e46da
Packit 5e46da
struct file_identifier {
Packit 5e46da
    struct long_ad icb;
Packit 5e46da
    uint8_t        characteristic; /* CHAR_FLAG_* */
Packit 5e46da
    uint8_t        filename_len;
Packit 5e46da
    uint8_t        filename[256];
Packit 5e46da
};
Packit 5e46da
Packit 5e46da
size_t decode_file_identifier(const uint8_t *p, size_t size, struct file_identifier *fi);
Packit 5e46da
Packit 5e46da
/* File Entry (ECMA 167, 4/14.9) */
Packit 5e46da
/* Extended File Entry (ECMA 167, 4/14.17) */
Packit 5e46da
Packit 5e46da
enum {
Packit 5e46da
    /* ECMA 167, 14.6.6 File Type */
Packit 5e46da
    ECMA_FT_UNSPECIFIED     = 0,
Packit 5e46da
    ECMA_FT_INDIRECT        = 3,
Packit 5e46da
    ECMA_FT_DIR             = 4,
Packit 5e46da
    ECMA_FT_BYTESTREAM      = 5,  /* random-access byte stream - regular file - udf 2.60, 2.3.5.2 */
Packit 5e46da
    ECMA_FT_TERMINAL_ENTRY  = 11,
Packit 5e46da
    ECMA_FT_SYMLINK         = 12,
Packit 5e46da
};
Packit 5e46da
Packit 5e46da
struct file_entry {
Packit 5e46da
    uint64_t       length;         /* in bytes */
Packit 5e46da
    uint8_t        file_type;      /* ECMA_FT_* */
Packit 5e46da
    uint8_t        content_inline; /* 1 if file data is embedded in file entry */
Packit 5e46da
    uint8_t        ad_type;        /* from icb_flags; used when parsing allocation extents */
Packit 5e46da
Packit 5e46da
    union {
Packit 5e46da
        /* "normal" file */
Packit 5e46da
        struct {
Packit 5e46da
            uint32_t       num_ad;
Packit 5e46da
            struct long_ad ad[1];      /* Most files have only single extent, files in 3D BDs can have 100+. */
Packit 5e46da
        } ads;
Packit 5e46da
Packit 5e46da
        /* inline file */
Packit 5e46da
        struct {
Packit 5e46da
            uint32_t       information_length; /* recorded information length, may be different than file length */
Packit 5e46da
            uint8_t        content[1]; /* content of small files is embedded here */
Packit 5e46da
        } data;
Packit 5e46da
    } u;
Packit 5e46da
};
Packit 5e46da
Packit 5e46da
struct file_entry *decode_file_entry    (const uint8_t *p, size_t size, uint16_t partition);
Packit 5e46da
struct file_entry *decode_ext_file_entry(const uint8_t *p, size_t size, uint16_t partition);
Packit 5e46da
void               free_file_entry      (struct file_entry **p_fe);
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
#endif /* UDFREAD_ECMA167_H_ */