void AutoMounter::_MountVolumes(mount_mode normal, mount_mode removable, bool initialRescan, partition_id deviceID) { if (normal == kNoVolumes && removable == kNoVolumes) return; class InitialMountVisitor : public BDiskDeviceVisitor { public: InitialMountVisitor(mount_mode normalMode, mount_mode removableMode, bool initialRescan, BMessage& previous, partition_id deviceID) : fNormalMode(normalMode), fRemovableMode(removableMode), fInitialRescan(initialRescan), fPrevious(previous), fOnlyOnDeviceID(deviceID) { } virtual ~InitialMountVisitor() { } virtual bool Visit(BDiskDevice* device) { return Visit(device, 0); } virtual bool Visit(BPartition* partition, int32 level) { if (fOnlyOnDeviceID >= 0) { // only mount partitions on the given device id // or if the partition ID is already matched BPartition* device = partition; while (device->Parent() != NULL) { if (device->ID() == fOnlyOnDeviceID) { // we are happy break; } device = device->Parent(); } if (device->ID() != fOnlyOnDeviceID) return false; } mount_mode mode = !fInitialRescan && partition->Device()->IsRemovableMedia() ? fRemovableMode : fNormalMode; if (mode == kNoVolumes || partition->IsMounted() || !partition->ContainsFileSystem()) return false; BPath path; if (partition->GetPath(&path) != B_OK) return false; if (mode == kRestorePreviousVolumes) { // mount all volumes that were stored in the settings file const char *volumeName = NULL; if (partition->ContentName() == NULL || fPrevious.FindString(path.Path(), &volumeName) != B_OK || strcmp(volumeName, partition->ContentName())) return false; } else if (mode == kOnlyBFSVolumes) { if (partition->ContentType() == NULL || strcmp(partition->ContentType(), kPartitionTypeBFS)) return false; } uint32 mountFlags; if (!fInitialRescan) { // Ask the user about mount flags if this is not the // initial scan. if (!_SuggestMountFlags(partition, &mountFlags)) return false; } else { BString mountFlagsKey(path.Path()); mountFlagsKey << kMountFlagsKeyExtension; if (fPrevious.FindInt32(mountFlagsKey.String(), (int32*)&mountFlags) < B_OK) { mountFlags = 0; } } if (partition->Mount(NULL, mountFlags) != B_OK) { // TODO: Error to syslog } return false; } private: mount_mode fNormalMode; mount_mode fRemovableMode; bool fInitialRescan; BMessage& fPrevious; partition_id fOnlyOnDeviceID; } visitor(normal, removable, initialRescan, fSettings, deviceID); BDiskDeviceList devices; status_t status = devices.Fetch(); if (status == B_OK) devices.VisitEachPartition(&visitor); }
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); }