2 FUSE: Filesystem in Userspace
3 Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
5 This program can be distributed under the terms of the GNU LGPLv2.
6 See the file COPYING.LIB.
12 #include "mount_util.h"
21 #include <sys/socket.h>
24 #include <sys/mount.h>
27 #define MS_DIRSYNC 128
50 char *fusermount_opts
;
54 #define FUSE_MOUNT_OPT(t, p) { t, offsetof(struct mount_opts, p), 1 }
56 static const struct fuse_opt fuse_mount_opts
[] = {
57 FUSE_MOUNT_OPT("allow_other", allow_other
),
58 FUSE_MOUNT_OPT("allow_root", allow_root
),
59 FUSE_MOUNT_OPT("blkdev", blkdev
),
60 FUSE_MOUNT_OPT("fsname=%s", fsname
),
61 FUSE_OPT_KEY("allow_other", KEY_KERN_OPT
),
62 FUSE_OPT_KEY("allow_root", KEY_ALLOW_ROOT
),
63 FUSE_OPT_KEY("blkdev", KEY_FUSERMOUNT_OPT
),
64 FUSE_OPT_KEY("fsname=", KEY_FUSERMOUNT_OPT
),
65 FUSE_OPT_KEY("large_read", KEY_KERN_OPT
),
66 FUSE_OPT_KEY("blksize=", KEY_KERN_OPT
),
67 FUSE_OPT_KEY("default_permissions", KEY_KERN_OPT
),
68 FUSE_OPT_KEY("context=", KEY_KERN_OPT
),
69 FUSE_OPT_KEY("max_read=", KEY_KERN_OPT
),
70 FUSE_OPT_KEY("max_read=", FUSE_OPT_KEY_KEEP
),
71 FUSE_OPT_KEY("user=", KEY_MTAB_OPT
),
72 FUSE_OPT_KEY("-r", KEY_RO
),
73 FUSE_OPT_KEY("ro", KEY_KERN_FLAG
),
74 FUSE_OPT_KEY("rw", KEY_KERN_FLAG
),
75 FUSE_OPT_KEY("suid", KEY_KERN_FLAG
),
76 FUSE_OPT_KEY("nosuid", KEY_KERN_FLAG
),
77 FUSE_OPT_KEY("dev", KEY_KERN_FLAG
),
78 FUSE_OPT_KEY("nodev", KEY_KERN_FLAG
),
79 FUSE_OPT_KEY("exec", KEY_KERN_FLAG
),
80 FUSE_OPT_KEY("noexec", KEY_KERN_FLAG
),
81 FUSE_OPT_KEY("async", KEY_KERN_FLAG
),
82 FUSE_OPT_KEY("sync", KEY_KERN_FLAG
),
83 FUSE_OPT_KEY("dirsync", KEY_KERN_FLAG
),
84 FUSE_OPT_KEY("atime", KEY_KERN_FLAG
),
85 FUSE_OPT_KEY("noatime", KEY_KERN_FLAG
),
86 FUSE_OPT_KEY("-h", KEY_HELP
),
87 FUSE_OPT_KEY("--help", KEY_HELP
),
88 FUSE_OPT_KEY("-V", KEY_VERSION
),
89 FUSE_OPT_KEY("--version", KEY_VERSION
),
99 static struct mount_flags mount_flags
[] = {
100 {"rw", MS_RDONLY
, 0},
101 {"ro", MS_RDONLY
, 1},
102 {"suid", MS_NOSUID
, 0},
103 {"nosuid", MS_NOSUID
, 1},
104 {"dev", MS_NODEV
, 0},
105 {"nodev", MS_NODEV
, 1},
106 {"exec", MS_NOEXEC
, 0},
107 {"noexec", MS_NOEXEC
, 1},
108 {"async", MS_SYNCHRONOUS
, 0},
109 {"sync", MS_SYNCHRONOUS
, 1},
110 {"atime", MS_NOATIME
, 0},
111 {"noatime", MS_NOATIME
, 1},
112 {"dirsync", MS_DIRSYNC
, 1},
116 static void set_mount_flag(const char *s
, int *flags
)
120 for (i
= 0; mount_flags
[i
].opt
!= NULL
; i
++) {
121 const char *opt
= mount_flags
[i
].opt
;
122 if (strcmp(opt
, s
) == 0) {
123 if (mount_flags
[i
].on
)
124 *flags
|= mount_flags
[i
].flag
;
126 *flags
&= ~mount_flags
[i
].flag
;
130 fprintf(stderr
, "fuse: internal error, can't find mount flag\n");
134 static int fuse_mount_opt_proc(void *data
, const char *arg
, int key
,
135 struct fuse_args
*outargs
)
137 struct mount_opts
*mo
= data
;
141 if (fuse_opt_add_opt(&mo
->kernel_opts
, "allow_other") == -1 ||
142 fuse_opt_add_arg(outargs
, "-oallow_root") == -1)
150 set_mount_flag(arg
, &mo
->flags
);
154 return fuse_opt_add_opt(&mo
->kernel_opts
, arg
);
156 case KEY_FUSERMOUNT_OPT
:
157 return fuse_opt_add_opt(&mo
->fusermount_opts
, arg
);
160 return fuse_opt_add_opt(&mo
->mtab_opts
, arg
);
173 void fuse_kern_unmount(const char *mountpoint
, int fd
)
185 res
= poll(&pfd
, 1, 0);
186 /* If file poll returns POLLERR on the device file descriptor,
187 then the filesystem is already unmounted */
188 if (res
== 1 && (pfd
.revents
& POLLERR
))
193 fusermount(1, 0, 1, "", mountpoint
);
196 static int get_mnt_flag_opts(char **mnt_optsp
, int flags
)
200 if (!(flags
& MS_RDONLY
) && fuse_opt_add_opt(mnt_optsp
, "rw") == -1)
203 for (i
= 0; mount_flags
[i
].opt
!= NULL
; i
++) {
204 if (mount_flags
[i
].on
&& (flags
& mount_flags
[i
].flag
) &&
205 fuse_opt_add_opt(mnt_optsp
, mount_flags
[i
].opt
) == -1)
211 int fuse_kern_mount(const char *mountpoint
, struct fuse_args
*args
)
213 struct mount_opts mo
;
215 char *mnt_opts
= NULL
;
217 memset(&mo
, 0, sizeof(mo
));
219 mo
.flags
= MS_NOSUID
| MS_NODEV
;
222 fuse_opt_parse(args
, &mo
, fuse_mount_opts
, fuse_mount_opt_proc
) == -1)
225 if (mo
.allow_other
&& mo
.allow_root
) {
226 fprintf(stderr
, "fuse: 'allow_other' and 'allow_root' options are mutually exclusive\n");
234 if (get_mnt_flag_opts(&mnt_opts
, mo
.flags
) == -1)
236 if (!(mo
.flags
& MS_NODEV
) && fuse_opt_add_opt(&mnt_opts
, "dev") == -1)
238 if (!(mo
.flags
& MS_NOSUID
) && fuse_opt_add_opt(&mnt_opts
, "suid") == -1)
240 if (mo
.kernel_opts
&& fuse_opt_add_opt(&mnt_opts
, mo
.kernel_opts
) == -1)
242 if (mo
.mtab_opts
&& fuse_opt_add_opt(&mnt_opts
, mo
.mtab_opts
) == -1)
244 if (mo
.fusermount_opts
&& fuse_opt_add_opt(&mnt_opts
, mo
.fusermount_opts
) < 0)
247 res
= fusermount(0, 0, 0, mnt_opts
? mnt_opts
: "", mountpoint
);
252 free(mo
.fusermount_opts
);
253 free(mo
.kernel_opts
);