static void parse_int(struct mount *mp, const char *opt, int *val, int *error) { char *tmp, *ep; tmp = vfs_getopts(mp->mnt_optnew, opt, error); if (*error != 0) { return; } if (tmp != NULL) { *val = (int)strtol(tmp, &ep, 10); if (*ep) { *error = EINVAL; return; } } }
static int cd9660_mount(struct mount *mp, struct thread *td) { struct vnode *devvp; char *fspec; int error; mode_t accessmode; struct nameidata ndp; struct iso_mnt *imp = 0; /* * Unconditionally mount as read-only. */ MNT_ILOCK(mp); mp->mnt_flag |= MNT_RDONLY; MNT_IUNLOCK(mp); fspec = vfs_getopts(mp->mnt_optnew, "from", &error); if (error) return (error); imp = VFSTOISOFS(mp); if (mp->mnt_flag & MNT_UPDATE) { if (vfs_flagopt(mp->mnt_optnew, "export", NULL, 0)) return (0); } /* * Not an update, or updating the name: look up the name * and verify that it refers to a sensible block device. */ NDINIT(&ndp, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, fspec, td); if ((error = namei(&ndp))) return (error); NDFREE(&ndp, NDF_ONLY_PNBUF); devvp = ndp.ni_vp; if (!vn_isdisk(devvp, &error)) { vput(devvp); return (error); } /* * Verify that user has necessary permissions on the device, * or has superuser abilities */ accessmode = VREAD; error = VOP_ACCESS(devvp, accessmode, td->td_ucred, td); if (error) error = priv_check(td, PRIV_VFS_MOUNT_PERM); if (error) { vput(devvp); return (error); } if ((mp->mnt_flag & MNT_UPDATE) == 0) { error = iso_mountfs(devvp, mp, td); if (error) vrele(devvp); } else { if (devvp != imp->im_devvp) error = EINVAL; /* needs translation */ vput(devvp); } if (error) return (error); vfs_mountedfrom(mp, fspec); return (0); }
/*ARGSUSED*/ int coda_mount(struct mount *vfsp) { struct vnode *dvp; struct cnode *cp; struct cdev *dev; struct coda_mntinfo *mi; struct vnode *rootvp; struct CodaFid rootfid = INVAL_FID; struct CodaFid ctlfid = CTL_FID; int error; struct nameidata ndp; ENTRY; char *from; if (vfs_filteropt(vfsp->mnt_optnew, coda_opts)) return (EINVAL); from = vfs_getopts(vfsp->mnt_optnew, "from", &error); if (error) return (error); coda_vfsopstats_init(); coda_vnodeopstats_init(); MARK_ENTRY(CODA_MOUNT_STATS); if (CODA_MOUNTED(vfsp)) { MARK_INT_FAIL(CODA_MOUNT_STATS); return (EBUSY); } /* * Validate mount device. Similar to getmdev(). */ NDINIT(&ndp, LOOKUP, FOLLOW, UIO_SYSSPACE, from, curthread); error = namei(&ndp); dvp = ndp.ni_vp; if (error) { MARK_INT_FAIL(CODA_MOUNT_STATS); return (error); } if (dvp->v_type != VCHR) { MARK_INT_FAIL(CODA_MOUNT_STATS); vrele(dvp); NDFREE(&ndp, NDF_ONLY_PNBUF); return (ENXIO); } dev = dvp->v_rdev; vrele(dvp); NDFREE(&ndp, NDF_ONLY_PNBUF); /* * Initialize the mount record and link it to the vfs struct. */ mi = dev2coda_mntinfo(dev); if (!mi) { MARK_INT_FAIL(CODA_MOUNT_STATS); printf("Coda mount: %s is not a cfs device\n", from); return (ENXIO); } if (!VC_OPEN(&mi->mi_vcomm)) { MARK_INT_FAIL(CODA_MOUNT_STATS); return (ENODEV); } /* * No initialization (here) of mi_vcomm! */ vfsp->mnt_data = mi; vfs_getnewfsid (vfsp); mi->mi_vfsp = vfsp; mi->mi_started = 0; /* XXX See coda_root() */ /* * Make a root vnode to placate the Vnode interface, but don't * actually make the CODA_ROOT call to venus until the first call to * coda_root in case a server is down while venus is starting. */ cp = make_coda_node(&rootfid, vfsp, VDIR); rootvp = CTOV(cp); rootvp->v_vflag |= VV_ROOT; cp = make_coda_node(&ctlfid, vfsp, VREG); coda_ctlvp = CTOV(cp); /* * Add vfs and rootvp to chain of vfs hanging off mntinfo. */ mi->mi_vfsp = vfsp; mi->mi_rootvp = rootvp; vfs_mountedfrom(vfsp, from); /* * Error is currently guaranteed to be zero, but in case some code * changes... */ CODADEBUG(1, myprintf(("coda_mount returned %d\n", error)););
static int ntfs_mount(struct mount *mp) { int err = 0, error; struct vnode *devvp; struct nameidata ndp; struct thread *td; char *from; td = curthread; if (vfs_filteropt(mp->mnt_optnew, ntfs_opts)) return (EINVAL); /* Force mount as read-only. */ MNT_ILOCK(mp); mp->mnt_flag |= MNT_RDONLY; MNT_IUNLOCK(mp); from = vfs_getopts(mp->mnt_optnew, "from", &error); if (error) return (error); /* * If updating, check whether changing from read-only to * read/write. */ if (mp->mnt_flag & MNT_UPDATE) { if (vfs_flagopt(mp->mnt_optnew, "export", NULL, 0)) { /* Process export requests in vfs_mount.c */ return (0); } else { printf("ntfs_mount(): MNT_UPDATE not supported\n"); return (EINVAL); } } /* * Not an update, or updating the name: look up the name * and verify that it refers to a sensible block device. */ NDINIT(&ndp, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, from, td); err = namei(&ndp); if (err) return (err); NDFREE(&ndp, NDF_ONLY_PNBUF); devvp = ndp.ni_vp; if (!vn_isdisk(devvp, &err)) { vput(devvp); return (err); } /* * If mount by non-root, then verify that user has necessary * permissions on the device. */ err = VOP_ACCESS(devvp, VREAD, td->td_ucred, td); if (err) err = priv_check(td, PRIV_VFS_MOUNT_PERM); if (err) { vput(devvp); return (err); } /* * Since this is a new mount, we want the names for the device and * the mount point copied in. If an error occurs, the mountpoint is * discarded by the upper level code. Note that vfs_mount() handles * copying the mountpoint f_mntonname for us, so we don't have to do * it here unless we want to set it to something other than "path" * for some rason. */ err = ntfs_mountfs(devvp, mp, td); if (err == 0) { /* Save "mounted from" info for mount point. */ vfs_mountedfrom(mp, from); } else vrele(devvp); return (err); }
static int _xfs_param_copyin(struct mount *mp, struct thread *td) { struct xfsmount *xmp = MNTTOXFS(mp); struct xfs_mount_args *args = &xmp->m_args; char *path; char *fsname; char *rtname; char *logname; int error; path = vfs_getopts(mp->mnt_optnew, "fspath", &error); if (error) return (error); bzero(args, sizeof(struct xfs_mount_args)); args->logbufs = -1; args->logbufsize = -1; parse_int(mp, "flags", &args->flags, &error); if (error != 0 && error != ENOENT) return error; args->flags |= XFSMNT_32BITINODES; parse_int(mp, "sunit", &args->sunit, &error); if (error != 0 && error != ENOENT) return error; parse_int(mp, "swidth", &args->swidth, &error); if (error != 0 && error != ENOENT) return error; parse_int(mp, "logbufs", &args->logbufs, &error); if (error != 0 && error != ENOENT) return error; parse_int(mp, "logbufsize", &args->logbufsize, &error); if (error != 0 && error != ENOENT) return error; fsname = vfs_getopts(mp->mnt_optnew, "from", &error); if (error == 0 && fsname != NULL) { strncpy(args->fsname, fsname, sizeof(args->fsname) - 1); } logname = vfs_getopts(mp->mnt_optnew, "logname", &error); if (error == 0 && logname != NULL) { strncpy(args->logname, logname, sizeof(args->logname) - 1); } rtname = vfs_getopts(mp->mnt_optnew, "rtname", &error); if (error == 0 && rtname != NULL) { strncpy(args->rtname, rtname, sizeof(args->rtname) - 1); } strncpy(args->mtpt, path, sizeof(args->mtpt)); printf("fsname '%s' logname '%s' rtname '%s'\n" "flags 0x%x sunit %d swidth %d logbufs %d logbufsize %d\n", args->fsname, args->logname, args->rtname, args->flags, args->sunit, args->swidth, args->logbufs, args->logbufsize); vfs_mountedfrom(mp, args->fsname); return (0); }
static int fuse_vfsop_mount(struct mount *mp) { int err; uint64_t mntopts, __mntopts; int max_read_set; uint32_t max_read; int daemon_timeout; int fd; size_t len; struct cdev *fdev; struct fuse_data *data; struct thread *td; struct file *fp, *fptmp; char *fspec, *subtype; struct vfsoptlist *opts; subtype = NULL; max_read_set = 0; max_read = ~0; err = 0; mntopts = 0; __mntopts = 0; td = curthread; fuse_trace_printf_vfsop(); if (mp->mnt_flag & MNT_UPDATE) return EOPNOTSUPP; mp->mnt_flag |= MNT_SYNCHRONOUS; mp->mnt_data = NULL; /* Get the new options passed to mount */ opts = mp->mnt_optnew; if (!opts) return EINVAL; /* `fspath' contains the mount point (eg. /mnt/fuse/sshfs); REQUIRED */ if (!vfs_getopts(opts, "fspath", &err)) return err; /* `from' contains the device name (eg. /dev/fuse0); REQUIRED */ fspec = vfs_getopts(opts, "from", &err); if (!fspec) return err; /* `fd' contains the filedescriptor for this session; REQUIRED */ if (vfs_scanopt(opts, "fd", "%d", &fd) != 1) return EINVAL; err = fuse_getdevice(fspec, td, &fdev); if (err != 0) return err; /* * With the help of underscored options the mount program * can inform us from the flags it sets by default */ FUSE_FLAGOPT(allow_other, FSESS_DAEMON_CAN_SPY); FUSE_FLAGOPT(push_symlinks_in, FSESS_PUSH_SYMLINKS_IN); FUSE_FLAGOPT(default_permissions, FSESS_DEFAULT_PERMISSIONS); FUSE_FLAGOPT(no_attrcache, FSESS_NO_ATTRCACHE); FUSE_FLAGOPT(no_readahed, FSESS_NO_READAHEAD); FUSE_FLAGOPT(no_datacache, FSESS_NO_DATACACHE); FUSE_FLAGOPT(no_namecache, FSESS_NO_NAMECACHE); FUSE_FLAGOPT(no_mmap, FSESS_NO_MMAP); FUSE_FLAGOPT(brokenio, FSESS_BROKENIO); if (vfs_scanopt(opts, "max_read=", "%u", &max_read) == 1) max_read_set = 1; if (vfs_scanopt(opts, "timeout=", "%u", &daemon_timeout) == 1) { if (daemon_timeout < FUSE_MIN_DAEMON_TIMEOUT) daemon_timeout = FUSE_MIN_DAEMON_TIMEOUT; else if (daemon_timeout > FUSE_MAX_DAEMON_TIMEOUT) daemon_timeout = FUSE_MAX_DAEMON_TIMEOUT; } else { daemon_timeout = FUSE_DEFAULT_DAEMON_TIMEOUT; } subtype = vfs_getopts(opts, "subtype=", &err); FS_DEBUG2G("mntopts 0x%jx\n", (uintmax_t)mntopts); err = fget(td, fd, CAP_READ, &fp); if (err != 0) { FS_DEBUG("invalid or not opened device: data=%p\n", data); goto out; } fptmp = td->td_fpop; td->td_fpop = fp; err = devfs_get_cdevpriv((void **)&data); td->td_fpop = fptmp; fdrop(fp, td); FUSE_LOCK(); if (err != 0 || data == NULL || data->mp != NULL) { FS_DEBUG("invalid or not opened device: data=%p data.mp=%p\n", data, data != NULL ? data->mp : NULL); err = ENXIO; FUSE_UNLOCK(); goto out; } if (fdata_get_dead(data)) { FS_DEBUG("device is dead during mount: data=%p\n", data); err = ENOTCONN; FUSE_UNLOCK(); goto out; } /* Sanity + permission checks */ if (!data->daemoncred) panic("fuse daemon found, but identity unknown"); if (mntopts & FSESS_DAEMON_CAN_SPY) err = priv_check(td, PRIV_VFS_FUSE_ALLOWOTHER); if (err == 0 && td->td_ucred->cr_uid != data->daemoncred->cr_uid) /* are we allowed to do the first mount? */ err = priv_check(td, PRIV_VFS_FUSE_MOUNT_NONUSER); if (err) { FUSE_UNLOCK(); goto out; } /* We need this here as this slot is used by getnewvnode() */ mp->mnt_stat.f_iosize = PAGE_SIZE; mp->mnt_data = data; data->ref++; data->mp = mp; data->dataflags |= mntopts; data->max_read = max_read; data->daemon_timeout = daemon_timeout; #ifdef XXXIP if (!priv_check(td, PRIV_VFS_FUSE_SYNC_UNMOUNT)) data->dataflags |= FSESS_CAN_SYNC_UNMOUNT; #endif FUSE_UNLOCK(); vfs_getnewfsid(mp); mp->mnt_flag |= MNT_LOCAL; mp->mnt_kern_flag |= MNTK_MPSAFE; if (subtype) { strlcat(mp->mnt_stat.f_fstypename, ".", MFSNAMELEN); strlcat(mp->mnt_stat.f_fstypename, subtype, MFSNAMELEN); } copystr(fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, &len); bzero(mp->mnt_stat.f_mntfromname + len, MNAMELEN - len); FS_DEBUG2G("mp %p: %s\n", mp, mp->mnt_stat.f_mntfromname); /* Now handshaking with daemon */ fuse_internal_send_init(data, td); out: if (err) { FUSE_LOCK(); if (data->mp == mp) { /* * Destroy device only if we acquired reference to * it */ FS_DEBUG("mount failed, destroy device: data=%p mp=%p" " err=%d\n", data, mp, err); data->mp = NULL; fdata_trydestroy(data); } FUSE_UNLOCK(); dev_rel(fdev); } return err; }