1 /*
2 * This file is part of libudfread
3 * Copyright (C) 2014-2015 VLC authors and VideoLAN
4 *
5 * Authors: Petri Hintukainen <phintuka@users.sourceforge.net>
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library. If not, see
19 * <http://www.gnu.org/licenses/>.
20 */
21
22 #ifndef UDFREAD_ECMA167_H_
23 #define UDFREAD_ECMA167_H_
24
25 #include <stdint.h> /* *int_t */
26 #include <stddef.h> /* size_t */
27
28 /*
29 * Minimal implementation of ECMA-167:
30 * Volume and File Structure for Write-Once and Rewritable
31 * Media using Non-Sequential Recording for Information Interchange
32 *
33 * Based on 3rd Edition, June 1997
34 * http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-167.pdf
35 *
36 */
37
38 /*
39 * Part 1: General
40 */
41
42 /* Numerical Values (ECMA 167, 1/7.1) */
43
_get_u8(const uint8_t * p)44 static inline uint32_t _get_u8(const uint8_t *p)
45 {
46 return (uint32_t)p[0];
47 }
48
_get_u16(const uint8_t * p)49 static inline uint32_t _get_u16(const uint8_t *p)
50 {
51 return _get_u8(p) | (_get_u8(p + 1) << 8);
52 }
53
_get_u32(const uint8_t * p)54 static inline uint32_t _get_u32(const uint8_t *p)
55 {
56 return _get_u16(p) | (_get_u16(p + 2) << 16);
57 }
58
_get_u64(const uint8_t * p)59 static inline uint64_t _get_u64(const uint8_t *p)
60 {
61 return (uint64_t)_get_u32(p) | ((uint64_t)_get_u32(p + 4) << 32);
62 }
63
64 /* Entity Identifier (ECMA 167, 1/7.4) */
65
66 struct entity_id {
67 uint8_t identifier[23];
68 uint8_t identifier_suffix[8];
69 };
70
71 void decode_entity_id(const uint8_t *p, struct entity_id *eid);
72
73 /*
74 * Part 3: Volume Structure
75 */
76
77 /* Extent Descriptor (ECMA 167, 3/7.1) */
78
79 struct extent_ad {
80 uint32_t lba;
81 uint32_t length; /* in bytes */
82 };
83
84 /* Descriptor Tag (ECMA 167, 3/7.2) */
85
86 enum tag_identifier {
87 /* ECMA 167, 3/7.2.1) */
88 ECMA_PrimaryVolumeDescriptor = 1,
89 ECMA_AnchorVolumeDescriptorPointer = 2,
90 ECMA_VolumeDescriptorPointer = 3,
91 ECMA_PartitionDescriptor = 5,
92 ECMA_LogicalVolumeDescriptor = 6,
93 ECMA_TerminatingDescriptor = 8,
94
95 /* ECMA 167, 4/7.2.1 */
96 ECMA_FileSetDescriptor = 256,
97 ECMA_FileIdentifierDescriptor = 257,
98 ECMA_AllocationExtentDescriptor = 258,
99 ECMA_FileEntry = 261,
100 ECMA_ExtendedFileEntry = 266,
101
102 ECMA_TAG_INVALID = -1, /* checksum failed */
103 };
104
105 enum tag_identifier decode_descriptor_tag(const uint8_t *buf);
106
107 /* Primary Volume Descriptor (ECMA 167, 3/10.1) */
108
109 struct primary_volume_descriptor {
110 uint8_t volume_identifier[31];
111 uint8_t volume_identifier_length;
112 uint8_t volume_set_identifier[128];
113 };
114
115 void decode_primary_volume(const uint8_t *p, struct primary_volume_descriptor *pvd);
116
117 /* Anchor Volume Descriptor (ECMA 167, 3/10.2) */
118
119 struct anchor_volume_descriptor {
120 struct extent_ad mvds; /* Main Volume Descriptor Sequence extent */
121 struct extent_ad rvds; /* Reserve Volume Descriptor Sequence extent */
122 };
123
124 void decode_avdp(const uint8_t *p, struct anchor_volume_descriptor *avdp);
125
126 /* Volume Descriptor Pointer (ECMA 167, 3/10.3) */
127
128 struct volume_descriptor_pointer {
129 struct extent_ad next_extent; /* Next Volume Descriptor Sequence Extent */
130 };
131
132 void decode_vdp(const uint8_t *p, struct volume_descriptor_pointer *vdp);
133
134 /* Partition Descriptor (ECMA 167, 3/10.5) */
135
136 struct partition_descriptor {
137 uint16_t number;
138 uint32_t start_block;
139 uint32_t num_blocks;
140 };
141
142 void decode_partition(const uint8_t *p, struct partition_descriptor *pd);
143
144 /* Logical Volume Descriptor (ECMA 167, 3/10.6) */
145
146 struct logical_volume_descriptor {
147 uint32_t block_size;
148 struct entity_id domain_id;
149 uint8_t contents_use[16];
150
151 uint32_t num_partition_maps;
152 uint32_t partition_map_lable_length;
153 uint8_t partition_map_table[2048];
154 };
155
156 void decode_logical_volume(const uint8_t *p, struct logical_volume_descriptor *lvd);
157
158 /*
159 * Part 4: File Structure
160 */
161
162 enum {
163 ECMA_AD_EXTENT_NORMAL = 0, /* allocated and recorded file data */
164 ECMA_AD_EXTENT_NOT_RECORDED = 1,
165 ECMA_AD_EXTENT_NOT_ALLOCATED = 2,
166 ECMA_AD_EXTENT_AD = 3, /* pointer to next extent of allocation descriptors */
167 };
168
169
170 /* Short/Long/Extended Allocation Descriptor (ECMA 167, 4/14.14.[1,2,3]) */
171
172 struct long_ad {
173 uint32_t lba; /* start block, relative to partition start */
174 uint32_t length; /* in bytes */
175 uint16_t partition;
176 uint8_t extent_type;
177 };
178
179 void decode_long_ad(const uint8_t *p, struct long_ad *ad);
180
181 /* File Set Descriptor (ECMA 167 4/14.1) */
182
183 struct file_set_descriptor {
184 struct long_ad root_icb;
185 };
186
187 void decode_file_set_descriptor(const uint8_t *p, struct file_set_descriptor *fsd);
188
189 /* File Identifier (ECMA 167 4/14.4) */
190
191 enum {
192 CHAR_FLAG_HIDDEN = 0x01,
193 CHAR_FLAG_DIR = 0x02,
194 CHAR_FLAG_DELETED = 0x04,
195 CHAR_FLAG_PARENT = 0x08,
196 };
197
198 struct file_identifier {
199 struct long_ad icb;
200 uint8_t characteristic; /* CHAR_FLAG_* */
201 uint8_t filename_len;
202 uint8_t filename[256];
203 };
204
205 size_t decode_file_identifier(const uint8_t *p, size_t size, struct file_identifier *fi);
206
207 /* File Entry (ECMA 167, 4/14.9) */
208 /* Extended File Entry (ECMA 167, 4/14.17) */
209
210 enum {
211 /* ECMA 167, 14.6.6 File Type */
212 ECMA_FT_UNSPECIFIED = 0,
213 ECMA_FT_INDIRECT = 3,
214 ECMA_FT_DIR = 4,
215 ECMA_FT_BYTESTREAM = 5, /* random-access byte stream - regular file - udf 2.60, 2.3.5.2 */
216 ECMA_FT_TERMINAL_ENTRY = 11,
217 ECMA_FT_SYMLINK = 12,
218 };
219
220 struct file_entry {
221 uint64_t length; /* in bytes */
222 uint8_t file_type; /* ECMA_FT_* */
223 uint8_t content_inline; /* 1 if file data is embedded in file entry */
224 uint8_t ad_type; /* from icb_flags; used when parsing allocation extents */
225
226 union {
227 /* "normal" file */
228 struct {
229 uint32_t num_ad;
230 struct long_ad ad[1]; /* Most files have only single extent, files in 3D BDs can have 100+. */
231 } ads;
232
233 /* inline file */
234 struct {
235 uint32_t information_length; /* recorded information length, may be different than file length */
236 uint8_t content[1]; /* content of small files is embedded here */
237 } data;
238 } u;
239 };
240
241 struct file_entry *decode_file_entry (const uint8_t *p, size_t size, uint16_t partition);
242 struct file_entry *decode_ext_file_entry(const uint8_t *p, size_t size, uint16_t partition);
243 void free_file_entry (struct file_entry **p_fe);
244
245 int decode_allocation_extent(struct file_entry **p_fe, const uint8_t *p, size_t size, uint16_t partition);
246
247 #endif /* UDFREAD_ECMA167_H_ */
248