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 #if HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include "udfread.h"
27
28 #ifdef HAVE_UDFREAD_VERSION_H
29 #include "udfread-version.h"
30 #endif
31
32 #include "blockinput.h"
33 #include "default_blockinput.h"
34 #include "ecma167.h"
35
36 #include <stdint.h>
37 #include <stdlib.h>
38 #include <string.h>
39
40 #ifdef _WIN32
41 #define strtok_r strtok_s
42 #endif
43
44
45 /*
46 * Logging
47 */
48
49 #include <stdio.h>
50
51 static int enable_log = 0;
52 static int enable_trace = 0;
53
54 #define udf_error(...) do { fprintf(stderr, "udfread ERROR: " __VA_ARGS__); } while (0)
55 #define udf_log(...) do { if (enable_log) fprintf(stderr, "udfread LOG : " __VA_ARGS__); } while (0)
56 #define udf_trace(...) do { if (enable_trace) fprintf(stderr, "udfread TRACE: " __VA_ARGS__); } while (0)
57
58
59 /*
60 * atomic operations
61 */
62
63 #if defined (__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) || (defined (__clang__) && (defined (__x86_64__) || defined (__i386__)))
64
65 # define atomic_pointer_compare_and_exchange(atomic, oldval, newval) \
66 __sync_bool_compare_and_swap((atomic), (oldval), (newval))
67
68 #elif defined(_WIN32)
69
70 #include <windows.h>
71
atomic_pointer_compare_and_exchange(void * atomic,void * oldval,void * newval)72 static int atomic_pointer_compare_and_exchange(void *atomic, void *oldval, void *newval)
73 {
74 static int init = 0;
75 static CRITICAL_SECTION cs = {0};
76 if (!init) {
77 init = 1;
78 InitializeCriticalSection(&cs);
79 }
80 int result;
81 EnterCriticalSection(&cs);
82 result = *(void**)atomic == oldval;
83 if (result) {
84 *(void**)atomic = newval;
85 }
86 LeaveCriticalSection(&cs);
87 return result;
88 }
89
90 #elif defined(HAVE_PTHREAD_H)
91
92 #include <pthread.h>
93
atomic_pointer_compare_and_exchange(void * atomic,void * oldval,void * newval)94 static int atomic_pointer_compare_and_exchange(void *atomic, void *oldval, void *newval)
95 {
96 static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
97 int result;
98 pthread_mutex_lock(&lock);
99 result = *(void**)atomic == oldval;
100 if (result) {
101 *(void**)atomic = newval;
102 }
103 pthread_mutex_unlock(&lock);
104 return result;
105 }
106
107 #else
108 # error no atomic operation support
109 #endif
110
111
112 /*
113 * utils
114 */
115
_str_dup(const char * s)116 static char *_str_dup(const char *s)
117 {
118 size_t len = strlen(s);
119 char *p = (char *)malloc(len + 1);
120 if (p) {
121 memcpy(p, s, len + 1);
122 } else {
123 udf_error("out of memory\n");
124 }
125 return p;
126 }
127
_safe_realloc(void * p,size_t s)128 static void *_safe_realloc(void *p, size_t s)
129 {
130 void *result = realloc(p, s);
131 if (!result) {
132 udf_error("out of memory\n");
133 free(p);
134 }
135 return result;
136 }
137
138
139 /*
140 * Decoding
141 */
142
143 /*
144 * outputs Modified UTF-8 (MUTF-8).
145 * The null character (U+0000) uses the two-byte overlong encoding 11000000 10000000 (hexadecimal C0 80), instead of 00000000 (hexadecimal 00).
146 *
147 * - not strictly UTF-8 compilant, but works with C str*() functions and Java, while \0 bytes in middle of strings won't.
148 */
149
150 #define utf16lo_to_mutf8(out, out_pos, out_size, ch) \
151 do { \
152 if (ch != 0 && ch < 0x80) { \
153 out[out_pos++] = (uint8_t)ch; \
154 } else { \
155 out_size++; \
156 out = (uint8_t *)_safe_realloc(out, out_size);\
157 if (!out) return NULL; \
158 \
159 out[out_pos++] = 0xc0 | (ch >> 6); \
160 out[out_pos++] = 0x80 | (ch & 0x3f); \
161 } \
162 } while (0)
163
164 #define utf16_to_mutf8(out, out_pos, out_size, ch) \
165 do { \
166 if (ch < 0x7ff) { \
167 utf16lo_to_mutf8(out, out_pos, out_size, ch); \
168 } else { \
169 out_size += 2; \
170 out = (uint8_t *)_safe_realloc(out, out_size); \
171 if (!out) return NULL; \
172 \
173 out[out_pos++] = 0xe0 | (ch >> 12); \
174 out[out_pos++] = 0x80 | ((ch >> 6) & 0x3f); \
175 out[out_pos++] = 0x80 | (ch & 0x3f); \
176 \
177 } \
178 } while (0)
179
180 /* Strings, CS0 (UDF 2.1.1) */
_cs0_to_mutf8(const uint8_t * cs0,size_t size)181 static char *_cs0_to_mutf8(const uint8_t *cs0, size_t size)
182 {
183 size_t out_pos = 0;
184 size_t out_size = size;
185 size_t i;
186 uint8_t *out;
187
188 if (size < 1) {
189 /* empty string */
190 return calloc(1, 1);
191 }
192
193 out = (uint8_t *)malloc(size);
194 if (!out) {
195 udf_error("out of memory\n");
196 return NULL;
197 }
198
199 switch (cs0[0]) {
200 case 8:
201 /*udf_trace("string in utf-8\n");*/
202 for (i = 1; i < size; i++) {
203 utf16lo_to_mutf8(out, out_pos, out_size, cs0[i]);
204 }
205 break;
206 case 16:
207 for (i = 1; i < size - 1; i+=2) {
208 uint16_t ch = cs0[i + 1] | (cs0[i] << 8);
209 utf16_to_mutf8(out, out_pos, out_size, ch);
210 }
211 break;
212 default:
213 udf_error("unregonized string encoding %u\n", cs0[0]);
214 free(out);
215 return NULL;
216 }
217
218 out[out_pos] = 0;
219 return (char*)out;
220 }
221
222
223 /* Domain Identifiers, UDF 2.1.5.2 */
224
225 static const char lvd_domain_id[] = "*OSTA UDF Compliant";
226 static const char meta_domain_id[] = "*UDF Metadata Partition";
227
_check_domain_identifier(const struct entity_id * eid,const char * value)228 static int _check_domain_identifier(const struct entity_id *eid, const char *value)
229 {
230 return (!memcmp(value, eid->identifier, strlen(value))) ? 0 : -1;
231 }
232
233 /* Additional File Types (UDF 2.60, 2.3.5.2) */
234
235 enum udf_file_type {
236 UDF_FT_METADATA = 250,
237 UDF_FT_METADATA_MIRROR = 251,
238 };
239
240
241 /*
242 * Block access
243 *
244 * read block(s) from absolute lba
245 */
246
_read_blocks(udfread_block_input * input,uint32_t lba,void * buf,uint32_t nblocks,int flags)247 static uint32_t _read_blocks(udfread_block_input *input,
248 uint32_t lba, void *buf, uint32_t nblocks,
249 int flags)
250 {
251 int result;
252
253 if (!input || (int)nblocks < 1) {
254 return 0;
255 }
256
257 result = input->read(input, lba, buf, nblocks, flags);
258
259 return result < 0 ? 0 : (uint32_t)result;
260 }
261
_read_descriptor_block(udfread_block_input * input,uint32_t lba,uint8_t * buf)262 static int _read_descriptor_block(udfread_block_input *input, uint32_t lba, uint8_t *buf)
263 {
264 if (_read_blocks(input, lba, buf, 1, 0) == 1) {
265 return decode_descriptor_tag(buf);
266 }
267
268 return -1;
269 }
270
271
272 /*
273 * Disc probing
274 */
275
_probe_volume(udfread_block_input * input)276 static int _probe_volume(udfread_block_input *input)
277 {
278 /* Volume Recognition (ECMA 167 2/8, UDF 2.60 2.1.7) */
279
280 static const char bea[] = {'\0', 'B', 'E', 'A', '0', '1', '\1'};
281 static const char nsr_02[] = {'\0', 'N', 'S', 'R', '0', '2', '\1'};
282 static const char nsr_03[] = {'\0', 'N', 'S', 'R', '0', '3', '\1'};
283 static const char tea[] = {'\0', 'T', 'E', 'A', '0', '1', '\1'};
284 static const char nul[] = {'\0', '\0', '\0', '\0', '\0', '\0', '\0'};
285
286 uint8_t buf[UDF_BLOCK_SIZE];
287 uint32_t lba;
288 int bea_seen = 0;
289
290 for (lba = 16; lba < 256; lba++) {
291 if (_read_blocks(input, lba, buf, 1, 0) == 1) {
292
293 /* Terminating Extended Area Descriptor */
294 if (!memcmp(buf, tea, sizeof(tea))) {
295 udf_error("ECMA 167 Volume Recognition failed (no NSR descriptor)\n");
296 return -1;
297 }
298 if (!memcmp(buf, nul, sizeof(nul))) {
299 break;
300 }
301 if (!memcmp(buf, bea, sizeof(bea))) {
302 udf_trace("ECMA 167 Volume, BEA01\n");
303 bea_seen = 1;
304 }
305
306 if (bea_seen) {
307 if (!memcmp(buf, nsr_02, sizeof(nsr_02))) {
308 udf_trace("ECMA 167 Volume, NSR02\n");
309 return 0;
310 }
311 if (!memcmp(buf, nsr_03, sizeof(nsr_03))) {
312 udf_trace("ECMA 167 Volume, NSR03\n");
313 return 0;
314 }
315 }
316 }
317 }
318
319 udf_error("ECMA 167 Volume Recognition failed\n");
320 return -1;
321 }
322
_read_avdp(udfread_block_input * input,struct anchor_volume_descriptor * avdp)323 static int _read_avdp(udfread_block_input *input, struct anchor_volume_descriptor *avdp)
324 {
325 uint8_t buf[UDF_BLOCK_SIZE];
326 int tag_id;
327 uint32_t lba = 256;
328
329 /*
330 * Find Anchor Volume Descriptor Pointer.
331 * It is in block 256, last block or (last block - 256)
332 * (UDF 2.60, 2.2.3)
333 */
334
335 /* try block 256 */
336 tag_id = _read_descriptor_block(input, lba, buf);
337 if (tag_id != ECMA_AnchorVolumeDescriptorPointer) {
338
339 /* try last block */
340 if (!input->size) {
341 udf_error("Can't find Anchor Volume Descriptor Pointer\n");
342 return -1;
343 }
344
345 lba = input->size(input) - 1;
346 tag_id = _read_descriptor_block(input, lba, buf);
347 if (tag_id != ECMA_AnchorVolumeDescriptorPointer) {
348
349 /* try last block - 256 */
350 lba -= 256;
351 tag_id = _read_descriptor_block(input, lba, buf);
352 if (tag_id != ECMA_AnchorVolumeDescriptorPointer) {
353 udf_error("Can't find Anchor Volume Descriptor Pointer\n");
354 return -1;
355 }
356 }
357 }
358 udf_log("Found Anchor Volume Descriptor Pointer from lba %u\n", lba);
359
360 decode_avdp(buf, avdp);
361
362 return 1;
363 }
364
365
366 /*
367 * Volume structure
368 */
369
370 /* Logical Partitions from Logical Volume Descriptor */
371 struct udf_partitions {
372 uint32_t num_partition;
373 struct {
374 uint16_t number;
375 uint32_t lba;
376 uint32_t mirror_lba;
377 } p[2];
378 };
379
380 struct volume_descriptor_set {
381 struct partition_descriptor pd;
382 struct primary_volume_descriptor pvd;
383 struct logical_volume_descriptor lvd;
384 };
385
_search_vds(udfread_block_input * input,int part_number,const struct extent_ad * loc,struct volume_descriptor_set * vds)386 static int _search_vds(udfread_block_input *input, int part_number,
387 const struct extent_ad *loc,
388 struct volume_descriptor_set *vds)
389
390 {
391 struct volume_descriptor_pointer vdp;
392 uint8_t buf[UDF_BLOCK_SIZE];
393 int tag_id;
394 uint32_t lba;
395 uint32_t end_lba;
396 int have_part = 0, have_lvd = 0, have_pvd = 0;
397
398 memset(vds, 0, sizeof(*vds));
399
400 next_extent:
401 udf_trace("reading Volume Descriptor Sequence at lba %u, len %u bytes\n", loc->lba, loc->length);
402
403 end_lba = loc->lba + loc->length / UDF_BLOCK_SIZE;
404
405 /* parse Volume Descriptor Sequence */
406 for (lba = loc->lba; lba < end_lba; lba++) {
407
408 tag_id = _read_descriptor_block(input, lba, buf);
409
410 switch (tag_id) {
411
412 case ECMA_VolumeDescriptorPointer:
413 decode_vdp(buf, &vdp);
414 loc = &vdp.next_extent;
415 goto next_extent;
416
417 case ECMA_PrimaryVolumeDescriptor:
418 udf_log("Primary Volume Descriptor in lba %u\n", lba);
419 decode_primary_volume(buf, &vds->pvd);
420 have_pvd = 1;
421 break;
422
423 case ECMA_LogicalVolumeDescriptor:
424 udf_log("Logical volume descriptor in lba %u\n", lba);
425 decode_logical_volume(buf, &vds->lvd);
426 have_lvd = 1;
427 break;
428
429 case ECMA_PartitionDescriptor:
430 udf_log("Partition Descriptor in lba %u\n", lba);
431 if (!have_part) {
432 decode_partition(buf, &vds->pd);
433 have_part = (part_number < 0 || part_number == vds->pd.number);
434 udf_log(" partition %u at lba %u, %u blocks\n", vds->pd.number, vds->pd.start_block, vds->pd.num_blocks);
435 }
436 break;
437
438 case ECMA_TerminatingDescriptor:
439 udf_trace("Terminating Descriptor in lba %u\n", lba);
440 return (have_part && have_lvd) ? 0 : -1;
441 }
442
443 if (have_part && have_lvd && have_pvd) {
444 /* got everything interesting, skip rest blocks */
445 return 0;
446 }
447 }
448
449 return (have_part && have_lvd) ? 0 : -1;
450 }
451
_read_vds(udfread_block_input * input,int part_number,struct volume_descriptor_set * vds)452 static int _read_vds(udfread_block_input *input, int part_number,
453 struct volume_descriptor_set *vds)
454 {
455 struct anchor_volume_descriptor avdp;
456
457 /* Find Anchor Volume Descriptor */
458 if (_read_avdp(input, &avdp) < 0) {
459 return -1;
460 }
461
462 // XXX we could read part of descriptors from main area and rest from backup if both are partially corrupted ...
463
464 /* try to read Main Volume Descriptor Sequence */
465 if (!_search_vds(input, part_number, &avdp.mvds, vds)) {
466 return 0;
467 }
468
469 /* try to read Backup Volume Descriptor */
470 if (!_search_vds(input, part_number, &avdp.rvds, vds)) {
471 return 0;
472 }
473
474 udf_error("failed reading Volume Descriptor Sequence\n");
475 return -1;
476 }
477
_validate_logical_volume(const struct logical_volume_descriptor * lvd,struct long_ad * fsd_loc)478 static int _validate_logical_volume(const struct logical_volume_descriptor *lvd, struct long_ad *fsd_loc)
479 {
480 if (lvd->block_size != UDF_BLOCK_SIZE) {
481 udf_error("incompatible block size %u\n", lvd->block_size);
482 return -1;
483 }
484
485 /* UDF 2.60 2.1.5.2 */
486 if (_check_domain_identifier(&lvd->domain_id, lvd_domain_id) < 0) {
487 udf_error("unknown Domain ID in Logical Volume Descriptor: %1.22s\n", lvd->domain_id.identifier);
488 return -1;
489
490 } else {
491
492 /* UDF 2.60 2.1.5.3 */
493 uint16_t rev = _get_u16(lvd->domain_id.identifier_suffix);
494 udf_log("Found UDF %x.%02x Logical Volume\n", rev >> 8, rev & 0xff);
495
496 /* UDF 2.60 2.2.4.4 */
497
498 /* location of File Set Descriptors */
499 decode_long_ad(lvd->contents_use, fsd_loc);
500
501 udf_log("File Set Descriptor location: partition %u lba %u (len %u)\n",
502 fsd_loc->partition, fsd_loc->lba, fsd_loc->length);
503 }
504
505 return 0;
506 }
507
_map_metadata_partition(udfread_block_input * input,struct udf_partitions * part,uint32_t lba,uint32_t mirror_lba,const struct partition_descriptor * pd)508 static int _map_metadata_partition(udfread_block_input *input,
509 struct udf_partitions *part,
510 uint32_t lba, uint32_t mirror_lba,
511 const struct partition_descriptor *pd)
512 {
513 struct file_entry *fe;
514 uint8_t buf[UDF_BLOCK_SIZE];
515 int tag_id;
516 unsigned int i;
517
518 /* resolve metadata partition location (it is virtual partition inside another partition) */
519 udf_trace("Reading metadata file entry: lba %u, mirror lba %u\n", lba, mirror_lba);
520
521 for (i = 0; i < 2; i++) {
522
523 if (i == 0) {
524 tag_id = _read_descriptor_block(input, pd->start_block + lba, buf);
525 } else {
526 tag_id = _read_descriptor_block(input, pd->start_block + mirror_lba, buf);
527 }
528
529 if (tag_id != ECMA_ExtendedFileEntry) {
530 udf_error("read metadata file %u: unexpected tag %d\n", i, tag_id);
531 continue;
532 }
533
534 fe = decode_ext_file_entry(buf, UDF_BLOCK_SIZE, pd->number);
535 if (!fe) {
536 udf_error("parsing metadata file entry %u failed\n", i);
537 continue;
538 }
539
540 if (fe->content_inline) {
541 udf_error("invalid metadata file (content inline)\n");
542 } else if (!fe->u.ads.num_ad) {
543 udf_error("invalid metadata file (no allocation descriptors)\n");
544 } else if (fe->file_type == UDF_FT_METADATA) {
545 part->p[1].lba = pd->start_block + fe->u.ads.ad[0].lba;
546 udf_log("metadata file at lba %u\n", part->p[1].lba);
547 } else if (fe->file_type == UDF_FT_METADATA_MIRROR) {
548 part->p[1].mirror_lba = pd->start_block + fe->u.ads.ad[0].lba;
549 udf_log("metadata mirror file at lba %u\n", part->p[1].mirror_lba);
550 } else {
551 udf_error("unknown metadata file type %u\n", fe->file_type);
552 }
553
554 free_file_entry(&fe);
555 }
556
557 if (!part->p[1].lba && part->p[1].mirror_lba) {
558 /* failed reading primary location, must use mirror */
559 part->p[1].lba = part->p[1].mirror_lba;
560 part->p[1].mirror_lba = 0;
561 }
562
563 return part->p[1].lba ? 0 : -1;
564 }
565
_parse_udf_partition_maps(udfread_block_input * input,struct udf_partitions * part,const struct volume_descriptor_set * vds)566 static int _parse_udf_partition_maps(udfread_block_input *input,
567 struct udf_partitions *part,
568 const struct volume_descriptor_set *vds)
569 {
570 /* parse partition maps
571 * There should be one type1 partition.
572 * There may be separate metadata partition.
573 * metadata partition is virtual partition that is mapped to metadata file.
574 */
575
576 const uint8_t *map = vds->lvd.partition_map_table;
577 const uint8_t *end = map + vds->lvd.partition_map_lable_length;
578 unsigned int i;
579 int num_type1_partition = 0;
580
581 udf_log("Partition map count: %u\n", vds->lvd.num_partition_maps);
582 if (vds->lvd.partition_map_lable_length > sizeof(vds->lvd.partition_map_table)) {
583 udf_error("partition map table too big !\n");
584 end -= vds->lvd.partition_map_lable_length - sizeof(vds->lvd.partition_map_table);
585 }
586
587 for (i = 0; i < vds->lvd.num_partition_maps && map + 2 < end; i++) {
588
589 /* Partition map, ECMA 167 3/10.7 */
590 uint8_t type = _get_u8(map + 0);
591 uint8_t len = _get_u8(map + 1);
592 uint16_t ref;
593
594 if (len < 2) {
595 udf_error("invalid partition map length %d\n", (int)len);
596 break;
597 }
598
599 udf_trace("map %u: type %u\n", i, type);
600 if (map + len > end) {
601 udf_error("partition map table too short !\n");
602 break;
603 }
604
605 if (type == 1) {
606
607 /* ECMA 167 Type 1 partition map */
608
609 if (len != 6) {
610 udf_error("invalid type 1 partition map length %d\n", (int)len);
611 break;
612 }
613
614 ref = _get_u16(map + 4);
615 udf_log("partition map: %u: type 1 partition, ref %u\n", i, ref);
616
617 if (num_type1_partition) {
618 udf_error("more than one type1 partitions not supported\n");
619 } else if (ref != vds->pd.number) {
620 udf_error("Logical partition %u refers to another physical partition %u (expected %u)\n", i, ref, vds->pd.number);
621 } else {
622 part->num_partition = 1;
623 part->p[0].number = i;
624 part->p[0].lba = vds->pd.start_block;
625 part->p[0].mirror_lba = 0; /* no mirror for data partition */
626
627 num_type1_partition++;
628 }
629
630 } else if (type == 2) {
631
632 /* Type 2 partition map, UDF 2.60 2.2.18 */
633
634 if (len != 64) {
635 udf_error("invalid type 2 partition map length %d\n", (int)len);
636 break;
637 }
638
639 struct entity_id type_id;
640 decode_entity_id(map + 4, &type_id);
641 if (!_check_domain_identifier(&type_id, meta_domain_id)) {
642
643 /* Metadata Partition, UDF 2.60 2.2.10 */
644
645 uint32_t lba, mirror_lba;
646
647 ref = _get_u16(map + 38);
648 lba = _get_u32(map + 40);
649 mirror_lba = _get_u32(map + 44);
650 if (ref != vds->pd.number) {
651 udf_error("metadata file partition %u != %u\n", ref, vds->pd.number);
652 }
653
654 if (!_map_metadata_partition(input, part, lba, mirror_lba, &vds->pd)) {
655 part->num_partition = 2;
656 part->p[1].number = i;
657 udf_log("partition map: %u: metadata partition, ref %u. lba %u, mirror %u\n", i, ref, part->p[1].lba, part->p[1].mirror_lba);
658 }
659
660 } else {
661 udf_log("%u: unsupported type 2 partition\n", i);
662 }
663 }
664 map += len;
665 }
666
667 return num_type1_partition ? 0 : -1;
668 }
669
670
671 /*
672 * Cached directory data
673 */
674
675 struct udf_file_identifier {
676 char *filename; /* MUTF-8 */
677 struct long_ad icb; /* location of file entry */
678 uint8_t characteristic; /* CHAR_FLAG_* */
679 };
680
681 struct udf_dir {
682 uint32_t num_entries;
683 struct udf_file_identifier *files;
684 struct udf_dir **subdirs;
685 };
686
_free_dir(struct udf_dir ** pp)687 static void _free_dir(struct udf_dir **pp)
688 {
689 if (pp && *pp) {
690 struct udf_dir *p = *pp;
691 uint32_t i;
692
693 if (p->subdirs) {
694 for (i = 0; i < p->num_entries; i++) {
695 _free_dir(&(p->subdirs[i]));
696 }
697 free(p->subdirs);
698 }
699
700 if (p->files) {
701 for (i = 0; i < p->num_entries; i++) {
702 free(p->files[i].filename);
703 }
704 free(p->files);
705 }
706
707 free(p);
708
709 *pp = NULL;
710 }
711 }
712
713
714 /*
715 *
716 */
717
718 struct udfread {
719
720 udfread_block_input *input;
721
722 /* Volume partitions */
723 struct udf_partitions part;
724
725 /* cached directory tree */
726 struct udf_dir *root_dir;
727
728 char *volume_identifier;
729 char volume_set_identifier[128];
730
731 };
732
udfread_init(void)733 udfread *udfread_init(void)
734 {
735 /* set up logging */
736 if (getenv("UDFREAD_LOG")) {
737 enable_log = 1;
738 }
739 if (getenv("UDFREAD_TRACE")) {
740 enable_trace = 1;
741 enable_log = 1;
742 }
743
744 #ifdef HAVE_UDFREAD_VERSION_H
745 udf_log("libudfread " UDFREAD_VERSION_STRING "\n");
746 #endif
747
748 return (udfread *)calloc(1, sizeof(udfread));
749 }
750
751 /*
752 * Metadata
753 */
754
_partition_index(udfread * udf,uint16_t partition_number)755 static int _partition_index(udfread *udf, uint16_t partition_number)
756 {
757 if (partition_number == udf->part.p[0].number) {
758 return 0;
759 } else if (udf->part.num_partition > 1 && partition_number == udf->part.p[1].number) {
760 return 1;
761 }
762
763 udf_error("unknown partition %u\n", partition_number);
764 return -1;
765 }
766
767 /* read metadata blocks. If read fails, try from mirror (if available). */
_read_metadata_blocks(udfread * udf,uint8_t * buf,const struct long_ad * loc)768 static int _read_metadata_blocks(udfread *udf, uint8_t *buf,
769 const struct long_ad *loc)
770 {
771 int tag_id;
772 uint32_t lba, i, got;
773 int part_idx;
774
775 udf_trace("reading metadata from part %u lba %u\n", loc->partition, loc->lba);
776
777 part_idx = _partition_index(udf, loc->partition);
778 if (part_idx < 0) {
779 return -1;
780 }
781
782 /* read first block. Parse and check tag. */
783
784 lba = udf->part.p[part_idx].lba + loc->lba;
785 tag_id = _read_descriptor_block(udf->input, lba, buf);
786
787 if (tag_id < 0) {
788
789 /* try mirror */
790 if (udf->part.p[part_idx].mirror_lba) {
791 udf_log("read metadata from lba %u failed, trying mirror\n", lba);
792 lba = udf->part.p[part_idx].mirror_lba + loc->lba;
793 tag_id = _read_descriptor_block(udf->input, lba, buf);
794 }
795
796 if (tag_id < 0) {
797 udf_error("read metadata from lba %u failed\n", lba);
798 return -1;
799 }
800 }
801
802 /* read following blocks without tag parsing and checksum validation */
803
804 for (i = 1; i <= (loc->length - 1) / UDF_BLOCK_SIZE; i++) {
805
806 lba = udf->part.p[part_idx].lba + loc->lba + i;
807 buf += UDF_BLOCK_SIZE;
808
809 got = _read_blocks(udf->input, lba, buf, 1, 0);
810 if (got != 1) {
811 if (udf->part.p[part_idx].mirror_lba) {
812 udf_log("read metadata from lba %u failed, trying mirror\n", lba);
813 lba = udf->part.p[part_idx].mirror_lba + loc->lba + i;
814 got = _read_blocks(udf->input, lba, buf, 1, 0);
815 }
816 if (got != 1) {
817 udf_error("read metadata from lba %u failed\n", lba);
818 return -1;
819 }
820 }
821 }
822
823 return tag_id;
824 }
825
_read_metadata(udfread * udf,const struct long_ad * icb,int * tag_id)826 static uint8_t *_read_metadata(udfread *udf, const struct long_ad *icb, int *tag_id)
827 {
828 uint32_t num_blocks = (icb->length + UDF_BLOCK_SIZE - 1) / UDF_BLOCK_SIZE;
829 uint8_t *buf;
830
831 if (num_blocks < 1) {
832 return NULL;
833 }
834
835 buf = (uint8_t *)malloc(num_blocks * UDF_BLOCK_SIZE);
836 if (!buf) {
837 udf_error("out of memory\n");
838 return NULL;
839 }
840
841 *tag_id = _read_metadata_blocks(udf, buf, icb);
842 if (*tag_id < 0) {
843 udf_log("reading icb blocks failed\n");
844 free(buf);
845 return NULL;
846 }
847
848 return buf;
849 }
850
_read_file_entry(udfread * udf,const struct long_ad * icb)851 static struct file_entry *_read_file_entry(udfread *udf,
852 const struct long_ad *icb)
853 {
854 struct file_entry *fe = NULL;
855 uint8_t *buf;
856 int tag_id;
857
858 udf_trace("file entry size %u bytes\n", icb->length);
859
860 buf = _read_metadata(udf, icb, &tag_id);
861 if (!buf) {
862 udf_error("reading file entry failed\n");
863 return NULL;
864 }
865
866 switch (tag_id) {
867 case ECMA_FileEntry:
868 fe = decode_file_entry(buf, UDF_BLOCK_SIZE, icb->partition);
869 break;
870 case ECMA_ExtendedFileEntry:
871 fe = decode_ext_file_entry(buf, UDF_BLOCK_SIZE, icb->partition);
872 break;
873 default:
874 udf_error("_read_file_entry: unknown tag %d\n", tag_id);
875 break;
876 }
877
878 free(buf);
879
880 /* read possible additional allocation extents */
881 if (fe && !fe->content_inline) {
882 while (fe->u.ads.num_ad > 0 &&
883 fe->u.ads.ad[fe->u.ads.num_ad - 1].extent_type == ECMA_AD_EXTENT_AD) {
884
885 /* drop pointer to this extent from the end of AD list */
886 fe->u.ads.num_ad--;
887
888 icb = &fe->u.ads.ad[fe->u.ads.num_ad];
889 udf_log("_read_file_entry: reading allocation extent @%u\n", icb->lba);
890
891 buf = _read_metadata(udf, icb, &tag_id);
892 if (!buf) {
893 udf_error("_read_file_entry: reading allocation extent @%u failed\n", icb->lba);
894 break;
895 }
896
897 if (tag_id != ECMA_AllocationExtentDescriptor) {
898 free(buf);
899 udf_error("_read_file_entry: unexpected tag %d (expected ECMA_AllocationExtentDescriptor)\n", tag_id);
900 break;
901 }
902
903 if (decode_allocation_extent(&fe, buf, icb->length, icb->partition) < 0) {
904 free(buf);
905 udf_error("_read_file_entry: decode_allocation_extent() failed\n");
906 break;
907 }
908
909 /* failure before this point will cause an error when reading the file past extent point.
910 (extent ad is left in file ad list). */
911
912 free(buf);
913 }
914 }
915
916 return fe;
917 }
918
_parse_dir(const uint8_t * data,uint32_t length,struct udf_dir * dir)919 static int _parse_dir(const uint8_t *data, uint32_t length, struct udf_dir *dir)
920 {
921 struct file_identifier fid;
922 const uint8_t *p = data;
923 const uint8_t *end = data + length;
924 int tag_id;
925
926 if (length < 16) {
927 return 0;
928 }
929
930 while (p < end - 16) {
931 size_t used;
932
933 if (dir->num_entries == UINT32_MAX) {
934 return 0;
935 }
936
937 tag_id = decode_descriptor_tag(p);
938 if (tag_id != ECMA_FileIdentifierDescriptor) {
939 udf_error("unexpected tag %d in directory file\n", tag_id);
940 return -1;
941 }
942
943 dir->files = (struct udf_file_identifier *)_safe_realloc(dir->files, sizeof(dir->files[0]) * (dir->num_entries + 1));
944 if (!dir->files) {
945 return -1;
946 }
947
948 used = decode_file_identifier(p, (size_t)(end - p), &fid);
949 if (used == 0) {
950 /* not enough data. keep the entries we already have. */
951 break;
952 }
953 p += used;
954
955 if (fid.characteristic & CHAR_FLAG_PARENT) {
956 continue;
957 }
958 if (fid.filename_len < 1) {
959 continue;
960 }
961
962 dir->files[dir->num_entries].characteristic = fid.characteristic;
963 dir->files[dir->num_entries].icb = fid.icb;
964 dir->files[dir->num_entries].filename = _cs0_to_mutf8(fid.filename, fid.filename_len);
965
966 if (!dir->files[dir->num_entries].filename) {
967 continue;
968 }
969
970 /* Skip empty file identifiers.
971 * Not strictly compilant (?), \0 is allowed in
972 * ECMA167 file identifier.
973 */
974 if (!dir->files[dir->num_entries].filename[0]) {
975 udf_error("skipping empty file identifier\n");
976 free(dir->files[dir->num_entries].filename);
977 continue;
978 }
979
980 dir->num_entries++;
981 }
982
983 return 0;
984 }
985
_read_dir_file(udfread * udf,const struct long_ad * loc)986 static struct udf_dir *_read_dir_file(udfread *udf, const struct long_ad *loc)
987 {
988 struct udf_dir *dir = NULL;
989 uint8_t *data;
990 int tag_id;
991
992 udf_trace("directory size %u bytes\n", loc->length);
993
994 data = _read_metadata(udf, loc, &tag_id);
995 if (!data) {
996 udf_error("reading directory file failed\n");
997 return NULL;
998 }
999
1000 dir = (struct udf_dir *)calloc(1, sizeof(struct udf_dir));
1001 if (dir) {
1002 if (_parse_dir(data, loc->length, dir) < 0) {
1003 _free_dir(&dir);
1004 }
1005 }
1006
1007 free(data);
1008 return dir;
1009 }
1010
_read_dir(udfread * udf,const struct long_ad * icb)1011 static struct udf_dir *_read_dir(udfread *udf, const struct long_ad *icb)
1012 {
1013 struct file_entry *fe;
1014 struct udf_dir *dir = NULL;
1015
1016 fe = _read_file_entry(udf, icb);
1017 if (!fe) {
1018 udf_error("error reading directory file entry\n");
1019 return NULL;
1020 }
1021
1022 if (fe->file_type != ECMA_FT_DIR) {
1023 udf_error("directory file type is not directory\n");
1024 free_file_entry(&fe);
1025 return NULL;
1026 }
1027
1028 if (fe->content_inline) {
1029 dir = (struct udf_dir *)calloc(1, sizeof(struct udf_dir));
1030 if (dir) {
1031 if (_parse_dir(&fe->u.data.content[0], fe->u.data.information_length, dir) < 0) {
1032 udf_error("failed parsing inline directory file\n");
1033 _free_dir(&dir);
1034 }
1035 }
1036
1037 } else if (fe->u.ads.num_ad == 0) {
1038 udf_error("empty directory file");
1039 } else {
1040 if (fe->u.ads.num_ad > 1) {
1041 udf_error("unsupported fragmented directory file\n");
1042 }
1043 dir = _read_dir_file(udf, &fe->u.ads.ad[0]);
1044 }
1045
1046 free_file_entry(&fe);
1047 return dir;
1048 }
1049
_read_root_dir(udfread * udf,const struct long_ad * fsd_loc)1050 static int _read_root_dir(udfread *udf, const struct long_ad *fsd_loc)
1051 {
1052 struct file_set_descriptor fsd;
1053 uint8_t buf[UDF_BLOCK_SIZE];
1054 int tag_id = -1;
1055 struct long_ad loc = *fsd_loc;
1056
1057 udf_trace("reading root directory fsd from part %u lba %u\n", fsd_loc->partition, fsd_loc->lba);
1058
1059 /* search for File Set Descriptor from the area described by fsd_loc */
1060
1061 loc.length = UDF_BLOCK_SIZE;
1062 for (; loc.lba <= fsd_loc->lba + (fsd_loc->length - 1) / UDF_BLOCK_SIZE; loc.lba++) {
1063
1064 tag_id = _read_metadata_blocks(udf, buf, &loc);
1065 if (tag_id == ECMA_FileSetDescriptor) {
1066 break;
1067 }
1068 if (tag_id == ECMA_TerminatingDescriptor) {
1069 break;
1070 }
1071 udf_error("unhandled tag %d in File Set Descriptor area\n", tag_id);
1072 }
1073 if (tag_id != ECMA_FileSetDescriptor) {
1074 udf_error("didn't find File Set Descriptor\n");
1075 return -1;
1076 }
1077
1078 decode_file_set_descriptor(buf, &fsd);
1079 udf_log("root directory in part %u lba %u\n", fsd.root_icb.partition, fsd.root_icb.lba);
1080
1081 /* read root directory from location given in File Set Descriptor */
1082
1083 udf->root_dir = _read_dir(udf, &fsd.root_icb);
1084 if (!udf->root_dir) {
1085 udf_error("error reading root directory\n");
1086 return -1;
1087 }
1088
1089 return 0;
1090 }
1091
_read_subdir(udfread * udf,struct udf_dir * dir,uint32_t index)1092 static struct udf_dir *_read_subdir(udfread *udf, struct udf_dir *dir, uint32_t index)
1093 {
1094 if (!(dir->files[index].characteristic & CHAR_FLAG_DIR)) {
1095 return NULL;
1096 }
1097
1098 if (!dir->subdirs) {
1099 struct udf_dir **subdirs = (struct udf_dir **)calloc(sizeof(struct udf_dir *), dir->num_entries);
1100 if (!subdirs) {
1101 udf_error("out of memory\n");
1102 return NULL;
1103 }
1104 if (!atomic_pointer_compare_and_exchange(&dir->subdirs, NULL, subdirs)) {
1105 free(subdirs);
1106 }
1107 }
1108
1109 if (!dir->subdirs[index]) {
1110 struct udf_dir *subdir = _read_dir(udf, &dir->files[index].icb);
1111 if (!subdir) {
1112 return NULL;
1113 }
1114 if (!atomic_pointer_compare_and_exchange(&dir->subdirs[index], NULL, subdir)) {
1115 _free_dir(&subdir);
1116 }
1117 }
1118
1119 return dir->subdirs[index];
1120 }
1121
_scan_dir(const struct udf_dir * dir,const char * filename,uint32_t * index)1122 static int _scan_dir(const struct udf_dir *dir, const char *filename, uint32_t *index)
1123 {
1124 uint32_t i;
1125
1126 for (i = 0; i < dir->num_entries; i++) {
1127 if (!strcmp(filename, dir->files[i].filename)) {
1128 *index = i;
1129 return 0;
1130 }
1131 }
1132
1133 udf_log("file %s not found\n", filename);
1134 return -1;
1135 }
1136
_find_file(udfread * udf,const char * path,struct udf_dir ** p_dir,const struct udf_file_identifier ** p_fid)1137 static int _find_file(udfread *udf, const char *path,
1138 struct udf_dir **p_dir,
1139 const struct udf_file_identifier **p_fid)
1140 {
1141 const struct udf_file_identifier *fid = NULL;
1142 struct udf_dir *current_dir;
1143 char *tmp_path, *save_ptr, *token;
1144
1145 current_dir = udf->root_dir;
1146 if (!current_dir) {
1147 return -1;
1148 }
1149
1150 tmp_path = _str_dup(path);
1151 if (!tmp_path) {
1152 return -1;
1153 }
1154
1155 token = strtok_r(tmp_path, "/\\", &save_ptr);
1156 if (token == NULL) {
1157 udf_trace("_find_file: requested root dir\n");
1158 }
1159
1160 while (token) {
1161 uint32_t index;
1162 if (_scan_dir(current_dir, token, &index) < 0) {
1163 udf_log("_find_file: entry %s not found\n", token);
1164 goto error;
1165 }
1166 fid = ¤t_dir->files[index];
1167
1168 token = strtok_r(NULL, "/\\", &save_ptr);
1169
1170 if (fid->characteristic & CHAR_FLAG_DIR) {
1171 current_dir = _read_subdir(udf, current_dir, index);
1172 if (!current_dir) {
1173 goto error;
1174 }
1175 } else if (token) {
1176 udf_log("_find_file: entry %s not found (parent is file, not directory)\n", token);
1177 goto error;
1178 } else {
1179 // found a file, make sure we won't return directory data
1180 current_dir = NULL;
1181 }
1182 }
1183
1184 if (p_fid) {
1185 if (!fid) {
1186 udf_log("no file identifier found for %s\n", path);
1187 goto error;
1188 }
1189 *p_fid = fid;
1190 }
1191 if (p_dir) {
1192 *p_dir = current_dir;
1193 }
1194
1195 free(tmp_path);
1196 return 0;
1197
1198 error:
1199 free(tmp_path);
1200 return -1;
1201 }
1202
1203
1204 /*
1205 * Volume access API
1206 */
1207
udfread_open_input(udfread * udf,udfread_block_input * input)1208 int udfread_open_input(udfread *udf, udfread_block_input *input/*, int partition*/)
1209 {
1210 struct volume_descriptor_set vds;
1211 struct long_ad fsd_location;
1212
1213 if (!udf || !input || !input->read) {
1214 return -1;
1215 }
1216
1217 if (_probe_volume(input) < 0) {
1218 return -1;
1219 }
1220
1221 /* read Volume Descriptor Sequence */
1222 if (_read_vds(input, 0, &vds) < 0) {
1223 return -1;
1224 }
1225
1226 /* validate logical volume structure */
1227 if (_validate_logical_volume(&vds.lvd, &fsd_location) < 0) {
1228 return -1;
1229 }
1230
1231 /* Volume Identifier. CS0, UDF 2.1.1 */
1232 udf->volume_identifier = _cs0_to_mutf8(vds.pvd.volume_identifier, vds.pvd.volume_identifier_length);
1233 if (udf->volume_identifier) {
1234 udf_log("Volume Identifier: %s\n", udf->volume_identifier);
1235 }
1236
1237 memcpy(udf->volume_set_identifier, vds.pvd.volume_set_identifier, 128);
1238
1239 /* map partitions */
1240 if (_parse_udf_partition_maps(input, &udf->part, &vds) < 0) {
1241 return -1;
1242 }
1243
1244 /* Read root directory */
1245 udf->input = input;
1246 if (_read_root_dir(udf, &fsd_location) < 0) {
1247 udf->input = NULL;
1248 return -1;
1249 }
1250
1251 return 0;
1252 }
1253
udfread_open(udfread * udf,const char * path)1254 int udfread_open(udfread *udf, const char *path)
1255 {
1256 udfread_block_input *input;
1257 int result;
1258
1259 if (!path) {
1260 return -1;
1261 }
1262
1263 input = block_input_new(path);
1264 if (!input) {
1265 return -1;
1266 }
1267
1268 result = udfread_open_input(udf, input);
1269 if (result < 0) {
1270 if (input->close) {
1271 input->close(input);
1272 }
1273 }
1274
1275 return result;
1276 }
1277
udfread_close(udfread * udf)1278 void udfread_close(udfread *udf)
1279 {
1280 if (udf) {
1281 if (udf->input) {
1282 if (udf->input->close) {
1283 udf->input->close(udf->input);
1284 }
1285 udf->input = NULL;
1286 }
1287
1288 _free_dir(&udf->root_dir);
1289 free(udf->volume_identifier);
1290 free(udf);
1291 }
1292 }
1293
udfread_get_volume_id(udfread * udf)1294 const char *udfread_get_volume_id(udfread *udf)
1295 {
1296 if (udf) {
1297 return udf->volume_identifier;
1298 }
1299 return NULL;
1300 }
1301
udfread_get_volume_set_id(udfread * udf,void * buffer,size_t size)1302 size_t udfread_get_volume_set_id (udfread *udf, void *buffer, size_t size)
1303 {
1304 if (udf) {
1305 if (size > sizeof(udf->volume_set_identifier)) {
1306 size = sizeof(udf->volume_set_identifier);
1307 }
1308 memcpy(buffer, udf->volume_set_identifier, size);
1309 return sizeof(udf->volume_set_identifier);
1310 }
1311 return 0;
1312 }
1313
1314 /*
1315 * Directory access API
1316 */
1317
1318 struct udfread_dir {
1319 udfread *udf;
1320 struct udf_dir *dir;
1321 uint32_t current_file;
1322 };
1323
_new_udfdir(udfread * udf,struct udf_dir * dir)1324 static UDFDIR *_new_udfdir(udfread *udf, struct udf_dir *dir)
1325 {
1326 UDFDIR *result;
1327
1328 if (!dir) {
1329 return NULL;
1330 }
1331
1332 result = (UDFDIR *)calloc(1, sizeof(UDFDIR));
1333 if (result) {
1334 result->dir = dir;
1335 result->udf = udf;
1336 }
1337
1338 return result;
1339 }
1340
udfread_opendir(udfread * udf,const char * path)1341 UDFDIR *udfread_opendir(udfread *udf, const char *path)
1342 {
1343 struct udf_dir *dir = NULL;
1344
1345 if (!udf || !udf->input || !path) {
1346 return NULL;
1347 }
1348
1349 if (_find_file(udf, path, &dir, NULL) < 0) {
1350 return NULL;
1351 }
1352
1353 return _new_udfdir(udf, dir);
1354 }
1355
udfread_opendir_at(UDFDIR * p,const char * name)1356 UDFDIR *udfread_opendir_at(UDFDIR *p, const char *name)
1357 {
1358 struct udf_dir *dir = NULL;
1359 uint32_t index;
1360
1361 if (!p || !name) {
1362 return NULL;
1363 }
1364
1365 if (_scan_dir(p->dir, name, &index) < 0) {
1366 udf_log("udfread_opendir_at: entry %s not found\n", name);
1367 return NULL;
1368 }
1369
1370 dir = _read_subdir(p->udf, p->dir, index);
1371
1372 return _new_udfdir(p->udf, dir);
1373 }
1374
udfread_readdir(UDFDIR * p,struct udfread_dirent * entry)1375 struct udfread_dirent *udfread_readdir(UDFDIR *p, struct udfread_dirent *entry)
1376 {
1377 const struct udf_file_identifier *fi;
1378
1379 if (!p || !entry || !p->dir) {
1380 return NULL;
1381 }
1382
1383 if (p->current_file >= p->dir->num_entries) {
1384 return NULL;
1385 }
1386
1387 fi = &p->dir->files[p->current_file];
1388
1389 entry->d_name = fi->filename;
1390
1391 if (fi->characteristic & CHAR_FLAG_PARENT) {
1392 entry->d_type = UDF_DT_DIR;
1393 entry->d_name = "..";
1394 } else if (fi->characteristic & CHAR_FLAG_DIR) {
1395 entry->d_type = UDF_DT_DIR;
1396 } else {
1397 entry->d_type = UDF_DT_REG;
1398 }
1399
1400 p->current_file++;
1401
1402 return entry;
1403 }
1404
udfread_rewinddir(UDFDIR * p)1405 void udfread_rewinddir(UDFDIR *p)
1406 {
1407 if (p) {
1408 p->current_file = 0;
1409 }
1410 }
1411
udfread_closedir(UDFDIR * p)1412 void udfread_closedir(UDFDIR *p)
1413 {
1414 free(p);
1415 }
1416
1417
1418 /*
1419 * File access API
1420 */
1421
1422 struct udfread_file {
1423 udfread *udf;
1424 struct file_entry *fe;
1425
1426 /* byte stream access */
1427 uint64_t pos;
1428 uint8_t *block;
1429 int block_valid;
1430
1431 void *block_mem;
1432 };
1433
_file_open(udfread * udf,const char * path,const struct udf_file_identifier * fi)1434 static UDFFILE *_file_open(udfread *udf, const char *path, const struct udf_file_identifier *fi)
1435 {
1436 struct file_entry *fe;
1437 UDFFILE *result;
1438
1439 if (fi->characteristic & CHAR_FLAG_DIR) {
1440 udf_log("error opening file %s (is directory)\n", path);
1441 return NULL;
1442 }
1443
1444 fe = _read_file_entry(udf, &fi->icb);
1445 if (!fe) {
1446 udf_error("error reading file entry for %s\n", path);
1447 return NULL;
1448 }
1449
1450 result = (UDFFILE *)calloc(1, sizeof(UDFFILE));
1451 if (!result) {
1452 free_file_entry(&fe);
1453 return NULL;
1454 }
1455
1456 result->udf = udf;
1457 result->fe = fe;
1458
1459 return result;
1460 }
1461
udfread_file_open(udfread * udf,const char * path)1462 UDFFILE *udfread_file_open(udfread *udf, const char *path)
1463 {
1464 const struct udf_file_identifier *fi = NULL;
1465
1466 if (!udf || !udf->input || !path) {
1467 return NULL;
1468 }
1469
1470 if (_find_file(udf, path, NULL, &fi) < 0) {
1471 return NULL;
1472 }
1473
1474 return _file_open(udf, path, fi);
1475 }
1476
udfread_file_openat(UDFDIR * dir,const char * name)1477 UDFFILE *udfread_file_openat(UDFDIR *dir, const char *name)
1478 {
1479 uint32_t index;
1480
1481 if (!dir || !name) {
1482 return NULL;
1483 }
1484
1485 if (_scan_dir(dir->dir, name, &index) < 0) {
1486 udf_log("udfread_file_openat: entry %s not found\n", name);
1487 return NULL;
1488 }
1489
1490 return _file_open(dir->udf, name, &dir->dir->files[index]);
1491 }
1492
udfread_file_size(UDFFILE * p)1493 int64_t udfread_file_size(UDFFILE *p)
1494 {
1495 if (p) {
1496 return (int64_t)p->fe->length;
1497 }
1498 return -1;
1499 }
1500
udfread_file_close(UDFFILE * p)1501 void udfread_file_close(UDFFILE *p)
1502 {
1503 if (p) {
1504 free_file_entry(&p->fe);
1505 free(p->block_mem);
1506 free(p);
1507 }
1508 }
1509
1510 /*
1511 * block access
1512 */
1513
_file_lba(UDFFILE * p,uint32_t file_block,uint32_t * extent_length)1514 static uint32_t _file_lba(UDFFILE *p, uint32_t file_block, uint32_t *extent_length)
1515 {
1516 const struct file_entry *fe;
1517 unsigned int i;
1518 uint32_t ad_size;
1519
1520 fe = p->fe;
1521
1522 for (i = 0; i < fe->u.ads.num_ad; i++) {
1523 const struct long_ad *ad = &fe->u.ads.ad[0];
1524 ad_size = (ad[i].length + UDF_BLOCK_SIZE - 1) / UDF_BLOCK_SIZE;
1525 if (file_block < ad_size) {
1526
1527 if (ad[i].extent_type != ECMA_AD_EXTENT_NORMAL) {
1528 if (ad[i].extent_type == ECMA_AD_EXTENT_AD) {
1529 udf_error("unsupported allocation descriptor: extent type %u\n", ad[i].extent_type);
1530 }
1531 return 0;
1532 }
1533
1534 if (!ad[i].lba) {
1535 /* empty file / no allocated space */
1536 return 0;
1537 }
1538
1539 if (ad[i].partition != p->udf->part.p[0].number) {
1540 udf_error("file partition %u != %u\n", ad[i].partition, p->udf->part.p[0].number);
1541 }
1542
1543 if (extent_length) {
1544 *extent_length = ad_size - file_block;
1545 }
1546 return p->udf->part.p[0].lba + ad[i].lba + file_block;
1547 }
1548
1549 file_block -= ad_size;
1550 }
1551
1552 return 0;
1553 }
1554
_file_lba_exists(UDFFILE * p)1555 static int _file_lba_exists(UDFFILE *p)
1556 {
1557 if (!p) {
1558 return 0;
1559 }
1560
1561 if (p->fe->content_inline) {
1562 udf_error("can't map lba for inline file\n");
1563 return 0;
1564 }
1565
1566 return 1;
1567 }
1568
udfread_file_lba(UDFFILE * p,uint32_t file_block)1569 uint32_t udfread_file_lba(UDFFILE *p, uint32_t file_block)
1570 {
1571 if (!_file_lba_exists(p)) {
1572 return 0;
1573 }
1574
1575 return _file_lba(p, file_block, NULL);
1576 }
1577
udfread_read_blocks(UDFFILE * p,void * buf,uint32_t file_block,uint32_t num_blocks,int flags)1578 uint32_t udfread_read_blocks(UDFFILE *p, void *buf, uint32_t file_block, uint32_t num_blocks, int flags)
1579 {
1580 uint32_t i;
1581
1582 if (!num_blocks || !buf) {
1583 return 0;
1584 }
1585
1586 if (!_file_lba_exists(p)) {
1587 return 0;
1588 }
1589
1590 for (i = 0; i < num_blocks; ) {
1591 uint32_t extent_length = 0;
1592 uint32_t lba;
1593 uint8_t *block = (uint8_t *)buf + UDF_BLOCK_SIZE * i;
1594
1595 lba = _file_lba(p, file_block + i, &extent_length);
1596 udf_trace("map block %u to lba %u\n", file_block + i, lba);
1597
1598 if (!lba) {
1599 /* unallocated/unwritten block or EOF */
1600 uint32_t file_blocks = (udfread_file_size(p) + UDF_BLOCK_SIZE - 1) / UDF_BLOCK_SIZE;
1601 if (file_block + i < file_blocks) {
1602 udf_trace("zero-fill unallocated / unwritten block %u\n", file_block + i);
1603 memset(block, 0, UDF_BLOCK_SIZE);
1604 i++;
1605 continue;
1606 }
1607 udf_error("block %u outside of file (size %u blocks)\n", file_block + i, file_blocks);
1608 break;
1609 }
1610
1611 if (extent_length > num_blocks - i) {
1612 extent_length = num_blocks - i;
1613 }
1614
1615 extent_length = _read_blocks(p->udf->input, lba, block, extent_length, flags);
1616 if (extent_length < 1) {
1617 break;
1618 }
1619 i += extent_length;
1620 }
1621 return i;
1622 }
1623
1624 /*
1625 * byte stream
1626 */
1627
_read(UDFFILE * p,void * buf,size_t bytes)1628 static ssize_t _read(UDFFILE *p, void *buf, size_t bytes)
1629 {
1630 /* start from middle of block ?
1631 * maximal file size, i.e. position, is 2^32 * block size
1632 */
1633
1634 size_t pos_off = p->pos % UDF_BLOCK_SIZE;
1635 uint32_t file_block = (uint32_t)(p->pos / UDF_BLOCK_SIZE);
1636 if (pos_off) {
1637 size_t chunk_size = UDF_BLOCK_SIZE - pos_off;
1638 if (!p->block_valid) {
1639 if (udfread_read_blocks(p, p->block, file_block, 1, 0) != 1) {
1640 return -1;
1641 }
1642 p->block_valid = 1;
1643 }
1644 if (chunk_size > bytes) {
1645 chunk_size = bytes;
1646 }
1647 memcpy(buf, p->block + pos_off, chunk_size);
1648 p->pos += (uint64_t)chunk_size;
1649 return (ssize_t)chunk_size;
1650 }
1651
1652 /* read full block(s) ? */
1653 if (bytes >= UDF_BLOCK_SIZE) {
1654 uint32_t num_blocks = bytes / UDF_BLOCK_SIZE;
1655 num_blocks = udfread_read_blocks(p, buf, file_block, num_blocks, 0);
1656 if (num_blocks < 1) {
1657 return -1;
1658 }
1659 p->pos += num_blocks * UDF_BLOCK_SIZE;
1660 return num_blocks * UDF_BLOCK_SIZE;
1661 }
1662
1663 /* read beginning of a block */
1664 if (udfread_read_blocks(p, p->block, file_block, 1, 0) != 1) {
1665 return -1;
1666 }
1667 p->block_valid = 1;
1668 memcpy(buf, p->block, bytes);
1669 p->pos += bytes;
1670 return (ssize_t)bytes;
1671 }
1672
_read_inline(UDFFILE * p,void * buf,size_t bytes)1673 static ssize_t _read_inline(UDFFILE *p, void *buf, size_t bytes)
1674 {
1675 uint64_t information_length = p->fe->u.data.information_length;
1676 size_t pad_size = 0;
1677
1678 if (p->pos + bytes > information_length) {
1679 udf_log("read hits padding in inline file\n");
1680 if (p->pos > information_length) {
1681 pad_size = bytes;
1682 } else {
1683 pad_size = (size_t)(p->pos + bytes - information_length);
1684 }
1685 memset((char*)buf + bytes - pad_size, 0, pad_size);
1686 }
1687
1688 if (pad_size < bytes) {
1689 memcpy(buf, &p->fe->u.data.content[p->pos], bytes - pad_size);
1690 }
1691
1692 p->pos = p->pos + bytes;
1693 return (ssize_t)bytes;
1694 }
1695
1696 #define ALIGN(p, align) \
1697 (uint8_t *)( ((uintptr_t)(p) + ((align)-1)) & ~((uintptr_t)((align)-1)))
1698
udfread_file_read(UDFFILE * p,void * buf,size_t bytes)1699 ssize_t udfread_file_read(UDFFILE *p, void *buf, size_t bytes)
1700 {
1701 uint8_t *bufpt = (uint8_t *)buf;
1702
1703 /* sanity checks */
1704 if (!p || !buf) {
1705 return -1;
1706 }
1707 if ((ssize_t)bytes < 0 || (int64_t)bytes < 0) {
1708 return -1;
1709 }
1710
1711 if (p->pos >= p->fe->length) {
1712 return 0;
1713 }
1714
1715 /* limit range to file size */
1716 if (p->pos + bytes > p->fe->length) {
1717 bytes = (size_t)(p->fe->length - p->pos);
1718 }
1719
1720 /* small files may be stored inline in file entry */
1721 if (p->fe->content_inline) {
1722 return _read_inline(p, buf, bytes);
1723 }
1724
1725 /* allocate temp storage for input block */
1726 if (!p->block) {
1727 p->block_mem = malloc(2 * UDF_BLOCK_SIZE);
1728 if (!p->block_mem) {
1729 return -1;
1730 }
1731 p->block = ALIGN(p->block_mem, UDF_BLOCK_SIZE);
1732 }
1733
1734 /* read chunks */
1735 while (bytes > 0) {
1736 ssize_t r = _read(p, bufpt, bytes);
1737 if (r < 0) {
1738 if (bufpt != buf) {
1739 /* got some bytes */
1740 break;
1741 }
1742 /* got nothing */
1743 return -1;
1744 }
1745 bufpt += r;
1746 bytes -= (size_t)r;
1747 }
1748
1749 return (intptr_t)bufpt - (intptr_t)buf;
1750 }
1751
udfread_file_tell(UDFFILE * p)1752 int64_t udfread_file_tell(UDFFILE *p)
1753 {
1754 if (p) {
1755 return (int64_t)p->pos;
1756 }
1757 return -1;
1758 }
1759
udfread_file_seek(UDFFILE * p,int64_t pos,int whence)1760 int64_t udfread_file_seek(UDFFILE *p, int64_t pos, int whence)
1761 {
1762 if (!p) {
1763 return -1;
1764 }
1765
1766 switch (whence) {
1767 case UDF_SEEK_CUR:
1768 pos = udfread_file_tell(p) + pos;
1769 break;
1770 case UDF_SEEK_END:
1771 pos = udfread_file_size(p) + pos;
1772 break;
1773 case UDF_SEEK_SET:
1774 break;
1775 default:
1776 return -1;
1777 }
1778
1779 if (pos >= 0 && pos <= udfread_file_size(p)) {
1780 p->pos = (uint64_t)pos;
1781 p->block_valid = 0;
1782 return udfread_file_tell(p);
1783 }
1784
1785 return -1;
1786 }
1787