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:
parent
6a10aabdcf
commit
a1cdecff94
@ -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;
|
||||
|
@ -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];
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user