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:
@@ -8,9 +8,10 @@
|
|||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
#include "Volume.h"
|
#include "Volume.h"
|
||||||
|
|
||||||
|
#include "Icb.h"
|
||||||
#include "MemoryChunk.h"
|
#include "MemoryChunk.h"
|
||||||
|
|
||||||
using namespace UDF;
|
using namespace Udf;
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
// Volume
|
// Volume
|
||||||
@@ -19,12 +20,13 @@ using namespace UDF;
|
|||||||
/*! \brief Creates an unmounted volume with the given id.
|
/*! \brief Creates an unmounted volume with the given id.
|
||||||
*/
|
*/
|
||||||
Volume::Volume(nspace_id id)
|
Volume::Volume(nspace_id id)
|
||||||
: fID(id)
|
: fId(id)
|
||||||
, fDevice(0)
|
, fDevice(0)
|
||||||
, fReadOnly(false)
|
, fReadOnly(false)
|
||||||
, fStartAddress(0)
|
, fStart(0)
|
||||||
, fBlockSize(0)
|
, fBlockSize(0)
|
||||||
, fInitStatus(B_UNINITIALIZED)
|
, fInitStatus(B_UNINITIALIZED)
|
||||||
|
, fRootIcb(NULL)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -35,6 +37,9 @@ Volume::Identify(int device, off_t base)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Attempts to mount the given device.
|
/*! \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
|
status_t
|
||||||
Volume::Mount(const char *deviceName, off_t volumeStart, off_t volumeLength,
|
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
|
// Already mounted, thank you for asking
|
||||||
|
|
||||||
fReadOnly = flags & B_READ_ONLY;
|
fReadOnly = flags & B_READ_ONLY;
|
||||||
fStartAddress = volumeStart;
|
fStart = volumeStart;
|
||||||
fLength = volumeLength;
|
fLength = volumeLength;
|
||||||
fBlockSize = blockSize;
|
fBlockSize = blockSize;
|
||||||
|
|
||||||
@@ -80,20 +85,59 @@ Volume::Mount(const char *deviceName, off_t volumeStart, off_t volumeLength,
|
|||||||
// Now identify the volume
|
// Now identify the volume
|
||||||
if (!err)
|
if (!err)
|
||||||
err = _Identify();
|
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
|
off_t
|
||||||
Volume::_MapAddress(udf_extent_address address)
|
Volume::_MapAddress(udf_extent_address address)
|
||||||
{
|
{
|
||||||
return address.location() * BlockSize();
|
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
|
off_t
|
||||||
@@ -102,7 +146,7 @@ Volume::_MapAddress(udf_short_address address)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t
|
/*status_t
|
||||||
Volume::_Read(udf_extent_address address, ssize_t length, void *data)
|
Volume::_Read(udf_extent_address address, ssize_t length, void *data)
|
||||||
{
|
{
|
||||||
DEBUG_INIT(CF_PRIVATE | CF_HIGH_VOLUME, "Volume");
|
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));
|
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,
|
/*! \brief Walks through the volume recognition and descriptor sequences,
|
||||||
gathering volume description info as it goes.
|
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
|
// At this point we've found a valid set of volume descriptors. We
|
||||||
// now need to investigate the file set descriptor pointed to by
|
// now need to investigate the file set descriptor pointed to by
|
||||||
// the logical volume descriptor
|
// the logical volume descriptor
|
||||||
if (!err)
|
if (!err) {
|
||||||
|
fInitStatus = B_LOGICAL_VOLUME_INITIALIZED;
|
||||||
err = _InitFileSetDescriptor();
|
err = _InitFileSetDescriptor();
|
||||||
|
}
|
||||||
|
|
||||||
RETURN(err);
|
RETURN(err);
|
||||||
}
|
}
|
||||||
@@ -410,19 +477,20 @@ Volume::_InitFileSetDescriptor()
|
|||||||
{
|
{
|
||||||
DEBUG_INIT(CF_PRIVATE | CF_VOLUME_OPS, "Volume");
|
DEBUG_INIT(CF_PRIVATE | CF_VOLUME_OPS, "Volume");
|
||||||
MemoryChunk chunk(fLogicalVD.file_set_address().length());
|
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();
|
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) {
|
if (!err) {
|
||||||
fileSet = reinterpret_cast<udf_file_set_descriptor*>(chunk.Data());
|
// err = Read(ad, fLogicalVD.file_set_address().length(), chunk.Data());
|
||||||
fileSet->tag().init_check(0);
|
err = Read(fLogicalVD.file_set_address(), fLogicalVD.file_set_address().length(), chunk.Data());
|
||||||
PDUMP(fileSet);
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,9 @@ extern "C" {
|
|||||||
#include "DiskStructures.h"
|
#include "DiskStructures.h"
|
||||||
#include "PartitionMap.h"
|
#include "PartitionMap.h"
|
||||||
|
|
||||||
namespace UDF {
|
namespace Udf {
|
||||||
|
|
||||||
|
class Icb;
|
||||||
|
|
||||||
class Volume {
|
class Volume {
|
||||||
public:
|
public:
|
||||||
@@ -41,19 +43,28 @@ public:
|
|||||||
|
|
||||||
const char *Name() const;
|
const char *Name() const;
|
||||||
int Device() const { return fDevice; }
|
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; }
|
off_t Length() const { return fLength; }
|
||||||
|
|
||||||
uint32 BlockSize() const { return fBlockSize; }
|
uint32 BlockSize() const { return fBlockSize; }
|
||||||
off_t AddressForRelativeBlock(off_t block) { return StartAddress() + block * BlockSize(); }
|
off_t AddressForRelativeBlock(off_t block) { return (Start() + block) * BlockSize(); }
|
||||||
off_t RelativeAddress(off_t address) { return StartAddress() + address; }
|
off_t RelativeAddress(off_t address) { return Start() * BlockSize() + address; }
|
||||||
|
|
||||||
bool IsReadOnly() const { return fReadOnly; }
|
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:
|
private:
|
||||||
|
Volume(); // unimplemented
|
||||||
|
Volume(const Volume &ref); // unimplemented
|
||||||
|
Volume& operator=(const Volume &ref); // unimplemented
|
||||||
|
|
||||||
status_t _InitStatus() const { return fInitStatus; }
|
status_t _InitStatus() const { return fInitStatus; }
|
||||||
// Private _InitStatus() status_t values
|
// Private _InitStatus() status_t values
|
||||||
enum {
|
enum {
|
||||||
@@ -65,33 +76,59 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
off_t _MapAddress(udf_extent_address address);
|
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);
|
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
|
// Called by Mount(), either directly or indirectly
|
||||||
status_t _Identify();
|
status_t _Identify();
|
||||||
status_t _WalkVolumeRecognitionSequence();
|
status_t _WalkVolumeRecognitionSequence();
|
||||||
status_t _WalkAnchorVolumeDescriptorSequences();
|
status_t _WalkAnchorVolumeDescriptorSequences();
|
||||||
status_t _WalkVolumeDescriptorSequence(udf_extent_address extent);
|
status_t _WalkVolumeDescriptorSequence(udf_extent_address extent);
|
||||||
status_t _InitFileSetDescriptor();
|
status_t _InitFileSetDescriptor();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
nspace_id fID;
|
nspace_id fId;
|
||||||
int fDevice;
|
int fDevice;
|
||||||
bool fReadOnly;
|
bool fReadOnly;
|
||||||
|
|
||||||
off_t fStartAddress; //!< Start address of volume on given device
|
off_t fStart; //!< Starting block of the volume on the given device
|
||||||
off_t fLength; //!< Length of volume (in blocks)
|
off_t fLength; //!< Block length of volume on the given device
|
||||||
uint32 fBlockSize;
|
uint32 fBlockSize;
|
||||||
|
|
||||||
status_t fInitStatus;
|
status_t fInitStatus;
|
||||||
|
|
||||||
udf_logical_descriptor fLogicalVD;
|
udf_logical_descriptor fLogicalVD;
|
||||||
PartitionMap fPartitionMap;
|
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
|
#endif // _UDF_VOLUME_H
|
||||||
|
|||||||
Reference in New Issue
Block a user