Ejemplo n.º 1
0
int32
DirEntryBlock::FindInsertionIndex(const char* name, size_t nameLength,
	bool& _exactMatch) const
{
	int32 entryCount = EntryCount();
	if (entryCount == 0) {
		_exactMatch = false;
		return 0;
	}

	const char* entryNames = (char*)(fBlock->nameEnds + entryCount);
	uint32 nameOffset = 0;

	int32 index = 0;
	int cmp = -1;

	// TODO: Binary search!
	for (; index < entryCount; index++) {
		const char* entryName = entryNames + nameOffset;
		size_t entryNameLength = fBlock->nameEnds[index] - nameOffset;

		cmp = compare_names(entryName, entryNameLength, name, nameLength);
		if (cmp >= 0)
			break;

		nameOffset += entryNameLength;
	}

	_exactMatch = cmp == 0;
	return index;
}
Ejemplo n.º 2
0
void
DirEntryBlock::RemoveEntry(int32 index)
{
	ASSERT(index >= 0 && index < EntryCount());

	int32 entryCount = EntryCount();
	if (entryCount == 1) {
		// simple case -- removing the last entry
		fBlock->entryCount = 0;
		return;
	}

	uint64* blockIndices = (uint64*)((uint8*)fBlock + fBlockSize) - 1;
	char* entryNames = (char*)(fBlock->nameEnds + entryCount);

	uint32 nameOffset = index == 0 ? 0 : fBlock->nameEnds[index - 1];
	uint32 nameEnd = fBlock->nameEnds[index];
	uint32 lastNameEnd = entryCount == 0
		? 0 : fBlock->nameEnds[entryCount - 1];

	if (index < entryCount - 1) {
		uint32 nameLength = nameEnd - nameOffset;

		// remove the element from the block indices array
		memmove(&blockIndices[-entryCount + 2], &blockIndices[-entryCount + 1],
			8 * (entryCount - index - 1));

		// move and update the nameEnds entries > index
		for (int32 i = index + 1; i < entryCount; i++)
			fBlock->nameEnds[i - 1] = fBlock->nameEnds[i] - nameLength;

		// move the names < index by 2 bytes
		if (index > 0)
			memmove(entryNames - 2, entryNames, nameOffset);

		// move the names > index
		memmove(entryNames - 2 + nameOffset, entryNames + nameEnd,
			lastNameEnd - nameEnd);
	} else {
		// the nameEnds array shrinks -- move all names
		memmove(entryNames - 2, entryNames, nameOffset);
	}

	// we have removed the entry
	fBlock->entryCount--;
ASSERT(Check());
}
Ejemplo n.º 3
0
/*!	Moves all entries beyond \a splitIndex (inclusively) to the empty block
	\a other.
*/
void
DirEntryBlock::SplitBlock(int32 splitIndex, DirEntryBlock& other)
{
	ASSERT(other.EntryCount() == 0);
	ASSERT(splitIndex <= EntryCount());

	int32 entryCount = EntryCount();
	if (splitIndex == entryCount)
		return;
	int32 otherEntryCount = entryCount - splitIndex;

	// copy block indices
	uint64* blockIndices = (uint64*)((uint8*)fBlock + fBlockSize);
	uint64* otherBlockIndices
		= (uint64*)((uint8*)other.fBlock + other.fBlockSize);
		// note: both point after the last entry, unlike in other methods
	memcpy(otherBlockIndices - otherEntryCount, blockIndices - entryCount,
		8 * otherEntryCount);

	// copy the name end offsets
	uint32 namesOffset = splitIndex > 0
		? fBlock->nameEnds[splitIndex - 1] : 0;
	for (int32 i = splitIndex; i < entryCount; i++) {
		other.fBlock->nameEnds[i - splitIndex] = fBlock->nameEnds[i]
			- namesOffset;
	}

	// copy the names
	char* entryNames = (char*)(fBlock->nameEnds + entryCount);
	char* otherEntryNames
		= (char*)(other.fBlock->nameEnds + otherEntryCount);
	memcpy(otherEntryNames, entryNames + namesOffset,
		fBlock->nameEnds[entryCount - 1] - namesOffset);

	// the name ends array shrinks -- move the names
	if (splitIndex > 0) {
		char* newEntryNames = (char*)(fBlock->nameEnds + splitIndex);
		memmove(newEntryNames, entryNames, namesOffset);
	}

	// update the entry counts
	fBlock->entryCount = splitIndex;
	other.fBlock->entryCount = otherEntryCount;
ASSERT(Check());
ASSERT(other.Check());
}
Ejemplo n.º 4
0
Generator * Model :: FindGen( const std::string & name ) const {
	for ( unsigned int i = 0; i < EntryCount() ; i++ ) {
		Generator * gp = GenAt( i );
		if ( gp && gp->Name() == name ) {
			return gp;
		}
	}
	return 0;
}
Ejemplo n.º 5
0
const char*
DirEntryBlock::NameAt(int32 index, size_t& _nameLength) const
{
	int32 entryCount = EntryCount();
	if (index < 0 || index >= entryCount)
		return NULL;

	uint32 nameOffset = index > 0 ? fBlock->nameEnds[index - 1] : 0;
	_nameLength = fBlock->nameEnds[index] - nameOffset;
	return (const char*)(fBlock->nameEnds + entryCount) + nameOffset;
}
Ejemplo n.º 6
0
/*!	Finds a good split index for an insertion of \a bytesNeeded bytes at
	index \a index.
*/
int32
DirEntryBlock::FindSplitIndex(int32 index, size_t bytesNeeded) const
{
	size_t splitSize = (BytesUsed() + bytesNeeded) / 2;

	int32 entryCount = EntryCount();
	for (int32 i = 0; i < entryCount; i++) {
		size_t bytesUsed = BytesUsedFor(i + 1);
		if (i == index)
			bytesUsed += bytesNeeded;
		if (bytesUsed > splitSize)
			return i;
	}

	// This should never happen.
	return entryCount;
}
Ejemplo n.º 7
0
void
Header::_DumpPartitions()
{
	for (uint32 i = 0; i < EntryCount(); i++) {
		const efi_partition_entry &entry = EntryAt(i);

		if (entry.partition_type == kEmptyGUID)
			continue;

		dprintf("[%3" B_PRIu32 "] partition type: %s\n", i,
			_PrintGUID(entry.partition_type));
		dprintf("      unique id: %s\n", _PrintGUID(entry.unique_guid));
		dprintf("      start block: %" B_PRIu64 "\n", entry.StartBlock());
		dprintf("      end block: %" B_PRIu64 "\n", entry.EndBlock());
		dprintf("      size: %g MB\n", (entry.EndBlock() - entry.StartBlock())
			* 512 / 1024.0 / 1024.0);
		dprintf("      attributes: %" B_PRIx64 "\n", entry.Attributes());

		char name[64];
		to_utf8(entry.name, EFI_PARTITION_NAME_LENGTH, name, sizeof(name));
		dprintf("      name: %s\n", name);
	}
}
Ejemplo n.º 8
0
bool
DirEntryBlock::Check() const
{
	int32 entryCount = EntryCount();
	if (entryCount == 0)
		return true;

	// Check size: Both name ends and block index arrays must fit and we need
	// at least one byte per name.
	size_t size = sizeof(*fBlock) + entryCount * 10;
	if (size + entryCount > fBlockSize) {
		ERROR("Invalid dir entry block: entry count %d requires minimum size "
			"of %" B_PRIuSIZE " + %d bytes, but block size is %" B_PRIuSIZE
			"\n", (int)entryCount, size, (int)entryCount, fBlockSize);
		return false;
	}

	// check the name ends and block indices arrays and the names
	const char* entryNames = (char*)(fBlock->nameEnds + entryCount);
	const uint64* blockIndices = (uint64*)((uint8*)fBlock + fBlockSize) - 1;
	const char* previousName = NULL;
	uint16 previousNameLength = 0;
	uint16 previousEnd = 0;

	for (int32 i = 0; i < entryCount; i++) {
		// check name end
		uint16 nameEnd = fBlock->nameEnds[i];
		if (nameEnd <= previousEnd || nameEnd > fBlockSize - size) {
			ERROR("Invalid dir entry block: name end offset of entry %" B_PRId32
				": %u, previous: %u\n", i, nameEnd, previousEnd);
			return false;
		}

		// check name length
		uint16 nameLength = nameEnd - previousEnd;
		if (nameLength > kCheckSumFSNameLength) {
			ERROR("Invalid dir entry block: name of entry %" B_PRId32 " too "
				"long: %u\n", i, nameLength);
			return false;
		}

		// verify that the name doesn't contain a null char
		const char* name = entryNames + previousEnd;
		if (strnlen(name, nameLength) != nameLength) {
			ERROR("Invalid dir entry block: name of entry %" B_PRId32
				" contains a null char\n", i);
			return false;
		}

		// compare the name with the previous name
		if (i > 0) {
			int cmp = compare_names(previousName, previousNameLength, name,
				nameLength);
			if (cmp == 0) {
				ERROR("Invalid dir entry block: entries %" B_PRId32 "/%"
					B_PRId32 " have the same name: \"%.*s\"\n", i - 1, i,
					(int)nameLength, name);
				return false;
			} else if (cmp > 0) {
				ERROR("Invalid dir entry block: entries %" B_PRId32 "/%"
					B_PRId32 " out of order: \"%.*s\" > \"%.*s\"\n", i - 1, i,
					(int)previousNameLength, previousName, (int)nameLength,
					name);
				return false;
			}
		}

		// check the block index
		if (blockIndices[-i] < kCheckSumFSSuperBlockOffset / B_PAGE_SIZE) {
			ERROR("Invalid dir entry block: entry %" B_PRId32
				" has invalid block index: %" B_PRIu64, i, blockIndices[-i]);
			return false;
		}

		previousName = name;
		previousNameLength = nameLength;
		previousEnd = nameEnd;
	}

	return true;
}
Ejemplo n.º 9
0
size_t
DirEntryBlock::BytesUsed() const
{
	return BytesUsedFor(EntryCount());
}
Ejemplo n.º 10
0
void Model :: Generate() {
	for ( unsigned int i = 0; i < EntryCount(); i++ ) {
		EntryAt( i )->Generate( this );
		EntryAt( i )->Discard();
	}
}