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
--- /dev/null
+/*
+ * getopt.c
+ */
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+
+#include <asm/errno.h>
+
+#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;
+}
--- /dev/null
+#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 */
#include <linux/ncp_fs.h>
#include "ncplib_kernel.h"
+#include "getopt.h"
static void ncp_delete_inode(struct inode *);
static void ncp_put_super(struct super_block *);
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;
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);
#include <linux/types.h>
#include <linux/ncp.h>
-#define NCP_MOUNT_VERSION 3
+#define NCP_MOUNT_VERSION 3 /* Binary */
/* Values for flags */
#define NCP_MOUNT_SOFT 0x0001
__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;