void AutoMounter::_MountVolume(const BMessage* message) { int32 id; if (message->FindInt32("id", &id) != B_OK) return; BDiskDeviceRoster roster; BPartition *partition; BDiskDevice device; if (roster.GetPartitionWithID(id, &device, &partition) != B_OK) return; uint32 mountFlags; if (!_SuggestMountFlags(partition, &mountFlags)) return; status_t status = partition->Mount(NULL, mountFlags); if (status < B_OK) { char text[512]; snprintf(text, sizeof(text), B_TRANSLATE("Error mounting volume:\n\n%s"), strerror(status)); BAlert* alert = new BAlert(B_TRANSLATE("Mount error"), text, B_TRANSLATE("OK")); alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); alert->Go(NULL); } }
void MainWindow::_Mount(BDiskDevice* disk, partition_id selectedPartition) { if (!disk || selectedPartition < 0) { _DisplayPartitionError(B_TRANSLATE("You need to select a partition " "entry from the list.")); return; } BPartition* partition = disk->FindDescendant(selectedPartition); if (!partition) { _DisplayPartitionError(B_TRANSLATE("Unable to find the selected " "partition by ID.")); return; } if (!partition->IsMounted()) { status_t ret = partition->Mount(); if (ret < B_OK) { _DisplayPartitionError( B_TRANSLATE("Could not mount partition %s."), partition, ret); } else { // successful mount, adapt to the changes _ScanDrives(); } } else { _DisplayPartitionError( B_TRANSLATE("The partition %s is already mounted."), partition); } }
void WorkerThread::MessageReceived(BMessage* message) { CALLED(); switch (message->what) { case MSG_START_INSTALLING: _PerformInstall(fWindow->GetSourceMenu(), fWindow->GetTargetMenu()); break; case MSG_WRITE_BOOT_SECTOR: { int32 id; if (message->FindInt32("id", &id) != B_OK) { _SetStatusMessage(B_TRANSLATE("Boot sector not written " "because of an internal error.")); break; } // TODO: Refactor with _PerformInstall() BPath targetDirectory; BDiskDevice device; BPartition* partition; if (fDDRoster.GetPartitionWithID(id, &device, &partition) == B_OK) { if (!partition->IsMounted()) { if (partition->Mount() < B_OK) { _SetStatusMessage(B_TRANSLATE("The partition can't be " "mounted. Please choose a different partition.")); break; } } if (partition->GetMountPoint(&targetDirectory) != B_OK) { _SetStatusMessage(B_TRANSLATE("The mount point could not " "be retrieved.")); break; } } else if (fDDRoster.GetDeviceWithID(id, &device) == B_OK) { if (!device.IsMounted()) { if (device.Mount() < B_OK) { _SetStatusMessage(B_TRANSLATE("The disk can't be " "mounted. Please choose a different disk.")); break; } } if (device.GetMountPoint(&targetDirectory) != B_OK) { _SetStatusMessage(B_TRANSLATE("The mount point could not " "be retrieved.")); break; } } _LaunchFinishScript(targetDirectory); // TODO: Get error from executing script! _SetStatusMessage( B_TRANSLATE("Boot sector successfully written.")); } default: BLooper::MessageReceived(message); } }
void WorkerThread::_PerformInstall(BMenu* srcMenu, BMenu* targetMenu) { CALLED(); BPath targetDirectory; BPath srcDirectory; BPath trashPath; BPath testPath; BDirectory targetDir; BDiskDevice device; BPartition* partition; BVolume targetVolume; status_t err = B_OK; int32 entries = 0; entry_ref testRef; const char* mountError = B_TRANSLATE("The disk can't be mounted. Please " "choose a different disk."); BMessenger messenger(fWindow); ProgressReporter reporter(messenger, new BMessage(MSG_STATUS_MESSAGE)); CopyEngine engine(&reporter); BList unzipEngines; PartitionMenuItem* targetItem = (PartitionMenuItem*)targetMenu->FindMarked(); PartitionMenuItem* srcItem = (PartitionMenuItem*)srcMenu->FindMarked(); if (!srcItem || !targetItem) { ERR("bad menu items\n"); goto error; } // check if target is initialized // ask if init or mount as is if (fDDRoster.GetPartitionWithID(targetItem->ID(), &device, &partition) == B_OK) { if (!partition->IsMounted()) { if ((err = partition->Mount()) < B_OK) { _SetStatusMessage(mountError); ERR("BPartition::Mount"); goto error; } } if ((err = partition->GetVolume(&targetVolume)) != B_OK) { ERR("BPartition::GetVolume"); goto error; } if ((err = partition->GetMountPoint(&targetDirectory)) != B_OK) { ERR("BPartition::GetMountPoint"); goto error; } } else if (fDDRoster.GetDeviceWithID(targetItem->ID(), &device) == B_OK) { if (!device.IsMounted()) { if ((err = device.Mount()) < B_OK) { _SetStatusMessage(mountError); ERR("BDiskDevice::Mount"); goto error; } } if ((err = device.GetVolume(&targetVolume)) != B_OK) { ERR("BDiskDevice::GetVolume"); goto error; } if ((err = device.GetMountPoint(&targetDirectory)) != B_OK) { ERR("BDiskDevice::GetMountPoint"); goto error; } } else goto error; // shouldn't happen // check if target has enough space if ((fSpaceRequired > 0 && targetVolume.FreeBytes() < fSpaceRequired) && ((new BAlert("", B_TRANSLATE("The destination disk may not have " "enough space. Try choosing a different disk or choose to not " "install optional items."), B_TRANSLATE("Try installing anyway"), B_TRANSLATE("Cancel"), 0, B_WIDTH_AS_USUAL, B_STOP_ALERT))->Go() != 0)) { goto error; } if (fDDRoster.GetPartitionWithID(srcItem->ID(), &device, &partition) == B_OK) { if ((err = partition->GetMountPoint(&srcDirectory)) != B_OK) { ERR("BPartition::GetMountPoint"); goto error; } } else if (fDDRoster.GetDeviceWithID(srcItem->ID(), &device) == B_OK) { if ((err = device.GetMountPoint(&srcDirectory)) != B_OK) { ERR("BDiskDevice::GetMountPoint"); goto error; } } else goto error; // shouldn't happen // check not installing on itself if (strcmp(srcDirectory.Path(), targetDirectory.Path()) == 0) { _SetStatusMessage(B_TRANSLATE("You can't install the contents of a " "disk onto itself. Please choose a different disk.")); goto error; } // check not installing on boot volume if ((strncmp(BOOT_PATH, targetDirectory.Path(), strlen(BOOT_PATH)) == 0) && ((new BAlert("", B_TRANSLATE("Are you sure you want to install " "onto the current boot disk? The Installer will have to reboot " "your machine if you proceed."), B_TRANSLATE("OK"), B_TRANSLATE("Cancel"), 0, B_WIDTH_AS_USUAL, B_STOP_ALERT))->Go() != 0)) { _SetStatusMessage("Installation stopped."); goto error; } // check if target volume's trash dir has anything in it // (target volume w/ only an empty trash dir is considered // an empty volume) if (find_directory(B_TRASH_DIRECTORY, &trashPath, false, &targetVolume) == B_OK && targetDir.SetTo(trashPath.Path()) == B_OK) { while (targetDir.GetNextRef(&testRef) == B_OK) { // Something in the Trash entries++; break; } } targetDir.SetTo(targetDirectory.Path()); // check if target volume otherwise has any entries while (entries == 0 && targetDir.GetNextRef(&testRef) == B_OK) { if (testPath.SetTo(&testRef) == B_OK && testPath != trashPath) entries++; } if (entries != 0 && ((new BAlert("", B_TRANSLATE("The target volume is not empty. Are " "you sure you want to install anyway?\n\nNote: The 'system' folder " "will be a clean copy from the source volume, all other folders " "will be merged, whereas files and links that exist on both the " "source and target volume will be overwritten with the source " "volume version."), B_TRANSLATE("Install anyway"), B_TRANSLATE("Cancel"), 0, B_WIDTH_AS_USUAL, B_STOP_ALERT))->Go() != 0)) { // TODO: Would be cool to offer the option here to clean additional // folders at the user's choice (like /boot/common and /boot/develop). err = B_CANCELED; goto error; } // Begin actual installation _LaunchInitScript(targetDirectory); // Create the default indices which should always be present on a proper // boot volume. We don't care if the source volume does not have them. // After all, the user might be re-installing to another drive and may // want problems fixed along the way... err = _CreateDefaultIndices(targetDirectory); if (err != B_OK) goto error; // Mirror all the indices which are present on the source volume onto // the target volume. err = _MirrorIndices(srcDirectory, targetDirectory); if (err != B_OK) goto error; // Let the engine collect information for the progress bar later on engine.ResetTargets(srcDirectory.Path()); err = engine.CollectTargets(srcDirectory.Path(), fCancelSemaphore); if (err != B_OK) goto error; // Collect selected packages also if (fPackages) { BPath pkgRootDir(srcDirectory.Path(), PACKAGES_DIRECTORY); int32 count = fPackages->CountItems(); for (int32 i = 0; i < count; i++) { Package *p = static_cast<Package*>(fPackages->ItemAt(i)); BPath packageDir(pkgRootDir.Path(), p->Folder()); err = engine.CollectTargets(packageDir.Path(), fCancelSemaphore); if (err != B_OK) goto error; } } // collect information about all zip packages err = _ProcessZipPackages(srcDirectory.Path(), targetDirectory.Path(), &reporter, unzipEngines); if (err != B_OK) goto error; reporter.StartTimer(); // copy source volume err = engine.CopyFolder(srcDirectory.Path(), targetDirectory.Path(), fCancelSemaphore); if (err != B_OK) goto error; // copy selected packages if (fPackages) { BPath pkgRootDir(srcDirectory.Path(), PACKAGES_DIRECTORY); int32 count = fPackages->CountItems(); for (int32 i = 0; i < count; i++) { Package *p = static_cast<Package*>(fPackages->ItemAt(i)); BPath packageDir(pkgRootDir.Path(), p->Folder()); err = engine.CopyFolder(packageDir.Path(), targetDirectory.Path(), fCancelSemaphore); if (err != B_OK) goto error; } } // Extract all zip packages. If an error occured, delete the rest of // the engines, but stop extracting. for (int32 i = 0; i < unzipEngines.CountItems(); i++) { UnzipEngine* engine = reinterpret_cast<UnzipEngine*>( unzipEngines.ItemAtFast(i)); if (err == B_OK) err = engine->UnzipPackage(); delete engine; } if (err != B_OK) goto error; _LaunchFinishScript(targetDirectory); BMessenger(fWindow).SendMessage(MSG_INSTALL_FINISHED); return; error: BMessage statusMessage(MSG_RESET); if (err == B_CANCELED) _SetStatusMessage(B_TRANSLATE("Installation canceled.")); else statusMessage.AddInt32("error", err); ERR("_PerformInstall failed"); BMessenger(fWindow).SendMessage(&statusMessage); }
void MountVolume::ArgvReceived(int32 argc, char** argv) { MountVisitor mountVisitor; PrintPartitionsVisitor printPartitionsVisitor; bool listAllDevices = false; if (argc < 2) printPartitionsVisitor.listMountablePartitions = true; // parse arguments for (int argi = 1; argi < argc; argi++) { const char* arg = argv[argi]; if (arg[0] != '\0' && arg[0] != '-') { mountVisitor.toMount.insert(arg); } else if (strcmp(arg, "-s") == 0) { mountVisitor.silent = true; } else if (strcmp(arg, "-h") == 0 || strcmp(arg, "--help") == 0) { print_usage_and_exit(false); } else if (strcmp(arg, "-all") == 0) { mountVisitor.mountAll = true; } else if (strcmp(arg, "-allbfs") == 0) { mountVisitor.mountBFS = true; } else if (strcmp(arg, "-allhfs") == 0) { mountVisitor.mountHFS = true; } else if (strcmp(arg, "-alldos") == 0) { mountVisitor.mountDOS = true; } else if (strcmp(arg, "-ro") == 0 || strcmp(arg, "-readonly") == 0) { mountVisitor.readOnly = true; } else if (strcmp(arg, "-u") == 0 || strcmp(arg, "-unmount") == 0) { argi++; if (argi >= argc) print_usage_and_exit(true); mountVisitor.toUnmount.insert(argv[argi]); } else if (strcmp(arg, "-p") == 0 || strcmp(arg, "-l") == 0) { printPartitionsVisitor.listMountablePartitions = true; } else if (strcmp(arg, "-lh") == 0) { printPartitionsVisitor.listAllPartitions = true; } else if (strcmp(arg, "-dd") == 0) { listAllDevices = true; } else if (strcmp(arg, "-r") == 0 || strcmp(arg, "-publishall") == 0 || strcmp(arg, "-publishbfs") == 0 || strcmp(arg, "-publishhfs") == 0 || strcmp(arg, "-publishdos") == 0) { // obsolete: ignore } else print_usage_and_exit(true); } // get a disk device list BDiskDeviceList deviceList; status_t error = deviceList.Fetch(); if (error != B_OK) { fprintf(stderr, "Failed to get the list of disk devices: %s", strerror(error)); exit(1); } // mount/unmount volumes deviceList.VisitEachMountablePartition(&mountVisitor); BDiskDeviceRoster roster; // try mount file images for (StringSet::iterator iterator = mountVisitor.toMount.begin(); iterator != mountVisitor.toMount.end();) { const char* name = (*iterator).c_str(); iterator++; BEntry entry(name, true); if (!entry.Exists()) continue; // TODO: improve error messages BPath path; if (entry.GetPath(&path) != B_OK) continue; partition_id id = -1; BDiskDevice device; BPartition* partition; if (!strncmp(path.Path(), "/dev/", 5)) { // seems to be a device path if (roster.GetPartitionForPath(path.Path(), &device, &partition) != B_OK) continue; } else { // a file with this name exists, so try to mount it id = roster.RegisterFileDevice(path.Path()); if (id < 0) continue; if (roster.GetPartitionWithID(id, &device, &partition) != B_OK) { roster.UnregisterFileDevice(id); continue; } } status_t status = partition->Mount(NULL, mountVisitor.readOnly ? B_MOUNT_READ_ONLY : 0); if (!mountVisitor.silent) { if (status >= B_OK) { BPath mountPoint; partition->GetMountPoint(&mountPoint); printf("%s \"%s\" mounted successfully at \"%s\".\n", id < 0 ? "Device" : "Image", name, mountPoint.Path()); } } if (status >= B_OK) { // remove from list mountVisitor.toMount.erase(name); } else if (id >= 0) roster.UnregisterFileDevice(id); } // TODO: support unmounting images by path! // print errors for the volumes to mount/unmount, that weren't found if (!mountVisitor.silent) { for (StringSet::iterator it = mountVisitor.toMount.begin(); it != mountVisitor.toMount.end(); it++) { fprintf(stderr, "Failed to mount volume `%s': Volume not found.\n", (*it).c_str()); } for (StringSet::iterator it = mountVisitor.toUnmount.begin(); it != mountVisitor.toUnmount.end(); it++) { fprintf(stderr, "Failed to unmount volume `%s': Volume not " "found.\n", (*it).c_str()); } } // update the disk device list error = deviceList.Fetch(); if (error != B_OK) { fprintf(stderr, "Failed to update the list of disk devices: %s", strerror(error)); exit(1); } // print information if (listAllDevices) { // TODO } // determine width of the terminal in order to shrink the columns if needed if (isatty(STDOUT_FILENO)) { winsize size; if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &size, sizeof(winsize)) == 0) { if (size.ws_col < 95) { sVolumeNameWidth -= (95 - size.ws_col) / 2; sFSNameWidth -= (95 - size.ws_col) / 2; } } } if (printPartitionsVisitor.IsUsed()) { printf("%-*s %-*s Size Mounted At (Device)\n", sVolumeNameWidth, "Volume", sFSNameWidth, "File System"); BString separator; separator.SetTo('-', sVolumeNameWidth + sFSNameWidth + 35); puts(separator.String()); if (printPartitionsVisitor.listAllPartitions) deviceList.VisitEachPartition(&printPartitionsVisitor); else deviceList.VisitEachMountablePartition(&printPartitionsVisitor); } exit(0); }