- Added beginnings of volume descriptor sequence walking code.

- Accounted for addition of "udf_" to beginning of on-disk structs.
- Accounted for Block<typename> to MemoryChunk change


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@3356 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Tyler Dauwalder
2003-05-27 08:06:43 +00:00
parent 81d91d069a
commit 0d383564c3
2 changed files with 250 additions and 77 deletions
+233 -72
View File
@@ -8,7 +8,7 @@
//---------------------------------------------------------------------- //----------------------------------------------------------------------
#include "Volume.h" #include "Volume.h"
#include "Block.h" #include "MemoryChunk.h"
using namespace UDF; using namespace UDF;
@@ -84,6 +84,41 @@ Volume::Mount(const char *deviceName, off_t volumeStart, off_t volumeLength,
RETURN(B_ERROR); 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, /*! \brief Walks through the volume recognition and descriptor sequences,
gathering volume description info as it goes. gathering volume description info as it goes.
@@ -105,57 +140,14 @@ Volume::_Identify()
// Now hunt down a volume descriptor sequence from one of // Now hunt down a volume descriptor sequence from one of
// the anchor volume pointers (if there are any). // the anchor volume pointers (if there are any).
if (!err) { if (!err)
const uint8 avds_location_count = 4; err = _WalkAnchorVolumeDescriptorSequences();
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++) { // At this point we've found a valid set of volume descriptors. We
off_t block = avds_locations[i]; // now need to investigate the file set descriptor pointed to by
off_t address = AddressForRelativeBlock(block); // the logical volume descriptor
Block<anchor_volume_descriptor_pointer> anchor(BlockSize()); if (!err)
status_t anchorErr = anchor.InitCheck(); err = _InitFileSetDescriptor();
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;
}
RETURN(err); RETURN(err);
} }
@@ -175,8 +167,8 @@ Volume::_WalkVolumeRecognitionSequence()
// vrs starts at block 16. Each volume structure descriptor (vsd) // vrs starts at block 16. Each volume structure descriptor (vsd)
// should be one block long. We're expecting to find 0 or more iso9660 // should be one block long. We're expecting to find 0 or more iso9660
// vsd's followed by some ECMA-167 vsd's. // vsd's followed by some ECMA-167 vsd's.
Block<volume_structure_descriptor_header> descriptor(BlockSize()); MemoryChunk chunk(BlockSize());
status_t err = descriptor.InitCheck(); status_t err = chunk.InitCheck();
if (!err) { if (!err) {
bool foundISO = false; bool foundISO = false;
bool foundExtended = false; bool foundExtended = false;
@@ -186,32 +178,34 @@ Volume::_WalkVolumeRecognitionSequence()
for (uint32 block = 16; true; block++) { for (uint32 block = 16; true; block++) {
PRINT(("block %ld: ", block)) PRINT(("block %ld: ", block))
off_t address = AddressForRelativeBlock(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 (bytesRead == (ssize_t)BlockSize())
{ {
if (descriptor.Data()->id_matches(kVSDID_ISO)) { udf_volume_structure_descriptor_header* descriptor =
reinterpret_cast<udf_volume_structure_descriptor_header*>(chunk.Data());
if (descriptor->id_matches(kVSDID_ISO)) {
SIMPLE_PRINT(("found ISO9660 descriptor\n")); SIMPLE_PRINT(("found ISO9660 descriptor\n"));
foundISO = true; foundISO = true;
} else if (descriptor.Data()->id_matches(kVSDID_BEA)) { } else if (descriptor->id_matches(kVSDID_BEA)) {
SIMPLE_PRINT(("found BEA descriptor\n")); SIMPLE_PRINT(("found BEA descriptor\n"));
foundExtended = true; foundExtended = true;
} else if (descriptor.Data()->id_matches(kVSDID_TEA)) { } else if (descriptor->id_matches(kVSDID_TEA)) {
SIMPLE_PRINT(("found TEA descriptor\n")); SIMPLE_PRINT(("found TEA descriptor\n"));
foundExtended = true; 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")); SIMPLE_PRINT(("found ECMA-167 rev 2 descriptor\n"));
foundECMA167 = true; 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")); SIMPLE_PRINT(("found ECMA-167 rev 3 descriptor\n"));
foundECMA167 = true; foundECMA167 = true;
} else if (descriptor.Data()->id_matches(kVSDID_BOOT)) { } else if (descriptor->id_matches(kVSDID_BOOT)) {
SIMPLE_PRINT(("found boot descriptor\n")); SIMPLE_PRINT(("found boot descriptor\n"));
foundBoot = true; foundBoot = true;
} else if (descriptor.Data()->id_matches(kVSDID_ECMA168)) { } else if (descriptor->id_matches(kVSDID_ECMA168)) {
SIMPLE_PRINT(("found ECMA-168 descriptor\n")); SIMPLE_PRINT(("found ECMA-168 descriptor\n"));
foundECMA168 = true; foundECMA168 = true;
} else { } else {
SIMPLE_PRINT(("found invalid descriptor, id = `%.5s'\n", descriptor.Data()->id)); SIMPLE_PRINT(("found invalid descriptor, id = `%.5s'\n", descriptor->id));
break; break;
} }
} else { } else {
@@ -232,19 +226,86 @@ Volume::_WalkVolumeRecognitionSequence()
} }
status_t 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<udf_anchor_descriptor*>(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", DEBUG_INIT_ETC(CF_PRIVATE | CF_VOLUME_OPS, "Volume", ("loc:%ld, len:%ld",
extent.location(), extent.length())); extent.location(), extent.length()));
uint32 count = extent.length()/BlockSize(); uint32 count = extent.length()/BlockSize();
bool foundLogicalVD = false;
for (uint32 i = 0; i < count; i++) for (uint32 i = 0; i < count; i++)
{ {
off_t block = extent.location()+i; off_t block = extent.location()+i;
off_t address = AddressForRelativeBlock(block); off_t address = AddressForRelativeBlock(block);
Block<descriptor_tag> tag(BlockSize()); MemoryChunk chunk(BlockSize());
status_t err = tag.InitCheck(); udf_tag *tag = NULL;
PRINT(("descriptor #%ld (block %lld):\n", i, block));
status_t err = chunk.InitCheck();
if (!err) { 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; err = bytesRead == (ssize_t)BlockSize() ? B_OK : B_IO_ERROR;
if (err) { if (err) {
PRINT(("block %lld: read_pos(pos:%lld, len:%ld) failed with error 0x%lx\n", 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) { if (!err) {
PRINT(("descriptor #%ld (block %lld):\n", i, block)); tag = reinterpret_cast<udf_tag*>(chunk.Data());
if (tag.Data()->id() == 1) { err = tag->init_check(block);
primary_vd *vd = (primary_vd*)tag.Data(); }
vd->dump(); 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<udf_primary_descriptor*>(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<udf_implementation_use_descriptor*>(tag);
PDUMP(imp_use);
break;
}
case TAGID_PARTITION_DESCRIPTOR:
{
udf_partition_descriptor *partition = reinterpret_cast<udf_partition_descriptor*>(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<udf_logical_descriptor*>(tag);
PDUMP(logical);
if (foundLogicalVD) {
// Keep the vd with the highest vds_number
if (logical->vds_number() > fLogicalVD.vds_number())
fLogicalVD = *(logical);
} else { } else {
tag.Data()->dump(); fLogicalVD = *(logical);
foundLogicalVD = true;
}
break;
}
case TAGID_UNALLOCATED_SPACE_DESCRIPTOR:
{
udf_unallocated_space_descriptor *unallocated = reinterpret_cast<udf_unallocated_space_descriptor*>(tag);
PDUMP(unallocated);
break;
}
case TAGID_TERMINATING_DESCRIPTOR:
{
udf_terminating_descriptor *terminating = reinterpret_cast<udf_terminating_descriptor*>(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<udf_file_set_descriptor*>(chunk.Data());
fileSet->tag().init_check(0);
PDUMP(fileSet);
}
return err;
}
+14 -2
View File
@@ -25,6 +25,7 @@ extern "C" {
#include "UdfDebug.h" #include "UdfDebug.h"
#include "DiskStructures.h" #include "DiskStructures.h"
#include "PartitionMap.h"
namespace UDF { namespace UDF {
@@ -49,7 +50,6 @@ public:
off_t AddressForRelativeBlock(off_t block) { return StartAddress() + block * BlockSize(); } off_t AddressForRelativeBlock(off_t block) { return StartAddress() + block * BlockSize(); }
off_t RelativeAddress(off_t address) { return StartAddress() + address; } off_t RelativeAddress(off_t address) { return StartAddress() + 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; }
@@ -59,14 +59,23 @@ private:
enum { enum {
B_UNINITIALIZED = B_ERRORS_END+1, //!< Completely uninitialized B_UNINITIALIZED = B_ERRORS_END+1, //!< Completely uninitialized
B_DEVICE_INITIALIZED, //!< Initialized enough to access underlying device safely B_DEVICE_INITIALIZED, //!< Initialized enough to access underlying device safely
B_LOGICAL_VOLUME_INITIALIZED, //!< Initialized enough to map addresses
B_INITIALIZED = B_OK, 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 // Called by Mount(), either directly or indirectly
status_t _Identify(); status_t _Identify();
status_t _WalkVolumeRecognitionSequence(); status_t _WalkVolumeRecognitionSequence();
status_t _WalkVolumeDescriptorSequence(extent_address extent); status_t _WalkAnchorVolumeDescriptorSequences();
status_t _WalkVolumeDescriptorSequence(udf_extent_address extent);
status_t _InitFileSetDescriptor();
private: private:
nspace_id fID; nspace_id fID;
@@ -78,6 +87,9 @@ private:
uint32 fBlockSize; uint32 fBlockSize;
status_t fInitStatus; status_t fInitStatus;
udf_logical_descriptor fLogicalVD;
PartitionMap fPartitionMap;
}; };
}; // namespace UDF }; // namespace UDF