Annotation of src/lib/librefuse/refuse_opt.c, Revision 1.10
1.10 ! christos 1: /* $NetBSD: refuse_opt.c,v 1.9 2007/04/17 06:34:48 agc Exp $ */
1.1 xtraeme 2:
3: /*-
4: * Copyright (c) 2007 Juan Romero Pardines.
5: * All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
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.
15: * 3. The name of the company nor the name of the author may be used to
16: * endorse or promote products derived from this software without
17: * specific prior written permission.
18: *
19: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29: */
30:
31: /*
32: * TODO:
33: * * -oblah,foo... works, but the options are not enabled.
34: * * -ofoo=%s (accepts a string) or -ofoo=%u (int) is not
35: * supported for now.
36: * * void *data: how is it used? I think it's used to enable
37: * options or pass values for the matching options.
38: */
39:
40: #include "defs.h"
41: #include "fuse.h"
42: #include "fuse_opt.h"
1.10 ! christos 43: #include <err.h>
1.1 xtraeme 44:
45: #ifdef FUSE_OPT_DEBUG
1.2 agc 46: #define DPRINTF(x) do { printf x; } while ( /* CONSTCOND */ 0)
1.1 xtraeme 47: #else
48: #define DPRINTF(x)
49: #endif
50:
51: enum {
52: KEY_HELP,
53: KEY_VERBOSE,
54: KEY_VERSION
55: };
56:
57: struct fuse_opt_option {
58: const struct fuse_opt *fop;
59: char *option;
60: int key;
61: void *data;
62: };
63:
64: static int fuse_opt_popt(struct fuse_opt_option *, const struct fuse_opt *);
65:
66: /*
67: * Public API.
68: *
69: * The following functions always return 0:
70: *
1.7 xtraeme 71: * int fuse_opt_add_opt(char **, const char *);
72: *
73: * We implement the next ones:
74: *
1.1 xtraeme 75: * int fuse_opt_add_arg(struct fuse_args *, const char *);
76: * void fuse_opt_free_args(struct fuse_args *);
77: * int fuse_opt_insert_arg(struct fuse_args *, const char *);
78: * int fuse_opt_match(const struct fuse_opt *, const char *);
79: * int fuse_opt_parse(struct fuse_args *, void *,
80: * const struct fuse_opt *, fuse_opt_proc_t);
81: *
82: */
83:
1.4 agc 84: /* ARGSUSED */
1.1 xtraeme 85: int
86: fuse_opt_add_arg(struct fuse_args *args, const char *arg)
87: {
1.5 agc 88: struct fuse_args *ap;
89:
90: if (args->allocated == 0) {
1.10 ! christos 91: ap = _fuse_deep_copy_args(args->argc, args->argv);
1.5 agc 92: args->argv = ap->argv;
93: args->argc = ap->argc;
94: args->allocated = ap->allocated;
95: (void) free(ap);
96: } else if (args->allocated == args->argc) {
1.10 ! christos 97: void *a;
! 98: int na = args->allocated + 10;
! 99:
! 100: if ((a = realloc(args->argv, na * sizeof(*args->argv))) == NULL)
! 101: return -1;
! 102:
! 103: args->argv = a;
! 104: args->allocated = na;
1.5 agc 105: }
1.1 xtraeme 106: DPRINTF(("%s: arguments passed: [arg:%s]\n", __func__, arg));
1.10 ! christos 107: if ((args->argv[args->argc++] = strdup(arg)) == NULL)
! 108: err(1, "fuse_opt_add_arg");
1.5 agc 109: return 0;
1.1 xtraeme 110: }
111:
1.4 agc 112: /* ARGSUSED */
1.1 xtraeme 113: void
114: fuse_opt_free_args(struct fuse_args *args)
115: {
1.10 ! christos 116: _fuse_free_args(args);
1.5 agc 117: args->allocated = args->argc = 0;
1.1 xtraeme 118: }
119:
1.4 agc 120: /* ARGSUSED */
1.1 xtraeme 121: int
122: fuse_opt_insert_arg(struct fuse_args *args, int pos, const char *arg)
123: {
1.5 agc 124: int i;
1.10 ! christos 125: int na;
! 126: void *a;
1.5 agc 127:
1.4 agc 128: DPRINTF(("%s: arguments passed: [pos=%d] [arg=%s]\n",
129: __func__, pos, arg));
1.10 ! christos 130: if (args->argv == NULL) {
! 131: na = 10;
! 132: a = malloc(na * sizeof(*args->argv));
! 133: } else {
! 134: na = args->allocated + 10;
! 135: a = realloc(args->argv, na * sizeof(*args->argv));
! 136: }
! 137: if (a == NULL) {
! 138: warn("fuse_opt_insert_arg");
! 139: return -1;
! 140: }
! 141: args->argv = a;
! 142: args->allocated = na;
! 143:
! 144: for (i = args->argc++; i > pos; --i) {
1.5 agc 145: args->argv[i] = args->argv[i - 1];
146: }
1.10 ! christos 147: if ((args->argv[pos] = strdup(arg)) == NULL)
! 148: err(1, "fuse_opt_insert_arg");
1.5 agc 149: return 0;
1.1 xtraeme 150: }
151:
152: /* ARGSUSED */
153: int fuse_opt_add_opt(char **opts, const char *opt)
154: {
155: DPRINTF(("%s: arguments passed: [opts=%s] [opt=%s]\n",
156: __func__, *opts, opt));
1.5 agc 157: return 0;
1.1 xtraeme 158: }
159:
160: /*
161: * Returns 0 if opt was matched with any option from opts,
162: * otherwise returns 1.
163: */
164: int
165: fuse_opt_match(const struct fuse_opt *opts, const char *opt)
166: {
167: while (opts++) {
168: if (strcmp(opt, opts->templ) == 0)
1.5 agc 169: return 0;
1.1 xtraeme 170: }
171:
1.5 agc 172: return 1;
1.1 xtraeme 173: }
174:
175: /*
176: * Returns 0 if foo->option was matched with any option from opts,
177: * and sets the following on match:
178: *
179: * * foo->key is set to the foo->fop->value if offset == -1.
180: * * foo->fop points to the matched struct opts.
181: *
182: * otherwise returns 1.
183: */
184: static int
185: fuse_opt_popt(struct fuse_opt_option *foo, const struct fuse_opt *opts)
186: {
187: int i, found = 0;
188: char *match;
189:
190: if (!foo->option) {
191: (void)fprintf(stderr, "fuse: missing argument after -o\n");
1.5 agc 192: return 1;
1.1 xtraeme 193: }
194: /*
195: * iterate over argv and opts to see
196: * if there's a match with any template.
197: */
198: for (match = strtok(foo->option, ",");
199: match; match = strtok(NULL, ",")) {
200:
201: DPRINTF(("%s: specified option='%s'\n", __func__, match));
202: found = 0;
203:
204: for (i = 0; opts && opts->templ; opts++, i++) {
205:
206: DPRINTF(("%s: opts->templ='%s' opts->offset=%d "
207: "opts->value=%d\n", __func__, opts->templ,
208: opts->offset, opts->value));
209:
210: /* option is ok */
211: if (strcmp(match, opts->templ) == 0) {
212: DPRINTF(("%s: option matched='%s'\n",
213: __func__, match));
214: found++;
215: /*
216: * our fop pointer now points
217: * to the matched struct opts.
218: */
219: foo->fop = opts;
220: /*
221: * assign default key value, necessary for
222: * KEY_HELP, KEY_VERSION and KEY_VERBOSE.
223: */
224: if (foo->fop->offset == -1)
225: foo->key = foo->fop->value;
226: /* reset counter */
227: opts -= i;
228: break;
229: }
230: }
231: /* invalid option */
232: if (!found) {
233: (void)fprintf(stderr, "fuse: '%s' is not a "
234: "valid option\n", match);
1.5 agc 235: return 1;
1.1 xtraeme 236: }
237: }
238:
1.5 agc 239: return 0;
1.1 xtraeme 240: }
241:
1.2 agc 242: /* ARGSUSED1 */
1.1 xtraeme 243: int
244: fuse_opt_parse(struct fuse_args *args, void *data,
245: const struct fuse_opt *opts, fuse_opt_proc_t proc)
246: {
247: struct fuse_opt_option foo;
248: char *buf;
1.5 agc 249: int i, rv = 0;
1.1 xtraeme 250:
1.4 agc 251: if (!args || !args->argv || !args->argc || !proc)
1.1 xtraeme 252: return 0;
253:
254: if (args->argc == 1)
255: return proc(foo.data, *args->argv, FUSE_OPT_KEY_OPT, args);
256:
257: /* the real loop to process the arguments */
258: for (i = 1; i < args->argc; i++) {
259:
260: /* assign current argv string */
261: foo.option = buf = args->argv[i];
262:
263: /* argvn != -foo... */
264: if (buf[0] != '-') {
265:
266: foo.key = FUSE_OPT_KEY_NONOPT;
1.2 agc 267: rv = proc(foo.data, foo.option, foo.key, args);
268: if (rv != 0)
1.1 xtraeme 269: break;
270:
271: /* -o was specified... */
272: } else if (buf[0] == '-' && buf[1] == 'o') {
273:
274: /* -oblah,foo... */
275: if (buf[2]) {
276: /* skip -o */
277: foo.option = args->argv[i] + 2;
278: /* -o blah,foo... */
279: } else {
280: /*
281: * skip current argv and pass to the
282: * next one to parse the options.
283: */
284: ++i;
285: foo.option = args->argv[i];
286: }
287:
1.2 agc 288: rv = fuse_opt_popt(&foo, opts);
289: if (rv != 0)
1.1 xtraeme 290: break;
291:
292: /* help/version/verbose argument */
293: } else if (buf[0] == '-' && buf[1] != 'o') {
294: /*
295: * check if the argument matches
296: * with any template in opts.
297: */
1.2 agc 298: rv = fuse_opt_popt(&foo, opts);
299: if (rv != 0) {
1.1 xtraeme 300: break;
301: } else {
302: DPRINTF(("%s: foo.fop->templ='%s' "
303: "foo.fop->offset: %d "
304: "foo.fop->value: %d\n",
305: __func__, foo.fop->templ,
306: foo.fop->offset, foo.fop->value));
307:
308: /* argument needs to be discarded */
309: if (foo.key == FUSE_OPT_KEY_DISCARD) {
1.5 agc 310: rv = 1;
1.1 xtraeme 311: break;
312: }
313:
314: /* process help/version argument */
315: if (foo.key != KEY_VERBOSE &&
316: foo.key != FUSE_OPT_KEY_KEEP) {
317: rv = proc(foo.data, foo.option,
318: foo.key, args);
319: break;
320: } else {
321: /* process verbose argument */
1.2 agc 322: rv = proc(foo.data, foo.option,
323: foo.key, args);
324: if (rv != 0)
1.1 xtraeme 325: break;
326: }
327: }
328: /* unknown option, how could that happen? */
329: } else {
330: DPRINTF(("%s: unknown option\n", __func__));
1.5 agc 331: rv = 1;
1.1 xtraeme 332: break;
333: }
334: }
335:
336: return rv;
337: }
CVSweb <webmaster@jp.NetBSD.org>