source: mainline/uspace/srv/fs/udf/udf_volume.c@ 5c702a8

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 5c702a8 was 5c702a8, checked in by Martin Decky <martin@…>, 13 years ago

dead and unfinished code elimination

  • Property mode set to 100644
File size: 24.3 KB
Line 
1/*
2 * Copyright (c) 2012 Julia Medvedeva
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup fs
30 * @{
31 */
32/**
33 * @file udf_volume.c
34 * @brief Implementation of volume recognition operations.
35 */
36
37#include <byteorder.h>
38#include <block.h>
39#include <libfs.h>
40#include <errno.h>
41#include <str.h>
42#include <malloc.h>
43#include <mem.h>
44#include <inttypes.h>
45#include <io/log.h>
46#include "udf.h"
47#include "udf_volume.h"
48#include "udf_osta.h"
49#include "udf_cksum.h"
50#include "udf_file.h"
51
52/** Convert long_ad to absolute sector position
53 *
54 * Convert address sector concerning origin of partition to position
55 * sector concerning origin of start of disk.
56 *
57 * @param instance UDF instance
58 * @param long_ad UDF long address
59 *
60 * @return Position of sector concerning origin of start of disk.
61 *
62 */
63fs_index_t udf_long_ad_to_pos(udf_instance_t *instance, udf_long_ad_t *long_ad)
64{
65 log_msg(LVL_DEBUG, "Long_Ad to Pos: "
66 "partition_num=%" PRIu16 ", partition_block=%" PRIu32,
67 FLE16(long_ad->location.partition_num),
68 FLE32(long_ad->location.lblock_num));
69
70 return instance->partitions[
71 FLE16(long_ad->location.partition_num)].start +
72 FLE32(long_ad->location.lblock_num);
73}
74
75/** Check type and version of VRS
76 *
77 * Not exactly clear which values could have type and version.
78 *
79 * @param service_id
80 * @param addr Position sector with Volume Descriptor
81 * @param vd Returned value - Volume Descriptor.
82 *
83 * @return EOK on success or a negative error code.
84 *
85 */
86static int udf_volume_recongnition_structure_test(service_id_t service_id,
87 aoff64_t addr, udf_vrs_descriptor_t *vd)
88{
89 return block_read_bytes_direct(service_id, addr,
90 sizeof(udf_vrs_descriptor_t), vd);
91}
92
93/** Read Volume Recognition Sequence
94 *
95 * It is a first udf data which we read.
96 * It stars from fixed address VRS_ADDR = 32768 (bytes)
97 *
98 * @param service_id
99 *
100 * @return EOK on success or a negative error code.
101 */
102int udf_volume_recongnition(service_id_t service_id)
103{
104 aoff64_t addr = VRS_ADDR;
105 bool nsr_found = false;
106
107 udf_vrs_descriptor_t *vd = malloc(sizeof(udf_vrs_descriptor_t));
108 if (!vd)
109 return ENOMEM;
110
111 int rc = udf_volume_recongnition_structure_test(service_id, addr, vd);
112 if (rc != EOK) {
113 free(vd);
114 return rc;
115 }
116
117 for (size_t i = 0; i < VRS_DEPTH; i++) {
118 addr += sizeof(udf_vrs_descriptor_t);
119
120 rc = udf_volume_recongnition_structure_test(service_id, addr, vd);
121 if (rc != EOK) {
122 free(vd);
123 return rc;
124 }
125
126 /*
127 * UDF standard identifier. According to ECMA 167 2/9.1.2
128 */
129 if ((str_lcmp(VRS_NSR2, (char *) vd->identifier, VRS_ID_LEN) == 0) ||
130 (str_lcmp(VRS_NSR3, (char *) vd->identifier, VRS_ID_LEN) == 0)) {
131 nsr_found = true;
132 log_msg(LVL_DEBUG, "VRS: NSR found");
133 continue;
134 }
135
136 if (str_lcmp(VRS_END, (char *) vd->identifier, VRS_ID_LEN) == 0) {
137 log_msg(LVL_DEBUG, "VRS: end found");
138 break;
139 }
140 }
141
142 free(vd);
143
144 if (nsr_found)
145 return EOK;
146 else
147 return EINVAL;
148}
149
150/** Convert descriptor tag fields from little-endian to current byte order
151 *
152 */
153static void udf_prepare_tag(udf_descriptor_tag_t *tag)
154{
155 GET_LE16(tag->id);
156 GET_LE16(tag->version);
157 GET_LE16(tag->serial);
158 GET_LE16(tag->descriptor_crc);
159 GET_LE16(tag->descriptor_crc_length);
160 GET_LE32(tag->location);
161}
162
163/** Read AVD by using one of default sector size from array
164 *
165 * @param service_id
166 * @param avd Returned value - Anchor Volume Descriptor
167 * @param sector_size Expected sector size
168 *
169 * @return EOK on success or a negative error code.
170 *
171 */
172static int udf_get_anchor_volume_descriptor_by_ssize(service_id_t service_id,
173 udf_anchor_volume_descriptor_t *avd, uint32_t sector_size)
174{
175 int rc = block_read_bytes_direct(service_id,
176 UDF_AVDP_SECTOR * sector_size,
177 sizeof(udf_anchor_volume_descriptor_t), avd);
178 if (rc != EOK)
179 return rc;
180
181 if (avd->tag.checksum != udf_tag_checksum((uint8_t *) &avd->tag))
182 return EINVAL;
183
184 // TODO: Should be tested in big-endian mode
185 udf_prepare_tag(&avd->tag);
186
187 if (avd->tag.id != UDF_TAG_AVDP)
188 return EINVAL;
189
190 GET_LE32(avd->main_extent.length);
191 GET_LE32(avd->main_extent.location);
192 GET_LE32(avd->reserve_extent.length);
193 GET_LE32(avd->reserve_extent.location);
194
195 return EOK;
196}
197
198/** Identification of the sector size
199 *
200 * We try to read Anchor Volume Descriptor by using one item from
201 * sequence of default values. If we could read avd, we found sector size.
202 *
203 * @param service_id
204 * @param avd Returned value - Anchor Volume Descriptor
205 *
206 * @return EOK on success or a negative error code.
207 *
208 */
209int udf_get_anchor_volume_descriptor(service_id_t service_id,
210 udf_anchor_volume_descriptor_t *avd)
211{
212 uint32_t default_sector_size[] = {512, 1024, 2048, 4096, 8192, 0};
213
214 udf_instance_t *instance;
215 int rc = fs_instance_get(service_id, (void **) &instance);
216 if (rc != EOK)
217 return rc;
218
219 if (instance->sector_size) {
220 return udf_get_anchor_volume_descriptor_by_ssize(service_id, avd,
221 instance->sector_size);
222 } else {
223 size_t i = 0;
224 while (default_sector_size[i] != 0) {
225 rc = udf_get_anchor_volume_descriptor_by_ssize(service_id, avd,
226 default_sector_size[i]);
227 if (rc == EOK) {
228 instance->sector_size = default_sector_size[i];
229 return EOK;
230 }
231
232 i++;
233 }
234 }
235
236 return EINVAL;
237}
238
239/** Check on prevailing primary volume descriptor
240 *
241 * Some discs couldn't be rewritten and new information is identified
242 * by descriptors with same data as one of already created descriptors.
243 * We should find prevailing descriptor (descriptor with the highest number)
244 * and delete old descriptor.
245 *
246 * @param pvd Array of primary volumes descriptors
247 * @param cnt Count of items in array
248 * @param desc Descriptor which could prevail over one
249 * of descriptors in array.
250 *
251 * @return True if desc prevails over some descriptor in array
252 *
253 */
254static bool udf_check_prevailing_pvd(udf_primary_volume_descriptor_t *pvd,
255 size_t cnt, udf_primary_volume_descriptor_t *desc)
256{
257 for (size_t i = 0; i < cnt; i++) {
258 /*
259 * According to ECMA 167 3/8.4.3
260 * PVD, each of which has same contents of the corresponding
261 * Volume Identifier, Volume set identifier
262 * and Descriptor char set field.
263 */
264 if ((bcmp((uint8_t *) pvd[i].volume_id,
265 (uint8_t *) desc->volume_id, 32) == 0) &&
266 (bcmp((uint8_t *) pvd[i].volume_set_id,
267 (uint8_t *) desc->volume_set_id, 128) == 0) &&
268 (bcmp((uint8_t *) &pvd[i].descriptor_charset,
269 (uint8_t *) &desc->descriptor_charset, 64) == 0) &&
270 (FLE32(desc->sequence_number) > FLE32(pvd[i].sequence_number))) {
271 memcpy(&pvd[i], desc, sizeof(udf_primary_volume_descriptor_t));
272 return true;
273 }
274 }
275
276 return false;
277}
278
279/** Check on prevailing logic volume descriptor
280 *
281 * Some discs couldn't be rewritten and new information is identified
282 * by descriptors with same data as one of already created descriptors.
283 * We should find prevailing descriptor (descriptor with the highest number)
284 * and delete old descriptor.
285 *
286 * @param lvd Array of logic volumes descriptors
287 * @param cnt Count of items in array
288 * @param desc Descriptor which could prevail over one
289 * of descriptors in array.
290 *
291 * @return True if desc prevails over some descriptor in array
292 *
293 */
294static bool udf_check_prevailing_lvd(udf_logical_volume_descriptor_t *lvd,
295 size_t cnt, udf_logical_volume_descriptor_t *desc)
296{
297 for (size_t i = 0; i < cnt; i++) {
298 /*
299 * According to ECMA 167 3/8.4.3
300 * LVD, each of which has same contents of the corresponding
301 * Logic Volume Identifier and Descriptor char set field.
302 */
303 if ((bcmp((uint8_t *) lvd[i].logical_volume_id,
304 (uint8_t *) desc->logical_volume_id, 128) == 0) &&
305 (bcmp((uint8_t *) &lvd[i].charset,
306 (uint8_t *) &desc->charset, 64) == 0) &&
307 (FLE32(desc->sequence_number) > FLE32(lvd[i].sequence_number))) {
308 memcpy(&lvd[i], desc, sizeof(udf_logical_volume_descriptor_t));
309 return true;
310 }
311 }
312
313 return false;
314}
315
316/** Check on prevailing partition descriptor
317 *
318 * Some discs couldn't be rewritten and new information is identified
319 * by descriptors with same data as one of already created descriptors.
320 * We should find prevailing descriptor (descriptor with the highest number)
321 * and delete old descriptor.
322 *
323 * @param pvd Array of partition descriptors
324 * @param cnt Count of items in array
325 * @param desc Descriptor which could prevail over one
326 * of descriptors in array.
327 *
328 * @return True if desc prevails over some descriptor in array
329 *
330 */
331static bool udf_check_prevailing_pd(udf_partition_descriptor_t *pd, size_t cnt,
332 udf_partition_descriptor_t *desc)
333{
334 for (size_t i = 0; i < cnt; i++) {
335 /*
336 * According to ECMA 167 3/8.4.3
337 * Partition descriptors with identical Partition Number
338 */
339 if ((FLE16(pd[i].number) == FLE16(desc->number)) &&
340 (FLE32(desc->sequence_number) > FLE32(pd[i].sequence_number))) {
341 memcpy(&pd[i], desc, sizeof(udf_partition_descriptor_t));
342 return true;
343 }
344 }
345
346 return false;
347}
348
349/** Read information about virtual partition
350 *
351 * Fill start and length fields for partition. This function quite similar of
352 * udf_read_icd. But in this we can meet only two descriptors and
353 * we have to read only one allocator.
354 *
355 * @param instance UDF instance
356 * @param pos Position (Extended) File entry descriptor
357 * @param id Index of partition in instance::partitions array
358 *
359 * @return EOK on success or a negative error code.
360 *
361 */
362static int udf_read_virtual_partition(udf_instance_t *instance, uint32_t pos,
363 uint32_t id)
364{
365 block_t *block = NULL;
366 int rc = block_get(&block, instance->service_id, pos,
367 BLOCK_FLAGS_NONE);
368 if (rc != EOK)
369 return rc;
370
371 udf_descriptor_tag_t *desc = (udf_descriptor_tag_t *) (block->data);
372 if (desc->checksum != udf_tag_checksum((uint8_t *) desc)) {
373 block_put(block);
374 return EINVAL;
375 }
376
377 /*
378 * We think that we have only one allocator. It is means that virtual
379 * partition, like physical, isn't fragmented.
380 * According to doc the type of allocator is short_ad.
381 */
382 switch (FLE16(desc->id)) {
383 case UDF_FILE_ENTRY:
384 log_msg(LVL_DEBUG, "ICB: File entry descriptor found");
385
386 udf_file_entry_descriptor_t *fed =
387 (udf_file_entry_descriptor_t *) block->data;
388 uint32_t start_alloc = FLE32(fed->ea_lenght) + UDF_FE_OFFSET;
389 udf_short_ad_t *short_d =
390 (udf_short_ad_t *) ((uint8_t *) fed + start_alloc);
391 instance->partitions[id].start = FLE32(short_d->position);
392 instance->partitions[id].lenght = FLE32(short_d->length);
393 break;
394
395 case UDF_EFILE_ENTRY:
396 log_msg(LVL_DEBUG, "ICB: Extended file entry descriptor found");
397
398 udf_extended_file_entry_descriptor_t *efed =
399 (udf_extended_file_entry_descriptor_t *) block->data;
400 start_alloc = FLE32(efed->ea_lenght) + UDF_EFE_OFFSET;
401 short_d = (udf_short_ad_t *) ((uint8_t *) efed + start_alloc);
402 instance->partitions[id].start = FLE32(short_d->position);
403 instance->partitions[id].lenght = FLE32(short_d->length);
404 break;
405 }
406
407 return block_put(block);
408}
409
410/** Search partition in array of partitions
411 *
412 * Used only in function udf_fill_volume_info
413 *
414 * @param pd Array of partitions
415 * @param pd_cnt Count items in array
416 * @param id Number partition (not index) which we want to find
417 *
418 * @return Index of partition or (size_t) -1 if we didn't find anything
419 *
420 */
421static size_t udf_find_partition(udf_partition_descriptor_t *pd, size_t pd_cnt,
422 size_t id)
423{
424 for (size_t i = 0; i < pd_cnt; i++) {
425 if (FLE16(pd[i].number) == id)
426 return i;
427 }
428
429 return (size_t) -1;
430}
431
432/** Fill instance structures by information about partitions and logic
433 *
434 * @param lvd Array of logic volumes descriptors
435 * @param lvd_cnt Count of items in lvd array
436 * @param pd Array of partition descriptors
437 * @param pd_cnt Count of items in pd array
438 * @param instance UDF instance
439 *
440 * @return EOK on success or a negative error code.
441 *
442 */
443static int udf_fill_volume_info(udf_logical_volume_descriptor_t *lvd,
444 size_t lvd_cnt, udf_partition_descriptor_t *pd, size_t pd_cnt,
445 udf_instance_t *instance)
446{
447 instance->volumes = calloc(lvd_cnt, sizeof(udf_lvolume_t));
448 if (instance->volumes == NULL)
449 return ENOMEM;
450
451 instance->partitions = calloc(pd_cnt, sizeof(udf_partition_t));
452 if (instance->partitions == NULL) {
453 free(instance->volumes);
454 return ENOMEM;
455 }
456
457 instance->partition_cnt = pd_cnt;
458
459 /*
460 * Fill information about logical volumes. We will save
461 * information about all partitions placed inside each volumes.
462 */
463
464 size_t vir_pd_cnt = 0;
465 for (size_t i = 0; i < lvd_cnt; i++) {
466 instance->volumes[i].partitions =
467 calloc(FLE32(lvd[i].number_of_partitions_maps),
468 sizeof(udf_partition_t *));
469 if (instance->volumes[i].partitions == NULL) {
470 // FIXME: Memory leak, cleanup code missing
471 return ENOMEM;
472 }
473
474 instance->volumes[i].partition_cnt = 0;
475 instance->volumes[i].logical_block_size =
476 FLE32(lvd[i].logical_block_size);
477
478 /*
479 * In theory we could have more than 1 logical volume. But now
480 * for current work of driver we will think that it single and all
481 * partitions from array pd belong to only first lvd
482 */
483
484 uint8_t *idx = lvd[i].partition_map;
485 for (size_t j = 0; j < FLE32(lvd[i].number_of_partitions_maps);
486 j++) {
487 udf_type1_partition_map_t *pm1 =
488 (udf_type1_partition_map_t *) idx;
489
490 if (pm1->partition_map_type == 1) {
491 size_t pd_num = udf_find_partition(pd, pd_cnt,
492 FLE16(pm1->partition_number));
493 if (pd_num == (size_t) -1) {
494 // FIXME: Memory leak, cleanup code missing
495 return ENOENT;
496 }
497
498 /*
499 * Fill information about physical partitions. We will save all
500 * partitions (physical and virtual) inside one array
501 * instance::partitions
502 */
503 instance->partitions[j].access_type =
504 FLE32(pd[pd_num].access_type);
505 instance->partitions[j].lenght =
506 FLE32(pd[pd_num].length);
507 instance->partitions[j].number =
508 FLE16(pm1->partition_number);
509 instance->partitions[j].start =
510 FLE32(pd[pd_num].starting_location);
511
512 instance->volumes[i].partitions[
513 instance->volumes[i].partition_cnt] =
514 &instance->partitions[j];
515
516 log_msg(LVL_DEBUG, "Volume[%" PRIun "]: partition [type %u] "
517 "found and filled", i, pm1->partition_map_type);
518
519 instance->volumes[i].partition_cnt++;
520 idx += pm1->partition_map_lenght;
521 continue;
522 }
523
524 udf_type2_partition_map_t *pm2 =
525 (udf_type2_partition_map_t *) idx;
526
527 if (pm2->partition_map_type == 2) {
528 // TODO: check partition_ident for metadata_partition_map
529
530 udf_metadata_partition_map_t *metadata =
531 (udf_metadata_partition_map_t *) idx;
532
533 log_msg(LVL_DEBUG, "Metadata file location=%u",
534 FLE32(metadata->metadata_fileloc));
535
536 vir_pd_cnt++;
537 instance->partitions = realloc(instance->partitions,
538 (pd_cnt + vir_pd_cnt) * sizeof(udf_partition_t));
539 if (instance->partitions == NULL) {
540 // FIXME: Memory leak, cleanup code missing
541 return ENOMEM;
542 }
543
544 instance->partition_cnt++;
545
546 size_t pd_num = udf_find_partition(pd, pd_cnt,
547 FLE16(metadata->partition_number));
548 if (pd_num == (size_t) -1) {
549 // FIXME: Memory leak, cleanup code missing
550 return ENOENT;
551 }
552
553 instance->partitions[j].number =
554 FLE16(metadata->partition_number);
555 int rc = udf_read_virtual_partition(instance,
556 FLE32(metadata->metadata_fileloc) +
557 FLE32(pd[pd_num].starting_location), j);
558 if (rc != EOK) {
559 // FIXME: Memory leak, cleanup code missing
560 return rc;
561 }
562
563 /* Virtual partition placed inside physical */
564 instance->partitions[j].start +=
565 FLE32(pd[pd_num].starting_location);
566
567 instance->volumes[i].partitions[
568 instance->volumes[i].partition_cnt] =
569 &instance->partitions[j];
570
571 log_msg(LVL_DEBUG, "Virtual partition: num=%d, start=%d",
572 instance->partitions[j].number,
573 instance->partitions[j].start);
574 log_msg(LVL_DEBUG, "Volume[%" PRIun "]: partition [type %u] "
575 "found and filled", i, pm2->partition_map_type);
576
577 instance->volumes[i].partition_cnt++;
578 idx += metadata->partition_map_length;
579 continue;
580 }
581
582 /* Not type 1 nor type 2 */
583 udf_general_type_t *pm = (udf_general_type_t *) idx;
584
585 log_msg(LVL_DEBUG, "Volume[%" PRIun "]: partition [type %u] "
586 "found and skipped", i, pm->partition_map_type);
587
588 idx += pm->partition_map_lenght;
589 }
590 }
591
592 return EOK;
593}
594
595/** Read volume descriptors sequence
596 *
597 * @param service_id
598 * @param addr UDF extent descriptor (ECMA 167 3/7.1)
599 *
600 * @return EOK on success or a negative error code.
601 *
602 */
603int udf_read_volume_descriptor_sequence(service_id_t service_id,
604 udf_extent_t addr)
605{
606 udf_instance_t *instance;
607 int rc = fs_instance_get(service_id, (void **) &instance);
608 if (rc != EOK)
609 return rc;
610
611 aoff64_t pos = addr.location;
612 aoff64_t end = pos + (addr.length / instance->sector_size) - 1;
613
614 if (pos == end)
615 return EINVAL;
616
617 size_t max_descriptors = ALL_UP(addr.length, instance->sector_size);
618
619 udf_primary_volume_descriptor_t *pvd = calloc(max_descriptors,
620 sizeof(udf_primary_volume_descriptor_t));
621 if (pvd == NULL)
622 return ENOMEM;
623
624 udf_logical_volume_descriptor_t *lvd = calloc(max_descriptors,
625 instance->sector_size);
626 if (lvd == NULL) {
627 free(pvd);
628 return ENOMEM;
629 }
630
631 udf_partition_descriptor_t *pd = calloc(max_descriptors,
632 sizeof(udf_partition_descriptor_t));
633 if (pd == NULL) {
634 free(pvd);
635 free(lvd);
636 return ENOMEM;
637 }
638
639 size_t pvd_cnt = 0;
640 size_t lvd_cnt = 0;
641 size_t pd_cnt = 0;
642
643 while (pos <= end) {
644 block_t *block = NULL;
645 rc = block_get(&block, service_id, pos, BLOCK_FLAGS_NONE);
646 if (rc != EOK) {
647 free(pvd);
648 free(lvd);
649 free(pd);
650 return rc;
651 }
652
653 udf_volume_descriptor_t *vol =
654 (udf_volume_descriptor_t *) block->data;
655
656 switch (FLE16(vol->common.tag.id)) {
657 /* One sector size descriptors */
658 case UDF_TAG_PVD:
659 log_msg(LVL_DEBUG, "Volume: Primary volume descriptor found");
660
661 if (!udf_check_prevailing_pvd(pvd, pvd_cnt, &vol->volume)) {
662 memcpy(&pvd[pvd_cnt], &vol->volume,
663 sizeof(udf_primary_volume_descriptor_t));
664 pvd_cnt++;
665 }
666
667 pos++;
668 break;
669
670 case UDF_TAG_VDP:
671 log_msg(LVL_DEBUG, "Volume: Volume descriptor pointer found");
672 pos++;
673 break;
674
675 case UDF_TAG_IUVD:
676 log_msg(LVL_DEBUG,
677 "Volume: Implementation use volume descriptor found");
678 pos++;
679 break;
680
681 case UDF_TAG_PD:
682 log_msg(LVL_DEBUG, "Volume: Partition descriptor found");
683 log_msg(LVL_DEBUG, "Partition number: %u, contents: '%.6s', "
684 "access type: %" PRIu32, FLE16(vol->partition.number),
685 vol->partition.contents.id, FLE32(vol->partition.access_type));
686 log_msg(LVL_DEBUG, "Partition start: %" PRIu32 " (sector), "
687 "size: %" PRIu32 " (sectors)",
688 FLE32(vol->partition.starting_location),
689 FLE32(vol->partition.length));
690
691 if (!udf_check_prevailing_pd(pd, pd_cnt, &vol->partition)) {
692 memcpy(&pd[pd_cnt], &vol->partition,
693 sizeof(udf_partition_descriptor_t));
694 pd_cnt++;
695 }
696
697 udf_partition_header_descriptor_t *phd =
698 (udf_partition_header_descriptor_t *) vol->partition.contents_use;
699 if (FLE32(phd->unallocated_space_table.length)) {
700 log_msg(LVL_DEBUG,
701 "space table: length=%" PRIu32 ", pos=%" PRIu32,
702 FLE32(phd->unallocated_space_table.length),
703 FLE32(phd->unallocated_space_table.position));
704
705 instance->space_type = SPACE_TABLE;
706 instance->uaspace_start =
707 FLE32(vol->partition.starting_location) +
708 FLE32(phd->unallocated_space_table.position);
709 instance->uaspace_lenght =
710 FLE32(phd->unallocated_space_table.length);
711 }
712
713 if (FLE32(phd->unallocated_space_bitmap.length)) {
714 log_msg(LVL_DEBUG,
715 "space bitmap: length=%" PRIu32 ", pos=%" PRIu32,
716 FLE32(phd->unallocated_space_bitmap.length),
717 FLE32(phd->unallocated_space_bitmap.position));
718
719 instance->space_type = SPACE_BITMAP;
720 instance->uaspace_start =
721 FLE32(vol->partition.starting_location) +
722 FLE32(phd->unallocated_space_bitmap.position);
723 instance->uaspace_lenght =
724 FLE32(phd->unallocated_space_bitmap.length);
725 }
726
727 pos++;
728 break;
729
730 /* Relative size descriptors */
731 case UDF_TAG_LVD:
732 log_msg(LVL_DEBUG, "Volume: Logical volume descriptor found");
733
734 aoff64_t sct =
735 ALL_UP((sizeof(udf_logical_volume_descriptor_t) +
736 FLE32(vol->logical.map_table_length)),
737 sizeof(udf_common_descriptor_t));
738 pos += sct;
739 char tmp[130];
740
741 udf_to_unix_name(tmp, 129,
742 (char *) vol->logical.logical_volume_id, 128,
743 &vol->logical.charset);
744
745 log_msg(LVL_DEBUG, "Logical Volume ID: '%s', "
746 "logical block size: %" PRIu32 " (bytes)", tmp,
747 FLE32(vol->logical.logical_block_size));
748 log_msg(LVL_DEBUG, "Map table size: %" PRIu32 " (bytes), "
749 "number of partition maps: %" PRIu32,
750 FLE32(vol->logical.map_table_length),
751 FLE32(vol->logical.number_of_partitions_maps));
752
753 if (!udf_check_prevailing_lvd(lvd, lvd_cnt, &vol->logical)) {
754 memcpy(&lvd[lvd_cnt], &vol->logical,
755 sizeof(udf_logical_volume_descriptor_t) +
756 FLE32(vol->logical.map_table_length));
757 lvd_cnt++;
758 }
759
760 break;
761
762 case UDF_TAG_USD:
763 log_msg(LVL_DEBUG, "Volume: Unallocated space descriptor found");
764
765 sct = ALL_UP((sizeof(udf_unallocated_space_descriptor_t) +
766 FLE32(vol->unallocated.allocation_descriptors_num)*
767 sizeof(udf_extent_t)), sizeof(udf_common_descriptor_t));
768 instance->uaspace_start = pos;
769 instance->uaspace_lenght = sct;
770 instance->uasd = (udf_unallocated_space_descriptor_t *)
771 malloc(sct * instance->sector_size);
772 if (instance->uasd == NULL) {
773 // FIXME: Memory leak, cleanup missing
774 return ENOMEM;
775 }
776
777 memcpy(instance->uasd, block->data, instance->sector_size);
778 pos += sct;
779 break;
780
781 case UDF_TAG_LVID:
782 log_msg(LVL_DEBUG,
783 "Volume: Logical volume integrity descriptor found");
784
785 pos++;
786 break;
787
788 case UDF_TAG_TD:
789 log_msg(LVL_DEBUG, "Volume: Terminating descriptor found");
790
791 /* Found terminating descriptor. Exiting */
792 pos = end + 1;
793 break;
794
795 default:
796 pos++;
797 }
798
799 rc = block_put(block);
800 if (rc != EOK) {
801 free(pvd);
802 free(lvd);
803 free(pd);
804 return rc;
805 }
806 }
807
808 /* Fill the instance */
809 udf_fill_volume_info(lvd, lvd_cnt, pd, pd_cnt, instance);
810
811 for (size_t i = 0; i < lvd_cnt; i++) {
812 pos = udf_long_ad_to_pos(instance,
813 (udf_long_ad_t *) &lvd[i].logical_volume_conents_use);
814
815 block_t *block = NULL;
816 rc = block_get(&block, instance->service_id, pos,
817 BLOCK_FLAGS_NONE);
818 if (rc != EOK) {
819 // FIXME: Memory leak, cleanup missing
820 return rc;
821 }
822
823 udf_descriptor_tag_t *desc = block->data;
824
825 log_msg(LVL_DEBUG, "First tag ID=%" PRIu16, desc->id);
826
827 if (desc->checksum != udf_tag_checksum((uint8_t *) desc)) {
828 // FIXME: Memory leak, cleanup missing
829 return EINVAL;
830 }
831
832 udf_prepare_tag(desc);
833
834 udf_fileset_descriptor_t *fd = block->data;
835 memcpy((uint8_t *) &instance->charset,
836 (uint8_t *) &fd->fileset_charset, sizeof(fd->fileset_charset));
837
838 instance->volumes[i].root_dir = udf_long_ad_to_pos(instance,
839 &fd->root_dir_icb);
840 }
841
842 free(pvd);
843 free(lvd);
844 free(pd);
845 return EOK;
846}
847
848/**
849 * @}
850 */
Note: See TracBrowser for help on using the repository browser.