Пример #1
0
static int devpts_remount(struct super_block *sb, int *flags, char *data)
{
	int err;
	struct pts_fs_info *fsi = DEVPTS_SB(sb);
	struct pts_mount_opts *opts = &fsi->mount_opts;

	err = parse_mount_options(data, PARSE_REMOUNT, opts);

	/*
	 * parse_mount_options() restores options to default values
	 * before parsing and may have changed ptmxmode. So, update the
	 * mode in the inode too. Bogus options don't fail the remount,
	 * so do this even on error return.
	 */
	update_ptmx_mode(fsi);

	return err;
}
Пример #2
0
/*
 * devpts_get_sb()
 *
 *     If the '-o newinstance' mount option was specified, mount a new
 *     (private) instance of devpts.  PTYs created in this instance are
 *     independent of the PTYs in other devpts instances.
 *
 *     If the '-o newinstance' option was not specified, mount/remount the
 *     initial kernel mount of devpts.  This type of mount gives the
 *     legacy, single-instance semantics.
 *
 *     The 'newinstance' option is needed to support multiple namespace
 *     semantics in devpts while preserving backward compatibility of the
 *     current 'single-namespace' semantics. i.e all mounts of devpts
 *     without the 'newinstance' mount option should bind to the initial
 *     kernel mount, like get_sb_single().
 *
 *     Mounts with 'newinstance' option create a new, private namespace.
 *
 *     NOTE:
 *
 *     For single-mount semantics, devpts cannot use get_sb_single(),
 *     because get_sb_single()/sget() find and use the super-block from
 *     the most recent mount of devpts. But that recent mount may be a
 *     'newinstance' mount and get_sb_single() would pick the newinstance
 *     super-block instead of the initial super-block.
 */
