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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since a35b458 was a35b458, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 7 years ago

style: Remove trailing whitespace on _all_ lines, including empty ones, for particular file types.

Command used: tools/srepl '\s\+$' '' -- *.c *.h *.py *.sh *.s *.S *.ag

Currently, whitespace on empty lines is very inconsistent.
There are two basic choices: Either remove the whitespace, or keep empty lines
indented to the level of surrounding code. The former is AFAICT more common,
and also much easier to do automatically.

Alternatively, we could write script for automatic indentation, and use that
instead. However, if such a script exists, it's possible to use the indented
style locally, by having the editor apply relevant conversions on load/save,
without affecting remote repository. IMO, it makes more sense to adopt
the simpler rule.

  • Property mode set to 100644
File size: 24.4 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 <stdlib.h>
42#include <str.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(LOG_DEFAULT, 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 an error code.
84 *
85 */
86static errno_t 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 an error code.
101 */
102errno_t 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 errno_t 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(LOG_DEFAULT, 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(LOG_DEFAULT, 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 an error code.
170 *
171 */
172static errno_t 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 errno_t 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 an error code.
207 *
208 */
209errno_t 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 errno_t 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 ((memcmp((uint8_t *) pvd[i].volume_id,
265 (uint8_t *) desc->volume_id, 32) == 0) &&
266 (memcmp((uint8_t *) pvd[i].volume_set_id,
267 (uint8_t *) desc->volume_set_id, 128) == 0) &&
268 (memcmp((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 ((memcmp((uint8_t *) lvd[i].logical_volume_id,
304 (uint8_t *) desc->logical_volume_id, 128) == 0) &&
305 (memcmp((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 an error code.
360 *
361 */
362static errno_t udf_read_virtual_partition(udf_instance_t *instance, uint32_t pos,
363 uint32_t id)
364{
365 block_t *block = NULL;
366 errno_t 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(LOG_DEFAULT, 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(LOG_DEFAULT, 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 an error code.
441 *
442 */
443static errno_t 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(LOG_DEFAULT, 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(LOG_DEFAULT, 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 errno_t 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(LOG_DEFAULT, LVL_DEBUG, "Virtual partition: num=%d, start=%d",
572 instance->partitions[j].number,
573 instance->partitions[j].start);
574 log_msg(LOG_DEFAULT, 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(LOG_DEFAULT, 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 an error code.
601 *
602 */
603errno_t udf_read_volume_descriptor_sequence(service_id_t service_id,
604 udf_extent_t addr)
605{
606 udf_instance_t *instance;
607 errno_t 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(LOG_DEFAULT, 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(LOG_DEFAULT, LVL_DEBUG, "Volume: Volume descriptor pointer found");
672 pos++;
673 break;
674
675 case UDF_TAG_IUVD:
676 log_msg(LOG_DEFAULT, LVL_DEBUG,
677 "Volume: Implementation use volume descriptor found");
678 pos++;
679 break;
680
681 case UDF_TAG_PD:
682 log_msg(LOG_DEFAULT, LVL_DEBUG, "Volume: Partition descriptor found");
683 log_msg(LOG_DEFAULT, 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(LOG_DEFAULT, 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(LOG_DEFAULT, 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(LOG_DEFAULT, 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(LOG_DEFAULT, 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(LOG_DEFAULT, LVL_DEBUG, "Logical Volume ID: '%s', "
746 "logical block size: %" PRIu32 " (bytes)", tmp,
747 FLE32(vol->logical.logical_block_size));
748 log_msg(LOG_DEFAULT, 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(LOG_DEFAULT, 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(LOG_DEFAULT, LVL_DEBUG,
783 "Volume: Logical volume integrity descriptor found");
784
785 pos++;
786 break;
787
788 case UDF_TAG_TD:
789 log_msg(LOG_DEFAULT, 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(LOG_DEFAULT, 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.