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