From: Petr Vandrovec Date: Fri, 20 Sep 2002 22:34:14 +0000 (+0200) Subject: Add support for text mount option string to ncpfs. X-Git-Tag: v2.5.38~10^2^2~3 X-Git-Url: http://git.neil.brown.name/?a=commitdiff_plain;h=8612e0886498766a8eca36edb42032e0f4dd3f0d;p=history.git Add support for text mount option string to ncpfs. --- diff --git a/fs/ncpfs/Makefile b/fs/ncpfs/Makefile index f28ef2850982..60bcf9e2a528 100644 --- a/fs/ncpfs/Makefile +++ b/fs/ncpfs/Makefile @@ -5,7 +5,7 @@ obj-$(CONFIG_NCP_FS) += ncpfs.o ncpfs-objs := dir.o file.o inode.o ioctl.o mmap.o ncplib_kernel.o sock.o \ - ncpsign_kernel.o + ncpsign_kernel.o getopt.o ifeq ($(CONFIG_NCPFS_EXTRAS),y) ncpfs-objs += symlink.o endif diff --git a/fs/ncpfs/getopt.c b/fs/ncpfs/getopt.c new file mode 100644 index 000000000000..335b003dddf9 --- /dev/null +++ b/fs/ncpfs/getopt.c @@ -0,0 +1,75 @@ +/* + * getopt.c + */ + +#include +#include + +#include + +#include "getopt.h" + +/** + * ncp_getopt - option parser + * @caller: name of the caller, for error messages + * @options: the options string + * @opts: an array of &struct option entries controlling parser operations + * @optopt: output; will contain the current option + * @optarg: output; will contain the value (if one exists) + * @flag: output; may be NULL; should point to a long for or'ing flags + * @value: output; may be NULL; will be overwritten with the integer value + * of the current argument. + * + * Helper to parse options on the format used by mount ("a=b,c=d,e,f"). + * Returns opts->val if a matching entry in the 'opts' array is found, + * 0 when no more tokens are found, -1 if an error is encountered. + */ +int ncp_getopt(const char *caller, char **options, const struct ncp_option *opts, + char **optopt, char **optarg, unsigned long *value) +{ + char *token; + char *val; + + do { + if ((token = strsep(options, ",")) == NULL) + return 0; + } while (*token == '\0'); + if (optopt) + *optopt = token; + + if ((val = strchr (token, '=')) != NULL) { + *val++ = 0; + } + *optarg = val; + for (; opts->name; opts++) { + if (!strcmp(opts->name, token)) { + if (!val) { + if (opts->has_arg & OPT_NOPARAM) { + return opts->val; + } + printk(KERN_INFO "%s: the %s option requires an argument\n", + caller, token); + return -EINVAL; + } + if (opts->has_arg & OPT_INT) { + char* v; + + *value = simple_strtoul(val, &v, 0); + if (!*v) { + return opts->val; + } + printk(KERN_INFO "%s: invalid numeric value in %s=%s\n", + caller, token, val); + return -EDOM; + } + if (opts->has_arg & OPT_STRING) { + return opts->val; + } + printk(KERN_INFO "%s: unexpected argument %s to the %s option\n", + caller, val, token); + return -EINVAL; + } + } + printk(KERN_INFO "%s: Unrecognized mount option %s\n", caller, token); + return -EOPNOTSUPP; +} diff --git a/fs/ncpfs/getopt.h b/fs/ncpfs/getopt.h new file mode 100644 index 000000000000..cccc007dcaf9 --- /dev/null +++ b/fs/ncpfs/getopt.h @@ -0,0 +1,16 @@ +#ifndef _LINUX_GETOPT_H +#define _LINUX_GETOPT_H + +#define OPT_NOPARAM 1 +#define OPT_INT 2 +#define OPT_STRING 4 +struct ncp_option { + const char *name; + unsigned int has_arg; + int val; +}; + +extern int ncp_getopt(const char *caller, char **options, const struct ncp_option *opts, + char **optopt, char **optarg, unsigned long *value); + +#endif /* _LINUX_GETOPT_H */ diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c index 0a49d6a48d5f..c42a026b1448 100644 --- a/fs/ncpfs/inode.c +++ b/fs/ncpfs/inode.c @@ -32,6 +32,7 @@ #include #include "ncplib_kernel.h" +#include "getopt.h" static void ncp_delete_inode(struct inode *); static void ncp_put_super(struct super_block *); @@ -283,6 +284,88 @@ ncp_delete_inode(struct inode *inode) clear_inode(inode); } +static const struct ncp_option ncp_opts[] = { + { "uid", OPT_INT, 'u' }, + { "gid", OPT_INT, 'g' }, + { "owner", OPT_INT, 'o' }, + { "mode", OPT_INT, 'm' }, + { "dirmode", OPT_INT, 'd' }, + { "timeout", OPT_INT, 't' }, + { "retry", OPT_INT, 'r' }, + { "flags", OPT_INT, 'f' }, + { "wdogpid", OPT_INT, 'w' }, + { "ncpfd", OPT_INT, 'n' }, + { "version", OPT_INT, 'v' }, + { NULL, 0, 0 } }; + +static int ncp_parse_options(struct ncp_mount_data_kernel *data, char *options) { + int optval; + char *optarg; + unsigned long optint; + int version = 0; + + data->flags = 0; + data->int_flags = 0; + data->mounted_uid = 0; + data->wdog_pid = -1; + data->ncp_fd = ~0; + data->time_out = 10; + data->retry_count = 20; + data->uid = 0; + data->gid = 0; + data->file_mode = 0600; + data->dir_mode = 0700; + data->mounted_vol[0] = 0; + + while ((optval = ncp_getopt("ncpfs", &options, ncp_opts, NULL, &optarg, &optint)) != 0) { + if (optval < 0) + return optval; + switch (optval) { + case 'u': + data->uid = optint; + break; + case 'g': + data->gid = optint; + break; + case 'o': + data->mounted_uid = optint; + break; + case 'm': + data->file_mode = optint; + break; + case 'd': + data->dir_mode = optint; + break; + case 't': + data->time_out = optint; + break; + case 'r': + data->retry_count = optint; + break; + case 'f': + data->flags = optint; + break; + case 'w': + data->wdog_pid = optint; + break; + case 'n': + data->ncp_fd = optint; + break; + case 'v': + if (optint < NCP_MOUNT_VERSION_V4) { + return -ECHRNG; + } + if (optint > NCP_MOUNT_VERSION_V4) { + return -ECHRNG; + } + version = optint; + break; + + } + } + return 0; +} + static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent) { struct ncp_mount_data_kernel data; @@ -347,7 +430,12 @@ static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent) break; default: error = -ECHRNG; - goto out; + if (*(__u32*)raw_data == cpu_to_be32(0x76657273)) { + error = ncp_parse_options(&data, raw_data); + } + if (error) + goto out; + break; } error = -EBADF; ncp_filp = fget(data.ncp_fd); diff --git a/include/linux/ncp_mount.h b/include/linux/ncp_mount.h index 4bdcfff1f79e..38880685f6f6 100644 --- a/include/linux/ncp_mount.h +++ b/include/linux/ncp_mount.h @@ -11,7 +11,7 @@ #include #include -#define NCP_MOUNT_VERSION 3 +#define NCP_MOUNT_VERSION 3 /* Binary */ /* Values for flags */ #define NCP_MOUNT_SOFT 0x0001 @@ -41,7 +41,7 @@ struct ncp_mount_data { __kernel_mode_t dir_mode; }; -#define NCP_MOUNT_VERSION_V4 (4) +#define NCP_MOUNT_VERSION_V4 (4) /* Binary or text */ struct ncp_mount_data_v4 { int version;