1 /* 2 * Copyright 2002-2009 Haiku Inc. All rights reserved. 3 * Distributed under the terms of the MIT license. 4 * 5 * Authors: 6 * Erik Jaesler <ejakowatz@users.sourceforge.net> 7 * Ithamar R. Adema <ithamar@unet.nl> 8 * Stephan Aßmus <superstippi@gmx.de> 9 */ 10 11 #include "MainWindow.h" 12 #include "DiskView.h" 13 #include "InitParamsPanel.h" 14 #include "PartitionList.h" 15 #include "Support.h" 16 17 #include <stdio.h> 18 #include <string.h> 19 20 #include <Alert.h> 21 #include <Application.h> 22 23 #include <DiskDeviceVisitor.h> 24 #include <DiskSystem.h> 25 #include <DiskDevice.h> 26 #include <Partition.h> 27 #include <PartitioningInfo.h> 28 #include <Path.h> 29 30 #include <ColumnListView.h> 31 #include <ColumnTypes.h> 32 #include <MenuItem.h> 33 #include <MenuBar.h> 34 #include <Menu.h> 35 #include <Screen.h> 36 #include <Volume.h> 37 #include <VolumeRoster.h> 38 39 40 class ListPopulatorVisitor : public BDiskDeviceVisitor { 41 public: 42 ListPopulatorVisitor(PartitionListView* list, int32& diskCount, 43 SpaceIDMap& spaceIDMap) 44 : 45 fPartitionList(list), 46 fDiskCount(diskCount), 47 fSpaceIDMap(spaceIDMap) 48 { 49 fDiskCount = 0; 50 fSpaceIDMap.Clear(); 51 // start with an empty list 52 int32 rows = fPartitionList->CountRows(); 53 for (int32 i = rows - 1; i >= 0; i--) { 54 BRow* row = fPartitionList->RowAt(i); 55 fPartitionList->RemoveRow(row); 56 delete row; 57 } 58 } 59 60 virtual bool Visit(BDiskDevice* device) 61 { 62 fDiskCount++; 63 // if we don't prepare the device for modifications, 64 // we cannot get information about available empty 65 // regions on the device or child partitions 66 device->PrepareModifications(); 67 _AddPartition(device); 68 return false; // Don't stop yet! 69 } 70 71 virtual bool Visit(BPartition* partition, int32 level) 72 { 73 _AddPartition(partition); 74 return false; // Don't stop yet! 75 } 76 77 private: 78 void _AddPartition(BPartition* partition) const 79 { 80 // add the partition itself 81 fPartitionList->AddPartition(partition); 82 83 // add any available space on it 84 BPartitioningInfo info; 85 status_t ret = partition->GetPartitioningInfo(&info); 86 if (ret >= B_OK) { 87 partition_id parentID = partition->ID(); 88 off_t offset; 89 off_t size; 90 for (int32 i = 0; 91 info.GetPartitionableSpaceAt(i, &offset, &size) >= B_OK; 92 i++) { 93 // TODO: remove again once Disk Device API is fixed 94 if (!is_valid_partitionable_space(size)) 95 continue; 96 // 97 partition_id id = fSpaceIDMap.SpaceIDFor(parentID, offset); 98 fPartitionList->AddSpace(parentID, id, offset, size); 99 } 100 } 101 } 102 103 PartitionListView* fPartitionList; 104 int32& fDiskCount; 105 SpaceIDMap& fSpaceIDMap; 106 BDiskDevice* fLastPreparedDevice; 107 }; 108 109 110 class MountAllVisitor : public BDiskDeviceVisitor { 111 public: 112 MountAllVisitor() 113 { 114 } 115 116 virtual bool Visit(BDiskDevice* device) 117 { 118 return false; // Don't stop yet! 119 } 120 121 virtual bool Visit(BPartition* partition, int32 level) 122 { 123 partition->Mount(); 124 return false; // Don't stop yet! 125 } 126 127 private: 128 PartitionListView* fPartitionList; 129 }; 130 131 132 enum { 133 MSG_MOUNT_ALL = 'mnta', 134 MSG_MOUNT = 'mnts', 135 MSG_UNMOUNT = 'unmt', 136 MSG_FORMAT = 'frmt', 137 MSG_CREATE = 'crtp', 138 MSG_INITIALIZE = 'init', 139 MSG_DELETE = 'delt', 140 MSG_EJECT = 'ejct', 141 MSG_SURFACE_TEST = 'sfct', 142 MSG_RESCAN = 'rscn', 143 144 MSG_PARTITION_ROW_SELECTED = 'prsl', 145 }; 146 147 148 // #pragma mark - 149 150 151 MainWindow::MainWindow(BRect frame) 152 : BWindow(frame, "DriveSetup", B_DOCUMENT_WINDOW, 153 B_ASYNCHRONOUS_CONTROLS | B_NOT_ZOOMABLE), 154 fCurrentDisk(NULL), 155 fCurrentPartitionID(-1), 156 fSpaceIDMap() 157 { 158 BMenuBar* menuBar = new BMenuBar(Bounds(), "root menu"); 159 160 // create all the menu items 161 fFormatMI = new BMenuItem("Format (not implemented)", 162 new BMessage(MSG_FORMAT)); 163 fEjectMI = new BMenuItem("Eject", new BMessage(MSG_EJECT), 'E'); 164 fSurfaceTestMI = new BMenuItem("Surface Test (not implemented)", 165 new BMessage(MSG_SURFACE_TEST)); 166 fRescanMI = new BMenuItem("Rescan", new BMessage(MSG_RESCAN)); 167 168 fDeleteMI = new BMenuItem("Delete (not implemented)", 169 new BMessage(MSG_DELETE)); 170 fDeleteMI->SetEnabled(false); 171 172 fMountMI = new BMenuItem("Mount", new BMessage(MSG_MOUNT), 'M'); 173 fUnmountMI = new BMenuItem("Unmount", new BMessage(MSG_UNMOUNT), 'U'); 174 fMountAllMI = new BMenuItem("Mount All", 175 new BMessage(MSG_MOUNT_ALL), 'M', B_SHIFT_KEY); 176 177 // Disk menu 178 fDiskMenu = new BMenu("Disk"); 179 fDiskMenu->AddItem(fFormatMI); 180 fDiskMenu->AddItem(fEjectMI); 181 fDiskMenu->AddItem(fSurfaceTestMI); 182 183 fDiskMenu->AddSeparatorItem(); 184 185 fDiskMenu->AddItem(fRescanMI); 186 menuBar->AddItem(fDiskMenu); 187 188 // Parition menu 189 fPartitionMenu = new BMenu("Partition"); 190 fCreateMenu = new BMenu("Create (not implemented)"); 191 fPartitionMenu->AddItem(fCreateMenu); 192 193 fInitMenu = new BMenu("Initialize"); 194 fPartitionMenu->AddItem(fInitMenu); 195 196 fPartitionMenu->AddItem(fDeleteMI); 197 198 fPartitionMenu->AddSeparatorItem(); 199 200 fPartitionMenu->AddItem(fMountMI); 201 fPartitionMenu->AddItem(fUnmountMI); 202 203 fPartitionMenu->AddSeparatorItem(); 204 205 fPartitionMenu->AddItem(fMountAllMI); 206 menuBar->AddItem(fPartitionMenu); 207 208 AddChild(menuBar); 209 210 // add DiskView 211 BRect r(Bounds()); 212 r.top = menuBar->Frame().bottom + 1; 213 r.bottom = floorf(r.top + r.Height() * 0.33); 214 fDiskView = new DiskView(r, B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP, 215 fSpaceIDMap); 216 AddChild(fDiskView); 217 218 // add PartitionListView 219 r.top = r.bottom + 2; 220 r.bottom = Bounds().bottom; 221 r.InsetBy(-1, -1); 222 fListView = new PartitionListView(r, B_FOLLOW_ALL); 223 AddChild(fListView); 224 225 // configure PartitionListView 226 fListView->SetSelectionMessage(new BMessage(MSG_PARTITION_ROW_SELECTED)); 227 fListView->SetTarget(this); 228 229 BDiskDeviceRoster().StartWatching(this); 230 231 // populate the Initialiaze menu with the available file systems 232 _ScanFileSystems(); 233 234 // visit all disks in the system and show their contents 235 _ScanDrives(); 236 } 237 238 239 MainWindow::~MainWindow() 240 { 241 BDiskDeviceRoster().StopWatching(this); 242 delete fCurrentDisk; 243 } 244 245 246 void 247 MainWindow::MessageReceived(BMessage* message) 248 { 249 switch (message->what) { 250 case MSG_MOUNT_ALL: 251 _MountAll(); 252 break; 253 case MSG_MOUNT: 254 _Mount(fCurrentDisk, fCurrentPartitionID); 255 break; 256 case MSG_UNMOUNT: 257 _Unmount(fCurrentDisk, fCurrentPartitionID); 258 break; 259 260 case MSG_FORMAT: 261 printf("MSG_FORMAT\n"); 262 break; 263 264 case MSG_CREATE: 265 printf("MSG_CREATE\n"); 266 break; 267 268 case MSG_INITIALIZE: { 269 BString diskSystemName; 270 if (message->FindString("format", &diskSystemName) != B_OK) 271 break; 272 _Initialize(fCurrentDisk, fCurrentPartitionID, diskSystemName); 273 break; 274 } 275 276 case MSG_DELETE: 277 printf("MSG_DELETE\n"); 278 break; 279 280 case MSG_EJECT: 281 // TODO: completely untested, especially interesting 282 // if partition list behaves when partitions disappear 283 if (fCurrentDisk) { 284 // TODO: only if no partitions are mounted anymore? 285 fCurrentDisk->Eject(true); 286 _ScanDrives(); 287 } 288 break; 289 case MSG_SURFACE_TEST: 290 printf("MSG_SURFACE_TEST\n"); 291 break; 292 293 // TODO: this could probably be done better! 294 case B_DEVICE_UPDATE: 295 case MSG_RESCAN: 296 _ScanDrives(); 297 break; 298 299 case MSG_PARTITION_ROW_SELECTED: 300 // selection of partitions via list view 301 _AdaptToSelectedPartition(); 302 break; 303 case MSG_SELECTED_PARTITION_ID: { 304 // selection of partitions via disk view 305 partition_id id; 306 if (message->FindInt32("partition_id", &id) == B_OK) { 307 if (BRow* row = fListView->FindRow(id)) { 308 fListView->DeselectAll(); 309 fListView->AddToSelection(row); 310 _AdaptToSelectedPartition(); 311 } 312 } 313 break; 314 } 315 316 default: 317 BWindow::MessageReceived(message); 318 break; 319 } 320 } 321 322 323 bool 324 MainWindow::QuitRequested() 325 { 326 // TODO: ask about any unsaved changes 327 be_app->PostMessage(B_QUIT_REQUESTED); 328 Hide(); 329 return false; 330 } 331 332 333 // #pragma mark - 334 335 336 status_t 337 MainWindow::StoreSettings(BMessage* archive) const 338 { 339 if (archive->ReplaceRect("window frame", Frame()) < B_OK) 340 archive->AddRect("window frame", Frame()); 341 342 BMessage columnSettings; 343 fListView->SaveState(&columnSettings); 344 if (archive->ReplaceMessage("column settings", &columnSettings) < B_OK) 345 archive->AddMessage("column settings", &columnSettings); 346 347 return B_OK; 348 } 349 350 351 status_t 352 MainWindow::RestoreSettings(BMessage* archive) 353 { 354 BRect frame; 355 if (archive->FindRect("window frame", &frame) == B_OK) { 356 BScreen screen(this); 357 if (frame.Intersects(screen.Frame())) { 358 MoveTo(frame.LeftTop()); 359 ResizeTo(frame.Width(), frame.Height()); 360 } 361 } 362 363 BMessage columnSettings; 364 if (archive->FindMessage("column settings", &columnSettings) == B_OK) 365 fListView->LoadState(&columnSettings); 366 367 return B_OK; 368 } 369 370 371 // #pragma mark - 372 373 374 void 375 MainWindow::_ScanDrives() 376 { 377 fSpaceIDMap.Clear(); 378 int32 diskCount = 0; 379 ListPopulatorVisitor driveVisitor(fListView, diskCount, fSpaceIDMap); 380 fDDRoster.VisitEachPartition(&driveVisitor); 381 fDiskView->SetDiskCount(diskCount); 382 383 // restore selection 384 PartitionListRow* previousSelection 385 = fListView->FindRow(fCurrentPartitionID); 386 if (previousSelection) { 387 fListView->AddToSelection(previousSelection); 388 _EnabledDisableMenuItems(fCurrentDisk, fCurrentPartitionID, 389 previousSelection->ParentID()); 390 fDiskView->ForceUpdate(); 391 } else { 392 _EnabledDisableMenuItems(NULL, -1, -1); 393 } 394 } 395 396 397 void 398 MainWindow::_ScanFileSystems() 399 { 400 while (BMenuItem* item = fInitMenu->RemoveItem(0L)) 401 delete item; 402 403 BDiskSystem diskSystem; 404 fDDRoster.RewindDiskSystems(); 405 while (fDDRoster.GetNextDiskSystem(&diskSystem) == B_OK) { 406 if (diskSystem.IsFileSystem() && diskSystem.SupportsInitializing()) { 407 BMessage* message = new BMessage(MSG_INITIALIZE); 408 message->AddString("format", diskSystem.PrettyName()); 409 BString label = diskSystem.PrettyName(); 410 label << B_UTF8_ELLIPSIS; 411 fInitMenu->AddItem(new BMenuItem(label.String(), message)); 412 } 413 } 414 } 415 416 417 // #pragma mark - 418 419 420 void 421 MainWindow::_AdaptToSelectedPartition() 422 { 423 partition_id diskID = -1; 424 partition_id partitionID = -1; 425 partition_id parentID = -1; 426 427 BRow* _selectedRow = fListView->CurrentSelection(); 428 if (_selectedRow) { 429 // go up to top level row 430 BRow* _topLevelRow = _selectedRow; 431 BRow* parent = NULL; 432 while (fListView->FindParent(_topLevelRow, &parent, NULL)) 433 _topLevelRow = parent; 434 435 PartitionListRow* topLevelRow 436 = dynamic_cast<PartitionListRow*>(_topLevelRow); 437 PartitionListRow* selectedRow 438 = dynamic_cast<PartitionListRow*>(_selectedRow); 439 440 if (topLevelRow) 441 diskID = topLevelRow->ID(); 442 if (selectedRow) { 443 partitionID = selectedRow->ID(); 444 parentID = selectedRow->ParentID(); 445 } 446 } 447 448 _SetToDiskAndPartition(diskID, partitionID, parentID); 449 } 450 451 452 void 453 MainWindow::_SetToDiskAndPartition(partition_id disk, partition_id partition, 454 partition_id parent) 455 { 456 BDiskDevice* oldDisk = NULL; 457 if (!fCurrentDisk || fCurrentDisk->ID() != disk) { 458 oldDisk = fCurrentDisk; 459 fCurrentDisk = NULL; 460 if (disk >= 0) { 461 BDiskDevice* newDisk = new BDiskDevice(); 462 status_t ret = newDisk->SetTo(disk); 463 if (ret < B_OK) { 464 printf("error switching disks: %s\n", strerror(ret)); 465 delete newDisk; 466 } else 467 fCurrentDisk = newDisk; 468 } 469 } 470 471 fCurrentPartitionID = partition; 472 473 fDiskView->SetDisk(fCurrentDisk, fCurrentPartitionID); 474 _EnabledDisableMenuItems(fCurrentDisk, fCurrentPartitionID, parent); 475 476 delete oldDisk; 477 } 478 479 480 void 481 MainWindow::_EnabledDisableMenuItems(BDiskDevice* disk, 482 partition_id selectedPartition, partition_id parentID) 483 { 484 // clean out Create menu 485 while (BMenuItem* item = fCreateMenu->RemoveItem(0L)) 486 delete item; 487 488 if (!disk) { 489 fFormatMI->SetEnabled(false); 490 fEjectMI->SetEnabled(false); 491 fSurfaceTestMI->SetEnabled(false); 492 493 fPartitionMenu->SetEnabled(false); 494 } else { 495 // fFormatMI->SetEnabled(true); 496 fFormatMI->SetEnabled(false); 497 fEjectMI->SetEnabled(disk->IsRemovableMedia()); 498 // fSurfaceTestMI->SetEnabled(true); 499 fSurfaceTestMI->SetEnabled(false); 500 501 // Create menu and items 502 fPartitionMenu->SetEnabled(true); 503 504 BPartition* parentPartition = NULL; 505 if (selectedPartition <= -2) 506 parentPartition = disk->FindDescendant(parentID); 507 508 if (parentPartition) { 509 bool prepared = disk->PrepareModifications() == B_OK; 510 fCreateMenu->SetEnabled(true); 511 BString supportedChildType; 512 int32 cookie = 0; 513 status_t ret; 514 while ((ret = parentPartition->GetNextSupportedChildType(&cookie, 515 &supportedChildType)) == B_OK) { 516 BMessage* message = new BMessage(MSG_CREATE); 517 message->AddInt32("parent id", parentID); 518 message->AddInt32("space id", selectedPartition); 519 message->AddString("type", supportedChildType); 520 BMenuItem* item = new BMenuItem(supportedChildType.String(), 521 message); 522 fCreateMenu->AddItem(item); 523 } 524 if (fCreateMenu->CountItems() == 0) 525 fprintf(stderr, "Failed to get supported child types: %s\n", 526 strerror(ret)); 527 if (prepared) 528 disk->CancelModifications(); 529 } else { 530 fCreateMenu->SetEnabled(false); 531 } 532 533 // Mount items 534 BPartition* partition = disk->FindDescendant(selectedPartition); 535 if (partition) { 536 fInitMenu->SetEnabled(!partition->IsMounted()); 537 // fDeleteMI->SetEnabled(!partition->IsMounted()); 538 fDeleteMI->SetEnabled(false); 539 fMountMI->SetEnabled(!partition->IsMounted()); 540 541 bool unMountable = false; 542 if (partition->IsMounted()) { 543 // see if this partition is the boot volume 544 BVolume volume; 545 BVolume bootVolume; 546 if (BVolumeRoster().GetBootVolume(&bootVolume) == B_OK 547 && partition->GetVolume(&volume) == B_OK) { 548 unMountable = volume != bootVolume; 549 } else 550 unMountable = true; 551 } 552 fUnmountMI->SetEnabled(unMountable); 553 } else { 554 fInitMenu->SetEnabled(false); 555 fDeleteMI->SetEnabled(false); 556 fMountMI->SetEnabled(false); 557 fUnmountMI->SetEnabled(false); 558 } 559 fMountAllMI->SetEnabled(true); 560 } 561 } 562 563 564 void 565 MainWindow::_DisplayPartitionError(BString _message, 566 const BPartition* partition, status_t error) const 567 { 568 char message[1024]; 569 570 if (partition && _message.FindFirst("%s") >= 0) { 571 BString name; 572 name << " \"" << partition->ContentName() << "\""; 573 sprintf(message, _message.String(), name.String()); 574 } else { 575 _message.ReplaceAll("%s", ""); 576 sprintf(message, _message.String()); 577 } 578 579 if (error < B_OK) { 580 BString helper = message; 581 sprintf(message, "%s\n\nError: %s", helper.String(), strerror(error)); 582 } 583 584 BAlert* alert = new BAlert("error", message, "Ok", NULL, NULL, 585 B_WIDTH_FROM_WIDEST, error < B_OK ? B_STOP_ALERT : B_INFO_ALERT); 586 alert->Go(NULL); 587 } 588 589 590 // #pragma mark - 591 592 593 void 594 MainWindow::_Mount(BDiskDevice* disk, partition_id selectedPartition) 595 { 596 if (!disk || selectedPartition < 0) { 597 _DisplayPartitionError("You need to select a partition " 598 "entry from the list."); 599 return; 600 } 601 602 BPartition* partition = disk->FindDescendant(selectedPartition); 603 if (!partition) { 604 _DisplayPartitionError("Unable to find the selected partition by id."); 605 return; 606 } 607 608 if (!partition->IsMounted()) { 609 status_t ret = partition->Mount(); 610 if (ret < B_OK) { 611 _DisplayPartitionError("Could not mount partition %s.", 612 partition, ret); 613 } else { 614 // successful mount, adapt to the changes 615 _ScanDrives(); 616 } 617 } else { 618 _DisplayPartitionError("The partition %s is already mounted.", 619 partition); 620 } 621 } 622 623 624 void 625 MainWindow::_Unmount(BDiskDevice* disk, partition_id selectedPartition) 626 { 627 if (!disk || selectedPartition < 0) { 628 _DisplayPartitionError("You need to select a partition " 629 "entry from the list."); 630 return; 631 } 632 633 BPartition* partition = disk->FindDescendant(selectedPartition); 634 if (!partition) { 635 _DisplayPartitionError("Unable to find the selected partition by id."); 636 return; 637 } 638 639 if (partition->IsMounted()) { 640 BPath path; 641 partition->GetMountPoint(&path); 642 status_t ret = partition->Unmount(); 643 if (ret < B_OK) { 644 _DisplayPartitionError("Could not unmount partition %s.", 645 partition, ret); 646 } else { 647 if (dev_for_path(path.Path()) == dev_for_path("/")) 648 rmdir(path.Path()); 649 // successful unmount, adapt to the changes 650 _ScanDrives(); 651 } 652 } else { 653 _DisplayPartitionError("The partition %s is already unmounted.", 654 partition); 655 } 656 } 657 658 659 void 660 MainWindow::_MountAll() 661 { 662 MountAllVisitor visitor; 663 fDDRoster.VisitEachPartition(&visitor); 664 } 665 666 667 // #pragma mark - 668 669 670 class ModificationPreparer { 671 public: 672 ModificationPreparer(BDiskDevice* disk) 673 : 674 fDisk(disk), 675 fModificationStatus(fDisk->PrepareModifications()) 676 { 677 } 678 ~ModificationPreparer() 679 { 680 if (fModificationStatus == B_OK) 681 fDisk->CancelModifications(); 682 } 683 status_t ModificationStatus() const 684 { 685 return fModificationStatus; 686 } 687 status_t CommitModifications() 688 { 689 status_t ret = fDisk->CommitModifications(); 690 if (ret == B_OK) 691 fModificationStatus = B_ERROR; 692 return ret; 693 } 694 695 private: 696 BDiskDevice* fDisk; 697 status_t fModificationStatus; 698 }; 699 700 701 void 702 MainWindow::_Initialize(BDiskDevice* disk, partition_id selectedPartition, 703 const BString& diskSystemName) 704 { 705 if (!disk || selectedPartition < 0) { 706 _DisplayPartitionError("You need to select a partition " 707 "entry from the list."); 708 return; 709 } 710 711 if (disk->IsReadOnly()) { 712 _DisplayPartitionError("The selected disk is read-only."); 713 return; 714 } 715 716 BPartition* partition = disk->FindDescendant(selectedPartition); 717 if (!partition) { 718 _DisplayPartitionError("Unable to find the selected partition by id."); 719 return; 720 } 721 722 if (partition->IsMounted()) { 723 _DisplayPartitionError("The partition %s is currently mounted."); 724 // TODO: option to unmount and continue on success to unmount 725 return; 726 } 727 728 BString message("Are you sure you want to initialize the partition "); 729 message << "\"" << partition->ContentName(); 730 message << "\"? After entering the initialization parameters, "; 731 message << "you can abort this operation right before writing "; 732 message << "changes back to the disk."; 733 BAlert* alert = new BAlert("first notice", message.String(), 734 "Continue", "Cancel", NULL, B_WIDTH_FROM_WIDEST, B_WARNING_ALERT); 735 int32 choice = alert->Go(); 736 737 if (choice == 1) 738 return; 739 740 BDiskSystem diskSystem; 741 fDDRoster.RewindDiskSystems(); 742 bool found = false; 743 while (fDDRoster.GetNextDiskSystem(&diskSystem) == B_OK) { 744 if (diskSystem.IsFileSystem() && diskSystem.SupportsInitializing()) { 745 if (diskSystemName == diskSystem.PrettyName()) { 746 found = true; 747 break; 748 } 749 } 750 } 751 752 if (!found) { 753 BString message("Disk system \""); 754 message << diskSystemName << "\" not found!"; 755 _DisplayPartitionError(message); 756 return; 757 } 758 759 760 // allow BFS only, since our parameter string 761 // construction only handles BFS at the moment 762 if (diskSystemName != "Be File System") { 763 _DisplayPartitionError("Don't know how to construct parameters " 764 "for this file system."); 765 return; 766 } 767 768 ModificationPreparer modificationPreparer(disk); 769 status_t ret = modificationPreparer.ModificationStatus(); 770 if (ret != B_OK) { 771 _DisplayPartitionError("There was an error preparing the " 772 "disk for modifications.", NULL, ret); 773 return; 774 } 775 776 // TODO: use partition initialization editor 777 // (partition->GetInitializationParameterEditor()) 778 779 BString name = partition->ContentName(); 780 if (name.Length() == 0) 781 name = "Haiku"; 782 BString parameters; 783 InitParamsPanel* panel = new InitParamsPanel(this); 784 if (panel->Go(name, parameters) == GO_CANCELED) 785 return; 786 787 bool supportsName = diskSystem.SupportsContentName(); 788 BString validatedName(name); 789 ret = partition->ValidateInitialize(diskSystem.PrettyName(), 790 supportsName ? &validatedName : NULL, parameters.String()); 791 if (ret != B_OK) { 792 _DisplayPartitionError("Validation of the given initialization " 793 "parameters failed.", partition, ret); 794 return; 795 } 796 797 BString previousName = partition->ContentName(); 798 799 ret = partition->Initialize(diskSystem.PrettyName(), 800 supportsName ? name.String() : NULL, parameters.String()); 801 if (ret != B_OK) { 802 _DisplayPartitionError("Initialization of the partition %s " 803 "failed. (Nothing has been written to disk.)", partition, ret); 804 return; 805 } 806 807 // everything looks fine, we are ready to actually write the changes 808 // to disk 809 810 message = "Are you sure you want to write the changes back to " 811 "disk now?\n\n"; 812 message << "All data on the partition \"" << previousName; 813 message << "\" will be irrevertably lost if you do so!"; 814 alert = new BAlert("final notice", message.String(), 815 "Write Changes", "Cancel", NULL, B_WIDTH_FROM_WIDEST, B_WARNING_ALERT); 816 choice = alert->Go(); 817 818 if (choice == 1) 819 return; 820 821 // commit 822 ret = modificationPreparer.CommitModifications(); 823 824 // The partition pointer is toast now! Use the partition id to 825 // retrieve it again. 826 partition = disk->FindDescendant(selectedPartition); 827 828 if (ret == B_OK) { 829 _DisplayPartitionError("The partition %s has been successfully " 830 "initialized.\n", partition); 831 } else { 832 _DisplayPartitionError("Failed to initialize the partition " 833 "%s!\n", partition, ret); 834 } 835 836 _ScanDrives(); 837 } 838 839