1 /* 2 * linux/fs/hfsplus/options.c 3 * 4 * Copyright (C) 2001 5 * Brad Boyer (flar@allandria.com) 6 * (C) 2003 Ardis Technologies <roman@ardistech.com> 7 * 8 * Option parsing 9 */ 10 11 #include <linux/string.h> 12 #include <linux/kernel.h> 13 #include <linux/sched.h> 14 #include <linux/parser.h> 15 #include <linux/nls.h> 16 #include "hfsplus_fs.h" 17 18 enum { 19 opt_creator, opt_type, 20 opt_umask, opt_uid, opt_gid, 21 opt_part, opt_session, opt_nls, 22 opt_nodecompose, opt_decompose, 23 opt_err 24 }; 25 26 static match_table_t tokens = { 27 { opt_creator, "creator=%s" }, 28 { opt_type, "type=%s" }, 29 { opt_umask, "umask=%o" }, 30 { opt_uid, "uid=%u" }, 31 { opt_gid, "gid=%u" }, 32 { opt_part, "part=%u" }, 33 { opt_session, "session=%u" }, 34 { opt_nls, "nls=%s" }, 35 { opt_decompose, "decompose" }, 36 { opt_nodecompose, "nodecompose" }, 37 { opt_err, NULL } 38 }; 39 40 /* Initialize an options object to reasonable defaults */ 41 void fill_defaults(struct hfsplus_sb_info *opts) 42 { 43 if (!opts) 44 return; 45 46 opts->creator = HFSPLUS_DEF_CR_TYPE; 47 opts->type = HFSPLUS_DEF_CR_TYPE; 48 opts->umask = current->fs->umask; 49 opts->uid = current->uid; 50 opts->gid = current->gid; 51 opts->part = -1; 52 opts->session = -1; 53 } 54 55 /* convert a "four byte character" to a 32 bit int with error checks */ 56 static inline int match_fourchar(substring_t *arg, u32 *result) 57 { 58 if (arg->to - arg->from != 4) 59 return -EINVAL; 60 memcpy(result, arg->from, 4); 61 return 0; 62 } 63 64 /* Parse options from mount. Returns 0 on failure */ 65 /* input is the options passed to mount() as a string */ 66 int parse_options(char *input, struct hfsplus_sb_info *sbi) 67 { 68 char *p; 69 substring_t args[MAX_OPT_ARGS]; 70 int tmp, token; 71 72 if (!input) 73 goto done; 74 75 while ((p = strsep(&input, ",")) != NULL) { 76 if (!*p) 77 continue; 78 79 token = match_token(p, tokens, args); 80 switch (token) { 81 case opt_creator: 82 if (match_fourchar(&args[0], &sbi->creator)) { 83 printk("HFS+-fs: creator requires a 4 character value\n"); 84 return 0; 85 } 86 break; 87 case opt_type: 88 if (match_fourchar(&args[0], &sbi->type)) { 89 printk("HFS+-fs: type requires a 4 character value\n"); 90 return 0; 91 } 92 break; 93 case opt_umask: 94 if (match_octal(&args[0], &tmp)) { 95 printk("HFS+-fs: umask requires a value\n"); 96 return 0; 97 } 98 sbi->umask = (umode_t)tmp; 99 break; 100 case opt_uid: 101 if (match_int(&args[0], &tmp)) { 102 printk("HFS+-fs: uid requires an argument\n"); 103 return 0; 104 } 105 sbi->uid = (uid_t)tmp; 106 break; 107 case opt_gid: 108 if (match_int(&args[0], &tmp)) { 109 printk("HFS+-fs: gid requires an argument\n"); 110 return 0; 111 } 112 sbi->gid = (gid_t)tmp; 113 break; 114 case opt_part: 115 if (match_int(&args[0], &sbi->part)) { 116 printk("HFS+-fs: part requires an argument\n"); 117 return 0; 118 } 119 break; 120 case opt_session: 121 if (match_int(&args[0], &sbi->session)) { 122 printk("HFS+-fs: session requires an argument\n"); 123 return 0; 124 } 125 break; 126 case opt_nls: 127 if (sbi->nls) { 128 printk("HFS+-fs: unable to change nls mapping\n"); 129 return 0; 130 } 131 p = match_strdup(&args[0]); 132 sbi->nls = load_nls(p); 133 if (!sbi->nls) { 134 printk("HFS+-fs: unable to load nls mapping \"%s\"\n", p); 135 kfree(p); 136 return 0; 137 } 138 kfree(p); 139 break; 140 case opt_decompose: 141 sbi->flags &= ~HFSPLUS_SB_NODECOMPOSE; 142 break; 143 case opt_nodecompose: 144 sbi->flags |= HFSPLUS_SB_NODECOMPOSE; 145 break; 146 default: 147 return 0; 148 } 149 } 150 151 done: 152 if (!sbi->nls) { 153 /* try utf8 first, as this is the old default behaviour */ 154 sbi->nls = load_nls("utf8"); 155 if (!sbi->nls) 156 sbi->nls = load_nls_default(); 157 if (!sbi->nls) 158 return 0; 159 } 160 161 return 1; 162 } 163