Пример #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;
}
Пример #2
0
// FindDirEntry
status_t
Tree::FindDirEntry(uint32 dirID, uint32 objectID, const char *name,
				   size_t nameLen, DirItem *foundItem, int32 *entryIndex)
{
	status_t error = (name && foundItem && entryIndex ? InitCheck()
													  : B_BAD_VALUE);
	if (error == B_OK) {
		uint64 offset = 0;
		if (fVolume->GetKeyOffsetForName(name, nameLen, &offset) == B_OK) {
//PRINT(("Tree::FindDirEntry(): hash function: offset: %Lu (`%.*s', %lu)\n",
//offset, (int)nameLen, name, nameLen));
			// offset computed -- we can directly iterate only over entries
			// with that offset
			DirEntryIterator iterator(this, dirID, objectID, offset, true);
			DirItem dirItem;
			int32 index = 0;
			error = B_ENTRY_NOT_FOUND;
			while (iterator.GetPrevious(&dirItem, &index) == B_OK) {
				size_t itemNameLen = 0;
				if (const char *itemName
					= dirItem.EntryNameAt(index, &itemNameLen)) {
					if (itemNameLen == nameLen
						&& !strncmp(name, itemName, nameLen)) {
						// item found
						*foundItem = dirItem;
						*entryIndex = index;
						error = B_OK;
						break;
					}
				}
			}
		} else {
//PRINT(("Tree::FindDirEntry(): no hash function\n"));
			// no offset (no hash function) -- do it the slow way
			ObjectItemIterator iterator(this, dirID, objectID);
			DirItem dirItem;
			error = B_ENTRY_NOT_FOUND;
			while (iterator.GetNext(&dirItem, TYPE_DIRENTRY) == B_OK) {
				if (dirItem.Check() != B_OK) // bad data: skip item
					continue;
				int32 index = dirItem.IndexOfName(name);
				if (index >= 0) {
					// item found
					*foundItem = dirItem;
					*entryIndex = index;
					error = B_OK;
//PRINT(("  offset: %lu\n", dirItem.EntryAt(index)->GetOffset()));
					break;
				}
			}
		}
	}
	return error;
}
Пример #3
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;
}
Пример #4
0
// reiserfs_read_dir
static status_t
reiserfs_read_dir(fs_volume *fs, fs_vnode *_node, void *cookie,
	struct dirent *buffer, size_t bufferSize, uint32 *count)
{
//	FUNCTION_START();
	Volume *volume = (Volume*)fs->private_volume;
	VNode *node = (VNode*)_node->private_node;
FUNCTION(("node: (%Ld: %lu, %lu)\n", node->GetID(), node->GetDirID(),
		  node->GetObjectID()));
	DirectoryCookie *iterator = (DirectoryCookie*)cookie;
	status_t error = iterator->Resume();
	if (error == B_OK) {
		// read one entry
		DirItem item;
		int32 index = 0;
		DirEntry *entry = NULL;
		bool done = false;
		while (error == B_OK && !done
			   && (error = iterator->GetNext(&item, &index, &entry)) == B_OK) {
			uint32 dirID = entry->GetDirID();
			uint32 objectID = entry->GetObjectID();
			// skip hidden entries and entries the user specified to be hidden
			if (entry->IsHidden() || volume->IsNegativeEntry(dirID, objectID))
				continue;
			// skip entry, if we can't get the stat data, or it is neither a
			// file, a dir nor a symlink and the user desired to hide those.
			StatData statData;
			StatItem statItem;
			if (volume->GetTree()->FindStatItem(dirID, objectID, &statItem)
					!= B_OK
				|| statItem.GetStatData(&statData) != B_OK
				|| (statData.IsEsoteric() && volume->GetHideEsoteric())) {
				continue;
			}
			if (error == B_OK) {
				// get the name
				size_t nameLen = 0;
				const char *name = item.EntryNameAt(index, &nameLen);
				if (!name || nameLen == 0)	// bad data: skip it gracefully
					continue;
				// fill in the entry name -- checks whether the
				// entry fits into the buffer
				error = set_dirent_name(buffer, bufferSize, name,
										nameLen);
				if (error == B_OK) {
					// fill in the other data
					buffer->d_dev = volume->GetID();
					buffer->d_ino = VNode::GetIDFor(dirID, objectID);
					*count = 1;
PRINT(("Successfully read entry: dir: (%Ld: %ld, %ld), name: `%s', "
	   "id: (%Ld, %ld, %ld), reclen: %hu\n", node->GetID(), node->GetDirID(),
	   node->GetObjectID(), buffer->d_name, buffer->d_ino, dirID, objectID,
	   buffer->d_reclen));
					if (!strcmp("..", buffer->d_name))
						iterator->SetEncounteredDotDot(true);
					done = true;
				}
	 		}
 		}
 		if (error == B_ENTRY_NOT_FOUND) {
 			if (iterator->EncounteredDotDot()) {
	 			error = B_OK;
				*count = 0;
			} else {
				// this is necessary for the root directory
				// it usually has no ".." entry, so we simulate one
				// get the name
				const char *name = "..";
				size_t nameLen = strlen(name);
				// fill in the entry name -- checks whether the
				// entry fits into the buffer
				error = set_dirent_name(buffer, bufferSize, name,
										nameLen);
				if (error == B_OK) {
					// fill in the other data
					buffer->d_dev = volume->GetID();
					buffer->d_ino = node->GetID();
	// < That's not correct!
					*count = 1;
PRINT(("faking `..' entry: dir: (%Ld: %ld, %ld), name: `%s', "
	   "id: (%Ld, %ld, %ld), reclen: %hu\n", node->GetID(), node->GetDirID(),
	   node->GetObjectID(), buffer->d_name, buffer->d_ino, node->GetDirID(),
	   node->GetObjectID(), buffer->d_reclen));
					iterator->SetEncounteredDotDot(true);
				}
			}
 		}
 		iterator->Suspend();
	}
PRINT(("returning %ld entries\n", *count));
	RETURN_ERROR(error);
}