- 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:
@@ -8,7 +8,7 @@
|
||||
//----------------------------------------------------------------------
|
||||
#include "Volume.h"
|
||||
|
||||
#include "Block.h"
|
||||
#include "MemoryChunk.h"
|
||||
|
||||
using namespace UDF;
|
||||
|
||||
@@ -84,6 +84,41 @@ Volume::Mount(const char *deviceName, off_t volumeStart, off_t volumeLength,
|
||||
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,
|
||||
gathering volume description info as it goes.
|
||||
|
||||
@@ -105,57 +140,14 @@ Volume::_Identify()
|
||||
|
||||
// Now hunt down a volume descriptor sequence from one of
|
||||
// the anchor volume pointers (if there are any).
|
||||
if (!err) {
|
||||
const uint8 avds_location_count = 4;
|
||||
const off_t avds_locations[avds_location_count] = { 256,
|
||||
Length()-256,
|
||||
Length(),
|
||||
512,
|
||||
};
|
||||
bool found_vds = false;
|
||||
if (!err)
|
||||
err = _WalkAnchorVolumeDescriptorSequences();
|
||||
|
||||
for (int32 i = 0; i < avds_location_count; i++) {
|
||||
off_t block = avds_locations[i];
|
||||
off_t address = AddressForRelativeBlock(block);
|
||||
Block<anchor_volume_descriptor_pointer> anchor(BlockSize());
|
||||
status_t anchorErr = anchor.InitCheck();
|
||||
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;
|
||||
}
|
||||
// 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();
|
||||
|
||||
RETURN(err);
|
||||
}
|
||||
@@ -175,8 +167,8 @@ Volume::_WalkVolumeRecognitionSequence()
|
||||
// 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.
|
||||
Block<volume_structure_descriptor_header> descriptor(BlockSize());
|
||||
status_t err = descriptor.InitCheck();
|
||||
MemoryChunk chunk(BlockSize());
|
||||
status_t err = chunk.InitCheck();
|
||||
if (!err) {
|
||||
bool foundISO = false;
|
||||
bool foundExtended = false;
|
||||
@@ -186,32 +178,34 @@ Volume::_WalkVolumeRecognitionSequence()
|
||||
for (uint32 block = 16; true; block++) {
|
||||
PRINT(("block %ld: ", 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 (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"));
|
||||
foundISO = true;
|
||||
} else if (descriptor.Data()->id_matches(kVSDID_BEA)) {
|
||||
} else if (descriptor->id_matches(kVSDID_BEA)) {
|
||||
SIMPLE_PRINT(("found BEA descriptor\n"));
|
||||
foundExtended = true;
|
||||
} else if (descriptor.Data()->id_matches(kVSDID_TEA)) {
|
||||
} else if (descriptor->id_matches(kVSDID_TEA)) {
|
||||
SIMPLE_PRINT(("found TEA descriptor\n"));
|
||||
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"));
|
||||
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"));
|
||||
foundECMA167 = true;
|
||||
} else if (descriptor.Data()->id_matches(kVSDID_BOOT)) {
|
||||
} else if (descriptor->id_matches(kVSDID_BOOT)) {
|
||||
SIMPLE_PRINT(("found boot descriptor\n"));
|
||||
foundBoot = true;
|
||||
} else if (descriptor.Data()->id_matches(kVSDID_ECMA168)) {
|
||||
} 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.Data()->id));
|
||||
SIMPLE_PRINT(("found invalid descriptor, id = `%.5s'\n", descriptor->id));
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
@@ -232,19 +226,86 @@ Volume::_WalkVolumeRecognitionSequence()
|
||||
}
|
||||
|
||||
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",
|
||||
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 = AddressForRelativeBlock(block);
|
||||
Block<descriptor_tag> tag(BlockSize());
|
||||
status_t err = tag.InitCheck();
|
||||
MemoryChunk chunk(BlockSize());
|
||||
udf_tag *tag = NULL;
|
||||
|
||||
PRINT(("descriptor #%ld (block %lld):\n", i, block));
|
||||
|
||||
status_t err = chunk.InitCheck();
|
||||
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;
|
||||
if (err) {
|
||||
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) {
|
||||
PRINT(("descriptor #%ld (block %lld):\n", i, block));
|
||||
if (tag.Data()->id() == 1) {
|
||||
primary_vd *vd = (primary_vd*)tag.Data();
|
||||
vd->dump();
|
||||
tag = reinterpret_cast<udf_tag*>(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<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 {
|
||||
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;
|
||||
}
|
||||
@@ -25,6 +25,7 @@ extern "C" {
|
||||
#include "UdfDebug.h"
|
||||
|
||||
#include "DiskStructures.h"
|
||||
#include "PartitionMap.h"
|
||||
|
||||
namespace UDF {
|
||||
|
||||
@@ -49,7 +50,6 @@ public:
|
||||
off_t AddressForRelativeBlock(off_t block) { return StartAddress() + block * BlockSize(); }
|
||||
off_t RelativeAddress(off_t address) { return StartAddress() + address; }
|
||||
|
||||
|
||||
bool IsReadOnly() const { return fReadOnly; }
|
||||
|
||||
vnode_id ToVnodeID(off_t block) const { return (vnode_id)block; }
|
||||
@@ -59,14 +59,23 @@ private:
|
||||
enum {
|
||||
B_UNINITIALIZED = B_ERRORS_END+1, //!< Completely uninitialized
|
||||
B_DEVICE_INITIALIZED, //!< Initialized enough to access underlying device safely
|
||||
B_LOGICAL_VOLUME_INITIALIZED, //!< Initialized enough to map addresses
|
||||
|
||||
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
|
||||
status_t _Identify();
|
||||
status_t _WalkVolumeRecognitionSequence();
|
||||
status_t _WalkVolumeDescriptorSequence(extent_address extent);
|
||||
status_t _WalkAnchorVolumeDescriptorSequences();
|
||||
status_t _WalkVolumeDescriptorSequence(udf_extent_address extent);
|
||||
status_t _InitFileSetDescriptor();
|
||||
|
||||
private:
|
||||
nspace_id fID;
|
||||
@@ -78,6 +87,9 @@ private:
|
||||
uint32 fBlockSize;
|
||||
|
||||
status_t fInitStatus;
|
||||
|
||||
udf_logical_descriptor fLogicalVD;
|
||||
PartitionMap fPartitionMap;
|
||||
};
|
||||
|
||||
}; // namespace UDF
|
||||
|
||||
Reference in New Issue
Block a user