From 0d383564c32019d5dfb1effaf055c94c41c5898d Mon Sep 17 00:00:00 2001 From: Tyler Dauwalder Date: Tue, 27 May 2003 08:06:43 +0000 Subject: [PATCH] - Added beginnings of volume descriptor sequence walking code. - Accounted for addition of "udf_" to beginning of on-disk structs. - Accounted for Block to MemoryChunk change git-svn-id: file:///srv/svn/repos/haiku/trunk/current@3356 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../kernel/file_systems/udf/Volume.cpp | 309 +++++++++++++----- src/add-ons/kernel/file_systems/udf/Volume.h | 18 +- 2 files changed, 250 insertions(+), 77 deletions(-) diff --git a/src/add-ons/kernel/file_systems/udf/Volume.cpp b/src/add-ons/kernel/file_systems/udf/Volume.cpp index bc84ddd973..4426d5445a 100644 --- a/src/add-ons/kernel/file_systems/udf/Volume.cpp +++ b/src/add-ons/kernel/file_systems/udf/Volume.cpp @@ -8,7 +8,7 @@ //---------------------------------------------------------------------- #include "Volume.h" -#include "Block.h" +#include "MemoryChunk.h" using namespace UDF; @@ -84,6 +84,41 @@ Volume::Mount(const char *deviceName, off_t volumeStart, off_t volumeLength, RETURN(B_ERROR); } +off_t +Volume::_MapAddress(udf_extent_address address) +{ + return address.location() * BlockSize(); +} + +off_t +Volume::_MapAddress(udf_long_address address) +{ + return 0; +} + +off_t +Volume::_MapAddress(udf_short_address address) +{ + return 0; +} + +status_t +Volume::_Read(udf_extent_address address, ssize_t length, void *data) +{ + DEBUG_INIT(CF_PRIVATE | CF_HIGH_VOLUME, "Volume"); + off_t mappedAddress = _MapAddress(address); + status_t err = data ? B_OK : B_BAD_VALUE; + if (!err) { + ssize_t bytesRead = read_pos(fDevice, mappedAddress, data, BlockSize()); + if (bytesRead != (ssize_t)BlockSize()) { + err = B_IO_ERROR; + PRINT(("read_pos(pos:%lld, len:%ld) failed with: 0x%lx\n", mappedAddress, + length, bytesRead)); + } + } + return err; +} + /*! \brief Walks through the volume recognition and descriptor sequences, gathering volume description info as it goes. @@ -105,57 +140,14 @@ Volume::_Identify() // Now hunt down a volume descriptor sequence from one of // the anchor volume pointers (if there are any). - if (!err) { - const uint8 avds_location_count = 4; - const off_t avds_locations[avds_location_count] = { 256, - Length()-256, - Length(), - 512, - }; - bool found_vds = false; - - for (int32 i = 0; i < avds_location_count; i++) { - off_t block = avds_locations[i]; - off_t address = AddressForRelativeBlock(block); - Block anchor(BlockSize()); - status_t anchorErr = anchor.InitCheck(); - if (!anchorErr) { - ssize_t bytesRead = read_pos(fDevice, address, anchor.Data(), BlockSize()); - anchorErr = bytesRead == (ssize_t)BlockSize() ? B_OK : B_IO_ERROR; - if (anchorErr) { - PRINT(("block %lld: read_pos(pos:%lld, len:%ld) failed with error 0x%lx\n", - block, address, BlockSize(), bytesRead)); - } - } - if (!anchorErr) { - anchor.Data()->tag().dump(); - anchorErr = anchor.Data()->tag().init_check(block); - if (anchorErr) { - PRINT(("block %lld: invalid anchor\n", block)); - } else { - PRINT(("block %lld: valid anchor\n", block)); - } - } - if (!anchorErr) { - // Found an avds, so try the main sequence first, then - // the reserve sequence if the main one fails. - anchorErr = _WalkVolumeDescriptorSequence(anchor.Data()->main_vds()); - if (anchorErr) - anchorErr = _WalkVolumeDescriptorSequence(anchor.Data()->reserve_vds()); - - - } - if (!anchorErr) { - PRINT(("block %lld: found valid vds\n", avds_locations[i])); - found_vds = true; - break; - } //else { - // Both failed, so loop around and try another avds -// PRINT(("block %lld: vds search failed\n", avds_locations[i])); -// } - } - err = found_vds ? B_OK : B_ERROR; - } + if (!err) + err = _WalkAnchorVolumeDescriptorSequences(); + + // At this point we've found a valid set of volume descriptors. We + // now need to investigate the file set descriptor pointed to by + // the logical volume descriptor + if (!err) + err = _InitFileSetDescriptor(); RETURN(err); } @@ -175,8 +167,8 @@ Volume::_WalkVolumeRecognitionSequence() // vrs starts at block 16. Each volume structure descriptor (vsd) // should be one block long. We're expecting to find 0 or more iso9660 // vsd's followed by some ECMA-167 vsd's. - Block descriptor(BlockSize()); - status_t err = descriptor.InitCheck(); + MemoryChunk chunk(BlockSize()); + status_t err = chunk.InitCheck(); if (!err) { bool foundISO = false; bool foundExtended = false; @@ -186,32 +178,34 @@ Volume::_WalkVolumeRecognitionSequence() for (uint32 block = 16; true; block++) { PRINT(("block %ld: ", block)) off_t address = AddressForRelativeBlock(block); - ssize_t bytesRead = read_pos(fDevice, address, descriptor.Data(), BlockSize()); + ssize_t bytesRead = read_pos(fDevice, address, chunk.Data(), BlockSize()); if (bytesRead == (ssize_t)BlockSize()) { - if (descriptor.Data()->id_matches(kVSDID_ISO)) { + udf_volume_structure_descriptor_header* descriptor = + reinterpret_cast(chunk.Data()); + if (descriptor->id_matches(kVSDID_ISO)) { SIMPLE_PRINT(("found ISO9660 descriptor\n")); foundISO = true; - } else if (descriptor.Data()->id_matches(kVSDID_BEA)) { + } else if (descriptor->id_matches(kVSDID_BEA)) { SIMPLE_PRINT(("found BEA descriptor\n")); foundExtended = true; - } else if (descriptor.Data()->id_matches(kVSDID_TEA)) { + } else if (descriptor->id_matches(kVSDID_TEA)) { SIMPLE_PRINT(("found TEA descriptor\n")); foundExtended = true; - } else if (descriptor.Data()->id_matches(kVSDID_ECMA167_2)) { + } else if (descriptor->id_matches(kVSDID_ECMA167_2)) { SIMPLE_PRINT(("found ECMA-167 rev 2 descriptor\n")); foundECMA167 = true; - } else if (descriptor.Data()->id_matches(kVSDID_ECMA167_3)) { + } else if (descriptor->id_matches(kVSDID_ECMA167_3)) { SIMPLE_PRINT(("found ECMA-167 rev 3 descriptor\n")); foundECMA167 = true; - } else if (descriptor.Data()->id_matches(kVSDID_BOOT)) { + } else if (descriptor->id_matches(kVSDID_BOOT)) { SIMPLE_PRINT(("found boot descriptor\n")); foundBoot = true; - } else if (descriptor.Data()->id_matches(kVSDID_ECMA168)) { + } else if (descriptor->id_matches(kVSDID_ECMA168)) { SIMPLE_PRINT(("found ECMA-168 descriptor\n")); foundECMA168 = true; } else { - SIMPLE_PRINT(("found invalid descriptor, id = `%.5s'\n", descriptor.Data()->id)); + SIMPLE_PRINT(("found invalid descriptor, id = `%.5s'\n", descriptor->id)); break; } } else { @@ -232,19 +226,86 @@ Volume::_WalkVolumeRecognitionSequence() } status_t -Volume::_WalkVolumeDescriptorSequence(extent_address extent) +Volume::_WalkAnchorVolumeDescriptorSequences() +{ + DEBUG_INIT(CF_PRIVATE | CF_VOLUME_OPS, "Volume"); + const uint8 avds_location_count = 4; + const off_t avds_locations[avds_location_count] = { 256, + Length()-256, + Length(), + 512, + }; + bool found_vds = false; + + for (int32 i = 0; i < avds_location_count; i++) { + off_t block = avds_locations[i]; + off_t address = AddressForRelativeBlock(block); + MemoryChunk chunk(BlockSize()); + udf_anchor_descriptor *anchor = NULL; + + status_t anchorErr = chunk.InitCheck(); + if (!anchorErr) { + ssize_t bytesRead = read_pos(fDevice, address, chunk.Data(), BlockSize()); + anchorErr = bytesRead == (ssize_t)BlockSize() ? B_OK : B_IO_ERROR; + if (anchorErr) { + PRINT(("block %lld: read_pos(pos:%lld, len:%ld) failed with error 0x%lx\n", + block, address, BlockSize(), bytesRead)); + } + } + if (!anchorErr) { + anchor = reinterpret_cast(chunk.Data()); + anchorErr = anchor->tag().init_check(block); + if (anchorErr) { + PRINT(("block %lld: invalid anchor\n", block)); + } else { + PRINT(("block %lld: valid anchor\n", block)); + } + } + if (!anchorErr) { + PRINT(("block %lld: anchor:\n", block)); + PDUMP(anchor); + // Found an avds, so try the main sequence first, then + // the reserve sequence if the main one fails. + anchorErr = _WalkVolumeDescriptorSequence(anchor->main_vds()); + if (anchorErr) + anchorErr = _WalkVolumeDescriptorSequence(anchor->reserve_vds()); + + + } + if (!anchorErr) { + PRINT(("block %lld: found valid vds\n", avds_locations[i])); + found_vds = true; + break; + } //else { + // Both failed, so loop around and try another avds +// PRINT(("block %lld: vds search failed\n", avds_locations[i])); +// } + } + status_t err = found_vds ? B_OK : B_ERROR; + RETURN(err); +} + +status_t +Volume::_WalkVolumeDescriptorSequence(udf_extent_address extent) { DEBUG_INIT_ETC(CF_PRIVATE | CF_VOLUME_OPS, "Volume", ("loc:%ld, len:%ld", extent.location(), extent.length())); uint32 count = extent.length()/BlockSize(); + + bool foundLogicalVD = false; + for (uint32 i = 0; i < count; i++) { off_t block = extent.location()+i; off_t address = AddressForRelativeBlock(block); - Block tag(BlockSize()); - status_t err = tag.InitCheck(); + MemoryChunk chunk(BlockSize()); + udf_tag *tag = NULL; + + PRINT(("descriptor #%ld (block %lld):\n", i, block)); + + status_t err = chunk.InitCheck(); if (!err) { - ssize_t bytesRead = read_pos(fDevice, address, tag.Data(), BlockSize()); + ssize_t bytesRead = read_pos(fDevice, address, chunk.Data(), BlockSize()); err = bytesRead == (ssize_t)BlockSize() ? B_OK : B_IO_ERROR; if (err) { PRINT(("block %lld: read_pos(pos:%lld, len:%ld) failed with error 0x%lx\n", @@ -252,16 +313,116 @@ Volume::_WalkVolumeDescriptorSequence(extent_address extent) } } if (!err) { - PRINT(("descriptor #%ld (block %lld):\n", i, block)); - if (tag.Data()->id() == 1) { - primary_vd *vd = (primary_vd*)tag.Data(); - vd->dump(); - } else { - tag.Data()->dump(); + tag = reinterpret_cast(chunk.Data()); + err = tag->init_check(block); + } + if (!err) { + // Now decide what type of descriptor we have + switch (tag->id()) { + case TAGID_UNDEFINED: + break; + + case TAGID_PRIMARY_VOLUME_DESCRIPTOR: + { + udf_primary_descriptor *primary = reinterpret_cast(tag); + PDUMP(primary); + break; + } + + case TAGID_ANCHOR_VOLUME_DESCRIPTOR_POINTER: + break; + + case TAGID_VOLUME_DESCRIPTOR_POINTER: + break; + + case TAGID_IMPLEMENTATION_USE_VOLUME_DESCRIPTOR: + { + udf_implementation_use_descriptor *imp_use = reinterpret_cast(tag); + PDUMP(imp_use); + break; + } + + case TAGID_PARTITION_DESCRIPTOR: + { + udf_partition_descriptor *partition = reinterpret_cast(tag); + PDUMP(partition); + if (partition->tag().init_check(block) == B_OK) { + udf_partition_descriptor *current = fPartitionMap.Find(partition->partition_number()); + if (!current || current->vds_number() < partition->vds_number()) { + PRINT(("adding partition #%d with vds_number %ld to partition map\n", + partition->partition_number(), partition->vds_number())); + fPartitionMap.Add(partition); + } + } + break; + } + + case TAGID_LOGICAL_VOLUME_DESCRIPTOR: + { + udf_logical_descriptor *logical = reinterpret_cast(tag); + PDUMP(logical); + if (foundLogicalVD) { + // Keep the vd with the highest vds_number + if (logical->vds_number() > fLogicalVD.vds_number()) + fLogicalVD = *(logical); + } else { + fLogicalVD = *(logical); + foundLogicalVD = true; + } + break; + } + + case TAGID_UNALLOCATED_SPACE_DESCRIPTOR: + { + udf_unallocated_space_descriptor *unallocated = reinterpret_cast(tag); + PDUMP(unallocated); + break; + } + + case TAGID_TERMINATING_DESCRIPTOR: + { + udf_terminating_descriptor *terminating = reinterpret_cast(tag); + PDUMP(terminating); + break; + } + + case TAGID_LOGICAL_VOLUME_INTEGRITY_DESCRIPTOR: + // Not found in this descriptor sequence + break; + + default: + break; + } } } - RETURN(B_ERROR); + status_t err = foundLogicalVD ? B_OK : B_ERROR; + if (!err) { + PRINT(("partition map:\n")); + DUMP(fPartitionMap); + } + RETURN(err); } +status_t +Volume::_InitFileSetDescriptor() +{ + DEBUG_INIT(CF_PRIVATE | CF_VOLUME_OPS, "Volume"); + MemoryChunk chunk(fLogicalVD.file_set_address().length()); + udf_file_set_descriptor* fileSet = NULL; + + udf_extent_address ad; + ad.set_length(2048); + ad.set_location(257); + status_t err = chunk.InitCheck(); + if (!err) + err = _Read(ad, fLogicalVD.file_set_address().length(), chunk.Data()); +// err = _Read(fLogicalVD.file_set_address(), fLogicalVD.file_set_address().length(), fileSet); + if (!err) { + fileSet = reinterpret_cast(chunk.Data()); + fileSet->tag().init_check(0); + PDUMP(fileSet); + } + return err; +} \ No newline at end of file diff --git a/src/add-ons/kernel/file_systems/udf/Volume.h b/src/add-ons/kernel/file_systems/udf/Volume.h index 875c987404..b2e55bac49 100644 --- a/src/add-ons/kernel/file_systems/udf/Volume.h +++ b/src/add-ons/kernel/file_systems/udf/Volume.h @@ -25,6 +25,7 @@ extern "C" { #include "UdfDebug.h" #include "DiskStructures.h" +#include "PartitionMap.h" namespace UDF { @@ -48,8 +49,7 @@ public: uint32 BlockSize() const { return fBlockSize; } off_t AddressForRelativeBlock(off_t block) { return StartAddress() + block * BlockSize(); } off_t RelativeAddress(off_t address) { return StartAddress() + address; } - - + bool IsReadOnly() const { return fReadOnly; } vnode_id ToVnodeID(off_t block) const { return (vnode_id)block; } @@ -59,14 +59,23 @@ private: enum { B_UNINITIALIZED = B_ERRORS_END+1, //!< Completely uninitialized B_DEVICE_INITIALIZED, //!< Initialized enough to access underlying device safely + B_LOGICAL_VOLUME_INITIALIZED, //!< Initialized enough to map addresses B_INITIALIZED = B_OK, }; + off_t _MapAddress(udf_extent_address address); + off_t _MapAddress(udf_long_address address); + off_t _MapAddress(udf_short_address address); + + ssize_t _Read(udf_extent_address address, ssize_t length, void *data); + // Called by Mount(), either directly or indirectly status_t _Identify(); status_t _WalkVolumeRecognitionSequence(); - status_t _WalkVolumeDescriptorSequence(extent_address extent); + status_t _WalkAnchorVolumeDescriptorSequences(); + status_t _WalkVolumeDescriptorSequence(udf_extent_address extent); + status_t _InitFileSetDescriptor(); private: nspace_id fID; @@ -78,6 +87,9 @@ private: uint32 fBlockSize; status_t fInitStatus; + + udf_logical_descriptor fLogicalVD; + PartitionMap fPartitionMap; }; }; // namespace UDF