Example #1
0
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);
	}
}
Example #2
0
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);
	}
}
Example #3
0
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);
	}
}
Example #4
0
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);
}
Example #5
0
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);
}