Author: korli Date: 2010-11-07 16:19:08 +0100 (Sun, 07 Nov 2010) New Revision: 39343 Changeset: http://dev.haiku-os.org/changeset/39343 Modified: haiku/trunk/src/add-ons/kernel/file_systems/ext2/BlockAllocator.cpp haiku/trunk/src/add-ons/kernel/file_systems/ext2/DirectoryIterator.cpp haiku/trunk/src/add-ons/kernel/file_systems/ext2/DirectoryIterator.h haiku/trunk/src/add-ons/kernel/file_systems/ext2/kernel_interface.cpp Log: 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. Modified: haiku/trunk/src/add-ons/kernel/file_systems/ext2/BlockAllocator.cpp =================================================================== --- haiku/trunk/src/add-ons/kernel/file_systems/ext2/BlockAllocator.cpp 2010-11-07 14:16:48 UTC (rev 39342) +++ haiku/trunk/src/add-ons/kernel/file_systems/ext2/BlockAllocator.cpp 2010-11-07 15:19:08 UTC (rev 39343) @@ -660,7 +660,7 @@ 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; Modified: haiku/trunk/src/add-ons/kernel/file_systems/ext2/DirectoryIterator.cpp =================================================================== --- haiku/trunk/src/add-ons/kernel/file_systems/ext2/DirectoryIterator.cpp 2010-11-07 14:16:48 UTC (rev 39342) +++ haiku/trunk/src/add-ons/kernel/file_systems/ext2/DirectoryIterator.cpp 2010-11-07 15:19:08 UTC (rev 39343) @@ -52,12 +52,12 @@ : (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 @@ 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 @@ 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(); @@ -122,11 +126,24 @@ 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,21 +161,19 @@ 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; - } + if (entry->Length() != 0) { + if (!entry->IsValid()) { + TRACE("invalid entry.\n"); + return B_BAD_DATA; + } + fPreviousDisplacement = fDisplacement; + fDisplacement += entry->Length(); + } else + fDisplacement = fBlockSize; - fPreviousDisplacement = fDisplacement; - fDisplacement += entry->Length(); - if (fDisplacement == fBlockSize) { TRACE("Reached end of block\n"); @@ -167,23 +182,19 @@ 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,9 +203,12 @@ 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 @@ } 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 @@ 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 @@ 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 @@ 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 @@ return B_OK; } + TRACE("DirectoryIterator::RemoveEntry() fDisplacement %ld\n", fDisplacement); + if (fPreviousDisplacement == fDisplacement) { char buffer[EXT2_NAME_LENGTH + 1]; Modified: haiku/trunk/src/add-ons/kernel/file_systems/ext2/DirectoryIterator.h =================================================================== --- haiku/trunk/src/add-ons/kernel/file_systems/ext2/DirectoryIterator.h 2010-11-07 14:16:48 UTC (rev 39342) +++ haiku/trunk/src/add-ons/kernel/file_systems/ext2/DirectoryIterator.h 2010-11-07 15:19:08 UTC (rev 39343) @@ -25,6 +25,7 @@ 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 @@ bool firstSplit = false); status_t _NextBlock(); + off_t _Offset() { return fLogicalBlock * fBlockSize + + fDisplacement; } Inode* fDirectory; Modified: haiku/trunk/src/add-ons/kernel/file_systems/ext2/kernel_interface.cpp =================================================================== --- haiku/trunk/src/add-ons/kernel/file_systems/ext2/kernel_interface.cpp 2010-11-07 14:16:48 UTC (rev 39342) +++ haiku/trunk/src/add-ons/kernel/file_systems/ext2/kernel_interface.cpp 2010-11-07 15:19:08 UTC (rev 39343) @@ -1371,7 +1371,7 @@ 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;