From 4ee70e3bbaf997c862c7edf9ae8075c2c4734213 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20A=C3=9Fmus?= Date: Fri, 15 May 2009 18:19:10 +0000 Subject: [PATCH] * Adopt the Init menu to the currently available disk systems. For disk devices, we allow not only file systems, but any disk system. This gets us "Intel Partition Map" and "Intel Extended Partition". I managed to initialize a disk with Intel Partition Map this way. * I imported a large chunk of currently disabled code from Ingo's partitioner command line tool, which can eventually be used to create partitions in the empty space. I kept the "Create" menu still disabled, but the correct content types are actually retrieved already, which are "Intel Primary Partition" and "Intel Extended Partition". git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@30766 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/apps/drivesetup/MainWindow.cpp | 365 +++++++++++++++++++++++++---- src/apps/drivesetup/MainWindow.h | 6 +- 2 files changed, 324 insertions(+), 47 deletions(-) diff --git a/src/apps/drivesetup/MainWindow.cpp b/src/apps/drivesetup/MainWindow.cpp index c2fe2592c5..b9f0134891 100644 --- a/src/apps/drivesetup/MainWindow.cpp +++ b/src/apps/drivesetup/MainWindow.cpp @@ -5,6 +5,7 @@ * Authors: * Erik Jaesler * Ithamar R. Adema + * Ingo Weinhold * Stephan Aßmus */ @@ -37,6 +38,32 @@ #include +//static void +//print_partition_table_header() +//{ + //printf(" Index Start Size Content Type " + //"Content Name\n"); + //printf("--------------------------------------------------------------" + //"------------\n"); +//} + + +//static void +//print_partition(BPartition* partition, int level, int index) +//{ + //BString offset, size; + //get_size_string(partition->Offset(), offset); + //get_size_string(partition->Size(), size); + + //printf("%*s%02d%*s %8s %8s %26.26s %16.16s\n", 2 * level, "", + //index, + //2 * max_c(3 - level, 0), "", + //offset.String(), size.String(), + //(partition->ContentType() ? partition->ContentType() : "-"), + //(partition->ContentName() ? partition->ContentName() : "")); +//} + + class ListPopulatorVisitor : public BDiskDeviceVisitor { public: ListPopulatorVisitor(PartitionListView* list, int32& diskCount, @@ -228,9 +255,6 @@ MainWindow::MainWindow(BRect frame) BDiskDeviceRoster().StartWatching(this); - // populate the Initialiaze menu with the available file systems - _ScanFileSystems(); - // visit all disks in the system and show their contents _ScanDrives(); @@ -270,7 +294,7 @@ MainWindow::MessageReceived(BMessage* message) case MSG_INITIALIZE: { BString diskSystemName; - if (message->FindString("format", &diskSystemName) != B_OK) + if (message->FindString("disk system", &diskSystemName) != B_OK) break; _Initialize(fCurrentDisk, fCurrentPartitionID, diskSystemName); break; @@ -388,31 +412,11 @@ MainWindow::_ScanDrives() = fListView->FindRow(fCurrentPartitionID); if (previousSelection) { fListView->AddToSelection(previousSelection); - _EnabledDisableMenuItems(fCurrentDisk, fCurrentPartitionID, + _UpdateMenus(fCurrentDisk, fCurrentPartitionID, previousSelection->ParentID()); fDiskView->ForceUpdate(); } else { - _EnabledDisableMenuItems(NULL, -1, -1); - } -} - - -void -MainWindow::_ScanFileSystems() -{ - while (BMenuItem* item = fInitMenu->RemoveItem(0L)) - delete item; - - BDiskSystem diskSystem; - fDDRoster.RewindDiskSystems(); - while (fDDRoster.GetNextDiskSystem(&diskSystem) == B_OK) { - if (diskSystem.IsFileSystem() && diskSystem.SupportsInitializing()) { - BMessage* message = new BMessage(MSG_INITIALIZE); - message->AddString("format", diskSystem.PrettyName()); - BString label = diskSystem.PrettyName(); - label << B_UTF8_ELLIPSIS; - fInitMenu->AddItem(new BMenuItem(label.String(), message)); - } + _UpdateMenus(NULL, -1, -1); } } @@ -456,6 +460,8 @@ void MainWindow::_SetToDiskAndPartition(partition_id disk, partition_id partition, partition_id parent) { +printf("MainWindow::_SetToDiskAndPartition(disk: %ld, partition: %ld, " + "parent: %ld)\n", disk, partition, parent); BDiskDevice* oldDisk = NULL; if (!fCurrentDisk || fCurrentDisk->ID() != disk) { oldDisk = fCurrentDisk; @@ -474,20 +480,27 @@ MainWindow::_SetToDiskAndPartition(partition_id disk, partition_id partition, fCurrentPartitionID = partition; fDiskView->SetDisk(fCurrentDisk, fCurrentPartitionID); - _EnabledDisableMenuItems(fCurrentDisk, fCurrentPartitionID, parent); + _UpdateMenus(fCurrentDisk, fCurrentPartitionID, parent); delete oldDisk; } void -MainWindow::_EnabledDisableMenuItems(BDiskDevice* disk, +MainWindow::_UpdateMenus(BDiskDevice* disk, partition_id selectedPartition, partition_id parentID) { - // clean out Create menu +printf("MainWindow::_UpdateMenus(disk: %p, " + "selectedPartition: %ld, parentID: %ld)\n", disk, selectedPartition, + parentID); + + // clean out Create and Init menu while (BMenuItem* item = fCreateMenu->RemoveItem(0L)) delete item; + while (BMenuItem* item = fInitMenu->RemoveItem(0L)) + delete item; + if (!disk) { fFormatMI->SetEnabled(false); fEjectMI->SetEnabled(false); @@ -508,9 +521,45 @@ MainWindow::_EnabledDisableMenuItems(BDiskDevice* disk, if (selectedPartition <= -2) parentPartition = disk->FindDescendant(parentID); - if (parentPartition) { - bool prepared = disk->PrepareModifications() == B_OK; - fCreateMenu->SetEnabled(true); + BPartition* partition = disk->FindDescendant(selectedPartition); + if (partition == NULL) + partition = disk; + + bool prepared = disk->PrepareModifications() == B_OK; +printf(" prepared: %d\n", prepared); +// fCreateMenu->SetEnabled(prepared); +// TODO: Enable once _Create() is implemented... +fCreateMenu->SetEnabled(false); + fInitMenu->SetEnabled(prepared); + + BDiskSystem diskSystem; + fDDRoster.RewindDiskSystems(); + while (fDDRoster.GetNextDiskSystem(&diskSystem) == B_OK) { + if (!diskSystem.SupportsInitializing()) + continue; + + if (disk->ID() != selectedPartition + && disk->ContainsPartitioningSystem() + && !diskSystem.IsFileSystem()) { + // Do not confuse the user with nested partition maps? + continue; + } + BMessage* message = new BMessage(MSG_INITIALIZE); + message->AddInt32("parent id", parentID); + message->AddString("disk system", diskSystem.PrettyName()); + + BString label = diskSystem.PrettyName(); + label << B_UTF8_ELLIPSIS; + BMenuItem* item = new BMenuItem(label.String(), message); + +// TODO: Very unintuitive that we have to use the pretty name here! +// item->SetEnabled(partition->CanInitialize(diskSystem.Name())); + item->SetEnabled(partition->CanInitialize(diskSystem.PrettyName())); + fInitMenu->AddItem(item); + } + + if (parentPartition != NULL) { +printf(" parent partition: %p\n", parentPartition); BString supportedChildType; int32 cookie = 0; status_t ret; @@ -527,14 +576,15 @@ MainWindow::_EnabledDisableMenuItems(BDiskDevice* disk, if (fCreateMenu->CountItems() == 0) fprintf(stderr, "Failed to get supported child types: %s\n", strerror(ret)); - if (prepared) - disk->CancelModifications(); } else { +printf(" no parent partition\n"); fCreateMenu->SetEnabled(false); } + if (prepared) + disk->CancelModifications(); + // Mount items - BPartition* partition = disk->FindDescendant(selectedPartition); if (partition) { fInitMenu->SetEnabled(!partition->IsMounted()); // fDeleteMI->SetEnabled(!partition->IsMounted()); @@ -744,7 +794,7 @@ MainWindow::_Initialize(BDiskDevice* disk, partition_id selectedPartition, fDDRoster.RewindDiskSystems(); bool found = false; while (fDDRoster.GetNextDiskSystem(&diskSystem) == B_OK) { - if (diskSystem.IsFileSystem() && diskSystem.SupportsInitializing()) { + if (diskSystem.SupportsInitializing()) { if (diskSystemName == diskSystem.PrettyName()) { found = true; break; @@ -762,7 +812,9 @@ MainWindow::_Initialize(BDiskDevice* disk, partition_id selectedPartition, // allow BFS only, since our parameter string // construction only handles BFS at the moment - if (diskSystemName != "Be File System") { + if (diskSystemName != "Be File System" + && diskSystemName != "Intel Partition Map" + && diskSystemName != "Intel Extended Partition") { _DisplayPartitionError("Don't know how to construct parameters " "for this file system."); return; @@ -778,14 +830,19 @@ MainWindow::_Initialize(BDiskDevice* disk, partition_id selectedPartition, // TODO: use partition initialization editor // (partition->GetInitializationParameterEditor()) - BString name = partition->ContentName(); - if (name.Length() == 0) - name = "Haiku"; BString parameters; - InitParamsPanel* panel = new InitParamsPanel(this); - if (panel->Go(name, parameters) == GO_CANCELED) - return; + if (diskSystemName == "Be File System") { + if (name.Length() == 0) + name = "Haiku"; + InitParamsPanel* panel = new InitParamsPanel(this); + if (panel->Go(name, parameters) == GO_CANCELED) + return; + } else if (diskSystemName == "Intel Partition Map") { + // TODO: parameters? + } else if (diskSystemName == "Intel Extended Partition") { + // TODO: parameters? + } bool supportsName = diskSystem.SupportsContentName(); BString validatedName(name); @@ -810,10 +867,16 @@ MainWindow::_Initialize(BDiskDevice* disk, partition_id selectedPartition, // everything looks fine, we are ready to actually write the changes // to disk + // Warn the user one more time... message = "Are you sure you want to write the changes back to " "disk now?\n\n"; - message << "All data on the partition \"" << previousName; - message << "\" will be irrevertably lost if you do so!"; + if (partition->IsDevice()) + message << "All data on the disk"; + else + message << "All data on the partition"; + if (previousName.Length() > 0) + message << " \"" << previousName << "\""; + message << " will be irrevertably lost if you do so!"; alert = new BAlert("final notice", message.String(), "Write Changes", "Cancel", NULL, B_WIDTH_FROM_WIDEST, B_WARNING_ALERT); choice = alert->Go(); @@ -839,3 +902,215 @@ MainWindow::_Initialize(BDiskDevice* disk, partition_id selectedPartition, _ScanDrives(); } + +void +MainWindow::_Create(BDiskDevice* disk, partition_id selectedPartition, + const BString& partitionType) +{ + printf("_Create(disk: %p, selectedPartition: %ld)\n", disk, + selectedPartition); + + if (disk->IsReadOnly()) { + _DisplayPartitionError("The selected disk is read-only."); + return; + } + + //BPartition* partition = disk->FindDescendant(selectedPartition); + //if (!partition) { + //_DisplayPartitionError("Unable to find the selected partition by id."); + //return; + //} + + +#if 0 + // 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 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)); +#endif // 0 + + _ScanDrives(); +} diff --git a/src/apps/drivesetup/MainWindow.h b/src/apps/drivesetup/MainWindow.h index 691dd63fc5..d4aa79345f 100644 --- a/src/apps/drivesetup/MainWindow.h +++ b/src/apps/drivesetup/MainWindow.h @@ -44,13 +44,12 @@ public: private: void _ScanDrives(); - void _ScanFileSystems(); void _AdaptToSelectedPartition(); void _SetToDiskAndPartition(partition_id diskID, partition_id partitionID, partition_id parentID); - void _EnabledDisableMenuItems(BDiskDevice* disk, + void _UpdateMenus(BDiskDevice* disk, partition_id selectedPartition, partition_id parentID); @@ -67,6 +66,9 @@ private: void _Initialize(BDiskDevice* disk, partition_id selectedPartition, const BString& diskSystemName); + void _Create(BDiskDevice* disk, + partition_id selectedPartition, + const BString& partitionType); BDiskDeviceRoster fDDRoster;