From 53a05b7c3f9374995caa2dd72f01dd7442565627 Mon Sep 17 00:00:00 2001 From: Poul-Henning Kamp Date: Mon, 6 Dec 2004 18:18:35 +0000 Subject: [PATCH] Add more functions for handling mount arguments in VFS_MOUNT(): vfs_flagopt() for binary/boolean options. vfs_getopts() for string options vfs_filteropt() to check for unknown options. vfs_scanopt() for scanf() like processing of options. Also add function for setting the stat.f_mntfromname field. --- sys/kern/vfs_mount.c | 112 +++++++++++++++++++++++++++++++++++++++++++ sys/sys/mount.h | 5 ++ 2 files changed, 117 insertions(+) diff --git a/sys/kern/vfs_mount.c b/sys/kern/vfs_mount.c index cea921f254dc..8a8dac70716f 100644 --- a/sys/kern/vfs_mount.c +++ b/sys/kern/vfs_mount.c @@ -121,6 +121,18 @@ struct vnode *rootvnode; * to locate its physical store */ +/* + * Global opts, taken by all filesystems + */ +static const char *global_opts[] = { + "fstype", + "fspath", + "ro", + "suid", + "exec", + NULL +}; + /* * The root specifiers we will try if RB_CDROM is specified. */ @@ -1381,6 +1393,41 @@ DB_SHOW_COMMAND(disk, db_getdiskbyname) } #endif +/* + * --------------------------------------------------------------------- + * Functions for querying mount options/arguments from filesystems. + */ + +/* + * Check that no unknown options are given + */ +int +vfs_filteropt(struct vfsoptlist *opts, const char **legal) +{ + struct vfsopt *opt; + const char **t, *p; + + + TAILQ_FOREACH(opt, opts, link) { + p = opt->name; + if (p[0] == 'n' && p[1] == 'o') + p += 2; + for(t = global_opts; *t != NULL; t++) + if (!strcmp(*t, p)) + break; + if (*t != NULL) + continue; + for(t = legal; *t != NULL; t++) + if (!strcmp(*t, p)) + break; + if (*t != NULL) + continue; + printf("mount option <%s> is unknown\n", p); + return (EINVAL); + } + return (0); +} + /* * Get a mount option by its name. * @@ -1412,6 +1459,62 @@ vfs_getopt(opts, name, buf, len) return (ENOENT); } +char * +vfs_getopts(struct vfsoptlist *opts, const char *name, int *error) +{ + struct vfsopt *opt; + + *error = 0; + TAILQ_FOREACH(opt, opts, link) { + if (strcmp(name, opt->name) != 0) + continue; + if (((char *)opt->value)[opt->len - 1] != '\0') { + *error = EINVAL; + return (NULL); + } + return (opt->value); + } + return (NULL); +} + +int +vfs_flagopt(struct vfsoptlist *opts, const char *name, u_int *w, u_int val) +{ + struct vfsopt *opt; + + TAILQ_FOREACH(opt, opts, link) { + if (strcmp(name, opt->name) == 0) { + if (w != NULL) + *w |= val; + return (1); + } + } + if (w != NULL) + *w &= ~val; + return (0); +} + +int +vfs_scanopt(struct vfsoptlist *opts, const char *name, const char *fmt, ...) +{ + va_list ap; + struct vfsopt *opt; + int ret; + + KASSERT(opts != NULL, ("vfs_getopt: caller passed 'opts' as NULL")); + + TAILQ_FOREACH(opt, opts, link) { + if (strcmp(name, opt->name) != 0) + continue; + if (((char *)opt->value)[opt->len - 1] != '\0') + return (0); + va_start(ap, fmt); + ret = vsscanf(opt->value, fmt, ap); + va_end(ap); + return (ret); + } + return (0); +} /* * Find and copy a mount option. * @@ -1481,6 +1584,15 @@ __vfs_statfs(struct mount *mp, struct statfs *sbp, struct thread *td) return (error); } +void +vfs_mountedfrom(struct mount *mp, const char *from) +{ + + bzero(mp->mnt_stat.f_mntfromname, sizeof mp->mnt_stat.f_mntfromname); + strlcpy(mp->mnt_stat.f_mntfromname, from, + sizeof mp->mnt_stat.f_mntfromname); +} + /* * --------------------------------------------------------------------- * This is the api for building mount args and mounting filesystems from diff --git a/sys/sys/mount.h b/sys/sys/mount.h index a21c1a1fa793..2ab837d1bda3 100644 --- a/sys/sys/mount.h +++ b/sys/sys/mount.h @@ -571,8 +571,12 @@ struct mntarg *mount_argsu(struct mntarg *ma, const char *name, const void *val, struct vfsconf *vfs_byname(const char *); struct vfsconf *vfs_byname_kld(const char *, struct thread *td, int *); void vfs_event_signal(fsid_t *, u_int32_t, intptr_t); +int vfs_flagopt(struct vfsoptlist *opts, const char *name, u_int *w, u_int val); int vfs_getopt(struct vfsoptlist *, const char *, void **, int *); +char *vfs_getopts(struct vfsoptlist *, const char *, int *error); int vfs_copyopt(struct vfsoptlist *, const char *, void *, int); +int vfs_filteropt(struct vfsoptlist *, const char **legal); +int vfs_scanopt(struct vfsoptlist *opts, const char *name, const char *fmt, ...); int vfs_setpublicfs /* set publicly exported fs */ (struct mount *, struct netexport *, struct export_args *); int vfs_lock(struct mount *); /* lock a vfs */ @@ -589,6 +593,7 @@ struct cdev *vfs_getrootfsid(struct mount *); struct mount *vfs_getvfs(fsid_t *); /* return vfs given fsid */ int vfs_modevent(module_t, int, void *); void vfs_mountroot(void); /* mount our root filesystem */ +void vfs_mountedfrom(struct mount *, const char *from); void vfs_mount_destroy(struct mount *, struct thread *); int vfs_suser(struct mount *, struct thread *); void vfs_unbusy(struct mount *, struct thread *);