DirectoryIterator changes:

* RemoveEntry(): set inode id to zero when reaching the end of block
* FindEntry(): keep on searching if Get() returns B_BAD_DATA
* added _Offset() based on fLogicalBlock and fDisplacement
* Next(): keep on searching when inode id is zero; also when entry length is zero, keep on with next block
* added GetNext() to get the next valid entry.
* Get(): now returns B_BAD_DATA on a zero length or inode id.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@39343 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Jérôme Duval 2010-11-07 15:19:08 +00:00
parent 6a10aabdcf
commit a1cdecff94
4 changed files with 69 additions and 51 deletions

View File

@ -660,7 +660,7 @@ BlockAllocator::Free(Transaction& transaction, off_t start, uint32 length)
TRACE("BlockAllocator::Free(): first block: %lu, blocks per group: %lu\n",
fFirstBlock, fBlocksPerGroup);
//start -= fFirstBlock;
start -= fFirstBlock;
off_t end = start + length - 1;
uint32 group = start / fBlocksPerGroup;

View File

@ -52,12 +52,12 @@ DirectoryIterator::DirectoryIterator(Inode* directory, off_t start,
: (directory->Size() - 1) / fBlockSize + 1),
fLogicalBlock(start / fBlockSize),
fDisplacement(start % fBlockSize),
fPreviousDisplacement(fPreviousDisplacement),
fPreviousDisplacement(fDisplacement),
fStartLogicalBlock(fLogicalBlock),
fStartDisplacement(fDisplacement)
{
TRACE("DirectoryIterator::DirectoryIterator(): num blocks: %lu\n",
fNumBlocks);
TRACE("DirectoryIterator::DirectoryIterator() %lld: num blocks: %lu\n",
fDirectory->ID(), fNumBlocks);
fIndexing = parent != NULL;
fInitStatus = fDirectory->FindBlock(start, fPhysicalBlock);
fStartPhysicalBlock = fPhysicalBlock;
@ -83,7 +83,8 @@ DirectoryIterator::InitCheck()
status_t
DirectoryIterator::Get(char* name, size_t* _nameLength, ino_t* _id)
{
if (fLogicalBlock * fBlockSize + fDisplacement >= fDirectory->Size()) {
TRACE("DirectoryIterator::Get() ID %lld\n", fDirectory->ID());
if (_Offset() >= fDirectory->Size()) {
TRACE("DirectoryIterator::Get() out of entries\n");
return B_ENTRY_NOT_FOUND;
}
@ -96,6 +97,9 @@ DirectoryIterator::Get(char* name, size_t* _nameLength, ino_t* _id)
TRACE("DirectoryIterator::Get(): Displacement: %lu\n", fDisplacement);
const ext2_dir_entry* entry = (const ext2_dir_entry*)&block[fDisplacement];
if (entry->Length() == 0 || entry->InodeID() == 0)
return B_BAD_DATA;
if (entry->NameLength() != 0) {
size_t length = entry->NameLength();
@ -121,12 +125,25 @@ DirectoryIterator::Get(char* name, size_t* _nameLength, ino_t* _id)
}
status_t
DirectoryIterator::GetNext(char* name, size_t* _nameLength, ino_t* _id)
{
status_t status;
while ((status = Get(name, _nameLength, _id)) == B_BAD_DATA) {
status = Next();
if (status != B_OK)
return status;
}
return status;
}
status_t
DirectoryIterator::Next()
{
TRACE("DirectoryIterator::Next()\n");
TRACE("DirectoryIterator::Next() fDirectory->ID() %lld\n", fDirectory->ID());
if (fLogicalBlock * fBlockSize + fDisplacement >= fDirectory->Size()) {
if (_Offset() >= fDirectory->Size()) {
TRACE("DirectoryIterator::Next() out of entries\n");
return B_ENTRY_NOT_FOUND;
}
@ -144,20 +161,18 @@ DirectoryIterator::Next()
entry = (ext2_dir_entry*)(block + fDisplacement);
do {
TRACE("Checking entry at block %llu, displacement %lu\n", fPhysicalBlock,
fDisplacement);
TRACE("Checking entry at block %llu, displacement %lu entry inodeid %ld\n", fPhysicalBlock,
fDisplacement, entry->InodeID());
if (entry->Length() == 0) {
TRACE("empty entry.\n");
return B_ENTRY_NOT_FOUND;
}
if (!entry->IsValid()) {
TRACE("invalid entry.\n");
return B_BAD_DATA;
}
fPreviousDisplacement = fDisplacement;
fDisplacement += entry->Length();
if (entry->Length() != 0) {
if (!entry->IsValid()) {
TRACE("invalid entry.\n");
return B_BAD_DATA;
}
fPreviousDisplacement = fDisplacement;
fDisplacement += entry->Length();
} else
fDisplacement = fBlockSize;
if (fDisplacement == fBlockSize) {
TRACE("Reached end of block\n");
@ -167,23 +182,19 @@ DirectoryIterator::Next()
status_t status = _NextBlock();
if (status != B_OK)
return status;
if (fLogicalBlock * fBlockSize + ext2_dir_entry::MinimumSize()
< fDirectory->Size()) {
status_t status = fDirectory->FindBlock(
fLogicalBlock * fBlockSize, fPhysicalBlock);
if (status != B_OK)
return status;
} else {
if (_Offset() + ext2_dir_entry::MinimumSize()
>= fDirectory->Size()) {
TRACE("DirectoryIterator::Next() end of directory file\n");
return B_ENTRY_NOT_FOUND;
}
status = fDirectory->FindBlock(_Offset(), fPhysicalBlock);
if (status != B_OK)
return status;
if (entry->Length() == 0) {
block = cached.SetTo(fPhysicalBlock);
if (block == NULL)
return B_IO_ERROR;
}
block = cached.SetTo(fPhysicalBlock);
if (block == NULL)
return B_IO_ERROR;
} else if (fDisplacement > fBlockSize) {
TRACE("The entry isn't block aligned.\n");
// TODO: Is block alignment obligatory?
@ -192,8 +203,11 @@ DirectoryIterator::Next()
entry = (ext2_dir_entry*)(block + fDisplacement);
TRACE("DirectoryIterator::Next() skipping entry\n");
} while (entry->Length() == 0);
TRACE("DirectoryIterator::Next() skipping entry %d %ld\n", entry->Length(), entry->InodeID());
} while (entry->Length() == 0 || entry->InodeID() == 0);
TRACE("DirectoryIterator::Next() entry->Length() %d entry->name %s\n",
entry->Length(), entry->name);
return B_OK;
}
@ -244,11 +258,10 @@ DirectoryIterator::AddEntry(Transaction& transaction, const char* name,
} else if (status != B_DEVICE_FULL)
return status;
fDisplacement = 0;
status = _NextBlock();
if (status == B_OK) {
status = fDirectory->FindBlock(fLogicalBlock * fBlockSize,
fPhysicalBlock);
}
if (status == B_OK)
status = fDirectory->FindBlock(_Offset(), fPhysicalBlock);
}
if (status != B_ENTRY_NOT_FOUND)
@ -299,15 +312,14 @@ DirectoryIterator::FindEntry(const char* name, ino_t* _id)
while (status == B_OK) {
size_t nameLength = EXT2_NAME_LENGTH;
status = Get(buffer, &nameLength, &id);
if (status != B_OK)
return status;
if (strcmp(name, buffer) == 0) {
if (_id != NULL)
*_id = id;
return B_OK;
}
if (status == B_OK) {
if (strcmp(name, buffer) == 0) {
if (_id != NULL)
*_id = id;
return B_OK;
}
} else if (status != B_BAD_DATA)
break;
status = Next();
}
@ -318,6 +330,7 @@ DirectoryIterator::FindEntry(const char* name, ino_t* _id)
status_t
DirectoryIterator::RemoveEntry(Transaction& transaction)
{
TRACE("DirectoryIterator::RemoveEntry()\n");
ext2_dir_entry* previousEntry;
ext2_dir_entry* dirEntry;
CachedBlock cached(fVolume);
@ -331,9 +344,9 @@ DirectoryIterator::RemoveEntry(Transaction& transaction)
fDisplacement += previousEntry->Length();
if (fDisplacement == fBlockSize) {
memset(&previousEntry->name_length, 0, fBlockSize - 6);
previousEntry->SetInodeID(0);
fDisplacement = 0;
return Next();
return B_OK;
} else if (fDisplacement > fBlockSize) {
TRACE("DirectoryIterator::RemoveEntry(): Entry isn't aligned to "
"block entry.");
@ -350,6 +363,8 @@ DirectoryIterator::RemoveEntry(Transaction& transaction)
return B_OK;
}
TRACE("DirectoryIterator::RemoveEntry() fDisplacement %ld\n", fDisplacement);
if (fPreviousDisplacement == fDisplacement) {
char buffer[EXT2_NAME_LENGTH + 1];

View File

@ -25,6 +25,7 @@ public:
status_t Next();
status_t Get(char* name, size_t* _nameLength, ino_t* id);
status_t GetNext(char* name, size_t* _nameLength, ino_t* id);
status_t Rewind();
void Restart();
@ -56,6 +57,8 @@ protected:
bool firstSplit = false);
status_t _NextBlock();
off_t _Offset() { return fLogicalBlock * fBlockSize
+ fDisplacement; }
Inode* fDirectory;

View File

@ -1371,7 +1371,7 @@ ext2_read_dir(fs_volume *_volume, fs_vnode *_node, void *_cookie,
size_t length = bufferSize;
ino_t id;
status_t status = iterator->Get(dirent->d_name, &length, &id);
status_t status = iterator->GetNext(dirent->d_name, &length, &id);
if (status == B_ENTRY_NOT_FOUND) {
*_num = 0;
return B_OK;