1 /* $NetBSD: refuse_opt.c,v 1.15 2011/03/01 11:23:42 soda Exp $ */
4 * Copyright (c) 2007 Juan Romero Pardines.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 * * -oblah,foo... works, but the options are not enabled.
31 * * -ofoo=%s (accepts a string) or -ofoo=%u (int) is not
33 * * void *data: how is it used? I think it's used to enable
34 * options or pass values for the matching options.
37 #include <sys/types.h>
48 #define DPRINTF(x) do { printf x; } while ( /* CONSTCOND */ 0)
59 struct fuse_opt_option {
60 const struct fuse_opt *fop;
66 static int fuse_opt_popt(struct fuse_opt_option *, const struct fuse_opt *);
67 static int fuse_opt_realloc_args(struct fuse_args *args, int nargc);
72 * The following functions always return 0:
74 * int fuse_opt_add_opt(char **, const char *);
76 * We implement the next ones:
78 * int fuse_opt_add_arg(struct fuse_args *, const char *);
79 * void fuse_opt_free_args(struct fuse_args *);
80 * int fuse_opt_insert_arg(struct fuse_args *, const char *);
81 * int fuse_opt_match(const struct fuse_opt *, const char *);
82 * int fuse_opt_parse(struct fuse_args *, void *,
83 * const struct fuse_opt *, fuse_opt_proc_t);
89 fuse_opt_add_arg(struct fuse_args *args, const char *arg)
92 fuse_opt_realloc_args(args, args->argc + 1);
93 DPRINTF(("%s: arguments passed: [arg:%s]\n", __func__, arg));
94 if ((args->argv[args->argc++] = strdup(arg)) == NULL)
95 err(1, "fuse_opt_add_arg");
96 args->argv[args->argc] = NULL;
101 fuse_opt_deep_copy_args(int argc, char **argv)
103 struct fuse_args *ap;
106 if ((ap = malloc(sizeof(*ap))) == NULL)
107 err(1, "_fuse_deep_copy_args");
108 /* deep copy args structure into channel args */
109 ap->allocated = ((argc / 10) + 1) * 10;
111 if ((ap->argv = calloc((size_t)ap->allocated,
112 sizeof(*ap->argv))) == NULL)
113 err(1, "_fuse_deep_copy_args");
115 for (i = 0; i < argc; i++) {
116 if ((ap->argv[i] = strdup(argv[i])) == NULL)
117 err(1, "_fuse_deep_copy_args");
119 ap->argv[ap->argc = i] = NULL;
124 fuse_opt_realloc_args(struct fuse_args *args, int nargc)
126 struct fuse_args *ap;
128 if (args->allocated == 0) {
129 ap = fuse_opt_deep_copy_args(args->argc, args->argv);
130 args->argv = ap->argv;
131 args->argc = ap->argc;
132 args->allocated = ap->allocated;
134 } else if (args->allocated < nargc) {
138 if ((a = realloc(args->argv, na * sizeof(*args->argv))) == NULL)
142 args->allocated = na;
149 fuse_opt_free_args(struct fuse_args *ap)
153 for (i = 0; i < ap->argc; i++) {
158 ap->allocated = ap->argc = 0;
163 fuse_opt_insert_arg(struct fuse_args *args, int pos, const char *arg)
167 DPRINTF(("%s: arguments passed: [pos=%d] [arg=%s]\n",
168 __func__, pos, arg));
169 fuse_opt_realloc_args(args, args->argc + 1);
171 for (i = args->argc++; i > pos; --i) {
172 args->argv[i] = args->argv[i - 1];
174 if ((args->argv[pos] = strdup(arg)) == NULL)
175 err(1, "fuse_opt_insert_arg");
176 args->argv[args->argc] = NULL;
181 int fuse_opt_add_opt(char **opts, const char *opt)
183 DPRINTF(("%s: arguments passed: [opts=%s] [opt=%s]\n",
184 __func__, *opts, opt));
189 * Returns 0 if opt was matched with any option from opts,
190 * otherwise returns 1.
193 fuse_opt_match(const struct fuse_opt *opts, const char *opt)
196 if (strcmp(opt, opts->templ) == 0)
204 * Returns 0 if foo->option was matched with any option from opts,
205 * and sets the following on match:
207 * * foo->key is set to the foo->fop->value if offset == -1.
208 * * foo->fop points to the matched struct opts.
210 * otherwise returns 1.
213 fuse_opt_popt(struct fuse_opt_option *foo, const struct fuse_opt *opts)
219 (void)fprintf(stderr, "fuse: missing argument after -o\n");
223 * iterate over argv and opts to see
224 * if there's a match with any template.
226 for (match = strtok(foo->option, ",");
227 match; match = strtok(NULL, ",")) {
229 DPRINTF(("%s: specified option='%s'\n", __func__, match));
232 for (i = 0; opts && opts->templ; opts++, i++) {
234 DPRINTF(("%s: opts->templ='%s' opts->offset=%d "
235 "opts->value=%d\n", __func__, opts->templ,
236 opts->offset, opts->value));
239 if (strcmp(match, opts->templ) == 0) {
240 DPRINTF(("%s: option matched='%s'\n",
244 * our fop pointer now points
245 * to the matched struct opts.
249 * assign default key value, necessary for
250 * KEY_HELP, KEY_VERSION and KEY_VERBOSE.
252 if (foo->fop->offset == -1)
253 foo->key = foo->fop->value;
261 (void)fprintf(stderr, "fuse: '%s' is not a "
262 "valid option\n", match);
272 fuse_opt_parse(struct fuse_args *args, void *data,
273 const struct fuse_opt *opts, fuse_opt_proc_t proc)
275 struct fuse_opt_option foo;
279 if (!args || !args->argv || !args->argc || !proc)
284 return proc(foo.data, *args->argv, FUSE_OPT_KEY_OPT, args);
286 /* the real loop to process the arguments */
287 for (i = 1; i < args->argc; i++) {
289 /* assign current argv string */
290 foo.option = buf = args->argv[i];
292 /* argvn != -foo... */
295 foo.key = FUSE_OPT_KEY_NONOPT;
296 rv = proc(foo.data, foo.option, foo.key, args);
300 /* -o was specified... */
301 } else if (buf[0] == '-' && buf[1] == 'o') {
306 foo.option = args->argv[i] + 2;
310 * skip current argv and pass to the
311 * next one to parse the options.
314 foo.option = args->argv[i];
317 rv = fuse_opt_popt(&foo, opts);
321 /* help/version/verbose argument */
322 } else if (buf[0] == '-' && buf[1] != 'o') {
324 * check if the argument matches
325 * with any template in opts.
327 rv = fuse_opt_popt(&foo, opts);
331 DPRINTF(("%s: foo.fop->templ='%s' "
332 "foo.fop->offset: %d "
333 "foo.fop->value: %d\n",
334 __func__, foo.fop->templ,
335 foo.fop->offset, foo.fop->value));
337 /* argument needs to be discarded */
338 if (foo.key == FUSE_OPT_KEY_DISCARD) {
343 /* process help/version argument */
344 if (foo.key != KEY_VERBOSE &&
345 foo.key != FUSE_OPT_KEY_KEEP) {
346 rv = proc(foo.data, foo.option,
350 /* process verbose argument */
351 rv = proc(foo.data, foo.option,
357 /* unknown option, how could that happen? */
359 DPRINTF(("%s: unknown option\n", __func__));