1/*
2  FUSE: Filesystem in Userspace
3  Copyright (C) 2001-2007  Miklos Szeredi <miklos@szeredi.hu>
4
5  This program can be distributed under the terms of the GNU LGPLv2.
6  See the file COPYING.LIB
7*/
8
9#include "fuse_config.h"
10
11#include <string.h>
12
13enum {
14	KEY_KERN_FLAG,
15	KEY_KERN_OPT,
16	KEY_FUSERMOUNT_OPT,
17	KEY_SUBTYPE_OPT,
18	KEY_MTAB_OPT,
19	KEY_ALLOW_ROOT,
20	KEY_RO,
21	KEY_HELP,
22	KEY_VERSION,
23};
24
25struct mount_opts {
26	int allow_other;
27	int allow_root;
28	int ishelp;
29	int flags;
30	int nonempty;
31	int blkdev;
32	char *fsname;
33	char *subtype;
34	char *subtype_opt;
35	char *mtab_opts;
36	char *fusermount_opts;
37	char *kernel_opts;
38};
39
40#define FUSE_LIB_OPT(t, p, v) { t, offsetof(struct fuse_config, p), v }
41
42static const struct fuse_opt fuse_lib_opts[] = {
43	FUSE_OPT_KEY("-h",		      KEY_HELP),
44	FUSE_OPT_KEY("--help",		      KEY_HELP),
45	FUSE_OPT_KEY("debug",		      FUSE_OPT_KEY_KEEP),
46	FUSE_OPT_KEY("-d",		      FUSE_OPT_KEY_KEEP),
47	FUSE_LIB_OPT("debug",		      debug, 1),
48	FUSE_LIB_OPT("-d",		      debug, 1),
49	FUSE_LIB_OPT("hard_remove",	      hard_remove, 1),
50	FUSE_LIB_OPT("use_ino",		      use_ino, 1),
51	FUSE_LIB_OPT("readdir_ino",	      readdir_ino, 1),
52	FUSE_LIB_OPT("direct_io",	      direct_io, 1),
53	FUSE_LIB_OPT("kernel_cache",	      kernel_cache, 1),
54	FUSE_LIB_OPT("auto_cache",	      auto_cache, 1),
55	FUSE_LIB_OPT("noauto_cache",	      auto_cache, 0),
56	FUSE_LIB_OPT("umask=",		      set_mode, 1),
57	FUSE_LIB_OPT("umask=%o",	      umask, 0),
58	FUSE_LIB_OPT("uid=",		      set_uid, 1),
59	FUSE_LIB_OPT("uid=%d",		      uid, 0),
60	FUSE_LIB_OPT("gid=",		      set_gid, 1),
61	FUSE_LIB_OPT("gid=%d",		      gid, 0),
62	FUSE_LIB_OPT("entry_timeout=%lf",     entry_timeout, 0),
63	FUSE_LIB_OPT("attr_timeout=%lf",      attr_timeout, 0),
64	FUSE_LIB_OPT("ac_attr_timeout=%lf",   ac_attr_timeout, 0),
65	FUSE_LIB_OPT("ac_attr_timeout=",      ac_attr_timeout_set, 1),
66	FUSE_LIB_OPT("negative_timeout=%lf",  negative_timeout, 0),
67	FUSE_LIB_OPT("intr",		      intr, 1),
68	FUSE_LIB_OPT("intr_signal=%d",	      intr_signal, 0),
69	FUSE_LIB_OPT("modules=%s",	      modules, 0),
70	FUSE_OPT_END
71};
72
73#define FUSE_MOUNT_OPT(t, p) { t, offsetof(struct mount_opts, p), 1 }
74
75static const struct fuse_opt fuse_mount_opts[] = {
76	FUSE_MOUNT_OPT("allow_other",	    allow_other),
77	FUSE_MOUNT_OPT("allow_root",	    allow_root),
78	FUSE_MOUNT_OPT("nonempty",	    nonempty),
79	FUSE_MOUNT_OPT("blkdev",	    blkdev),
80	FUSE_MOUNT_OPT("fsname=%s",	    fsname),
81	FUSE_MOUNT_OPT("subtype=%s",	    subtype),
82	FUSE_OPT_KEY("allow_other",	    KEY_KERN_OPT),
83	FUSE_OPT_KEY("allow_root",	    KEY_ALLOW_ROOT),
84	FUSE_OPT_KEY("nonempty",	    KEY_FUSERMOUNT_OPT),
85	FUSE_OPT_KEY("blkdev",		    KEY_FUSERMOUNT_OPT),
86	FUSE_OPT_KEY("fsname=",		    KEY_FUSERMOUNT_OPT),
87	FUSE_OPT_KEY("subtype=",	    KEY_SUBTYPE_OPT),
88	FUSE_OPT_KEY("large_read",	    KEY_KERN_OPT),
89	FUSE_OPT_KEY("blksize=",	    KEY_KERN_OPT),
90	FUSE_OPT_KEY("default_permissions", KEY_KERN_OPT),
91	FUSE_OPT_KEY("max_read=",	    KEY_KERN_OPT),
92	FUSE_OPT_KEY("max_read=",	    FUSE_OPT_KEY_KEEP),
93	FUSE_OPT_KEY("user=",		    KEY_MTAB_OPT),
94	FUSE_OPT_KEY("-r",		    KEY_RO),
95	FUSE_OPT_KEY("ro",		    KEY_KERN_FLAG),
96	FUSE_OPT_KEY("rw",		    KEY_KERN_FLAG),
97	FUSE_OPT_KEY("suid",		    KEY_KERN_FLAG),
98	FUSE_OPT_KEY("nosuid",		    KEY_KERN_FLAG),
99	FUSE_OPT_KEY("dev",		    KEY_KERN_FLAG),
100	FUSE_OPT_KEY("nodev",		    KEY_KERN_FLAG),
101	FUSE_OPT_KEY("exec",		    KEY_KERN_FLAG),
102	FUSE_OPT_KEY("noexec",		    KEY_KERN_FLAG),
103	FUSE_OPT_KEY("async",		    KEY_KERN_FLAG),
104	FUSE_OPT_KEY("sync",		    KEY_KERN_FLAG),
105	FUSE_OPT_KEY("dirsync",		    KEY_KERN_FLAG),
106	FUSE_OPT_KEY("atime",		    KEY_KERN_FLAG),
107	FUSE_OPT_KEY("noatime",		    KEY_KERN_FLAG),
108	FUSE_OPT_KEY("-h",		    KEY_HELP),
109	FUSE_OPT_KEY("--help",		    KEY_HELP),
110	FUSE_OPT_KEY("-V",		    KEY_VERSION),
111	FUSE_OPT_KEY("--version",	    KEY_VERSION),
112	FUSE_OPT_END
113};
114
115
116static int
117fuse_lib_opt_proc(void *data, const char *arg, int key,
118	struct fuse_args *outargs)
119{
120	(void)data;
121	(void)arg;
122	(void)key;
123	(void)outargs;
124
125	return 1;
126}
127
128
129int
130fuse_parse_lib_config_args(struct fuse_args* args, struct fuse_config* config)
131{
132	return fuse_opt_parse(args, config, fuse_lib_opts, fuse_lib_opt_proc) == 0;
133}
134
135
136int
137fuse_is_lib_option(const char* opt)
138{
139	return /*fuse_lowlevel_is_lib_option(opt) ||*/
140		fuse_opt_match(fuse_lib_opts, opt);
141}
142
143
144#if 0
145struct mount_flags {
146	const char *opt;
147	unsigned long flag;
148	int on;
149};
150
151static struct mount_flags mount_flags[] = {
152	{"rw",	    MS_RDONLY,	    0},
153	{"ro",	    MS_RDONLY,	    1},
154	{"suid",    MS_NOSUID,	    0},
155	{"nosuid",  MS_NOSUID,	    1},
156	{"dev",	    MS_NODEV,	    0},
157	{"nodev",   MS_NODEV,	    1},
158	{"exec",    MS_NOEXEC,	    0},
159	{"noexec",  MS_NOEXEC,	    1},
160	{"async",   MS_SYNCHRONOUS, 0},
161	{"sync",    MS_SYNCHRONOUS, 1},
162	{"atime",   MS_NOATIME,	    0},
163	{"noatime", MS_NOATIME,	    1},
164	{"dirsync", MS_DIRSYNC,	    1},
165	{NULL,	    0,		    0}
166};
167#endif	// 0
168
169static void set_mount_flag(const char *s, int *flags)
170{
171#if 0
172	int i;
173
174	for (i = 0; mount_flags[i].opt != NULL; i++) {
175		const char *opt = mount_flags[i].opt;
176		if (strcmp(opt, s) == 0) {
177			if (mount_flags[i].on)
178				*flags |= mount_flags[i].flag;
179			else
180				*flags &= ~mount_flags[i].flag;
181			return;
182		}
183	}
184	fprintf(stderr, "fuse: internal error, can't find mount flag\n");
185	abort();
186#endif
187}
188
189static int fuse_mount_opt_proc(void *data, const char *arg, int key,
190			       struct fuse_args *outargs)
191{
192	struct mount_opts *mo = data;
193
194	switch (key) {
195	case KEY_ALLOW_ROOT:
196		if (fuse_opt_add_opt(&mo->kernel_opts, "allow_other") == -1 ||
197		    fuse_opt_add_arg(outargs, "-oallow_root") == -1)
198			return -1;
199		return 0;
200
201	case KEY_RO:
202		arg = "ro";
203		/* fall through */
204	case KEY_KERN_FLAG:
205		set_mount_flag(arg, &mo->flags);
206		return 0;
207
208	case KEY_KERN_OPT:
209		return fuse_opt_add_opt(&mo->kernel_opts, arg);
210
211	case KEY_FUSERMOUNT_OPT:
212		return fuse_opt_add_opt(&mo->fusermount_opts, arg);
213
214	case KEY_SUBTYPE_OPT:
215		return fuse_opt_add_opt(&mo->subtype_opt, arg);
216
217	case KEY_MTAB_OPT:
218		return fuse_opt_add_opt(&mo->mtab_opts, arg);
219
220	case KEY_HELP:
221//		mount_help();
222		mo->ishelp = 1;
223		break;
224
225	case KEY_VERSION:
226//		mount_version();
227		mo->ishelp = 1;
228		break;
229	}
230	return 1;
231}
232
233
234int
235fuse_parse_mount_config_args(struct fuse_args* args)
236{
237	struct mount_opts mo;
238	memset(&mo, 0, sizeof(mo));
239
240	return args == 0
241		|| fuse_opt_parse(args, &mo, fuse_mount_opts, fuse_mount_opt_proc) == 0;
242}
243