Example #1
0
	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));
	}
Example #2
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();
}