From: Roman Zippel Make use of parser library to parse mount options. Signed-off-by: Roman Zippel Signed-off-by: Andrew Morton --- 25-akpm/fs/hfs/super.c | 166 ++++++++++++++++++++++++++----------------- 25-akpm/fs/hfsplus/options.c | 114 ++++++++++++++--------------- 2 files changed, 158 insertions(+), 122 deletions(-) diff -puN fs/hfsplus/options.c~hfs-use-parse-library-for-mount-options fs/hfsplus/options.c --- 25/fs/hfsplus/options.c~hfs-use-parse-library-for-mount-options 2005-03-18 23:43:03.000000000 -0800 +++ 25-akpm/fs/hfsplus/options.c 2005-03-18 23:43:03.000000000 -0800 @@ -11,8 +11,27 @@ #include #include #include +#include #include "hfsplus_fs.h" +enum { + opt_creator, opt_type, + opt_umask, opt_uid, opt_gid, + opt_part, opt_session, + opt_err +}; + +static match_table_t tokens = { + { opt_creator, "creator=%s" }, + { opt_type, "type=%s" }, + { opt_umask, "umask=%o" }, + { opt_uid, "uid=%u" }, + { opt_gid, "gid=%u" }, + { opt_part, "part=%u" }, + { opt_session, "session=%u" }, + { opt_err, NULL } +}; + /* Initialize an options object to reasonable defaults */ void fill_defaults(struct hfsplus_sb_info *opts) { @@ -29,96 +48,77 @@ void fill_defaults(struct hfsplus_sb_inf } /* convert a "four byte character" to a 32 bit int with error checks */ -static int fill_fourchar(u32 *result, char *input) +static inline int match_fourchar(substring_t *arg, u32 *result) { - u32 out; - int i; - - if (!result || !input || !*input || (strlen(input) != 4)) - return 0; - - for (out = 0, i = 0; i < 4; i++) { - out <<= 8; - out |= ((int)(input[i])) & 0xFF; - } - *result = out; - return 1; -} - -/* convert a string to int with error checks */ -static int fill_int(int *result, char *input, int base) -{ - char *tmp = input; - int intval; - - if (!result || !input || !*input) - return 0; - - intval = simple_strtoul(tmp, &tmp, base); - if (*tmp) - return 0; - - *result = intval; - return 1; + if (arg->to - arg->from != 4) + return -EINVAL; + memcpy(result, arg->from, 4); + return 0; } /* Parse options from mount. Returns 0 on failure */ /* input is the options passed to mount() as a string */ -int parse_options(char *input, struct hfsplus_sb_info *results) +int parse_options(char *input, struct hfsplus_sb_info *sbi) { - char *curropt, *value; - int tmp; + char *p; + substring_t args[MAX_OPT_ARGS]; + int tmp, token; if (!input) return 1; - while ((curropt = strsep(&input,",")) != NULL) { - if (!*curropt) + while ((p = strsep(&input, ",")) != NULL) { + if (!*p) continue; - if ((value = strchr(curropt, '=')) != NULL) - *value++ = '\0'; - - if (!strcmp(curropt, "creator")) { - if (!fill_fourchar(&(results->creator), value)) { + token = match_token(p, tokens, args); + switch (token) { + case opt_creator: + if (match_fourchar(&args[0], &sbi->creator)) { printk("HFS+-fs: creator requires a 4 character value\n"); return 0; } - } else if (!strcmp(curropt, "type")) { - if (!fill_fourchar(&(results->type), value)) { + break; + case opt_type: + if (match_fourchar(&args[0], &sbi->type)) { printk("HFS+-fs: type requires a 4 character value\n"); return 0; } - } else if (!strcmp(curropt, "umask")) { - if (!fill_int(&tmp, value, 8)) { + break; + case opt_umask: + if (match_octal(&args[0], &tmp)) { printk("HFS+-fs: umask requires a value\n"); return 0; } - results->umask = (umode_t)tmp; - } else if (!strcmp(curropt, "uid")) { - if (!fill_int(&tmp, value, 0)) { + sbi->umask = (umode_t)tmp; + break; + case opt_uid: + if (match_int(&args[0], &tmp)) { printk("HFS+-fs: uid requires an argument\n"); return 0; } - results->uid = (uid_t)tmp; - } else if (!strcmp(curropt, "gid")) { - if (!fill_int(&tmp, value, 0)) { + sbi->uid = (uid_t)tmp; + break; + case opt_gid: + if (match_int(&args[0], &tmp)) { printk("HFS+-fs: gid requires an argument\n"); return 0; } - results->gid = (gid_t)tmp; - } else if (!strcmp(curropt, "part")) { - if (!fill_int(&results->part, value, 0)) { + sbi->gid = (gid_t)tmp; + break; + case opt_part: + if (match_int(&args[0], &sbi->part)) { printk("HFS+-fs: part requires an argument\n"); return 0; } - } else if (!strcmp(curropt, "session")) { - if (!fill_int(&results->session, value, 0)) { + break; + case opt_session: + if (match_int(&args[0], &sbi->session)) { printk("HFS+-fs: session requires an argument\n"); return 0; } - } else { - printk("HFS+-fs: unknown option %s\n", curropt); + break; + default: return 0; } } diff -puN fs/hfs/super.c~hfs-use-parse-library-for-mount-options fs/hfs/super.c --- 25/fs/hfs/super.c~hfs-use-parse-library-for-mount-options 2005-03-18 23:43:03.000000000 -0800 +++ 25-akpm/fs/hfs/super.c 2005-03-18 23:43:03.000000000 -0800 @@ -16,6 +16,7 @@ #include #include #include +#include #include #include "hfs_fs.h" @@ -134,6 +135,34 @@ static struct super_operations hfs_super .remount_fs = hfs_remount, }; +enum { + opt_uid, opt_gid, opt_umask, opt_file_umask, opt_dir_umask, + opt_part, opt_session, opt_type, opt_creator, opt_quiet, + opt_err +}; + +static match_table_t tokens = { + { opt_uid, "uid=%u" }, + { opt_gid, "gid=%u" }, + { opt_umask, "umask=%o" }, + { opt_file_umask, "file_umask=%o" }, + { opt_dir_umask, "dir_umask=%o" }, + { opt_part, "part=%u" }, + { opt_session, "session=%u" }, + { opt_type, "type=%s" }, + { opt_creator, "creator=%s" }, + { opt_quiet, "quiet" }, + { opt_err, NULL } +}; + +static inline int match_fourchar(substring_t *arg, u32 *result) +{ + if (arg->to - arg->from != 4) + return -EINVAL; + memcpy(result, arg->from, 4); + return 0; +} + /* * parse_options() * @@ -142,7 +171,9 @@ static struct super_operations hfs_super */ static int parse_options(char *options, struct hfs_sb_info *hsb) { - char *this_char, *value; + char *p; + substring_t args[MAX_OPT_ARGS]; + int tmp, token; /* initialize the sb with defaults */ hsb->s_uid = current->uid; @@ -157,73 +188,78 @@ static int parse_options(char *options, if (!options) return 1; - while ((this_char = strsep(&options, ",")) != 0) { - if (!*this_char) + while ((p = strsep(&options, ",")) != NULL) { + if (!*p) continue; - value = strchr(this_char, '='); - if (value) - *value++ = 0; - - /* Numeric-valued options */ - if (!strcmp(this_char, "uid")) { - if (!value || !*value) - return 0; - hsb->s_uid = simple_strtoul(value, &value, 0); - if (*value) - return 0; - } else if (!strcmp(this_char, "gid")) { - if (!value || !*value) - return 0; - hsb->s_gid = simple_strtoul(value, &value, 0); - if (*value) - return 0; - } else if (!strcmp(this_char, "umask")) { - if (!value || !*value) - return 0; - hsb->s_file_umask = simple_strtoul(value, &value, 8); - hsb->s_dir_umask = hsb->s_file_umask; - if (*value) - return 0; - } else if (!strcmp(this_char, "file_umask")) { - if (!value || !*value) - return 0; - hsb->s_file_umask = simple_strtoul(value, &value, 8); - if (*value) - return 0; - } else if (!strcmp(this_char, "dir_umask")) { - if (!value || !*value) - return 0; - hsb->s_dir_umask = simple_strtoul(value, &value, 8); - if (*value) - return 0; - } else if (!strcmp(this_char, "part")) { - if (!value || !*value) - return 0; - hsb->part = simple_strtoul(value, &value, 0); - if (*value) - return 0; - } else if (!strcmp(this_char, "session")) { - if (!value || !*value) - return 0; - hsb->session = simple_strtoul(value, &value, 0); - if (*value) - return 0; - /* String-valued options */ - } else if (!strcmp(this_char, "type") && value) { - if (strlen(value) != 4) - return 0; - memcpy(&hsb->s_type, value, 4); - } else if (!strcmp(this_char, "creator") && value) { - if (strlen(value) != 4) - return 0; - memcpy(&hsb->s_creator, value, 4); - /* Boolean-valued options */ - } else if (!strcmp(this_char, "quiet")) { - if (value) - return 0; + + token = match_token(p, tokens, args); + switch (token) { + case opt_uid: + if (match_int(&args[0], &tmp)) { + printk("HFS: uid requires an argument\n"); + return 0; + } + hsb->s_uid = (uid_t)tmp; + break; + case opt_gid: + if (match_int(&args[0], &tmp)) { + printk("HFS: gid requires an argument\n"); + return 0; + } + hsb->s_gid = (gid_t)tmp; + break; + case opt_umask: + if (match_octal(&args[0], &tmp)) { + printk("HFS: umask requires a value\n"); + return 0; + } + hsb->s_file_umask = (umode_t)tmp; + hsb->s_dir_umask = (umode_t)tmp; + break; + case opt_file_umask: + if (match_octal(&args[0], &tmp)) { + printk("HFS: file_umask requires a value\n"); + return 0; + } + hsb->s_file_umask = (umode_t)tmp; + break; + case opt_dir_umask: + if (match_octal(&args[0], &tmp)) { + printk("HFS: dir_umask requires a value\n"); + return 0; + } + hsb->s_dir_umask = (umode_t)tmp; + break; + case opt_part: + if (match_int(&args[0], &hsb->part)) { + printk("HFS: part requires an argument\n"); + return 0; + } + break; + case opt_session: + if (match_int(&args[0], &hsb->session)) { + printk("HFS: session requires an argument\n"); + return 0; + } + break; + case opt_type: + if (match_fourchar(&args[0], &hsb->s_type)) { + printk("HFS+-fs: type requires a 4 character value\n"); + return 0; + } + break; + case opt_creator: + if (match_fourchar(&args[0], &hsb->s_creator)) { + printk("HFS+-fs: creator requires a 4 character value\n"); + return 0; + } + break; + case opt_quiet: hsb->s_quiet = 1; - } else + break; + default: return 0; + } } hsb->s_dir_umask &= 0777; _