Added verification of logical volume integrity sequence.
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@5899 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
663f03ef0e
commit
495b7e4743
@ -26,6 +26,10 @@ walk_volume_descriptor_sequence(extent_address descriptorSequence,
|
||||
logical_volume_descriptor &logicalVolumeDescriptor,
|
||||
partition_descriptor partitionDescriptors[],
|
||||
uint8 &partitionDescriptorCount);
|
||||
|
||||
static status_t
|
||||
walk_integrity_sequence(int device, uint32 blockSize, uint32 blockShift,
|
||||
extent_address descriptorSequence, uint32 sequenceNumber = 0);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// externally visible functions
|
||||
@ -58,6 +62,13 @@ Udf::udf_recognize(int device, off_t offset, off_t length, uint32 blockSize,
|
||||
partitionDescriptors,
|
||||
partitionDescriptorCount);
|
||||
}
|
||||
|
||||
// Now walk the integrity sequence and make sure the last integrity
|
||||
// descriptor is a closed descriptor
|
||||
if (!error) {
|
||||
error = walk_integrity_sequence(device, blockSize, blockShift,
|
||||
logicalVolumeDescriptor.integrity_sequence_extent());
|
||||
}
|
||||
} else {
|
||||
PRINT(("Block size must be a positive power of two! (blockSize = %ld)\n", blockSize));
|
||||
}
|
||||
@ -252,20 +263,20 @@ walk_volume_descriptor_sequence(extent_address descriptorSequence,
|
||||
|
||||
PRINT(("descriptor #%ld (block %Ld):\n", i, block));
|
||||
|
||||
status_t loopErr = chunk.InitCheck();
|
||||
if (!loopErr) {
|
||||
status_t loopError = chunk.InitCheck();
|
||||
if (!loopError) {
|
||||
ssize_t bytesRead = read_pos(device, address, chunk.Data(), blockSize);
|
||||
loopErr = bytesRead == (ssize_t)blockSize ? B_OK : B_IO_ERROR;
|
||||
if (loopErr) {
|
||||
loopError = bytesRead == (ssize_t)blockSize ? B_OK : B_IO_ERROR;
|
||||
if (loopError) {
|
||||
PRINT(("block %Ld: read_pos(pos:%Ld, len:%ld) failed with error 0x%lx\n",
|
||||
block, address, blockSize, bytesRead));
|
||||
}
|
||||
}
|
||||
if (!loopErr) {
|
||||
if (!loopError) {
|
||||
tag = reinterpret_cast<descriptor_tag *>(chunk.Data());
|
||||
loopErr = tag->init_check(block);
|
||||
loopError = tag->init_check(block);
|
||||
}
|
||||
if (!loopErr) {
|
||||
if (!loopError) {
|
||||
// Now decide what type of descriptor we have
|
||||
switch (tag->id()) {
|
||||
case TAGID_UNDEFINED:
|
||||
@ -423,3 +434,88 @@ walk_volume_descriptor_sequence(extent_address descriptorSequence,
|
||||
RETURN(error);
|
||||
}
|
||||
|
||||
/*! \brief Walks the integrity sequence in the extent given by \a descriptorSequence.
|
||||
|
||||
\return
|
||||
- \c B_OK: Success. the sequence was terminated by a valid, closed
|
||||
integrity descriptor.
|
||||
- \c B_ENTRY_NOT_FOUND: The sequence was empty.
|
||||
- (other error code): The sequence was non-empty and did not end in a valid,
|
||||
closed integrity descriptor.
|
||||
*/
|
||||
static status_t
|
||||
walk_integrity_sequence(int device, uint32 blockSize, uint32 blockShift,
|
||||
extent_address descriptorSequence, uint32 sequenceNumber)
|
||||
{
|
||||
DEBUG_INIT_ETC(NULL, ("descriptorSequence.loc:%ld, descriptorSequence.len:%ld",
|
||||
descriptorSequence.location(), descriptorSequence.length()));
|
||||
uint32 count = descriptorSequence.length() >> blockShift;
|
||||
|
||||
bool lastDescriptorWasClosed = false;
|
||||
status_t error = count > 0 ? B_OK : B_ENTRY_NOT_FOUND;
|
||||
for (uint32 i = 0; error == B_OK && i < count; i++)
|
||||
{
|
||||
off_t block = descriptorSequence.location()+i;
|
||||
off_t address = block << blockShift;
|
||||
MemoryChunk chunk(blockSize);
|
||||
descriptor_tag *tag = NULL;
|
||||
|
||||
PRINT(("integrity descriptor #%ld:%ld (block %Ld):\n", sequenceNumber, i, block));
|
||||
|
||||
status_t loopError = chunk.InitCheck();
|
||||
if (!loopError) {
|
||||
ssize_t bytesRead = read_pos(device, address, chunk.Data(), blockSize);
|
||||
loopError = check_size_error(bytesRead, blockSize);
|
||||
if (loopError) {
|
||||
PRINT(("block %Ld: read_pos(pos:%Ld, len:%ld) failed with error 0x%lx\n",
|
||||
block, address, blockSize, bytesRead));
|
||||
}
|
||||
}
|
||||
if (!loopError) {
|
||||
tag = reinterpret_cast<descriptor_tag *>(chunk.Data());
|
||||
loopError = tag->init_check(block);
|
||||
}
|
||||
if (!loopError) {
|
||||
// Check the descriptor type and see if it's closed.
|
||||
loopError = tag->id() == TAGID_LOGICAL_VOLUME_INTEGRITY_DESCRIPTOR
|
||||
? B_OK : B_BAD_DATA;
|
||||
if (!loopError) {
|
||||
logical_volume_integrity_descriptor *descriptor =
|
||||
reinterpret_cast<logical_volume_integrity_descriptor*>(chunk.Data());
|
||||
PDUMP(descriptor);
|
||||
lastDescriptorWasClosed = descriptor->integrity_type() == INTEGRITY_CLOSED;
|
||||
// Check a continuation extent if necessary. Note that this effectively
|
||||
// ends our search through this extent
|
||||
extent_address &next = descriptor->next_integrity_extent();
|
||||
if (next.length() > 0) {
|
||||
status_t nextError = walk_integrity_sequence(device, blockSize, blockShift,
|
||||
next, sequenceNumber+1);
|
||||
if (nextError && nextError != B_ENTRY_NOT_FOUND) {
|
||||
// Continuation proved invalid
|
||||
error = nextError;
|
||||
break;
|
||||
} else {
|
||||
// Either the continuation was valid or empty; either way,
|
||||
// we're done searching.
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
PDUMP(tag);
|
||||
}
|
||||
}
|
||||
// If we hit an error on the first item, consider the extent empty,
|
||||
// otherwise just break out of the loop and assume part of the
|
||||
// extent is unrecorded
|
||||
if (loopError) {
|
||||
if (i == 0)
|
||||
error = B_ENTRY_NOT_FOUND;
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!error)
|
||||
error = lastDescriptorWasClosed ? B_OK : B_BAD_DATA;
|
||||
RETURN(error);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user