Finished up initial volume recognition implementation

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@3833 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Tyler Dauwalder 2003-07-04 06:22:15 +00:00
parent 8279a93bdb
commit 3f4628f1ae
2 changed files with 143 additions and 38 deletions

View File

@ -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 <class AddressType>
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<udf_file_set_descriptor*>(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<udf_file_set_descriptor*>(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;
}
RETURN(err);
}

View File

@ -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 <class AddressType>
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 <class AddressType>
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