Exemple #1
0
	void _AddSpaces(BPartition* partition, PartitionView* parentView)
	{
		// add any available space on the partition
		BPartitioningInfo info;
		if (partition->GetPartitioningInfo(&info) >= B_OK) {
			off_t parentSize = partition->Size();
			off_t offset;
			off_t size;
			for (int32 i = 0;
					info.GetPartitionableSpaceAt(i, &offset, &size) >= B_OK;
					i++) {
				// TODO: remove again once Disk Device API is fixed
				if (!is_valid_partitionable_space(size))
					continue;
				//
				double scale = (double)size / parentSize;
				partition_id id
					= fSpaceIDMap.SpaceIDFor(partition->ID(), offset);
				PartitionView* view = new PartitionView(B_TRANSLATE("<empty>"),
					scale, offset, parentView->Level() + 1, id);

				fViewMap.Put(id, view);
				BGroupLayout* layout = parentView->GroupLayout();
				layout->AddView(_FindInsertIndex(view, layout), view, scale);
			}
		}
	}
uint32
ExtendedPartitionHandle::SupportedOperations(uint32 mask)
{
	uint32 flags = 0;

	// creating child
	if ((mask & B_DISK_SYSTEM_SUPPORTS_CREATING_CHILD) != 0) {
		BPartitioningInfo info;
		if (GetPartitioningInfo(&info) == B_OK
			&& info.CountPartitionableSpaces() > 1) {
			flags |= B_DISK_SYSTEM_SUPPORTS_CREATING_CHILD;
		}
	}

	return flags;
}
Exemple #3
0
uint32
GPTPartitionHandle::SupportedOperations(uint32 mask)
{
	uint32 flags = B_DISK_SYSTEM_SUPPORTS_RESIZING
		| B_DISK_SYSTEM_SUPPORTS_MOVING
		| B_DISK_SYSTEM_SUPPORTS_SETTING_CONTENT_PARAMETERS
		| B_DISK_SYSTEM_SUPPORTS_INITIALIZING;

	// creating child
	if ((mask & B_DISK_SYSTEM_SUPPORTS_CREATING_CHILD) != 0) {
		BPartitioningInfo info;
		if (GetPartitioningInfo(&info) == B_OK
			&& info.CountPartitionableSpaces() > 1) {
			flags |= B_DISK_SYSTEM_SUPPORTS_CREATING_CHILD;
		}
	}

	return flags;
}
Exemple #4
0
	void _AddPartition(BPartition* partition) const
	{
		// add the partition itself
		fPartitionList->AddPartition(partition);

		// add any available space on it
		BPartitioningInfo info;
		status_t ret = partition->GetPartitioningInfo(&info);
		if (ret >= B_OK) {
			partition_id parentID = partition->ID();
			off_t offset;
			off_t size;
			for (int32 i = 0;
				info.GetPartitionableSpaceAt(i, &offset, &size) >= B_OK;
				i++) {
				// TODO: remove again once Disk Device API is fixed
				if (!is_valid_partitionable_space(size))
					continue;
				//
				partition_id id = fSpaceIDMap.SpaceIDFor(parentID, offset);
				fPartitionList->AddSpace(parentID, id, offset, size);
			}
		}
	}
	void _NewPartition()
	{
		if (!fPrepared) {
			if (fDevice->IsReadOnly())
				printf("Device is read-only!\n");
			else
				printf("Sorry, not prepared for modifications!\n");
			return;
		}

		// get the parent partition
		BPartition* partition = NULL;
		int32 partitionIndex;
		if (!_SelectPartition("parent partition index [-1 to abort]: ",
				partition, partitionIndex)) {
			return;
		}

		printf("\nselected partition:\n\n");
		print_partition_table_header();
		print_partition(partition, 0, partitionIndex);

		if (!partition->ContainsPartitioningSystem()) {
			printf("The selected partition does not contain a partitioning "
				"system.\n");
			return;
		}

		// get supported types
		BObjectList<BString> supportedTypes(20, true);
		BString typeBuffer;
		int32 cookie = 0;
		while (partition->GetNextSupportedChildType(&cookie, &typeBuffer)
				== B_OK) {
			supportedTypes.AddItem(new BString(typeBuffer));
		}

		if (supportedTypes.IsEmpty()) {
			printf("The partitioning system is not able to create any "
				"child partition (no supported types).\n");
			return;
		}

		// get partitioning info
		BPartitioningInfo partitioningInfo;
		status_t error = partition->GetPartitioningInfo(&partitioningInfo);
		if (error != B_OK) {
			printf("Failed to get partitioning info for partition: %s\n",
				strerror(error));
			return;
		}

		int32 spacesCount = partitioningInfo.CountPartitionableSpaces();
		if (spacesCount == 0) {
			printf("There's no space on the partition where a child partition "
				"could be created\n");
			return;
		}

		// let the user select the partition type, if there's more than one
		int64 typeIndex = 0;
		int32 supportedTypesCount = supportedTypes.CountItems();
		if (supportedTypesCount > 1) {
			// list them
			printf("Possible partition types:\n");
			for (int32 i = 0; i < supportedTypesCount; i++)
				printf("%2ld  %s\n", i, supportedTypes.ItemAt(i)->String());

			if (!_ReadNumber("supported type index [-1 to abort]: ", 0,
					supportedTypesCount - 1, -1, "invalid index", typeIndex)) {
				return;
			}
		}

		const char* type = supportedTypes.ItemAt(typeIndex)->String();

		// list partitionable spaces
		printf("Unused regions where the new partition could be created:\n");
		for (int32 i = 0; i < spacesCount; i++) {
			off_t _offset;
			off_t _size;
			partitioningInfo.GetPartitionableSpaceAt(i, &_offset, &_size);
			BString offset, size;
			get_size_string(_offset, offset);
			get_size_string(_size, size);
			printf("%2ld  start: %8s,  size:  %8s\n", i, offset.String(),
				size.String());
		}

		// let the user select the partitionable space, if there's more than one
		int64 spaceIndex = 0;
		if (spacesCount > 1) {
			if (!_ReadNumber("unused region index [-1 to abort]: ", 0,
					spacesCount - 1, -1, "invalid index", spaceIndex)) {
				return;
			}
		}

		off_t spaceOffset;
		off_t spaceSize;
		partitioningInfo.GetPartitionableSpaceAt(spaceIndex, &spaceOffset,
			&spaceSize);

		off_t start;
		off_t size;
		BString parameters;
		while (true) {
			// let the user enter start, size, and parameters

			// start
			while (true) {
				BString spaceOffsetString;
				get_size_string(spaceOffset, spaceOffsetString);
				BString prompt("partition start [default: ");
				prompt << spaceOffsetString << "]: ";
				if (!_ReadSize(prompt.String(), spaceOffset, start))
					return;

				if (start >= spaceOffset && start <= spaceOffset + spaceSize)
					break;

				printf("invalid partition start\n");
			}

			// size
			off_t maxSize = spaceOffset + spaceSize - start;
			while (true) {
				BString maxSizeString;
				get_size_string(maxSize, maxSizeString);
				BString prompt("partition size [default: ");
				prompt << maxSizeString << "]: ";
				if (!_ReadSize(prompt.String(), maxSize, size))
					return;

				if (size >= 0 && start + size <= spaceOffset + spaceSize)
					break;

				printf("invalid partition size\n");
			}

			// parameters
			if (!_ReadLine("partition parameters: ", parameters))
				return;

			// validate parameters
			off_t validatedStart = start;
			off_t validatedSize = size;
// TODO: Support the name parameter!
			if (partition->ValidateCreateChild(&start, &size, type, NULL,
					parameters.String()) != B_OK) {
				printf("Validation of the given values failed. Sorry, can't "
					"continue.\n");
				return;
			}

			// did the disk system change offset or size?
			if (validatedStart == start && validatedSize == size) {
				printf("Everything looks dandy.\n");
			} else {
				BString startString, sizeString;
				get_size_string(validatedStart, startString);
				get_size_string(validatedSize, sizeString);
				printf("The disk system adjusted the partition start and "
					"size to %lld (%s) and %lld (%s).\n",
					validatedStart, startString.String(), validatedSize,
					sizeString.String());
				start = validatedStart;
				size = validatedSize;
			}

			// let the user decide whether to continue, change parameters, or
			// abort
			bool changeParameters = false;
			while (true) {
				BString line;
				_ReadLine("[c]ontinue, change [p]arameters, or [a]bort? ", line);
				if (line == "a")
					return;
				if (line == "p") {
					changeParameters = true;
					break;
				}
				if (line == "c")
					break;

				printf("invalid input\n");
			}

			if (!changeParameters)
				break;
		}

		// create child
		error = partition->CreateChild(start, size, type, NULL,
			parameters.String());
		if (error != B_OK)
			printf("Creating the partition failed: %s\n", strerror(error));
	}
