Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
options.c
Go to the documentation of this file.
1 /*
2  * linux/fs/hfsplus/options.c
3  *
4  * Copyright (C) 2001
5  * Brad Boyer ([email protected])
6  * (C) 2003 Ardis Technologies <[email protected]>
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 <linux/mount.h>
17 #include <linux/seq_file.h>
18 #include <linux/slab.h>
19 #include "hfsplus_fs.h"
20 
21 enum {
28 };
29 
30 static const match_table_t tokens = {
31  { opt_creator, "creator=%s" },
32  { opt_type, "type=%s" },
33  { opt_umask, "umask=%o" },
34  { opt_uid, "uid=%u" },
35  { opt_gid, "gid=%u" },
36  { opt_part, "part=%u" },
37  { opt_session, "session=%u" },
38  { opt_nls, "nls=%s" },
39  { opt_decompose, "decompose" },
40  { opt_nodecompose, "nodecompose" },
41  { opt_barrier, "barrier" },
42  { opt_nobarrier, "nobarrier" },
43  { opt_force, "force" },
44  { opt_err, NULL }
45 };
46 
47 /* Initialize an options object to reasonable defaults */
49 {
50  if (!opts)
51  return;
52 
54  opts->type = HFSPLUS_DEF_CR_TYPE;
55  opts->umask = current_umask();
56  opts->uid = current_uid();
57  opts->gid = current_gid();
58  opts->part = -1;
59  opts->session = -1;
60 }
61 
62 /* convert a "four byte character" to a 32 bit int with error checks */
63 static inline int match_fourchar(substring_t *arg, u32 *result)
64 {
65  if (arg->to - arg->from != 4)
66  return -EINVAL;
67  memcpy(result, arg->from, 4);
68  return 0;
69 }
70 
72 {
73  char *p;
75  int token;
76 
77  if (!input)
78  return 0;
79 
80  while ((p = strsep(&input, ",")) != NULL) {
81  if (!*p)
82  continue;
83 
84  token = match_token(p, tokens, args);
85  switch (token) {
86  case opt_force:
87  *force = 1;
88  break;
89  default:
90  break;
91  }
92  }
93 
94  return 1;
95 }
96 
97 /* Parse options from mount. Returns 0 on failure */
98 /* input is the options passed to mount() as a string */
100 {
101  char *p;
103  int tmp, token;
104 
105  if (!input)
106  goto done;
107 
108  while ((p = strsep(&input, ",")) != NULL) {
109  if (!*p)
110  continue;
111 
112  token = match_token(p, tokens, args);
113  switch (token) {
114  case opt_creator:
115  if (match_fourchar(&args[0], &sbi->creator)) {
116  printk(KERN_ERR "hfs: creator requires a 4 character value\n");
117  return 0;
118  }
119  break;
120  case opt_type:
121  if (match_fourchar(&args[0], &sbi->type)) {
122  printk(KERN_ERR "hfs: type requires a 4 character value\n");
123  return 0;
124  }
125  break;
126  case opt_umask:
127  if (match_octal(&args[0], &tmp)) {
128  printk(KERN_ERR "hfs: umask requires a value\n");
129  return 0;
130  }
131  sbi->umask = (umode_t)tmp;
132  break;
133  case opt_uid:
134  if (match_int(&args[0], &tmp)) {
135  printk(KERN_ERR "hfs: uid requires an argument\n");
136  return 0;
137  }
138  sbi->uid = make_kuid(current_user_ns(), (uid_t)tmp);
139  if (!uid_valid(sbi->uid)) {
140  printk(KERN_ERR "hfs: invalid uid specified\n");
141  return 0;
142  }
143  break;
144  case opt_gid:
145  if (match_int(&args[0], &tmp)) {
146  printk(KERN_ERR "hfs: gid requires an argument\n");
147  return 0;
148  }
149  sbi->gid = make_kgid(current_user_ns(), (gid_t)tmp);
150  if (!gid_valid(sbi->gid)) {
151  printk(KERN_ERR "hfs: invalid gid specified\n");
152  return 0;
153  }
154  break;
155  case opt_part:
156  if (match_int(&args[0], &sbi->part)) {
157  printk(KERN_ERR "hfs: part requires an argument\n");
158  return 0;
159  }
160  break;
161  case opt_session:
162  if (match_int(&args[0], &sbi->session)) {
163  printk(KERN_ERR "hfs: session requires an argument\n");
164  return 0;
165  }
166  break;
167  case opt_nls:
168  if (sbi->nls) {
169  printk(KERN_ERR "hfs: unable to change nls mapping\n");
170  return 0;
171  }
172  p = match_strdup(&args[0]);
173  if (p)
174  sbi->nls = load_nls(p);
175  if (!sbi->nls) {
176  printk(KERN_ERR "hfs: unable to load "
177  "nls mapping \"%s\"\n",
178  p);
179  kfree(p);
180  return 0;
181  }
182  kfree(p);
183  break;
184  case opt_decompose:
186  break;
187  case opt_nodecompose:
189  break;
190  case opt_barrier:
192  break;
193  case opt_nobarrier:
195  break;
196  case opt_force:
198  break;
199  default:
200  return 0;
201  }
202  }
203 
204 done:
205  if (!sbi->nls) {
206  /* try utf8 first, as this is the old default behaviour */
207  sbi->nls = load_nls("utf8");
208  if (!sbi->nls)
209  sbi->nls = load_nls_default();
210  if (!sbi->nls)
211  return 0;
212  }
213 
214  return 1;
215 }
216 
217 int hfsplus_show_options(struct seq_file *seq, struct dentry *root)
218 {
219  struct hfsplus_sb_info *sbi = HFSPLUS_SB(root->d_sb);
220 
221  if (sbi->creator != HFSPLUS_DEF_CR_TYPE)
222  seq_printf(seq, ",creator=%.4s", (char *)&sbi->creator);
223  if (sbi->type != HFSPLUS_DEF_CR_TYPE)
224  seq_printf(seq, ",type=%.4s", (char *)&sbi->type);
225  seq_printf(seq, ",umask=%o,uid=%u,gid=%u", sbi->umask,
228  if (sbi->part >= 0)
229  seq_printf(seq, ",part=%u", sbi->part);
230  if (sbi->session >= 0)
231  seq_printf(seq, ",session=%u", sbi->session);
232  if (sbi->nls)
233  seq_printf(seq, ",nls=%s", sbi->nls->charset);
235  seq_printf(seq, ",nodecompose");
236  if (test_bit(HFSPLUS_SB_NOBARRIER, &sbi->flags))
237  seq_printf(seq, ",nobarrier");
238  return 0;
239 }