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)); }
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(); }