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; }
/* * 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; }
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); }
// 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; }
/* * 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); }
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; }
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; }
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; }