Annotation of src/lib/librefuse/refuse_opt.c, Revision 1.3
1.3 ! agc 1: /* $NetBSD: refuse_opt.c,v 1.2 2007/02/28 21:48:46 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"
43:
44: #ifdef FUSE_OPT_DEBUG
1.2 agc 45: #define DPRINTF(x) do { printf x; } while ( /* CONSTCOND */ 0)
1.1 xtraeme 46: #else
47: #define DPRINTF(x)
48: #endif
49:
50: enum {
51: KEY_HELP,
52: KEY_VERBOSE,
53: KEY_VERSION
54: };
55:
56: struct fuse_opt_option {
57: const struct fuse_opt *fop;
58: char *option;
59: int key;
60: void *data;
61: };
62:
63: static int fuse_opt_popt(struct fuse_opt_option *, const struct fuse_opt *);
64:
65: /*
66: * Public API.
67: *
68: * The following functions always return 0:
69: *
70: * int fuse_opt_add_arg(struct fuse_args *, const char *);
71: * int fuse_opt_add_opt(char **, const char *);
72: * void fuse_opt_free_args(struct fuse_args *);
73: * int fuse_opt_insert_arg(struct fuse_args *, const char *);
74: *
75: * We implement the next ones:
76: *
77: * int fuse_opt_match(const struct fuse_opt *, const char *);
78: * int fuse_opt_parse(struct fuse_args *, void *,
79: * const struct fuse_opt *, fuse_opt_proc_t);
80: *
81: */
82:
1.3 ! agc 83: #define ARGS_CHUNK 32
! 84:
! 85: static int
! 86: growargs(struct fuse_args *args, const char *func)
! 87: {
! 88: if (args->allocated == 0) {
! 89: NEWARRAY(char *, args->argv, ARGS_CHUNK,
! 90: func, return 0);
! 91: args->allocated = ARGS_CHUNK;
! 92: } else if (args->argc % ARGS_CHUNK == 0) {
! 93: args->allocated += ARGS_CHUNK;
! 94: RENEW(char *, args->argv, args->allocated,
! 95: func, return 0);
! 96: }
! 97: return 1;
! 98: }
! 99:
1.1 xtraeme 100: int
101: fuse_opt_add_arg(struct fuse_args *args, const char *arg)
102: {
103: DPRINTF(("%s: arguments passed: [arg:%s]\n", __func__, arg));
1.3 ! agc 104: if (!growargs(args, "fuse_opt_add_arg")) {
! 105: return 1;
! 106: }
! 107: args->argv[args->argc++] = strdup(arg);
! 108: return 0;
1.1 xtraeme 109: }
110:
111: void
112: fuse_opt_free_args(struct fuse_args *args)
113: {
1.3 ! agc 114: int i;
! 115:
! 116: for (i = 0 ; i < args->allocated ; i++) {
! 117: (void) free(args->argv[i]);
! 118: }
! 119: if (args->allocated > 0) {
! 120: FREE(args->argv);
! 121: }
! 122: (void) memset(args, 0x0, sizeof(*args));
1.1 xtraeme 123: }
124:
125: int
126: fuse_opt_insert_arg(struct fuse_args *args, int pos, const char *arg)
127: {
1.3 ! agc 128: int i;
! 129:
! 130: __fuse_pargs("fuse_opt_insert_arg1", args->argc, args->argv);
! 131: if (!growargs(args, "fuse_opt_insert_arg")) {
! 132: return 1;
! 133: }
! 134: for (i = args->argc++ ; i > pos ; --i) {
! 135: args->argv[i] = args->argv[i - 1];
! 136: }
! 137: args->argv[pos] = strdup(arg);
! 138: __fuse_pargs("fuse_opt_insert_arg2", args->argc, args->argv);
! 139: return 0;
1.1 xtraeme 140: }
141:
142: /* ARGSUSED */
143: int fuse_opt_add_opt(char **opts, const char *opt)
144: {
145: DPRINTF(("%s: arguments passed: [opts=%s] [opt=%s]\n",
146: __func__, *opts, opt));
1.3 ! agc 147: return 0;
1.1 xtraeme 148: }
149:
150: /*
151: * Returns 0 if opt was matched with any option from opts,
152: * otherwise returns 1.
153: */
154: int
155: fuse_opt_match(const struct fuse_opt *opts, const char *opt)
156: {
157: while (opts++) {
158: if (strcmp(opt, opts->templ) == 0)
1.3 ! agc 159: return 0;
1.1 xtraeme 160: }
161:
1.3 ! agc 162: return 1;
1.1 xtraeme 163: }
164:
165: /*
166: * Returns 0 if foo->option was matched with any option from opts,
167: * and sets the following on match:
168: *
169: * * foo->key is set to the foo->fop->value if offset == -1.
170: * * foo->fop points to the matched struct opts.
171: *
172: * otherwise returns 1.
173: */
174: static int
175: fuse_opt_popt(struct fuse_opt_option *foo, const struct fuse_opt *opts)
176: {
177: int i, found = 0;
178: char *match;
179:
180: if (!foo->option) {
181: (void)fprintf(stderr, "fuse: missing argument after -o\n");
1.3 ! agc 182: return 1;
1.1 xtraeme 183: }
184: /*
185: * iterate over argv and opts to see
186: * if there's a match with any template.
187: */
188: for (match = strtok(foo->option, ",");
189: match; match = strtok(NULL, ",")) {
190:
191: DPRINTF(("%s: specified option='%s'\n", __func__, match));
192: found = 0;
193:
194: for (i = 0; opts && opts->templ; opts++, i++) {
195:
196: DPRINTF(("%s: opts->templ='%s' opts->offset=%d "
197: "opts->value=%d\n", __func__, opts->templ,
198: opts->offset, opts->value));
199:
200: /* option is ok */
201: if (strcmp(match, opts->templ) == 0) {
202: DPRINTF(("%s: option matched='%s'\n",
203: __func__, match));
204: found++;
205: /*
206: * our fop pointer now points
207: * to the matched struct opts.
208: */
209: foo->fop = opts;
210: /*
211: * assign default key value, necessary for
212: * KEY_HELP, KEY_VERSION and KEY_VERBOSE.
213: */
214: if (foo->fop->offset == -1)
215: foo->key = foo->fop->value;
216: /* reset counter */
217: opts -= i;
218: break;
219: }
220: }
221: /* invalid option */
222: if (!found) {
223: (void)fprintf(stderr, "fuse: '%s' is not a "
224: "valid option\n", match);
1.3 ! agc 225: return 1;
1.1 xtraeme 226: }
227: }
228:
1.3 ! agc 229: return 0;
1.1 xtraeme 230: }
231:
1.2 agc 232: /* ARGSUSED1 */
1.1 xtraeme 233: int
234: fuse_opt_parse(struct fuse_args *args, void *data,
235: const struct fuse_opt *opts, fuse_opt_proc_t proc)
236: {
237: struct fuse_opt_option foo;
238: char *buf;
1.3 ! agc 239: int i, rv = 0;
1.1 xtraeme 240:
1.3 ! agc 241: if (!args || !args->argv || !args->argc || !proc) {
! 242: if (__fuse_debug(0)) {
! 243: printf("fuse_opt_parse: null args\n");
! 244: }
1.1 xtraeme 245: return 0;
1.3 ! agc 246: }
! 247:
! 248: if (__fuse_debug(0)) {
! 249: __fuse_pargs("fuse_opt_parse", args->argc, args->argv);
! 250: }
1.1 xtraeme 251:
252: if (args->argc == 1)
253: return proc(foo.data, *args->argv, FUSE_OPT_KEY_OPT, args);
254:
255: /* the real loop to process the arguments */
256: for (i = 1; i < args->argc; i++) {
257:
258: /* assign current argv string */
259: foo.option = buf = args->argv[i];
260:
261: /* argvn != -foo... */
262: if (buf[0] != '-') {
263:
264: foo.key = FUSE_OPT_KEY_NONOPT;
1.2 agc 265: rv = proc(foo.data, foo.option, foo.key, args);
266: if (rv != 0)
1.1 xtraeme 267: break;
268:
269: /* -o was specified... */
270: } else if (buf[0] == '-' && buf[1] == 'o') {
271:
272: /* -oblah,foo... */
273: if (buf[2]) {
274: /* skip -o */
275: foo.option = args->argv[i] + 2;
276: /* -o blah,foo... */
277: } else {
278: /*
279: * skip current argv and pass to the
280: * next one to parse the options.
281: */
282: ++i;
283: foo.option = args->argv[i];
284: }
285:
1.2 agc 286: rv = fuse_opt_popt(&foo, opts);
287: if (rv != 0)
1.1 xtraeme 288: break;
289:
290: /* help/version/verbose argument */
291: } else if (buf[0] == '-' && buf[1] != 'o') {
292: /*
293: * check if the argument matches
294: * with any template in opts.
295: */
1.2 agc 296: rv = fuse_opt_popt(&foo, opts);
297: if (rv != 0) {
1.1 xtraeme 298: break;
299: } else {
300: DPRINTF(("%s: foo.fop->templ='%s' "
301: "foo.fop->offset: %d "
302: "foo.fop->value: %d\n",
303: __func__, foo.fop->templ,
304: foo.fop->offset, foo.fop->value));
305:
306: /* argument needs to be discarded */
307: if (foo.key == FUSE_OPT_KEY_DISCARD) {
1.3 ! agc 308: rv = 1;
1.1 xtraeme 309: break;
310: }
311:
312: /* process help/version argument */
313: if (foo.key != KEY_VERBOSE &&
314: foo.key != FUSE_OPT_KEY_KEEP) {
315: rv = proc(foo.data, foo.option,
316: foo.key, args);
317: break;
318: } else {
319: /* process verbose argument */
1.2 agc 320: rv = proc(foo.data, foo.option,
321: foo.key, args);
322: if (rv != 0)
1.1 xtraeme 323: break;
324: }
325: }
326: /* unknown option, how could that happen? */
327: } else {
328: DPRINTF(("%s: unknown option\n", __func__));
1.3 ! agc 329: rv = 1;
1.1 xtraeme 330: break;
331: }
332: }
333:
334: return rv;
335: }
CVSweb <webmaster@jp.NetBSD.org>