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