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