Esempio n. 1
0
// _VerifyHashFunction
bool
Volume::_VerifyHashFunction(hash_function_t function)
{
	bool result = true;
	// iterate over the entries in the root dir until we find an entry, that
	// doesn't falsify the hash function
	DirEntryIterator iterator(fTree, fRootVNode->GetDirID(),
							  fRootVNode->GetObjectID(), DOT_DOT_OFFSET + 1);
	DirItem item;
	int32 index = 0;
	while (iterator.GetNext(&item, &index) == B_OK) {
		DirEntry *entry = item.EntryAt(index);
		uint64 offset = entry->GetOffset();
		// try the hash function
		size_t nameLen = 0;
		if (const char *name = item.EntryNameAt(index, &nameLen)) {
			uint64 testOffset = key_offset_for_name(function, name, nameLen);
			if (offset_hash_value(offset) != offset_hash_value(testOffset)) {
				result = false;
				break;
			}
		} // else: bad data
	}
	return result;
}
Esempio n. 2
0
/*!	\brief Returns the next entry belonging to the directory.
	\param foundItem Pointer to a pre-allocated Item that shall be set
		   to the found item.
	\param entryIndex Pointer to a pre-allocated int32 that shall be set
		   to the found entry index.
	\param _entry Pointer to a pre-allocated DirEntry pointer that shall be set
		   to the found entry. May be \c NULL.
	\return \c B_OK, if everything went fine, \c B_ENTRY_NOT_FOUND, if we're
			through.
*/
status_t
DirEntryIterator::GetNext(DirItem *foundItem, int32 *entryIndex,
						  DirEntry **_entry)
{
	status_t error = (foundItem && entryIndex ? InitCheck() : B_BAD_VALUE);
	// get the next DirItem, if necessary
	// the loop skips empty DirItems gracefully
	while (error == B_OK
		   && (fIndex < 0 || fIndex >= fDirItem.GetEntryCount())) {
		error = fItemIterator.GetNext(&fDirItem, TYPE_DIRENTRY);
		if (error == B_OK) {
			if (fDirItem.Check() == B_OK)
				fIndex = 0;
			else	// bad data: skip the item
				fIndex = -1;
		}
	}
	// get the next entry and check whether it has the correct offset
	if (error == B_OK) {
		DirEntry *entry = fDirItem.EntryAt(fIndex);
		if (!fFixedHash
			|| offset_hash_value(entry->GetOffset())
			   == offset_hash_value(GetOffset())) {
			*foundItem = fDirItem;
			*entryIndex = fIndex;
			if (_entry)
				*_entry = entry;
			fIndex++;
		} else
			error = B_ENTRY_NOT_FOUND;
	}
	return error;
}
Esempio n. 3
0
/*!	\brief Returns the previous entry belonging to the directory.
	\param foundItem Pointer to a pre-allocated Item that shall be set
		   to the found item.
	\param entryIndex Pointer to a pre-allocated int32 that shall be set
		   to the found entry index.
	\param _entry Pointer to a pre-allocated DirEntry pointer that shall be set
		   to the found entry. May be \c NULL.
	\return \c B_OK, if everything went fine, \c B_ENTRY_NOT_FOUND, if we're
			through.
*/
status_t
DirEntryIterator::GetPrevious(DirItem *foundItem, int32 *entryIndex,
							  DirEntry **_entry)
{
//printf("DirEntryIterator::GetPrevious()\n");
	status_t error = (foundItem && entryIndex ? InitCheck() : B_BAD_VALUE);
	if (error == B_OK && fDone)
		error = B_ENTRY_NOT_FOUND;
	// get the next DirItem, if necessary
	// the loop skips empty DirItems gracefully
	while (error == B_OK
		   && (fIndex < 0 || fIndex >= fDirItem.GetEntryCount())) {
		error = fItemIterator.GetPrevious(&fDirItem, TYPE_DIRENTRY);
		if (error == B_OK) {
			if (fDirItem.Check() == B_OK)
				fIndex = fDirItem.GetEntryCount() - 1;
			else	// bad data: skip the item
				fIndex = -1;
		}
	}
//printf("  found dir item: %s\n", strerror(error));
	// skip entries with a greater offset
	while (error == B_OK && fIndex >= 0
		   && fDirItem.EntryAt(fIndex)->GetOffset() > GetOffset()) {
//printf("  skipping entry %ld: offset %lu\n", fIndex, fDirItem.EntryAt(fIndex)->GetOffset());
		fIndex--;
	}
	// get the entry and check whether it has the correct offset
	if (error == B_OK) {
//printf("  entries with greater offsets skipped: index: %ld\n", fIndex);
		if (fIndex >= 0
//&& (printf("  entry index %ld: offset %lu\n", fIndex, fDirItem.EntryAt(fIndex)->GetOffset()), true)
			&& (!fFixedHash
				|| offset_hash_value(fDirItem.EntryAt(fIndex)->GetOffset())
				   == offset_hash_value(GetOffset()))) {
//printf("  entry found\n");
			DirEntry *entry = fDirItem.EntryAt(fIndex);
			*foundItem = fDirItem;
			*entryIndex = fIndex;
			fDone = (fFixedHash
					 && offset_generation_number(entry->GetOffset()) == 0);
			if (_entry)
				*_entry = entry;
			fIndex--;
		} else
			error = B_ENTRY_NOT_FOUND;
	}
//printf("DirEntryIterator::GetPrevious() done: %s\n", strerror(error));
	return error;
}
Esempio n. 4
0
// _DetectHashFunction
uint32
Volume::_DetectHashFunction()
{
	// iterate over the entries in the root dir until we find an entry, that
	// let us draw an unambiguous conclusion
	DirEntryIterator iterator(fTree, fRootVNode->GetDirID(),
							  fRootVNode->GetObjectID(), DOT_DOT_OFFSET + 1);
	uint32 foundCode = UNSET_HASH;
	DirItem item;
	int32 index = 0;
	while (foundCode == UNSET_HASH
		   && iterator.GetNext(&item, &index) == B_OK) {
		DirEntry *entry = item.EntryAt(index);
		uint64 offset = entry->GetOffset();
		uint32 hashCodes[] = { TEA_HASH, YURA_HASH, R5_HASH };
		int32 hashCodeCount = sizeof(hashCodes) / sizeof(uint32);
		size_t nameLen = 0;
		const char *name = item.EntryNameAt(index, &nameLen);
		if (!name)	// bad data!
			continue;
		// try each hash function -- if there's a single winner, we're done,
		// otherwise the next entry must help
		for (int32 i = 0; i < hashCodeCount; i++) {
			hash_function_t function = hash_function_for_code(hashCodes[i]);
			uint64 testOffset = key_offset_for_name(function, name, nameLen);
			if (offset_hash_value(offset) == offset_hash_value(testOffset)) {
				if (foundCode != UNSET_HASH) {
					// ambiguous
					foundCode = UNSET_HASH;
					break;
				} else
					foundCode = hashCodes[i];
			}
		}
	}
	return foundCode;
}