status_t
ExtendedPartitionHandle::CreateChild(off_t offset, off_t size,
	const char* typeString, const char* name, const char* _parameters,
	BMutablePartition** _child)
{
	// check type
	PartitionType type;
	if (!type.SetType(typeString) || type.IsEmpty())
		return B_BAD_VALUE;

	// check name
	if (name != NULL && name[0] != '\0')
		return B_BAD_VALUE;

	// offset properly aligned?
	if (offset != sector_align(offset, Partition()->BlockSize())
		|| size != sector_align(size, Partition()->BlockSize()))
		return B_BAD_VALUE;

	// check the free space situation
	BPartitioningInfo info;
	status_t error = GetPartitioningInfo(&info);
	if (error != B_OK)
		return error;

	bool foundSpace = false;
	off_t end = offset + size;
	int32 spacesCount = info.CountPartitionableSpaces();
	for (int32 i = 0; i < spacesCount; i++) {
		off_t spaceOffset, spaceSize;
		info.GetPartitionableSpaceAt(i, &spaceOffset, &spaceSize);
		off_t spaceEnd = spaceOffset + spaceSize;

		if (offset >= spaceOffset && end <= spaceEnd) {
			foundSpace = true;
			break;
		}
	}

	if (!foundSpace)
		return B_BAD_VALUE;

	BString parameters(_parameters);
	parameters << "partition_table_offset " << offset - PTS_OFFSET << " ;\n";
	// everything looks good, create the child
	BMutablePartition* child;
	error = Partition()->CreateChild(-1, typeString,
		NULL, parameters.String(), &child);
	if (error != B_OK)
		return error;

	// init the child
	child->SetOffset(offset);
	child->SetSize(size);
	child->SetBlockSize(Partition()->BlockSize());
	//child->SetFlags(0);
	child->SetChildCookie(Partition());

	*_child = child;
	return B_OK;
}
status_t
ExtendedPartitionHandle::ValidateCreateChild(off_t* _offset, off_t* _size,
	const char* typeString, BString* name, const char* parameters)
{
	// check type
	if (!typeString)
		return B_BAD_VALUE;

	// check name
	if (name)
		name->Truncate(0);

	// check the free space situation
	BPartitioningInfo info;
	status_t error = GetPartitioningInfo(&info);
	if (error != B_OK)
		return error;

	// any space in the partition at all?
	int32 spacesCount = info.CountPartitionableSpaces();
	if (spacesCount == 0)
		return B_BAD_VALUE;

	// check offset and size
	off_t offset = sector_align(*_offset, Partition()->BlockSize());
	off_t size = sector_align(*_size, Partition()->BlockSize());
		// TODO: Rather round size up?
	off_t end = offset + size;

	// get the first partitionable space the requested interval intersects with
	int32 spaceIndex = -1;
	int32 closestSpaceIndex = -1;
	off_t closestSpaceDistance = 0;
	for (int32 i = 0; i < spacesCount; i++) {
		off_t spaceOffset, spaceSize;
		info.GetPartitionableSpaceAt(i, &spaceOffset, &spaceSize);
		off_t spaceEnd = spaceOffset + spaceSize;

		if ((spaceOffset >= offset && spaceOffset < end)
			|| (offset >= spaceOffset && offset < spaceEnd)) {
			spaceIndex = i;
			break;
		}

		off_t distance;
		if (offset < spaceOffset)
			distance = spaceOffset - end;
		else
			distance = spaceEnd - offset;

		if (closestSpaceIndex == -1 || distance < closestSpaceDistance) {
			closestSpaceIndex = i;
			closestSpaceDistance = distance;
		}
	}

	// get the space we found
	off_t spaceOffset, spaceSize;
	info.GetPartitionableSpaceAt(
		spaceIndex >= 0 ? spaceIndex : closestSpaceIndex, &spaceOffset,
		&spaceSize);
	off_t spaceEnd = spaceOffset + spaceSize;

	// If the requested intervald doesn't intersect with any space yet, move
	// it, so that it does.
	if (spaceIndex < 0) {
		spaceIndex = closestSpaceIndex;
		if (offset < spaceOffset) {
			offset = spaceOffset;
			end = offset + size;
		} else {
			end = spaceEnd;
			offset = end - size;
		}
	}

	// move/shrink the interval, so that it fully lies within the space
	if (offset < spaceOffset) {
		offset = spaceOffset;
		end = offset + size;
		if (end > spaceEnd) {
			end = spaceEnd;
			size = end - offset;
		}
	} else if (end > spaceEnd) {
		end = spaceEnd;
		offset = end - size;
		if (offset < spaceOffset) {
			offset = spaceOffset;
			size = end - offset;
		}
	}

	*_offset = offset;
	*_size = size;

	return B_OK;
}
Exemple #8
0
status_t
PartitionMapHandle::CreateChild(off_t offset, off_t size,
                                const char* typeString, const char* name, const char* parameters,
                                BMutablePartition** _child)
{
    // check type
    PartitionType type;
    if (!type.SetType(typeString) || type.IsEmpty())
        return B_BAD_VALUE;
    if (type.IsExtended() && fPartitionMap.ExtendedPartitionIndex() >= 0)
        return B_BAD_VALUE;

    // check name
    if (name && *name != '\0')
        return B_BAD_VALUE;

    // check parameters
    void* handle = parse_driver_settings_string(parameters);
    if (handle == NULL)
        return B_ERROR;

    bool active = get_driver_boolean_parameter(handle, "active", false, true);
    delete_driver_settings(handle);

    // get a spare primary partition
    PrimaryPartition* primary = NULL;
    for (int32 i = 0; i < 4; i++) {
        if (fPartitionMap.PrimaryPartitionAt(i)->IsEmpty()) {
            primary = fPartitionMap.PrimaryPartitionAt(i);
            break;
        }
    }
    if (!primary)
        return B_BAD_VALUE;

    // offset properly aligned?
    if (offset != sector_align(offset, Partition()->BlockSize())
            || size != sector_align(size, Partition()->BlockSize()))
        return B_BAD_VALUE;

    // check the free space situation
    BPartitioningInfo info;
    status_t error = GetPartitioningInfo(&info);
    if (error != B_OK)
        return error;

    bool foundSpace = false;
    off_t end = offset + size;
    int32 spacesCount = info.CountPartitionableSpaces();
    for (int32 i = 0; i < spacesCount; i++) {
        off_t spaceOffset, spaceSize;
        info.GetPartitionableSpaceAt(i, &spaceOffset, &spaceSize);
        off_t spaceEnd = spaceOffset + spaceSize;

        if (offset >= spaceOffset && end <= spaceEnd) {
            foundSpace = true;
            break;
        }
    }

    if (!foundSpace)
        return B_BAD_VALUE;

    // create the child
    // (Note: the primary partition index is indeed the child index, since
    // we picked the first empty primary partition.)
    BMutablePartition* partition = Partition();
    BMutablePartition* child;
    error = partition->CreateChild(primary->Index(), typeString, name,
                                   parameters, &child);
    if (error != B_OK)
        return error;

    // init the child
    child->SetOffset(offset);
    child->SetSize(size);
    child->SetBlockSize(partition->BlockSize());
    //child->SetFlags(0);
    child->SetChildCookie(primary);

    // init the primary partition
    primary->SetTo(offset, size, type.Type(), active, partition->BlockSize());

    *_child = child;
    return B_OK;
}
Exemple #9
0
status_t
PartitionMapHandle::ValidateCreateChild(off_t* _offset, off_t* _size,
                                        const char* typeString, BString* name, const char* parameters)
{
    // check type
    PartitionType type;
    if (!type.SetType(typeString) || type.IsEmpty())
        return B_BAD_VALUE;

    if (type.IsExtended() && fPartitionMap.ExtendedPartitionIndex() >= 0) {
        // There can only be a single extended partition
        return B_BAD_VALUE;
    }

    // check name
    if (name)
        name->Truncate(0);

    // check parameters
    void* handle = parse_driver_settings_string(parameters);
    if (handle == NULL)
        return B_ERROR;
    get_driver_boolean_parameter(handle, "active", false, true);
    delete_driver_settings(handle);

    // do we have a spare primary partition?
    if (fPartitionMap.CountNonEmptyPrimaryPartitions() == 4)
        return B_BAD_VALUE;

    // check the free space situation
    BPartitioningInfo info;
    status_t error = GetPartitioningInfo(&info);
    if (error != B_OK)
        return error;

    // any space in the partition at all?
    int32 spacesCount = info.CountPartitionableSpaces();
    if (spacesCount == 0)
        return B_BAD_VALUE;

    // check offset and size
    off_t offset = sector_align(*_offset, Partition()->BlockSize());
    off_t size = sector_align(*_size, Partition()->BlockSize());
    // TODO: Rather round size up?
    off_t end = offset + size;

    // get the first partitionable space the requested interval intersects with
    int32 spaceIndex = -1;
    int32 closestSpaceIndex = -1;
    off_t closestSpaceDistance = 0;
    for (int32 i = 0; i < spacesCount; i++) {
        off_t spaceOffset, spaceSize;
        info.GetPartitionableSpaceAt(i, &spaceOffset, &spaceSize);
        off_t spaceEnd = spaceOffset + spaceSize;

        if ((spaceOffset >= offset && spaceOffset < end)
                || (offset >= spaceOffset && offset < spaceEnd)) {
            spaceIndex = i;
            break;
        }

        off_t distance;
        if (offset < spaceOffset)
            distance = spaceOffset - end;
        else
            distance = spaceEnd - offset;

        if (closestSpaceIndex == -1 || distance < closestSpaceDistance) {
            closestSpaceIndex = i;
            closestSpaceDistance = distance;
        }
    }

    // get the space we found
    off_t spaceOffset, spaceSize;
    info.GetPartitionableSpaceAt(
        spaceIndex >= 0 ? spaceIndex : closestSpaceIndex, &spaceOffset,
        &spaceSize);
    off_t spaceEnd = spaceOffset + spaceSize;

    // If the requested intervald doesn't intersect with any space yet, move
    // it, so that it does.
    if (spaceIndex < 0) {
        spaceIndex = closestSpaceIndex;
        if (offset < spaceOffset) {
            offset = spaceOffset;
            end = offset + size;
        } else {
            end = spaceEnd;
            offset = end - size;
        }
    }

    // move/shrink the interval, so that it fully lies within the space
    if (offset < spaceOffset) {
        offset = spaceOffset;
        end = offset + size;
        if (end > spaceEnd) {
            end = spaceEnd;
            size = end - offset;
        }
    } else if (end > spaceEnd) {
        end = spaceEnd;
        offset = end - size;
        if (offset < spaceOffset) {
            offset = spaceOffset;
            size = end - offset;
        }
    }

    *_offset = offset;
    *_size = size;

    return B_OK;
}
Exemple #10
0
void
MainWindow::_Create(BDiskDevice* disk, partition_id selectedPartition)
{
	if (!disk || selectedPartition > -2) {
		_DisplayPartitionError(B_TRANSLATE("The currently selected partition "
			"is not empty."));
		return;
	}

	if (disk->IsReadOnly()) {
		_DisplayPartitionError(B_TRANSLATE("The selected disk is read-only."));
		return;
	}

	PartitionListRow* currentSelection = dynamic_cast<PartitionListRow*>(
		fListView->CurrentSelection());
	if (!currentSelection) {
		_DisplayPartitionError(B_TRANSLATE("There was an error acquiring the "
			"partition row."));
		return;
	}

	BPartition* parent = disk->FindDescendant(currentSelection->ParentID());
	if (!parent) {
		_DisplayPartitionError(B_TRANSLATE("The currently selected partition "
			"does not have a parent partition."));
		return;
	}

	if (!parent->ContainsPartitioningSystem()) {
		_DisplayPartitionError(B_TRANSLATE("The selected partition does not "
			"contain a partitioning system."));
		return;
	}

	ModificationPreparer modificationPreparer(disk);
	status_t ret = modificationPreparer.ModificationStatus();
	if (ret != B_OK) {
		_DisplayPartitionError(B_TRANSLATE("There was an error preparing the "
			"disk for modifications."), NULL, ret);
		return;
	}

	// get partitioning info
	BPartitioningInfo partitioningInfo;
	status_t error = parent->GetPartitioningInfo(&partitioningInfo);
	if (error != B_OK) {
		_DisplayPartitionError(B_TRANSLATE("Could not aquire partitioning "
			"information."));
		return;
	}

	int32 spacesCount = partitioningInfo.CountPartitionableSpaces();
	if (spacesCount == 0) {
		_DisplayPartitionError(B_TRANSLATE("There's no space on the partition "
			"where a child partition could be created."));
		return;
	}

	BString name, type, parameters;
	off_t offset = currentSelection->Offset();
	off_t size = currentSelection->Size();

	CreateParamsPanel* panel = new CreateParamsPanel(this, parent, offset,
		size);
	if (panel->Go(offset, size, name, type, parameters) == GO_CANCELED)
		return;

	ret = parent->ValidateCreateChild(&offset, &size, type.String(),
		&name, parameters.String());

	if (ret != B_OK) {
		_DisplayPartitionError(B_TRANSLATE("Validation of the given creation "
			"parameters failed."));
		return;
	}

	// Warn the user one more time...
	BAlert* alert = new BAlert("final notice", B_TRANSLATE("Are you sure you "
		"want to write the changes back to disk now?\n\n"
		"All data on the partition will be irretrievably lost if you do "
		"so!"), B_TRANSLATE("Write changes"), B_TRANSLATE("Cancel"), NULL,
		B_WIDTH_FROM_WIDEST, B_WARNING_ALERT);
	int32 choice = alert->Go();

	if (choice == 1)
		return;

	ret = parent->CreateChild(offset, size, type.String(),
		name.String(), parameters.String());

	if (ret != B_OK) {
		_DisplayPartitionError(B_TRANSLATE("Creation of the partition has "
			"failed."));
		return;
	}

	// commit
	ret = modificationPreparer.CommitModifications();

	if (ret != B_OK) {
		_DisplayPartitionError(B_TRANSLATE("Failed to format the "
			"partition. No changes have been written to disk."));
		return;
	}

	// The disk layout has changed, update disk information
	bool updated;
	ret = disk->Update(&updated);

	_ScanDrives();
	fDiskView->ForceUpdate();
}