static int devpts_get_sb(struct file_system_type *fs_type,
	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
{
	int error;
	struct pts_mount_opts opts;
	struct super_block *s;

	error = parse_mount_options(data, PARSE_MOUNT, &opts);
	if (error)
		return error;

	if (opts.newinstance)
		s = sget(fs_type, NULL, set_anon_super, NULL);
	else
		s = sget(fs_type, compare_init_pts_sb, set_anon_super, NULL);

	if (IS_ERR(s))
		return PTR_ERR(s);

	if (!s->s_root) {
		s->s_flags = flags;
		error = devpts_fill_super(s, data, flags & MS_SILENT ? 1 : 0);
		if (error)
			goto out_undo_sget;
		s->s_flags |= MS_ACTIVE;
	}

	simple_set_mnt(mnt, s);

	memcpy(&(DEVPTS_SB(s))->mount_opts, &opts, sizeof(opts));

	error = mknod_ptmx(s);
	if (error)
		goto out_dput;

	return 0;

out_dput:
	dput(s->s_root); /* undo dget() in simple_set_mnt() */

out_undo_sget:
	deactivate_locked_super(s);
	return error;
}
Пример #3
0
static struct dentry *devpts_mount(struct file_system_type *fs_type,
	int flags, const char *dev_name, void *data)
{
	int error;
	struct pts_mount_opts opts;
	struct super_block *s;

	error = parse_mount_options(data, PARSE_MOUNT, &opts);
	if (error)
		return ERR_PTR(error);

	if (opts.newinstance)
		s = sget(fs_type, NULL, set_anon_super, NULL);
	else
		s = sget(fs_type, compare_init_pts_sb, set_anon_super, NULL);

	if (IS_ERR(s))
		return ERR_CAST(s);

	if (!s->s_root) {
		s->s_flags = flags;
		error = devpts_fill_super(s, data, flags & MS_SILENT ? 1 : 0);
		if (error)
			goto out_undo_sget;
		s->s_flags |= MS_ACTIVE;
	}

	memcpy(&(DEVPTS_SB(s))->mount_opts, &opts, sizeof(opts));

	error = mknod_ptmx(s);
	if (error)
		goto out_undo_sget;

	return dget(s->s_root);

out_undo_sget:
	deactivate_locked_super(s);
	return ERR_PTR(error);
}
Пример #4
0
// Mount one directory.  Handles CIFS, NFS, loopback, autobind, and filesystem
// type detection.  Returns 0 for success, nonzero for failure.
// NB: mp->xxx fields may be trashed on exit
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") == 0)
		mp->mnt_type = 0;

	// Might this be an CIFS filesystem?

	if (ENABLE_FEATURE_MOUNT_CIFS
	 && (!mp->mnt_type || strcmp(mp->mnt_type,"cifs") == 0)
	 && (mp->mnt_fsname[0]=='/' || mp->mnt_fsname[0]=='\\')
	 && mp->mnt_fsname[0]==mp->mnt_fsname[1]
	) {
		len_and_sockaddr *lsa;
		char *ip, *dotted;
		char *s;

		rc = 1;
		// Replace '/' with '\' and verify that unc points to "//server/share".

		for (s = mp->mnt_fsname; *s; ++s)
			if (*s == '/') *s = '\\';

		// get server IP

		s = strrchr(mp->mnt_fsname, '\\');
		if (s <= mp->mnt_fsname+1) goto report_error;
		*s = '\0';
		lsa = host2sockaddr(mp->mnt_fsname+2, 0);
		*s = '\\';
		if (!lsa) goto report_error;

		// insert ip=... option into string flags.

		dotted = xmalloc_sockaddr2dotted_noport(&lsa->sa, lsa->len);
		ip = xasprintf("ip=%s", dotted);
		parse_mount_options(ip, &filteropts);

		// compose new unc '\\server-ip\share'
		// (s => slash after hostname)

		mp->mnt_fsname = xasprintf("\\\\%s%s", dotted, s);

		// lock is required
		vfsflags |= MS_MANDLOCK;

		mp->mnt_type = (char*)"cifs";
		rc = mount_it_now(mp, vfsflags, filteropts);
		if (ENABLE_FEATURE_CLEAN_UP) {
			free(mp->mnt_fsname);
			free(ip);
			free(dotted);
			free(lsa);
		}
		goto report_error;
	}

	// Might this be an NFS filesystem?

	if (ENABLE_FEATURE_MOUNT_NFS
	 && (!mp->mnt_type || !strcmp(mp->mnt_type,"nfs"))
	 && strchr(mp->mnt_fsname, ':') != NULL
	) {
		rc = nfsmount(mp, vfsflags, 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.)
	// (We use stat, not lstat, in order to allow
	// mount symlink_to_file_or_blkdev dir)

	if (!stat(mp->mnt_fsname, &st)
	 && !(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
					: "cannot 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);
	else {
		// Loop through filesystem types until mount succeeds
		// or we run out

		/* 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;
			rc = mount_it_now(mp, vfsflags, filteropts);
			if (!rc) break;
		}
	}

	// 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 (ENABLE_FEATURE_CLEAN_UP)
		free(filteropts);

	if (rc && errno == EBUSY && ignore_busy) rc = 0;
	if (rc < 0)
		/* perror here sometimes says "mounting ... on ... failed: Success" */
		bb_error_msg("mounting %s on %s failed", mp->mnt_fsname, mp->mnt_dir);

	return rc;
}
Пример #5
0
/*
 * Remount as initiated by VFS layer.  We just need to reparse the mount
 * options, no need to signal pvfs2-client-core about it.
 */
static int orangefs_remount_fs(struct super_block *sb, int *flags, char *data)
{
	gossip_debug(GOSSIP_SUPER_DEBUG, "orangefs_remount_fs: called\n");
	return parse_mount_options(sb, data, 1);
}
Пример #6
0
int main (int argc, char *argv[])
{
	int err = 0;
	struct stat sbuf;
	char *parsed_options = NULL;
	struct fuse_args fargs = FUSE_ARGS_INIT(0, NULL);
	struct extfs_data opts;

	debugf("version:'%s', fuse_version:'%d'", VERSION, fuse_version());

	memset(&opts, 0, sizeof(opts));

	if (parse_options(argc, argv, &opts)) {
		usage();
		return -1;
	}

	if (stat(opts.device, &sbuf)) {
		debugf_main("Failed to access '%s'", opts.device);
		err = -3;
		goto err_out;
	}

	if (do_probe(&opts) != 0) {
		debugf_main("Probe failed");
		err = -4;
		goto err_out;
	}

	parsed_options = parse_mount_options(opts.options ? opts.options : "", &opts);
	if (!parsed_options) {
		err = -2;
		goto err_out;
	}

	debugf_main("opts.device: %s", opts.device);
	debugf_main("opts.mnt_point: %s", opts.mnt_point);
	debugf_main("opts.volname: %s", (opts.volname != NULL) ? opts.volname : "");
	debugf_main("opts.options: %s", opts.options);
	debugf_main("parsed_options: %s", parsed_options);

	if (fuse_opt_add_arg(&fargs, PACKAGE) == -1 ||
	    fuse_opt_add_arg(&fargs, "-s") == -1 ||
	    fuse_opt_add_arg(&fargs, "-o") == -1 ||
	    fuse_opt_add_arg(&fargs, parsed_options) == -1 ||
	    fuse_opt_add_arg(&fargs, opts.mnt_point) == -1) {
		debugf_main("Failed to set FUSE options");
		fuse_opt_free_args(&fargs);
		err = -5;
		goto err_out;
	}

	if (opts.readonly == 0) {
		debugf_main("mounting read-write");
	} else {
		debugf_main("mounting read-only");
	}

	fuse_main(fargs.argc, fargs.argv, &ext2fs_ops, &opts);

err_out:
	fuse_opt_free_args(&fargs);
	free(parsed_options);
	free(opts.options);
	free(opts.device);
	free(opts.volname);
	return err;
}
Пример #7
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;
}
Пример #8
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;
}