From d4e8b936cc40118e3e9f0b93d4cf9657a5fa62b0 Mon Sep 17 00:00:00 2001 From: Tyler Dauwalder Date: Tue, 11 Nov 2003 09:11:43 +0000 Subject: [PATCH] Enormous cleanup. - Finished migration of current capabilities (i.e. vanilla physical partition support) to new partition mapping system. - Eliminated a lot of unnecesary cruft. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@5316 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../kernel/file_systems/udf/Volume.cpp | 793 +++++------------- src/add-ons/kernel/file_systems/udf/Volume.h | 103 +-- 2 files changed, 210 insertions(+), 686 deletions(-) diff --git a/src/add-ons/kernel/file_systems/udf/Volume.cpp b/src/add-ons/kernel/file_systems/udf/Volume.cpp index 7de0400d70..ef4b308f4c 100644 --- a/src/add-ons/kernel/file_systems/udf/Volume.cpp +++ b/src/add-ons/kernel/file_systems/udf/Volume.cpp @@ -10,58 +10,30 @@ #include "Icb.h" #include "MemoryChunk.h" +#include "PhysicalPartition.h" #include "Recognition.h" using namespace Udf; -//---------------------------------------------------------------------- -// Volume -//---------------------------------------------------------------------- - /*! \brief Creates an unmounted volume with the given id. */ Volume::Volume(nspace_id id) : fId(id) , fDevice(0) - , fReadOnly(false) , fMounted(false) , fOffset(0) + , fLength(0) , fBlockSize(0) , fBlockShift(0) - , fInitStatus(B_UNINITIALIZED) -#if (!DRIVE_SETUP_ADDON) , fRootIcb(NULL) -#endif { for (int i = 0; i < UDF_MAX_PARTITION_MAPS; i++) fPartitions[i] = NULL; } -status_t -Volume::Identify(int device, off_t offset, off_t length, uint32 blockSize, char *volumeName) +Volume::~Volume() { - DEBUG_INIT_ETC(CF_PUBLIC | CF_VOLUME_OPS, "static Volume", - ("device: %d, offset: %Ld, volumeName: %p", device, offset, volumeName)); - if (!volumeName) - RETURN(B_BAD_VALUE); - -// FILE *file = fopen("/boot/home/Desktop/outputIdentify.txt", "w+"); - - Volume volume(0); - status_t err = volume._Init(device, offset, length, blockSize); -// fprintf(file, "error = 0x%lx, `%s'\n", err, strerror(err)); -// fflush(file); - if (!err) - err = volume._Identify(); -// fprintf(file, "error = 0x%lx, `%s'\n", err, strerror(err)); -// fflush(file); - if (!err) - strcpy(volumeName, volume.Name()); -// fprintf(file, "error = 0x%lx, `%s'\n", err, strerror(err)); -// fflush(file); - -// fclose(file); - RETURN(err); + _Unset(); } /*! \brief Attempts to mount the given device. @@ -70,7 +42,7 @@ Volume::Identify(int device, off_t offset, off_t length, uint32 blockSize, char \param volumeLength The block length of the volume on the given device. */ status_t -Volume::Mount2(const char *deviceName, off_t offset, off_t length, +Volume::Mount(const char *deviceName, off_t offset, off_t length, uint32 blockSize, uint32 flags) { DEBUG_INIT_ETC(CF_PUBLIC | CF_VOLUME_OPS, "Volume", @@ -113,46 +85,144 @@ Volume::Mount2(const char *deviceName, off_t offset, off_t length, if (!error) error = init_cache_for_device(device, length); + int physicalCount = 0; + int virtualCount = 0; + int sparableCount = 0; + int metadataCount = 0; + // Set up the partitions if (!error) { // Set up physical and sparable partitions first int offset = 0; - for (uint8 i = 0; i < logicalVolumeDescriptor.partition_map_count(); i++) { + for (uint8 i = 0; i < logicalVolumeDescriptor.partition_map_count() + && !error; i++) + { uint8 *maps = logicalVolumeDescriptor.partition_maps(); - udf_generic_partition_map *header = - reinterpret_cast(maps+offset); -// logicalVolumeDescriptor.partition_maps() + offset); + udf_partition_map_header *header = + reinterpret_cast(maps+offset); PRINT(("partition map %d (type %d):\n", i, header->type())); if (header->type() == 1) { -// udf_physical_partition_map* map = -// reinterpret_cast(header); -// PDUMP(map); - PDUMP(reinterpret_cast(header)); + PRINT(("map type: physical\n")); + udf_physical_partition_map* map = + reinterpret_cast(header); + // Find the corresponding partition descriptor + udf_partition_descriptor *descriptor = NULL; + for (uint8 j = 0; j < partitionDescriptorCount; j++) { + if (map->partition_number() == + partitionDescriptors[j].partition_number()) + { + descriptor = &partitionDescriptors[j]; + break; + } + } + // Create and add the partition + if (descriptor) { + PhysicalPartition *partition = new PhysicalPartition( + map->partition_number(), + descriptor->start(), + descriptor->length()); + error = partition ? B_OK : B_NO_MEMORY; + if (!error) { + PRINT(("Adding PhysicalPartition(number: %d, start: %ld, " + "length: %ld)\n", map->partition_number(), + descriptor->start(), descriptor->length())); + error = _SetPartition(i, partition); + if (!error) + physicalCount++; + } + } else { + PRINT(("no matching partition descriptor found!\n")); + error = B_ERROR; + } + } else if (header->type() == 2) { + // Figure out what kind of partition map we have based + // on the type identifier + const udf_entity_id &typeId = header->partition_type_id(); + DUMP(typeId); + DUMP(kSparablePartitionMapId); + if (typeId.matches(kVirtualPartitionMapId)) { + PRINT(("map type: virtual\n")); + udf_virtual_partition_map* map = + reinterpret_cast(header); + virtualCount++; + (void)map; // kill the warning for now + } else if (typeId.matches(kSparablePartitionMapId)) { + PRINT(("map type: sparable\n")); + udf_sparable_partition_map* map = + reinterpret_cast(header); + sparableCount++; + (void)map; // kill the warning for now + } else if (typeId.matches(kMetadataPartitionMapId)) { + PRINT(("map type: metadata\n")); + udf_metadata_partition_map* map = + reinterpret_cast(header); + metadataCount++; + (void)map; // kill the warning for now + } else { + PRINT(("map type: unrecognized (`%.23s')\n", + typeId.identifier())); + error = B_ERROR; + } } else { - udf_sparable_partition_map* map = - reinterpret_cast(header); - DUMP(map->partition_type_id()); - } - + PRINT(("Invalid partition type %d found!\n", header->type())); + error = B_ERROR; + } offset += header->length(); } } - - RETURN(B_ERROR); - - // At this point we've found a valid set of volume descriptors, and we - // have our partitions set up. We - // now need to investigate the file set descriptor pointed to by - // the logical volume descriptor + + // Do some checking as to what sorts of partitions we've actually found. if (!error) { - MemoryChunk chunk(fLogicalVolumeDescriptor.file_set_address().length()); + error = (physicalCount == 1 && virtualCount == 0 + && sparableCount == 0 && metadataCount == 0) + || (physicalCount == 2 && virtualCount == 0 + && sparableCount == 0 && metadataCount == 0) + ? B_OK : B_ERROR; + if (error) { + PRINT(("Invalid partition layout found:\n")); + PRINT((" physical partitions: %d\n", physicalCount)); + PRINT((" virtual partitions: %d\n", virtualCount)); + PRINT((" sparable partitions: %d\n", sparableCount)); + PRINT((" metadata partitions: %d\n", metadataCount)); + } + } + + // We're now going to start creating Icb's, which will expect + // certain parts of the volume to be initialized properly. Thus, + // we initialize those parts here. + if (!error) { + fDevice = device; + fOffset = offset; + fLength = length; + fBlockSize = blockSize; + fBlockShift = blockShift; + } + + // At this point we've found a valid set of volume descriptors and + // our partitions are all set up. We now need to investigate the file + // set descriptor pointed to by the logical volume descriptor. + if (!error) { + MemoryChunk chunk(logicalVolumeDescriptor.file_set_address().length()); status_t error = chunk.InitCheck(); if (!error) { - error = Read(fLogicalVolumeDescriptor.file_set_address(), - fLogicalVolumeDescriptor.file_set_address().length(), - chunk.Data()); + off_t address; + // Read in the file set descriptor + error = MapBlock(logicalVolumeDescriptor.file_set_address(), + &address); + if (!error) + address <<= blockShift; + if (!error) { + ssize_t bytesRead = read_pos(device, address, chunk.Data(), + blockSize); + if (bytesRead != (ssize_t)blockSize) { + error = B_IO_ERROR; + PRINT(("read_pos(pos:%Ld, len:%ld) failed with: 0x%lx\n", + address, blockSize, bytesRead)); + } + } + // See if it's valid, and if so, create the root icb if (!error) { udf_file_set_descriptor *fileSet = reinterpret_cast(chunk.Data()); @@ -160,580 +230,103 @@ Volume::Mount2(const char *deviceName, off_t offset, off_t length, PDUMP(fileSet); fRootIcb = new Icb(this, fileSet->root_directory_icb()); error = fRootIcb ? fRootIcb->InitCheck() : B_NO_MEMORY; + if (!error) { + error = new_vnode(Id(), RootIcb()->Id(), (void*)RootIcb()); + if (error) { + PRINT(("Error creating vnode for root icb! " + "error = 0x%lx, `%s'\n", error, + strerror(error))); + // Clean up the icb we created, since _Unset() + // won't do this for us. + delete fRootIcb; + fRootIcb = NULL; + } + } } } } + // If we've made it this far, we're good to go; set the volume + // name and then flag that we're mounted. On the other hand, if + // an error occurred, we need to clean things up. if (!error) { - // Success, create a vnode for the root - error = new_vnode(Id(), RootIcb()->Id(), (void*)RootIcb()); - if (error) { - PRINT(("Error create vnode for root icb! error = 0x%lx, `%s'\n", - error, strerror(error))); - } + fName.SetTo(logicalVolumeDescriptor.logical_volume_identifier()); + fMounted = true; + } else { + _Unset(); } - - fInitStatus = error < B_OK ? B_UNINITIALIZED : B_LOGICAL_VOLUME_INITIALIZED; - - // set name and other member variables - if (!error) { - - } - - fDevice = device; - fReadOnly = true; - fOffset = offset; - fLength = length; - fBlockSize = blockSize; RETURN(error); - -/* if (!error && volumeName) { - CS0String name(logicalVolumeDescriptor.logical_volume_identifier()); - strcpy(volumeName, name.String()); - } -*/ -/* - status_t error = _Init(device, volumeStart, volumeLength, blockSize); - if (!error) - error = _Identify(); - if (!error) - error = _Mount(); - - if (error) - fInitStatus = B_UNINITIALIZED; - - RETURN(error); - -*/ } - -/*! \brief Attempts to mount the given device. - - \param volumeStart The block on the given device whereat the volume begins. - \param volumeLength The block length of the volume on the given device. -*/ -status_t -Volume::Mount(const char *deviceName, off_t volumeStart, off_t volumeLength, - uint32 flags, uint32 blockSize) -{ - DEBUG_INIT_ETC(CF_PUBLIC | CF_VOLUME_OPS, "Volume", - ("deviceName: `%s', offset: %Ld, length %Ld", deviceName, volumeStart, volumeLength)); - if (!deviceName) - RETURN(B_BAD_VALUE); - if (_InitStatus() == B_INITIALIZED) - RETURN(B_BUSY); - // Already mounted, thank you for asking - - // Open the device read only - int device = open(deviceName, O_RDONLY); - if (device < B_OK) - RETURN(device); - - status_t err = _Init(device, volumeStart, volumeLength, blockSize); - if (!err) - err = _Identify(); - if (!err) - err = _Mount(); - - if (err) - fInitStatus = B_UNINITIALIZED; - - RETURN(err); -} - const char* Volume::Name() const { return fName.String(); } -off_t -Volume::MapAddress(udf_extent_address address) -{ - return address.location() * BlockSize(); -} - - -/*! \brief Maps the given \c udf_long_address to an absolute block address. +/*! \brief Maps the given logical block to a physical block. */ status_t Volume::MapBlock(udf_long_address address, off_t *mappedBlock) { DEBUG_INIT_ETC(CF_PRIVATE | CF_HIGH_VOLUME, "Volume", ("long_address(block: %ld, partition: %d), %p", address.block(), address.partition(), mappedBlock)); - status_t err = mappedBlock ? B_OK : B_BAD_VALUE; - if (!err) - err = _InitStatus() >= B_IDENTIFIED ? B_OK : B_NO_INIT; - if (!err) { - const udf_partition_descriptor* partition = fPartitionMap.Find(address.partition()); - err = partition ? B_OK : B_BAD_ADDRESS; - if (!err) { - *mappedBlock = partition->start() + address.block(); - } - if (!err) { - PRINT(("mapped to block %Ld\n", *mappedBlock)); - } + status_t error = mappedBlock ? B_OK : B_BAD_VALUE; + if (!error) { + Partition *partition = _GetPartition(address.partition()); + error = partition ? B_OK : B_BAD_ADDRESS; + if (!error) + error = partition->MapBlock(address.block(), *mappedBlock); } - RETURN(err); + RETURN(error); } -/*! \brief Maps the given \c udf_long_address to an absolute byte address. +/*! \brief Unsets the volume and deletes any partitions. + + Does *not* delete the root icb object. +*/ +void +Volume::_Unset() +{ + fId = 0; + fDevice = 0; + fMounted = false; + fOffset = 0; + fLength = 0; + fBlockSize = 0; + fBlockShift = 0; + fName.SetTo(""); + // delete our partitions + for (int i = 0; i < UDF_MAX_PARTITION_MAPS; i++) + _SetPartition(i, NULL); +} + +/*! \brief Sets the partition associated with the given number after + deleting any previously associated partition. + + \param number The partition number (should be the same as the index + into the lvd's partition map array). + \param partition The new partition (may be NULL). */ status_t -Volume::MapAddress(udf_long_address address, off_t *mappedAddress) +Volume::_SetPartition(uint number, Partition *partition) { - DEBUG_INIT_ETC(CF_PRIVATE | CF_HIGH_VOLUME, "Volume", ("long_address(block: %ld, partition: %d), %p", - address.block(), address.partition(), mappedAddress)); - status_t err = MapBlock(address, mappedAddress); - if (!err) - *mappedAddress = *mappedAddress * BlockSize(); - if (!err) { - PRINT(("mapped to address %Ld\n", *mappedAddress)); + status_t error = number < UDF_MAX_PARTITION_MAPS + ? B_OK : B_BAD_VALUE; + if (!error) { + delete fPartitions[number]; + fPartitions[number] = partition; } - RETURN_ERROR(err); + return error; } -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:%Ld, len:%ld) failed with: 0x%lx\n", mappedAddress, - length, bytesRead)); - } - } - RETURN(err); -} +/*! \brief Returns the partition associated with the given number, or + NULL if no such partition exists or the number is invalid. */ - -/*template -status_t -Volume::_Read(AddressType address, ssize_t length, void *data) +Partition* +Volume::_GetPartition(uint number) { - DEBUG_INIT(CF_PRIVATE | CF_HIGH_VOLUME, "Volume"); - off_t mappedAddress; - status_t err = data ? B_OK : B_BAD_VALUE; - if (!err) - err = MapAddress(address, &mappedAddress); - if (!err) { - ssize_t bytesRead = read_pos(fDevice, mappedAddress, data, BlockSize()); - if (bytesRead != (ssize_t)BlockSize()) { - err = B_IO_ERROR; - PRINT(("read_pos(pos:%Ld, len:%ld) failed with: 0x%lx\n", mappedAddress, - length, bytesRead)); - } - } - RETURN(err); + return (number < UDF_MAX_PARTITION_MAPS) + ? fPartitions[number] : NULL; } -*/ -status_t -Volume::_Init(int device, off_t offset, off_t length, int blockSize) -{ - DEBUG_INIT(CF_PRIVATE | CF_HIGH_VOLUME, "Volume"); - if (_InitStatus() == B_INITIALIZED) - RETURN_ERROR(B_BUSY); - - // Check the block size - uint32 bitCount = 0; - for (int i = 0; i < 32; i++) { - // Zero out all bits except bit i - uint32 block = blockSize & (uint32(1) << i); - if (block) { - if (++bitCount > 1) { - PRINT(("Block size must be a power of two! (blockSize = %d)\n", blockSize)); - RETURN(B_BAD_VALUE); - } else { - fBlockShift = i; - PRINT(("BlockShift() = %ld\n", BlockShift())); - } - } - } - - fDevice = device; - fReadOnly = true; - fOffset = offset; - fLength = length; - fBlockSize = blockSize; - status_t err = B_OK; - -#if (!DRIVE_SETUP_ADDON) - // If the device is actually a normal file, try to disable the cache - // for the file in the parent filesystem - struct stat stat; - err = fstat(fDevice, &stat) < 0 ? B_ERROR : B_OK; - if (!err) { - if (stat.st_mode & S_IFREG && ioctl(fDevice, IOCTL_FILE_UNCACHED_IO, NULL) < 0) { - // Apparently it's a bad thing if you can't disable the file - // cache for a non-device disk image you're trying to mount... - DIE(("Unable to disable cache of underlying file system. " - "I hear that's bad. :-(\n")); - } - } -#endif - - fInitStatus = err < B_OK ? B_UNINITIALIZED : B_DEVICE_INITIALIZED; - - RETURN(err); -} - -/*! \brief Walks through the volume recognition and descriptor sequences, - gathering volume description info as it goes. - - Note that the 512 avdp location is, technically speaking, only valid on - unlosed CD-R media in the absense of an avdp at 256. For now I'm not - bothering with such silly details, and instead am just checking for it - last. -*/ -status_t -Volume::_Identify() -{ - DEBUG_INIT(CF_PRIVATE | CF_VOLUME_OPS, "Volume"); - - status_t err = _InitStatus() == B_DEVICE_INITIALIZED ? B_OK : B_BAD_VALUE; - - // Check for a valid volume recognition sequence - if (!err) - err = _WalkVolumeRecognitionSequence(); - - // Now hunt down a volume descriptor sequence from one of - // the anchor volume pointers (if there are any). - if (!err) - err = _WalkAnchorVolumeDescriptorSequences(); - - // Set the volume name - if (!err) { -// FILE *file = fopen("/boot/home/Desktop/vdoutput.txt", "w+"); -// fprint - - fName.SetTo(fLogicalVolumeDescriptor.logical_volume_identifier()); - } - - fInitStatus = err < B_OK ? B_UNINITIALIZED : B_IDENTIFIED; - - RETURN(err); -} - -status_t -Volume::_Mount() -{ - DEBUG_INIT(CF_PRIVATE | CF_VOLUME_OPS, "Volume"); - - status_t err = _InitStatus() == B_IDENTIFIED ? B_OK : B_BAD_VALUE; - -#if (!DRIVE_SETUP_ADDON) - if (!err) - err = init_cache_for_device(Device(), Length()); - - // 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(); - - if (!err) { - // Success, create a vnode for the root - err = new_vnode(Id(), RootIcb()->Id(), (void*)RootIcb()); - if (err) { - PRINT(("Error create vnode for root icb! error = 0x%lx, `%s'\n", - err, strerror(err))); - } - } - - fInitStatus = err < B_OK ? B_UNINITIALIZED : B_LOGICAL_VOLUME_INITIALIZED; -#endif - - RETURN(err); -} - -/*! \brief Walks the iso9660/ecma-167 volume recognition sequence, returning - \c B_OK if the presence of a UDF filesystem on this volume is likely. - - \return \c B_OK: An ECMA-167 vsd was found, or at least one extended area - vsd was found and no ECMA-168 vsds were found. - \return "error code": Only iso9660 vsds were found, an ECMA-168 vsd was - found (but no ECMA-167 vsd), or an error occurred. -*/ -status_t -Volume::_WalkVolumeRecognitionSequence() -{ - DEBUG_INIT(CF_PRIVATE | CF_VOLUME_OPS, "Volume"); - // 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. - MemoryChunk chunk(BlockSize()); - status_t err = chunk.InitCheck(); - if (!err) { - bool foundISO = false; - bool foundExtended = false; - bool foundECMA167 = false; - bool foundECMA168 = false; - bool foundBoot = false; - for (uint32 block = 16; true; block++) { - PRINT(("block %ld: ", block)) - off_t address = AddressForRelativeBlock(block); - ssize_t bytesRead = read_pos(fDevice, address, chunk.Data(), BlockSize()); - if (bytesRead == (ssize_t)BlockSize()) - { - 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->id_matches(kVSDID_BEA)) { - SIMPLE_PRINT(("found BEA descriptor\n")); - foundExtended = true; - } else if (descriptor->id_matches(kVSDID_TEA)) { - SIMPLE_PRINT(("found TEA descriptor\n")); - foundExtended = true; - } else if (descriptor->id_matches(kVSDID_ECMA167_2)) { - SIMPLE_PRINT(("found ECMA-167 rev 2 descriptor\n")); - foundECMA167 = true; - } else if (descriptor->id_matches(kVSDID_ECMA167_3)) { - SIMPLE_PRINT(("found ECMA-167 rev 3 descriptor\n")); - foundECMA167 = true; - } else if (descriptor->id_matches(kVSDID_BOOT)) { - SIMPLE_PRINT(("found boot descriptor\n")); - foundBoot = true; - } 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->id)); - break; - } - } else { - SIMPLE_PRINT(("read_pos(pos:%Ld, len:%ld) failed with: 0x%lx\n", address, - BlockSize(), bytesRead)); - break; - } - } - - // If we find an ECMA-167 descriptor, OR if we find a beginning - // or terminating extended area descriptor with NO ECMA-168 - // descriptors, we return B_OK to signal that we should go - // looking for valid anchors. - err = foundECMA167 || (foundExtended && !foundECMA168) ? B_OK : B_ERROR; - } - - RETURN(err); -} - -status_t -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 %Ld: read_pos(pos:%Ld, 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+Offset()); - if (anchorErr) { - PRINT(("block %Ld: invalid anchor\n", block)); - } else { - PRINT(("block %Ld: valid anchor\n", block)); - } - } - if (!anchorErr) { - PRINT(("block %Ld: 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 %Ld: found valid vds\n", avds_locations[i])); - found_vds = true; - break; - } //else { - // Both failed, so loop around and try another avds -// PRINT(("block %Ld: 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 = block << BlockShift(); //AddressForRelativeBlock(block); - MemoryChunk chunk(BlockSize()); - udf_tag *tag = NULL; - - PRINT(("descriptor #%ld (block %Ld):\n", i, block)); - - status_t err = chunk.InitCheck(); - if (!err) { - ssize_t bytesRead = read_pos(fDevice, address, chunk.Data(), BlockSize()); - err = bytesRead == (ssize_t)BlockSize() ? B_OK : B_IO_ERROR; - if (err) { - PRINT(("block %Ld: read_pos(pos:%Ld, len:%ld) failed with error 0x%lx\n", - block, address, BlockSize(), bytesRead)); - } - } - if (!err) { - 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) { - const 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() > fLogicalVolumeDescriptor.vds_number()) - fLogicalVolumeDescriptor = *(logical); - } else { - fLogicalVolumeDescriptor = *(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; - - } - } - } - - 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(fLogicalVolumeDescriptor.file_set_address().length()); - - status_t err = chunk.InitCheck(); - -#if (!DRIVE_SETUP_ADDON) - if (!err) { -// err = Read(ad, fLogicalVolumeDescriptor.file_set_address().length(), chunk.Data()); - err = Read(fLogicalVolumeDescriptor.file_set_address(), fLogicalVolumeDescriptor.file_set_address().length(), chunk.Data()); - if (!err) { - udf_file_set_descriptor *fileSet = reinterpret_cast(chunk.Data()); - fileSet->tag().init_check(0); - PDUMP(fileSet); - fRootIcb = new Icb(this, fileSet->root_directory_icb()); - err = fRootIcb ? fRootIcb->InitCheck() : B_NO_MEMORY; - } - } -#endif - - RETURN(err); -} - diff --git a/src/add-ons/kernel/file_systems/udf/Volume.h b/src/add-ons/kernel/file_systems/udf/Volume.h index 41be760fa9..0cabf50a4e 100644 --- a/src/add-ons/kernel/file_systems/udf/Volume.h +++ b/src/add-ons/kernel/file_systems/udf/Volume.h @@ -26,7 +26,6 @@ extern "C" { #include "CS0String.h" #include "DiskStructures.h" -#include "PartitionMap.h" #include "Partition.h" namespace Udf { @@ -35,121 +34,53 @@ class Icb; class Volume { public: - static status_t Identify(int device, off_t offset, off_t length, uint32 blockSize, char *volumeName); - - Volume(nspace_id id); + // Construction/destruction + Volume(nspace_id id); + ~Volume(); - status_t Mount(const char *deviceName, off_t volumeStart, off_t volumeLength, uint32 flags, - uint32 blockSize = 2048); - status_t Mount2(const char *deviceName, off_t offset, off_t length, - uint32 blockSize, uint32 flags); + // Mounting/unmounting + status_t Mount(const char *deviceName, off_t offset, off_t length, + uint32 blockSize, uint32 flags); status_t Unmount(); + // Address mapping + status_t MapBlock(udf_long_address address, off_t *mappedBlock); + status_t MapExtent(udf_long_address logicalExtent, udf_extent_address &physicalExtent); + + // Miscellaneous info const char *Name() const; int Device() const { return fDevice; } nspace_id Id() const { return fId; } - off_t Offset() const { return fOffset; } off_t Length() const { return fLength; } - uint32 BlockSize() const { return fBlockSize; } uint32 BlockShift() const { return fBlockShift; } - - off_t AddressForRelativeBlock(off_t block) { return (Offset() + block) * BlockSize(); } - off_t RelativeAddress(off_t address) { return Offset() * BlockSize() + address; } - - bool IsReadOnly() const { return fReadOnly; } bool Mounted() const { return fMounted; } - - vnode_id ToVnodeId(off_t block) const { return (vnode_id)block; } - - template - ssize_t Read(AddressType address, ssize_t length, void *data); - -#if (!DRIVE_SETUP_ADDON) Icb* RootIcb() { return fRootIcb; } -#endif - - status_t MapAddress(udf_long_address address, off_t *mappedAddress); - off_t MapAddress(udf_extent_address address); - status_t MapBlock(udf_long_address address, off_t *mappedBlock); - off_t MapAddress(udf_short_address address); - status_t MapExtent(udf_long_address logicalExtent, udf_extent_address &physicalExtent); - + private: Volume(); // unimplemented Volume(const Volume &ref); // unimplemented Volume& operator=(const Volume &ref); // unimplemented - status_t _InitStatus() const { return fInitStatus; } - // Private _InitStatus() status_t values - enum { - B_UNINITIALIZED = B_ERRORS_END+1, //!< Completely uninitialized - B_DEVICE_INITIALIZED, //!< Initialized enough to access underlying device safely - B_IDENTIFIED, //!< Verified to be a UDF volume on disc - B_LOGICAL_VOLUME_INITIALIZED, //!< Initialized enough to map addresses - - B_INITIALIZED = B_OK, - }; - - - // Called by Mount(), either directly or indirectly - status_t _Init(int device, off_t offset, off_t length, int blockSize); - status_t _Identify(); - status_t _Mount(); - status_t _WalkVolumeRecognitionSequence(); - status_t _WalkAnchorVolumeDescriptorSequences(); - status_t _WalkVolumeDescriptorSequence(udf_extent_address extent); - status_t _InitFileSetDescriptor(); - + void _Unset(); + + status_t _SetPartition(uint number, Partition *partition); + Partition* _GetPartition(uint number); + private: nspace_id fId; int fDevice; - bool fReadOnly; bool fMounted; - off_t fOffset; off_t fLength; uint32 fBlockSize; uint32 fBlockShift; - - status_t fInitStatus; - - udf_logical_descriptor fLogicalVolumeDescriptor; Partition *fPartitions[UDF_MAX_PARTITION_MAPS]; - PartitionMap fPartitionMap; -#if (!DRIVE_SETUP_ADDON) Icb *fRootIcb; // Destroyed by vfs via callback to udf_release_node() -#endif CS0String fName; }; -//---------------------------------------------------------------------- -// Template functions -//---------------------------------------------------------------------- - - -template -status_t -Volume::Read(AddressType address, ssize_t length, void *data) -{ - DEBUG_INIT(CF_PRIVATE | CF_HIGH_VOLUME, "Volume"); - off_t mappedAddress; - status_t err = data ? B_OK : B_BAD_VALUE; - if (!err) - err = MapAddress(address, &mappedAddress); - if (!err) { - ssize_t bytesRead = read_pos(fDevice, mappedAddress, data, BlockSize()); - if (bytesRead != (ssize_t)BlockSize()) { - err = B_IO_ERROR; - PRINT(("read_pos(pos:%Ld, len:%ld) failed with: 0x%lx\n", mappedAddress, - length, bytesRead)); - } - } - RETURN(err); -} - - }; // namespace Udf #endif // _UDF_VOLUME_H