示例#1
0
extern int mount_main(int argc, char **argv)
{
	struct stat statbuf;
	char *string_flags = xstrdup("");
	char *extra_opts;
	int flags = 0;
	char *filesystemType = "auto";
	int got_filesystemType = 0;
	char *device = xmalloc(PATH_MAX);
	char *directory = xmalloc(PATH_MAX);
	struct mntent *m = NULL;
	int all = FALSE;
	int fakeIt = FALSE;
	int useMtab = TRUE;
	int rc = EXIT_FAILURE;
	FILE *f = 0;
	int opt;

	/* Parse options */
	while ((opt = getopt(argc, argv, "o:rt:wafnv")) > 0) {
		switch (opt) {
		case 'o':
			parse_mount_options(optarg, &flags, &string_flags);
			break;
		case 'r':
			flags |= MS_RDONLY;
			break;
		case 't':
			filesystemType = optarg;
			got_filesystemType = 1;
			break;
		case 'w':
			flags &= ~MS_RDONLY;
			break;
		case 'a':
			all = TRUE;
			break;
		case 'f':
			fakeIt = TRUE;
			break;
#ifdef BB_FEATURE_MTAB_SUPPORT
		case 'n':
			useMtab = FALSE;
			break;
#endif
		case 'v':
			break; /* ignore -v */
		}
	}

	if (!all && optind == argc)
		show_mounts(got_filesystemType ? filesystemType : 0);

	if (optind < argc) {
		/* if device is a filename get its real path */
		if (stat(argv[optind], &statbuf) == 0) {
			char *tmp = simplify_path(argv[optind]);
			safe_strncpy(device, tmp, PATH_MAX);
		} else {
			safe_strncpy(device, argv[optind], PATH_MAX);
		}
	}

	if (optind + 1 < argc)
		directory = simplify_path(argv[optind + 1]);

	if (all || optind + 1 == argc) {
		f = setmntent("/etc/fstab", "r");

		if (f == NULL)
			perror_msg_and_die( "\nCannot read /etc/fstab");

		while ((m = getmntent(f)) != NULL) {
			if (! all && optind + 1 == argc && (
				(strcmp(device, m->mnt_fsname) != 0) &&
				(strcmp(device, m->mnt_dir) != 0) ) ) {
				continue;
			}
			
			if (all && (							// If we're mounting 'all'
				(strstr(m->mnt_opts, "noauto")) ||	// and the file system isn't noauto,
				(strstr(m->mnt_type, "swap")) ||	// and isn't swap or nfs, then mount it
				(strstr(m->mnt_type, "nfs")) ) ) {
				continue;
			}
			
			if (all || flags == 0) {	// Allow single mount to override fstab flags
				flags = 0;
				string_flags[0] = 0;
				parse_mount_options(m->mnt_opts, &flags, &string_flags);
			}
			
			strcpy(device, m->mnt_fsname);
			strcpy(directory, m->mnt_dir);
			filesystemType = xstrdup(m->mnt_type);
singlemount:			
			extra_opts = string_flags;
			rc = EXIT_SUCCESS;
#ifdef BB_NFSMOUNT
			if (strchr(device, ':') != NULL) {
				filesystemType = "nfs";
				if (nfsmount (device, directory, &flags, &extra_opts,
							&string_flags, 1)) {
					perror_msg("nfsmount failed");
					rc = EXIT_FAILURE;
				}
			}
#endif
			if (!mount_one(device, directory, filesystemType, flags,
					string_flags, useMtab, fakeIt, extra_opts, TRUE, all))
				rc = EXIT_FAILURE;
				
			if (! all)
				break;
		}
		if (f)
			endmntent(f);
			
		if (! all && f && m == NULL)
			fprintf(stderr, "Can't find %s in /etc/fstab\n", device);
	
		return rc;
	}
	
	goto singlemount;
}
示例#2
0
static int singlemount(struct mntent *mp, int ignore_busy)
{
	int rc = -1, vfsflags;
	char *loopFile = 0, *filteropts = 0;
	llist_t *fl = 0;
	struct stat st;

	vfsflags = parse_mount_options(mp->mnt_opts, &filteropts);

	// Treat fstype "auto" as unspecified.

	if (mp->mnt_type && !strcmp(mp->mnt_type,"auto")) mp->mnt_type = 0;

	// Might this be an NFS filesystem?

	if (ENABLE_FEATURE_MOUNT_NFS &&
		(!mp->mnt_type || !strcmp(mp->mnt_type,"nfs")) &&
		strchr(mp->mnt_fsname, ':') != NULL)
	{
		if (nfsmount(mp->mnt_fsname, mp->mnt_dir, &vfsflags, &filteropts, 1)) {
			bb_perror_msg("nfsmount failed");
			goto report_error;
		} else {
			// Strangely enough, nfsmount() doesn't actually mount() anything.
			mp->mnt_type = "nfs";
			rc = mount_it_now(mp, vfsflags, filteropts);
			if (ENABLE_FEATURE_CLEAN_UP) free(filteropts);
			
			goto report_error;
		}
	}

	// Look at the file.  (Not found isn't a failure for remount, or for
	// a synthetic filesystem like proc or sysfs.)

	if (stat(mp->mnt_fsname, &st));
	else if (!(vfsflags & (MS_REMOUNT | MS_BIND | MS_MOVE))) {
		// Do we need to allocate a loopback device for it?

		if (ENABLE_FEATURE_MOUNT_LOOP && S_ISREG(st.st_mode)) {
			loopFile = bb_simplify_path(mp->mnt_fsname);
			mp->mnt_fsname = 0;
			switch(set_loop(&(mp->mnt_fsname), loopFile, 0)) {
				case 0:
				case 1:
					break;
				default:
					bb_error_msg( errno == EPERM || errno == EACCES
						? bb_msg_perm_denied_are_you_root
					   	: "Couldn't setup loop device");
					return errno;
			}

		// Autodetect bind mounts

		} else if (S_ISDIR(st.st_mode) && !mp->mnt_type) vfsflags |= MS_BIND;
	}

	/* If we know the fstype (or don't need to), jump straight
	 * to the actual mount. */

	if (mp->mnt_type || (vfsflags & (MS_REMOUNT | MS_BIND | MS_MOVE)))
		rc = mount_it_now(mp, vfsflags, filteropts);

	// Loop through filesystem types until mount succeeds or we run out

	else {

		/* Initialize list of block backed filesystems.  This has to be
		 * done here so that during "mount -a", mounts after /proc shows up
		 * can autodetect. */

		if (!fslist) {
			fslist = get_block_backed_filesystems();
			if (ENABLE_FEATURE_CLEAN_UP && fslist)
				atexit(delete_block_backed_filesystems);
		}

		for (fl = fslist; fl; fl = fl->link) {
			mp->mnt_type = fl->data;

			if (!(rc = mount_it_now(mp,vfsflags, filteropts))) break;

			mp->mnt_type = 0;
		}
	}

	if (ENABLE_FEATURE_CLEAN_UP) free(filteropts);

	// If mount failed, clean up loop file (if any).

	if (ENABLE_FEATURE_MOUNT_LOOP && rc && loopFile) {
		del_loop(mp->mnt_fsname);
		if (ENABLE_FEATURE_CLEAN_UP) {
			free(loopFile);
			free(mp->mnt_fsname);
		}
	}
report_error:
	if (rc && errno == EBUSY && ignore_busy) rc = 0;
	if (rc < 0)
		bb_perror_msg("Mounting %s on %s failed", mp->mnt_fsname, mp->mnt_dir);

	return rc;
}