From 3f4628f1ae403c7ed9fbf20851c0cf03a206a7b7 Mon Sep 17 00:00:00 2001 From: Tyler Dauwalder Date: Fri, 4 Jul 2003 06:22:15 +0000 Subject: [PATCH] Finished up initial volume recognition implementation git-svn-id: file:///srv/svn/repos/haiku/trunk/current@3833 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../kernel/file_systems/udf/Volume.cpp | 116 ++++++++++++++---- src/add-ons/kernel/file_systems/udf/Volume.h | 65 +++++++--- 2 files changed, 143 insertions(+), 38 deletions(-) diff --git a/src/add-ons/kernel/file_systems/udf/Volume.cpp b/src/add-ons/kernel/file_systems/udf/Volume.cpp index 4426d5445a..c40ae524ed 100644 --- a/src/add-ons/kernel/file_systems/udf/Volume.cpp +++ b/src/add-ons/kernel/file_systems/udf/Volume.cpp @@ -8,9 +8,10 @@ //---------------------------------------------------------------------- #include "Volume.h" +#include "Icb.h" #include "MemoryChunk.h" -using namespace UDF; +using namespace Udf; //---------------------------------------------------------------------- // Volume @@ -19,12 +20,13 @@ using namespace UDF; /*! \brief Creates an unmounted volume with the given id. */ Volume::Volume(nspace_id id) - : fID(id) + : fId(id) , fDevice(0) , fReadOnly(false) - , fStartAddress(0) + , fStart(0) , fBlockSize(0) , fInitStatus(B_UNINITIALIZED) + , fRootIcb(NULL) { } @@ -35,6 +37,9 @@ Volume::Identify(int device, off_t base) } /*! \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, @@ -49,7 +54,7 @@ Volume::Mount(const char *deviceName, off_t volumeStart, off_t volumeLength, // Already mounted, thank you for asking fReadOnly = flags & B_READ_ONLY; - fStartAddress = volumeStart; + fStart = volumeStart; fLength = volumeLength; fBlockSize = blockSize; @@ -80,20 +85,59 @@ Volume::Mount(const char *deviceName, off_t volumeStart, off_t volumeLength, // Now identify the volume if (!err) err = _Identify(); + + // Success, create a vnode for the root + if (!err) + err = new_vnode(Id(), RootIcb()->Id(), (void*)RootIcb()); - RETURN(B_ERROR); + RETURN(err); } + off_t Volume::_MapAddress(udf_extent_address address) { return address.location() * BlockSize(); } -off_t -Volume::_MapAddress(udf_long_address address) + +/*! \brief Maps the given \c udf_long_address to an absolute block address. +*/ +status_t +Volume::_MapBlock(udf_long_address address, off_t *mappedBlock) { - return 0; + 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_LOGICAL_VOLUME_INITIALIZED ? B_OK : B_NO_INIT; + if (!err) { + udf_partition_descriptor* partition = fPartitionMap.Find(address.partition()); + err = partition ? B_OK : B_BAD_ADDRESS; + if (!err) { + *mappedBlock = Start() + partition->start() + address.block(); + } + if (!err) { + PRINT(("mapped to block %lld\n", *mappedBlock)); + } + } + RETURN_ERROR(err); +} + +/*! \brief Maps the given \c udf_long_address to an absolute byte address. +*/ +status_t +Volume::_MapAddress(udf_long_address address, off_t *mappedAddress) +{ + 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 %lld\n", *mappedAddress)); + } + RETURN_ERROR(err); } off_t @@ -102,7 +146,7 @@ Volume::_MapAddress(udf_short_address address) return 0; } -status_t +/*status_t Volume::_Read(udf_extent_address address, ssize_t length, void *data) { DEBUG_INIT(CF_PRIVATE | CF_HIGH_VOLUME, "Volume"); @@ -116,9 +160,30 @@ Volume::_Read(udf_extent_address address, ssize_t length, void *data) length, bytesRead)); } } - return err; + RETURN(err); } +*/ +/*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:%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. @@ -146,8 +211,10 @@ Volume::_Identify() // 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) + if (!err) { + fInitStatus = B_LOGICAL_VOLUME_INITIALIZED; err = _InitFileSetDescriptor(); + } RETURN(err); } @@ -410,19 +477,20 @@ 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); +// err = Read(ad, fLogicalVD.file_set_address().length(), chunk.Data()); + err = Read(fLogicalVD.file_set_address(), fLogicalVD.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; + } } - return err; -} \ No newline at end of file + + 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 b2e55bac49..e4cd8fbf33 100644 --- a/src/add-ons/kernel/file_systems/udf/Volume.h +++ b/src/add-ons/kernel/file_systems/udf/Volume.h @@ -27,7 +27,9 @@ extern "C" { #include "DiskStructures.h" #include "PartitionMap.h" -namespace UDF { +namespace Udf { + +class Icb; class Volume { public: @@ -41,19 +43,28 @@ public: const char *Name() const; int Device() const { return fDevice; } - nspace_id ID() const { return fID; } + nspace_id Id() const { return fId; } - off_t StartAddress() const { return fStartAddress; } + off_t Start() const { return fStart; } off_t Length() const { return fLength; } uint32 BlockSize() const { return fBlockSize; } - off_t AddressForRelativeBlock(off_t block) { return StartAddress() + block * BlockSize(); } - off_t RelativeAddress(off_t address) { return StartAddress() + address; } + off_t AddressForRelativeBlock(off_t block) { return (Start() + block) * BlockSize(); } + off_t RelativeAddress(off_t address) { return Start() * BlockSize() + address; } bool IsReadOnly() const { return fReadOnly; } - vnode_id ToVnodeID(off_t block) const { return (vnode_id)block; } + vnode_id ToVnodeId(off_t block) const { return (vnode_id)block; } + + template + ssize_t Read(AddressType address, ssize_t length, void *data); + + Icb* RootIcb() { return fRootIcb; } 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 { @@ -65,33 +76,59 @@ private: }; off_t _MapAddress(udf_extent_address address); - off_t _MapAddress(udf_long_address address); + status_t _MapBlock(udf_long_address address, off_t *mappedBlock); + status_t _MapAddress(udf_long_address address, off_t *mappedAddress); 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 _WalkAnchorVolumeDescriptorSequences(); status_t _WalkVolumeDescriptorSequence(udf_extent_address extent); status_t _InitFileSetDescriptor(); - + private: - nspace_id fID; + nspace_id fId; int fDevice; bool fReadOnly; - off_t fStartAddress; //!< Start address of volume on given device - off_t fLength; //!< Length of volume (in blocks) + off_t fStart; //!< Starting block of the volume on the given device + off_t fLength; //!< Block length of volume on the given device uint32 fBlockSize; status_t fInitStatus; udf_logical_descriptor fLogicalVD; PartitionMap fPartitionMap; + Icb *fRootIcb; // Destroyed by vfs via callback to udf_release_node() }; -}; // namespace UDF +//---------------------------------------------------------------------- +// 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:%lld, len:%ld) failed with: 0x%lx\n", mappedAddress, + length, bytesRead)); + } + } + RETURN(err); +} + + +}; // namespace Udf #endif // _UDF_VOLUME_H