Commit 8612e088 authored by Petr Vandrovec's avatar Petr Vandrovec

Add support for text mount option string to ncpfs.

parent 36093059
......@@ -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
......
/*
* 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;
}
#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 */
......@@ -32,6 +32,7 @@
#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 *);
......@@ -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);
......
......@@ -11,7 +11,7 @@
#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
......@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment