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 = &current_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