xref: /aosp_15_r20/external/libfuse/lib/mount.c (revision 9e5649576b786774a32d7b0252c9cd8c6538fa49)
1*9e564957SAndroid Build Coastguard Worker /*
2*9e564957SAndroid Build Coastguard Worker   FUSE: Filesystem in Userspace
3*9e564957SAndroid Build Coastguard Worker   Copyright (C) 2001-2007  Miklos Szeredi <[email protected]>
4*9e564957SAndroid Build Coastguard Worker 
5*9e564957SAndroid Build Coastguard Worker   Architecture specific file system mounting (Linux).
6*9e564957SAndroid Build Coastguard Worker 
7*9e564957SAndroid Build Coastguard Worker   This program can be distributed under the terms of the GNU LGPLv2.
8*9e564957SAndroid Build Coastguard Worker   See the file COPYING.LIB.
9*9e564957SAndroid Build Coastguard Worker */
10*9e564957SAndroid Build Coastguard Worker 
11*9e564957SAndroid Build Coastguard Worker /* For environ */
12*9e564957SAndroid Build Coastguard Worker #define _GNU_SOURCE
13*9e564957SAndroid Build Coastguard Worker 
14*9e564957SAndroid Build Coastguard Worker #include "fuse_config.h"
15*9e564957SAndroid Build Coastguard Worker #include "fuse_i.h"
16*9e564957SAndroid Build Coastguard Worker #include "fuse_misc.h"
17*9e564957SAndroid Build Coastguard Worker #include "fuse_opt.h"
18*9e564957SAndroid Build Coastguard Worker #include "mount_util.h"
19*9e564957SAndroid Build Coastguard Worker 
20*9e564957SAndroid Build Coastguard Worker #include <stdio.h>
21*9e564957SAndroid Build Coastguard Worker #include <stdlib.h>
22*9e564957SAndroid Build Coastguard Worker #include <unistd.h>
23*9e564957SAndroid Build Coastguard Worker #include <stddef.h>
24*9e564957SAndroid Build Coastguard Worker #include <string.h>
25*9e564957SAndroid Build Coastguard Worker #include <fcntl.h>
26*9e564957SAndroid Build Coastguard Worker #include <errno.h>
27*9e564957SAndroid Build Coastguard Worker #include <poll.h>
28*9e564957SAndroid Build Coastguard Worker #include <spawn.h>
29*9e564957SAndroid Build Coastguard Worker #include <sys/socket.h>
30*9e564957SAndroid Build Coastguard Worker #include <sys/un.h>
31*9e564957SAndroid Build Coastguard Worker #include <sys/wait.h>
32*9e564957SAndroid Build Coastguard Worker 
33*9e564957SAndroid Build Coastguard Worker #include "fuse_mount_compat.h"
34*9e564957SAndroid Build Coastguard Worker 
35*9e564957SAndroid Build Coastguard Worker #ifdef __NetBSD__
36*9e564957SAndroid Build Coastguard Worker #include <perfuse.h>
37*9e564957SAndroid Build Coastguard Worker 
38*9e564957SAndroid Build Coastguard Worker #define MS_RDONLY	MNT_RDONLY
39*9e564957SAndroid Build Coastguard Worker #define MS_NOSUID	MNT_NOSUID
40*9e564957SAndroid Build Coastguard Worker #define MS_NODEV	MNT_NODEV
41*9e564957SAndroid Build Coastguard Worker #define MS_NOEXEC	MNT_NOEXEC
42*9e564957SAndroid Build Coastguard Worker #define MS_SYNCHRONOUS	MNT_SYNCHRONOUS
43*9e564957SAndroid Build Coastguard Worker #define MS_NOATIME	MNT_NOATIME
44*9e564957SAndroid Build Coastguard Worker 
45*9e564957SAndroid Build Coastguard Worker #define umount2(mnt, flags) unmount(mnt, (flags == 2) ? MNT_FORCE : 0)
46*9e564957SAndroid Build Coastguard Worker #endif
47*9e564957SAndroid Build Coastguard Worker 
48*9e564957SAndroid Build Coastguard Worker #define FUSERMOUNT_PROG		"fusermount3"
49*9e564957SAndroid Build Coastguard Worker #define FUSE_COMMFD_ENV		"_FUSE_COMMFD"
50*9e564957SAndroid Build Coastguard Worker 
51*9e564957SAndroid Build Coastguard Worker #ifndef MS_DIRSYNC
52*9e564957SAndroid Build Coastguard Worker #define MS_DIRSYNC 128
53*9e564957SAndroid Build Coastguard Worker #endif
54*9e564957SAndroid Build Coastguard Worker 
55*9e564957SAndroid Build Coastguard Worker enum {
56*9e564957SAndroid Build Coastguard Worker 	KEY_KERN_FLAG,
57*9e564957SAndroid Build Coastguard Worker 	KEY_KERN_OPT,
58*9e564957SAndroid Build Coastguard Worker 	KEY_FUSERMOUNT_OPT,
59*9e564957SAndroid Build Coastguard Worker 	KEY_SUBTYPE_OPT,
60*9e564957SAndroid Build Coastguard Worker 	KEY_MTAB_OPT,
61*9e564957SAndroid Build Coastguard Worker 	KEY_ALLOW_OTHER,
62*9e564957SAndroid Build Coastguard Worker 	KEY_RO,
63*9e564957SAndroid Build Coastguard Worker };
64*9e564957SAndroid Build Coastguard Worker 
65*9e564957SAndroid Build Coastguard Worker struct mount_opts {
66*9e564957SAndroid Build Coastguard Worker 	int allow_other;
67*9e564957SAndroid Build Coastguard Worker 	int flags;
68*9e564957SAndroid Build Coastguard Worker 	int auto_unmount;
69*9e564957SAndroid Build Coastguard Worker 	int blkdev;
70*9e564957SAndroid Build Coastguard Worker 	char *fsname;
71*9e564957SAndroid Build Coastguard Worker 	char *subtype;
72*9e564957SAndroid Build Coastguard Worker 	char *subtype_opt;
73*9e564957SAndroid Build Coastguard Worker 	char *mtab_opts;
74*9e564957SAndroid Build Coastguard Worker 	char *fusermount_opts;
75*9e564957SAndroid Build Coastguard Worker 	char *kernel_opts;
76*9e564957SAndroid Build Coastguard Worker 	unsigned max_read;
77*9e564957SAndroid Build Coastguard Worker };
78*9e564957SAndroid Build Coastguard Worker 
79*9e564957SAndroid Build Coastguard Worker #define FUSE_MOUNT_OPT(t, p) { t, offsetof(struct mount_opts, p), 1 }
80*9e564957SAndroid Build Coastguard Worker 
81*9e564957SAndroid Build Coastguard Worker static const struct fuse_opt fuse_mount_opts[] = {
82*9e564957SAndroid Build Coastguard Worker 	FUSE_MOUNT_OPT("allow_other",		allow_other),
83*9e564957SAndroid Build Coastguard Worker 	FUSE_MOUNT_OPT("blkdev",		blkdev),
84*9e564957SAndroid Build Coastguard Worker 	FUSE_MOUNT_OPT("auto_unmount",		auto_unmount),
85*9e564957SAndroid Build Coastguard Worker 	FUSE_MOUNT_OPT("fsname=%s",		fsname),
86*9e564957SAndroid Build Coastguard Worker 	FUSE_MOUNT_OPT("max_read=%u",		max_read),
87*9e564957SAndroid Build Coastguard Worker 	FUSE_MOUNT_OPT("subtype=%s",		subtype),
88*9e564957SAndroid Build Coastguard Worker 	FUSE_OPT_KEY("allow_other",		KEY_KERN_OPT),
89*9e564957SAndroid Build Coastguard Worker 	FUSE_OPT_KEY("auto_unmount",		KEY_FUSERMOUNT_OPT),
90*9e564957SAndroid Build Coastguard Worker 	FUSE_OPT_KEY("blkdev",			KEY_FUSERMOUNT_OPT),
91*9e564957SAndroid Build Coastguard Worker 	FUSE_OPT_KEY("fsname=",			KEY_FUSERMOUNT_OPT),
92*9e564957SAndroid Build Coastguard Worker 	FUSE_OPT_KEY("subtype=",		KEY_SUBTYPE_OPT),
93*9e564957SAndroid Build Coastguard Worker 	FUSE_OPT_KEY("blksize=",		KEY_KERN_OPT),
94*9e564957SAndroid Build Coastguard Worker 	FUSE_OPT_KEY("default_permissions",	KEY_KERN_OPT),
95*9e564957SAndroid Build Coastguard Worker 	FUSE_OPT_KEY("context=",		KEY_KERN_OPT),
96*9e564957SAndroid Build Coastguard Worker 	FUSE_OPT_KEY("fscontext=",		KEY_KERN_OPT),
97*9e564957SAndroid Build Coastguard Worker 	FUSE_OPT_KEY("defcontext=",		KEY_KERN_OPT),
98*9e564957SAndroid Build Coastguard Worker 	FUSE_OPT_KEY("rootcontext=",		KEY_KERN_OPT),
99*9e564957SAndroid Build Coastguard Worker 	FUSE_OPT_KEY("max_read=",		KEY_KERN_OPT),
100*9e564957SAndroid Build Coastguard Worker 	FUSE_OPT_KEY("user=",			KEY_MTAB_OPT),
101*9e564957SAndroid Build Coastguard Worker 	FUSE_OPT_KEY("-n",			KEY_MTAB_OPT),
102*9e564957SAndroid Build Coastguard Worker 	FUSE_OPT_KEY("-r",			KEY_RO),
103*9e564957SAndroid Build Coastguard Worker 	FUSE_OPT_KEY("ro",			KEY_KERN_FLAG),
104*9e564957SAndroid Build Coastguard Worker 	FUSE_OPT_KEY("rw",			KEY_KERN_FLAG),
105*9e564957SAndroid Build Coastguard Worker 	FUSE_OPT_KEY("suid",			KEY_KERN_FLAG),
106*9e564957SAndroid Build Coastguard Worker 	FUSE_OPT_KEY("nosuid",			KEY_KERN_FLAG),
107*9e564957SAndroid Build Coastguard Worker 	FUSE_OPT_KEY("dev",			KEY_KERN_FLAG),
108*9e564957SAndroid Build Coastguard Worker 	FUSE_OPT_KEY("nodev",			KEY_KERN_FLAG),
109*9e564957SAndroid Build Coastguard Worker 	FUSE_OPT_KEY("exec",			KEY_KERN_FLAG),
110*9e564957SAndroid Build Coastguard Worker 	FUSE_OPT_KEY("noexec",			KEY_KERN_FLAG),
111*9e564957SAndroid Build Coastguard Worker 	FUSE_OPT_KEY("async",			KEY_KERN_FLAG),
112*9e564957SAndroid Build Coastguard Worker 	FUSE_OPT_KEY("sync",			KEY_KERN_FLAG),
113*9e564957SAndroid Build Coastguard Worker 	FUSE_OPT_KEY("dirsync",			KEY_KERN_FLAG),
114*9e564957SAndroid Build Coastguard Worker 	FUSE_OPT_KEY("noatime",			KEY_KERN_FLAG),
115*9e564957SAndroid Build Coastguard Worker 	FUSE_OPT_KEY("nodiratime",		KEY_KERN_FLAG),
116*9e564957SAndroid Build Coastguard Worker 	FUSE_OPT_KEY("nostrictatime",		KEY_KERN_FLAG),
117*9e564957SAndroid Build Coastguard Worker 	FUSE_OPT_END
118*9e564957SAndroid Build Coastguard Worker };
119*9e564957SAndroid Build Coastguard Worker 
120*9e564957SAndroid Build Coastguard Worker /*
121*9e564957SAndroid Build Coastguard Worker  * Running fusermount by calling 'posix_spawn'
122*9e564957SAndroid Build Coastguard Worker  *
123*9e564957SAndroid Build Coastguard Worker  * @param out_pid might be NULL
124*9e564957SAndroid Build Coastguard Worker  */
fusermount_posix_spawn(posix_spawn_file_actions_t * action,char const * const argv[],pid_t * out_pid)125*9e564957SAndroid Build Coastguard Worker static int fusermount_posix_spawn(posix_spawn_file_actions_t *action,
126*9e564957SAndroid Build Coastguard Worker 				  char const * const argv[], pid_t *out_pid)
127*9e564957SAndroid Build Coastguard Worker {
128*9e564957SAndroid Build Coastguard Worker 	const char *full_path = FUSERMOUNT_DIR "/" FUSERMOUNT_PROG;
129*9e564957SAndroid Build Coastguard Worker 	pid_t pid;
130*9e564957SAndroid Build Coastguard Worker 
131*9e564957SAndroid Build Coastguard Worker 	/* See man 7 environ for the global environ pointer */
132*9e564957SAndroid Build Coastguard Worker 
133*9e564957SAndroid Build Coastguard Worker 	/* first try the install path */
134*9e564957SAndroid Build Coastguard Worker 	int status = posix_spawn(&pid, full_path,  action, NULL,
135*9e564957SAndroid Build Coastguard Worker 				 (char * const *) argv, environ);
136*9e564957SAndroid Build Coastguard Worker 	if (status != 0) {
137*9e564957SAndroid Build Coastguard Worker 		/* if that fails, try a system install */
138*9e564957SAndroid Build Coastguard Worker 		status = posix_spawnp(&pid, FUSERMOUNT_PROG, action, NULL,
139*9e564957SAndroid Build Coastguard Worker 				      (char * const *) argv, environ);
140*9e564957SAndroid Build Coastguard Worker 	}
141*9e564957SAndroid Build Coastguard Worker 
142*9e564957SAndroid Build Coastguard Worker 	if (status != 0) {
143*9e564957SAndroid Build Coastguard Worker 		fuse_log(FUSE_LOG_ERR,
144*9e564957SAndroid Build Coastguard Worker 			 "On calling fusermount posix_spawn failed: %s\n",
145*9e564957SAndroid Build Coastguard Worker 			 strerror(status));
146*9e564957SAndroid Build Coastguard Worker 		return -status;
147*9e564957SAndroid Build Coastguard Worker 	}
148*9e564957SAndroid Build Coastguard Worker 
149*9e564957SAndroid Build Coastguard Worker 	if (out_pid)
150*9e564957SAndroid Build Coastguard Worker 		*out_pid = pid;
151*9e564957SAndroid Build Coastguard Worker 	else
152*9e564957SAndroid Build Coastguard Worker 		waitpid(pid, NULL, 0);
153*9e564957SAndroid Build Coastguard Worker 
154*9e564957SAndroid Build Coastguard Worker 	return 0;
155*9e564957SAndroid Build Coastguard Worker }
156*9e564957SAndroid Build Coastguard Worker 
fuse_mount_version(void)157*9e564957SAndroid Build Coastguard Worker void fuse_mount_version(void)
158*9e564957SAndroid Build Coastguard Worker {
159*9e564957SAndroid Build Coastguard Worker 	char const *const argv[] = {FUSERMOUNT_PROG, "--version", NULL};
160*9e564957SAndroid Build Coastguard Worker 	int status = fusermount_posix_spawn(NULL, argv, NULL);
161*9e564957SAndroid Build Coastguard Worker 
162*9e564957SAndroid Build Coastguard Worker 	if(status != 0)
163*9e564957SAndroid Build Coastguard Worker 		fuse_log(FUSE_LOG_ERR, "Running '%s --version' failed",
164*9e564957SAndroid Build Coastguard Worker 			 FUSERMOUNT_PROG);
165*9e564957SAndroid Build Coastguard Worker }
166*9e564957SAndroid Build Coastguard Worker 
167*9e564957SAndroid Build Coastguard Worker struct mount_flags {
168*9e564957SAndroid Build Coastguard Worker 	const char *opt;
169*9e564957SAndroid Build Coastguard Worker 	unsigned long flag;
170*9e564957SAndroid Build Coastguard Worker 	int on;
171*9e564957SAndroid Build Coastguard Worker };
172*9e564957SAndroid Build Coastguard Worker 
173*9e564957SAndroid Build Coastguard Worker static const struct mount_flags mount_flags[] = {
174*9e564957SAndroid Build Coastguard Worker 	{"rw",	    MS_RDONLY,	    0},
175*9e564957SAndroid Build Coastguard Worker 	{"ro",	    MS_RDONLY,	    1},
176*9e564957SAndroid Build Coastguard Worker 	{"suid",    MS_NOSUID,	    0},
177*9e564957SAndroid Build Coastguard Worker 	{"nosuid",  MS_NOSUID,	    1},
178*9e564957SAndroid Build Coastguard Worker 	{"dev",	    MS_NODEV,	    0},
179*9e564957SAndroid Build Coastguard Worker 	{"nodev",   MS_NODEV,	    1},
180*9e564957SAndroid Build Coastguard Worker 	{"exec",    MS_NOEXEC,	    0},
181*9e564957SAndroid Build Coastguard Worker 	{"noexec",  MS_NOEXEC,	    1},
182*9e564957SAndroid Build Coastguard Worker 	{"async",   MS_SYNCHRONOUS, 0},
183*9e564957SAndroid Build Coastguard Worker 	{"sync",    MS_SYNCHRONOUS, 1},
184*9e564957SAndroid Build Coastguard Worker 	{"noatime", MS_NOATIME,	    1},
185*9e564957SAndroid Build Coastguard Worker 	{"nodiratime",	    MS_NODIRATIME,	1},
186*9e564957SAndroid Build Coastguard Worker 	{"norelatime",	    MS_RELATIME,	0},
187*9e564957SAndroid Build Coastguard Worker 	{"nostrictatime",   MS_STRICTATIME,	0},
188*9e564957SAndroid Build Coastguard Worker #ifndef __NetBSD__
189*9e564957SAndroid Build Coastguard Worker 	{"dirsync", MS_DIRSYNC,	    1},
190*9e564957SAndroid Build Coastguard Worker #endif
191*9e564957SAndroid Build Coastguard Worker 	{NULL,	    0,		    0}
192*9e564957SAndroid Build Coastguard Worker };
193*9e564957SAndroid Build Coastguard Worker 
get_max_read(struct mount_opts * o)194*9e564957SAndroid Build Coastguard Worker unsigned get_max_read(struct mount_opts *o)
195*9e564957SAndroid Build Coastguard Worker {
196*9e564957SAndroid Build Coastguard Worker 	return o->max_read;
197*9e564957SAndroid Build Coastguard Worker }
198*9e564957SAndroid Build Coastguard Worker 
set_mount_flag(const char * s,int * flags)199*9e564957SAndroid Build Coastguard Worker static void set_mount_flag(const char *s, int *flags)
200*9e564957SAndroid Build Coastguard Worker {
201*9e564957SAndroid Build Coastguard Worker 	int i;
202*9e564957SAndroid Build Coastguard Worker 
203*9e564957SAndroid Build Coastguard Worker 	for (i = 0; mount_flags[i].opt != NULL; i++) {
204*9e564957SAndroid Build Coastguard Worker 		const char *opt = mount_flags[i].opt;
205*9e564957SAndroid Build Coastguard Worker 		if (strcmp(opt, s) == 0) {
206*9e564957SAndroid Build Coastguard Worker 			if (mount_flags[i].on)
207*9e564957SAndroid Build Coastguard Worker 				*flags |= mount_flags[i].flag;
208*9e564957SAndroid Build Coastguard Worker 			else
209*9e564957SAndroid Build Coastguard Worker 				*flags &= ~mount_flags[i].flag;
210*9e564957SAndroid Build Coastguard Worker 			return;
211*9e564957SAndroid Build Coastguard Worker 		}
212*9e564957SAndroid Build Coastguard Worker 	}
213*9e564957SAndroid Build Coastguard Worker 	fuse_log(FUSE_LOG_ERR, "fuse: internal error, can't find mount flag\n");
214*9e564957SAndroid Build Coastguard Worker 	abort();
215*9e564957SAndroid Build Coastguard Worker }
216*9e564957SAndroid Build Coastguard Worker 
fuse_mount_opt_proc(void * data,const char * arg,int key,struct fuse_args * outargs)217*9e564957SAndroid Build Coastguard Worker static int fuse_mount_opt_proc(void *data, const char *arg, int key,
218*9e564957SAndroid Build Coastguard Worker 			       struct fuse_args *outargs)
219*9e564957SAndroid Build Coastguard Worker {
220*9e564957SAndroid Build Coastguard Worker 	(void) outargs;
221*9e564957SAndroid Build Coastguard Worker 	struct mount_opts *mo = data;
222*9e564957SAndroid Build Coastguard Worker 
223*9e564957SAndroid Build Coastguard Worker 	switch (key) {
224*9e564957SAndroid Build Coastguard Worker 	case KEY_RO:
225*9e564957SAndroid Build Coastguard Worker 		arg = "ro";
226*9e564957SAndroid Build Coastguard Worker 		/* fall through */
227*9e564957SAndroid Build Coastguard Worker 	case KEY_KERN_FLAG:
228*9e564957SAndroid Build Coastguard Worker 		set_mount_flag(arg, &mo->flags);
229*9e564957SAndroid Build Coastguard Worker 		return 0;
230*9e564957SAndroid Build Coastguard Worker 
231*9e564957SAndroid Build Coastguard Worker 	case KEY_KERN_OPT:
232*9e564957SAndroid Build Coastguard Worker 		return fuse_opt_add_opt(&mo->kernel_opts, arg);
233*9e564957SAndroid Build Coastguard Worker 
234*9e564957SAndroid Build Coastguard Worker 	case KEY_FUSERMOUNT_OPT:
235*9e564957SAndroid Build Coastguard Worker 		return fuse_opt_add_opt_escaped(&mo->fusermount_opts, arg);
236*9e564957SAndroid Build Coastguard Worker 
237*9e564957SAndroid Build Coastguard Worker 	case KEY_SUBTYPE_OPT:
238*9e564957SAndroid Build Coastguard Worker 		return fuse_opt_add_opt(&mo->subtype_opt, arg);
239*9e564957SAndroid Build Coastguard Worker 
240*9e564957SAndroid Build Coastguard Worker 	case KEY_MTAB_OPT:
241*9e564957SAndroid Build Coastguard Worker 		return fuse_opt_add_opt(&mo->mtab_opts, arg);
242*9e564957SAndroid Build Coastguard Worker 
243*9e564957SAndroid Build Coastguard Worker 	/* Third party options like 'x-gvfs-notrash' */
244*9e564957SAndroid Build Coastguard Worker 	case FUSE_OPT_KEY_OPT:
245*9e564957SAndroid Build Coastguard Worker 		return (strncmp("x-", arg, 2) == 0) ?
246*9e564957SAndroid Build Coastguard Worker 			fuse_opt_add_opt(&mo->mtab_opts, arg) :
247*9e564957SAndroid Build Coastguard Worker 			1;
248*9e564957SAndroid Build Coastguard Worker 	}
249*9e564957SAndroid Build Coastguard Worker 
250*9e564957SAndroid Build Coastguard Worker 	/* Pass through unknown options */
251*9e564957SAndroid Build Coastguard Worker 	return 1;
252*9e564957SAndroid Build Coastguard Worker }
253*9e564957SAndroid Build Coastguard Worker 
254*9e564957SAndroid Build Coastguard Worker /* return value:
255*9e564957SAndroid Build Coastguard Worker  * >= 0	 => fd
256*9e564957SAndroid Build Coastguard Worker  * -1	 => error
257*9e564957SAndroid Build Coastguard Worker  */
receive_fd(int fd)258*9e564957SAndroid Build Coastguard Worker static int receive_fd(int fd)
259*9e564957SAndroid Build Coastguard Worker {
260*9e564957SAndroid Build Coastguard Worker 	struct msghdr msg;
261*9e564957SAndroid Build Coastguard Worker 	struct iovec iov;
262*9e564957SAndroid Build Coastguard Worker 	char buf[1];
263*9e564957SAndroid Build Coastguard Worker 	int rv;
264*9e564957SAndroid Build Coastguard Worker 	size_t ccmsg[CMSG_SPACE(sizeof(int)) / sizeof(size_t)];
265*9e564957SAndroid Build Coastguard Worker 	struct cmsghdr *cmsg;
266*9e564957SAndroid Build Coastguard Worker 
267*9e564957SAndroid Build Coastguard Worker 	iov.iov_base = buf;
268*9e564957SAndroid Build Coastguard Worker 	iov.iov_len = 1;
269*9e564957SAndroid Build Coastguard Worker 
270*9e564957SAndroid Build Coastguard Worker 	memset(&msg, 0, sizeof(msg));
271*9e564957SAndroid Build Coastguard Worker 	msg.msg_name = 0;
272*9e564957SAndroid Build Coastguard Worker 	msg.msg_namelen = 0;
273*9e564957SAndroid Build Coastguard Worker 	msg.msg_iov = &iov;
274*9e564957SAndroid Build Coastguard Worker 	msg.msg_iovlen = 1;
275*9e564957SAndroid Build Coastguard Worker 	/* old BSD implementations should use msg_accrights instead of
276*9e564957SAndroid Build Coastguard Worker 	 * msg_control; the interface is different. */
277*9e564957SAndroid Build Coastguard Worker 	msg.msg_control = ccmsg;
278*9e564957SAndroid Build Coastguard Worker 	msg.msg_controllen = sizeof(ccmsg);
279*9e564957SAndroid Build Coastguard Worker 
280*9e564957SAndroid Build Coastguard Worker 	while(((rv = recvmsg(fd, &msg, 0)) == -1) && errno == EINTR);
281*9e564957SAndroid Build Coastguard Worker 	if (rv == -1) {
282*9e564957SAndroid Build Coastguard Worker 		fuse_log(FUSE_LOG_ERR, "recvmsg failed: %s", strerror(errno));
283*9e564957SAndroid Build Coastguard Worker 		return -1;
284*9e564957SAndroid Build Coastguard Worker 	}
285*9e564957SAndroid Build Coastguard Worker 	if(!rv) {
286*9e564957SAndroid Build Coastguard Worker 		/* EOF */
287*9e564957SAndroid Build Coastguard Worker 		return -1;
288*9e564957SAndroid Build Coastguard Worker 	}
289*9e564957SAndroid Build Coastguard Worker 
290*9e564957SAndroid Build Coastguard Worker 	cmsg = CMSG_FIRSTHDR(&msg);
291*9e564957SAndroid Build Coastguard Worker 	if (cmsg->cmsg_type != SCM_RIGHTS) {
292*9e564957SAndroid Build Coastguard Worker 		fuse_log(FUSE_LOG_ERR, "got control message of unknown type %d\n",
293*9e564957SAndroid Build Coastguard Worker 			cmsg->cmsg_type);
294*9e564957SAndroid Build Coastguard Worker 		return -1;
295*9e564957SAndroid Build Coastguard Worker 	}
296*9e564957SAndroid Build Coastguard Worker 	return *(int*)CMSG_DATA(cmsg);
297*9e564957SAndroid Build Coastguard Worker }
298*9e564957SAndroid Build Coastguard Worker 
fuse_kern_unmount(const char * mountpoint,int fd)299*9e564957SAndroid Build Coastguard Worker void fuse_kern_unmount(const char *mountpoint, int fd)
300*9e564957SAndroid Build Coastguard Worker {
301*9e564957SAndroid Build Coastguard Worker 	int res;
302*9e564957SAndroid Build Coastguard Worker 
303*9e564957SAndroid Build Coastguard Worker 	if (fd != -1) {
304*9e564957SAndroid Build Coastguard Worker 		struct pollfd pfd;
305*9e564957SAndroid Build Coastguard Worker 
306*9e564957SAndroid Build Coastguard Worker 		pfd.fd = fd;
307*9e564957SAndroid Build Coastguard Worker 		pfd.events = 0;
308*9e564957SAndroid Build Coastguard Worker 		res = poll(&pfd, 1, 0);
309*9e564957SAndroid Build Coastguard Worker 
310*9e564957SAndroid Build Coastguard Worker 		/* Need to close file descriptor, otherwise synchronous umount
311*9e564957SAndroid Build Coastguard Worker 		   would recurse into filesystem, and deadlock.
312*9e564957SAndroid Build Coastguard Worker 
313*9e564957SAndroid Build Coastguard Worker 		   Caller expects fuse_kern_unmount to close the fd, so close it
314*9e564957SAndroid Build Coastguard Worker 		   anyway. */
315*9e564957SAndroid Build Coastguard Worker 		close(fd);
316*9e564957SAndroid Build Coastguard Worker 
317*9e564957SAndroid Build Coastguard Worker 		/* If file poll returns POLLERR on the device file descriptor,
318*9e564957SAndroid Build Coastguard Worker 		   then the filesystem is already unmounted or the connection
319*9e564957SAndroid Build Coastguard Worker 		   was severed via /sys/fs/fuse/connections/NNN/abort */
320*9e564957SAndroid Build Coastguard Worker 		if (res == 1 && (pfd.revents & POLLERR))
321*9e564957SAndroid Build Coastguard Worker 			return;
322*9e564957SAndroid Build Coastguard Worker 	}
323*9e564957SAndroid Build Coastguard Worker 
324*9e564957SAndroid Build Coastguard Worker 	if (geteuid() == 0) {
325*9e564957SAndroid Build Coastguard Worker 		fuse_mnt_umount("fuse", mountpoint, mountpoint,  1);
326*9e564957SAndroid Build Coastguard Worker 		return;
327*9e564957SAndroid Build Coastguard Worker 	}
328*9e564957SAndroid Build Coastguard Worker 
329*9e564957SAndroid Build Coastguard Worker 	res = umount2(mountpoint, 2);
330*9e564957SAndroid Build Coastguard Worker 	if (res == 0)
331*9e564957SAndroid Build Coastguard Worker 		return;
332*9e564957SAndroid Build Coastguard Worker 
333*9e564957SAndroid Build Coastguard Worker 	char const * const argv[] =
334*9e564957SAndroid Build Coastguard Worker 		{ FUSERMOUNT_PROG, "--unmount", "--quiet", "--lazy",
335*9e564957SAndroid Build Coastguard Worker 				"--", mountpoint, NULL };
336*9e564957SAndroid Build Coastguard Worker 	int status = fusermount_posix_spawn(NULL, argv, NULL);
337*9e564957SAndroid Build Coastguard Worker 	if(status != 0) {
338*9e564957SAndroid Build Coastguard Worker 		fuse_log(FUSE_LOG_ERR, "Spawaning %s to unumount failed",
339*9e564957SAndroid Build Coastguard Worker 			 FUSERMOUNT_PROG);
340*9e564957SAndroid Build Coastguard Worker 		return;
341*9e564957SAndroid Build Coastguard Worker 	}
342*9e564957SAndroid Build Coastguard Worker }
343*9e564957SAndroid Build Coastguard Worker 
setup_auto_unmount(const char * mountpoint,int quiet)344*9e564957SAndroid Build Coastguard Worker static int setup_auto_unmount(const char *mountpoint, int quiet)
345*9e564957SAndroid Build Coastguard Worker {
346*9e564957SAndroid Build Coastguard Worker 	int fds[2];
347*9e564957SAndroid Build Coastguard Worker 	pid_t pid;
348*9e564957SAndroid Build Coastguard Worker 	int res;
349*9e564957SAndroid Build Coastguard Worker 
350*9e564957SAndroid Build Coastguard Worker 	if (!mountpoint) {
351*9e564957SAndroid Build Coastguard Worker 		fuse_log(FUSE_LOG_ERR, "fuse: missing mountpoint parameter\n");
352*9e564957SAndroid Build Coastguard Worker 		return -1;
353*9e564957SAndroid Build Coastguard Worker 	}
354*9e564957SAndroid Build Coastguard Worker 
355*9e564957SAndroid Build Coastguard Worker 	res = socketpair(PF_UNIX, SOCK_STREAM, 0, fds);
356*9e564957SAndroid Build Coastguard Worker 	if(res == -1) {
357*9e564957SAndroid Build Coastguard Worker 		fuse_log(FUSE_LOG_ERR, "Setting up auto-unmountsocketpair() failed",
358*9e564957SAndroid Build Coastguard Worker 			 strerror(errno));
359*9e564957SAndroid Build Coastguard Worker 		return -1;
360*9e564957SAndroid Build Coastguard Worker 	}
361*9e564957SAndroid Build Coastguard Worker 
362*9e564957SAndroid Build Coastguard Worker 	char arg_fd_entry[30];
363*9e564957SAndroid Build Coastguard Worker 	snprintf(arg_fd_entry, sizeof(arg_fd_entry), "%i", fds[0]);
364*9e564957SAndroid Build Coastguard Worker 	setenv(FUSE_COMMFD_ENV, arg_fd_entry, 1);
365*9e564957SAndroid Build Coastguard Worker 
366*9e564957SAndroid Build Coastguard Worker 	char const *const argv[] = {
367*9e564957SAndroid Build Coastguard Worker 		FUSERMOUNT_PROG,
368*9e564957SAndroid Build Coastguard Worker 		"--auto-unmount",
369*9e564957SAndroid Build Coastguard Worker 		"--",
370*9e564957SAndroid Build Coastguard Worker 		mountpoint,
371*9e564957SAndroid Build Coastguard Worker 		NULL,
372*9e564957SAndroid Build Coastguard Worker 	};
373*9e564957SAndroid Build Coastguard Worker 
374*9e564957SAndroid Build Coastguard Worker 	// TODO: add error handling for all manipulations of action.
375*9e564957SAndroid Build Coastguard Worker 	posix_spawn_file_actions_t action;
376*9e564957SAndroid Build Coastguard Worker 	posix_spawn_file_actions_init(&action);
377*9e564957SAndroid Build Coastguard Worker 
378*9e564957SAndroid Build Coastguard Worker 	if (quiet) {
379*9e564957SAndroid Build Coastguard Worker 		posix_spawn_file_actions_addclose(&action, 1);
380*9e564957SAndroid Build Coastguard Worker 		posix_spawn_file_actions_addclose(&action, 2);
381*9e564957SAndroid Build Coastguard Worker 	}
382*9e564957SAndroid Build Coastguard Worker 	posix_spawn_file_actions_addclose(&action, fds[1]);
383*9e564957SAndroid Build Coastguard Worker 
384*9e564957SAndroid Build Coastguard Worker 	/*
385*9e564957SAndroid Build Coastguard Worker 	 * auto-umount runs in the background - it is not waiting for the
386*9e564957SAndroid Build Coastguard Worker 	 * process
387*9e564957SAndroid Build Coastguard Worker 	 */
388*9e564957SAndroid Build Coastguard Worker 	int status = fusermount_posix_spawn(&action, argv, &pid);
389*9e564957SAndroid Build Coastguard Worker 
390*9e564957SAndroid Build Coastguard Worker 	posix_spawn_file_actions_destroy(&action);
391*9e564957SAndroid Build Coastguard Worker 
392*9e564957SAndroid Build Coastguard Worker 	if(status != 0) {
393*9e564957SAndroid Build Coastguard Worker 		close(fds[0]);
394*9e564957SAndroid Build Coastguard Worker 		close(fds[1]);
395*9e564957SAndroid Build Coastguard Worker 		fuse_log(FUSE_LOG_ERR, "fuse: Setting up auto-unmount failed");
396*9e564957SAndroid Build Coastguard Worker 		return -1;
397*9e564957SAndroid Build Coastguard Worker 	}
398*9e564957SAndroid Build Coastguard Worker 	// passed to child now, so can close here.
399*9e564957SAndroid Build Coastguard Worker 	close(fds[0]);
400*9e564957SAndroid Build Coastguard Worker 
401*9e564957SAndroid Build Coastguard Worker 	// Now fusermount3 will only exit when fds[1] closes automatically when our
402*9e564957SAndroid Build Coastguard Worker 	// process exits.
403*9e564957SAndroid Build Coastguard Worker 	return 0;
404*9e564957SAndroid Build Coastguard Worker 	// Note: fds[1] is leakend and doesn't get FD_CLOEXEC
405*9e564957SAndroid Build Coastguard Worker }
406*9e564957SAndroid Build Coastguard Worker 
fuse_mount_fusermount(const char * mountpoint,struct mount_opts * mo,const char * opts,int quiet)407*9e564957SAndroid Build Coastguard Worker static int fuse_mount_fusermount(const char *mountpoint, struct mount_opts *mo,
408*9e564957SAndroid Build Coastguard Worker 		const char *opts, int quiet)
409*9e564957SAndroid Build Coastguard Worker {
410*9e564957SAndroid Build Coastguard Worker 	int fds[2];
411*9e564957SAndroid Build Coastguard Worker 	pid_t pid;
412*9e564957SAndroid Build Coastguard Worker 	int res;
413*9e564957SAndroid Build Coastguard Worker 
414*9e564957SAndroid Build Coastguard Worker 	if (!mountpoint) {
415*9e564957SAndroid Build Coastguard Worker 		fuse_log(FUSE_LOG_ERR, "fuse: missing mountpoint parameter\n");
416*9e564957SAndroid Build Coastguard Worker 		return -1;
417*9e564957SAndroid Build Coastguard Worker 	}
418*9e564957SAndroid Build Coastguard Worker 
419*9e564957SAndroid Build Coastguard Worker 	res = socketpair(PF_UNIX, SOCK_STREAM, 0, fds);
420*9e564957SAndroid Build Coastguard Worker 	if(res == -1) {
421*9e564957SAndroid Build Coastguard Worker 		fuse_log(FUSE_LOG_ERR, "Running %s: socketpair() failed: %s\n",
422*9e564957SAndroid Build Coastguard Worker 			 FUSERMOUNT_PROG, strerror(errno));
423*9e564957SAndroid Build Coastguard Worker 		return -1;
424*9e564957SAndroid Build Coastguard Worker 	}
425*9e564957SAndroid Build Coastguard Worker 
426*9e564957SAndroid Build Coastguard Worker 	char arg_fd_entry[30];
427*9e564957SAndroid Build Coastguard Worker 	snprintf(arg_fd_entry, sizeof(arg_fd_entry), "%i", fds[0]);
428*9e564957SAndroid Build Coastguard Worker 	setenv(FUSE_COMMFD_ENV, arg_fd_entry, 1);
429*9e564957SAndroid Build Coastguard Worker 
430*9e564957SAndroid Build Coastguard Worker 	char const *const argv[] = {
431*9e564957SAndroid Build Coastguard Worker 		FUSERMOUNT_PROG,
432*9e564957SAndroid Build Coastguard Worker 		"-o", opts ? opts : "",
433*9e564957SAndroid Build Coastguard Worker 		"--",
434*9e564957SAndroid Build Coastguard Worker 		mountpoint,
435*9e564957SAndroid Build Coastguard Worker 		NULL,
436*9e564957SAndroid Build Coastguard Worker 	};
437*9e564957SAndroid Build Coastguard Worker 
438*9e564957SAndroid Build Coastguard Worker 
439*9e564957SAndroid Build Coastguard Worker 	posix_spawn_file_actions_t action;
440*9e564957SAndroid Build Coastguard Worker 	posix_spawn_file_actions_init(&action);
441*9e564957SAndroid Build Coastguard Worker 
442*9e564957SAndroid Build Coastguard Worker 	if (quiet) {
443*9e564957SAndroid Build Coastguard Worker 		posix_spawn_file_actions_addclose(&action, 1);
444*9e564957SAndroid Build Coastguard Worker 		posix_spawn_file_actions_addclose(&action, 2);
445*9e564957SAndroid Build Coastguard Worker 	}
446*9e564957SAndroid Build Coastguard Worker 	posix_spawn_file_actions_addclose(&action, fds[1]);
447*9e564957SAndroid Build Coastguard Worker 
448*9e564957SAndroid Build Coastguard Worker 	int status = fusermount_posix_spawn(&action, argv, &pid);
449*9e564957SAndroid Build Coastguard Worker 
450*9e564957SAndroid Build Coastguard Worker 	posix_spawn_file_actions_destroy(&action);
451*9e564957SAndroid Build Coastguard Worker 
452*9e564957SAndroid Build Coastguard Worker 	if(status != 0) {
453*9e564957SAndroid Build Coastguard Worker 		close(fds[0]);
454*9e564957SAndroid Build Coastguard Worker 		close(fds[1]);
455*9e564957SAndroid Build Coastguard Worker 		fuse_log(FUSE_LOG_ERR, "posix_spawnp() for %s failed",
456*9e564957SAndroid Build Coastguard Worker 			 FUSERMOUNT_PROG, strerror(errno));
457*9e564957SAndroid Build Coastguard Worker 		return -1;
458*9e564957SAndroid Build Coastguard Worker 	}
459*9e564957SAndroid Build Coastguard Worker 
460*9e564957SAndroid Build Coastguard Worker 	// passed to child now, so can close here.
461*9e564957SAndroid Build Coastguard Worker 	close(fds[0]);
462*9e564957SAndroid Build Coastguard Worker 
463*9e564957SAndroid Build Coastguard Worker 	int fd = receive_fd(fds[1]);
464*9e564957SAndroid Build Coastguard Worker 
465*9e564957SAndroid Build Coastguard Worker 	if (!mo->auto_unmount) {
466*9e564957SAndroid Build Coastguard Worker 		/* with auto_unmount option fusermount3 will not exit until
467*9e564957SAndroid Build Coastguard Worker 		   this socket is closed */
468*9e564957SAndroid Build Coastguard Worker 		close(fds[1]);
469*9e564957SAndroid Build Coastguard Worker 		waitpid(pid, NULL, 0); /* bury zombie */
470*9e564957SAndroid Build Coastguard Worker 	}
471*9e564957SAndroid Build Coastguard Worker 
472*9e564957SAndroid Build Coastguard Worker 	if (fd >= 0)
473*9e564957SAndroid Build Coastguard Worker 		fcntl(fd, F_SETFD, FD_CLOEXEC);
474*9e564957SAndroid Build Coastguard Worker 
475*9e564957SAndroid Build Coastguard Worker 	return fd;
476*9e564957SAndroid Build Coastguard Worker }
477*9e564957SAndroid Build Coastguard Worker 
478*9e564957SAndroid Build Coastguard Worker #ifndef O_CLOEXEC
479*9e564957SAndroid Build Coastguard Worker #define O_CLOEXEC 0
480*9e564957SAndroid Build Coastguard Worker #endif
481*9e564957SAndroid Build Coastguard Worker 
fuse_mount_sys(const char * mnt,struct mount_opts * mo,const char * mnt_opts)482*9e564957SAndroid Build Coastguard Worker static int fuse_mount_sys(const char *mnt, struct mount_opts *mo,
483*9e564957SAndroid Build Coastguard Worker 			  const char *mnt_opts)
484*9e564957SAndroid Build Coastguard Worker {
485*9e564957SAndroid Build Coastguard Worker 	char tmp[128];
486*9e564957SAndroid Build Coastguard Worker 	const char *devname = "/dev/fuse";
487*9e564957SAndroid Build Coastguard Worker 	char *source = NULL;
488*9e564957SAndroid Build Coastguard Worker 	char *type = NULL;
489*9e564957SAndroid Build Coastguard Worker 	struct stat stbuf;
490*9e564957SAndroid Build Coastguard Worker 	int fd;
491*9e564957SAndroid Build Coastguard Worker 	int res;
492*9e564957SAndroid Build Coastguard Worker 
493*9e564957SAndroid Build Coastguard Worker 	if (!mnt) {
494*9e564957SAndroid Build Coastguard Worker 		fuse_log(FUSE_LOG_ERR, "fuse: missing mountpoint parameter\n");
495*9e564957SAndroid Build Coastguard Worker 		return -1;
496*9e564957SAndroid Build Coastguard Worker 	}
497*9e564957SAndroid Build Coastguard Worker 
498*9e564957SAndroid Build Coastguard Worker 	res = stat(mnt, &stbuf);
499*9e564957SAndroid Build Coastguard Worker 	if (res == -1) {
500*9e564957SAndroid Build Coastguard Worker 		fuse_log(FUSE_LOG_ERR, "fuse: failed to access mountpoint %s: %s\n",
501*9e564957SAndroid Build Coastguard Worker 			mnt, strerror(errno));
502*9e564957SAndroid Build Coastguard Worker 		return -1;
503*9e564957SAndroid Build Coastguard Worker 	}
504*9e564957SAndroid Build Coastguard Worker 
505*9e564957SAndroid Build Coastguard Worker 	fd = open(devname, O_RDWR | O_CLOEXEC);
506*9e564957SAndroid Build Coastguard Worker 	if (fd == -1) {
507*9e564957SAndroid Build Coastguard Worker 		if (errno == ENODEV || errno == ENOENT)
508*9e564957SAndroid Build Coastguard Worker 			fuse_log(FUSE_LOG_ERR, "fuse: device not found, try 'modprobe fuse' first\n");
509*9e564957SAndroid Build Coastguard Worker 		else
510*9e564957SAndroid Build Coastguard Worker 			fuse_log(FUSE_LOG_ERR, "fuse: failed to open %s: %s\n",
511*9e564957SAndroid Build Coastguard Worker 				devname, strerror(errno));
512*9e564957SAndroid Build Coastguard Worker 		return -1;
513*9e564957SAndroid Build Coastguard Worker 	}
514*9e564957SAndroid Build Coastguard Worker 	if (!O_CLOEXEC)
515*9e564957SAndroid Build Coastguard Worker 		fcntl(fd, F_SETFD, FD_CLOEXEC);
516*9e564957SAndroid Build Coastguard Worker 
517*9e564957SAndroid Build Coastguard Worker 	snprintf(tmp, sizeof(tmp),  "fd=%i,rootmode=%o,user_id=%u,group_id=%u",
518*9e564957SAndroid Build Coastguard Worker 		 fd, stbuf.st_mode & S_IFMT, getuid(), getgid());
519*9e564957SAndroid Build Coastguard Worker 
520*9e564957SAndroid Build Coastguard Worker 	res = fuse_opt_add_opt(&mo->kernel_opts, tmp);
521*9e564957SAndroid Build Coastguard Worker 	if (res == -1)
522*9e564957SAndroid Build Coastguard Worker 		goto out_close;
523*9e564957SAndroid Build Coastguard Worker 
524*9e564957SAndroid Build Coastguard Worker 	source = malloc((mo->fsname ? strlen(mo->fsname) : 0) +
525*9e564957SAndroid Build Coastguard Worker 			(mo->subtype ? strlen(mo->subtype) : 0) +
526*9e564957SAndroid Build Coastguard Worker 			strlen(devname) + 32);
527*9e564957SAndroid Build Coastguard Worker 
528*9e564957SAndroid Build Coastguard Worker 	type = malloc((mo->subtype ? strlen(mo->subtype) : 0) + 32);
529*9e564957SAndroid Build Coastguard Worker 	if (!type || !source) {
530*9e564957SAndroid Build Coastguard Worker 		fuse_log(FUSE_LOG_ERR, "fuse: failed to allocate memory\n");
531*9e564957SAndroid Build Coastguard Worker 		goto out_close;
532*9e564957SAndroid Build Coastguard Worker 	}
533*9e564957SAndroid Build Coastguard Worker 
534*9e564957SAndroid Build Coastguard Worker 	strcpy(type, mo->blkdev ? "fuseblk" : "fuse");
535*9e564957SAndroid Build Coastguard Worker 	if (mo->subtype) {
536*9e564957SAndroid Build Coastguard Worker 		strcat(type, ".");
537*9e564957SAndroid Build Coastguard Worker 		strcat(type, mo->subtype);
538*9e564957SAndroid Build Coastguard Worker 	}
539*9e564957SAndroid Build Coastguard Worker 	strcpy(source,
540*9e564957SAndroid Build Coastguard Worker 	       mo->fsname ? mo->fsname : (mo->subtype ? mo->subtype : devname));
541*9e564957SAndroid Build Coastguard Worker 
542*9e564957SAndroid Build Coastguard Worker 	res = mount(source, mnt, type, mo->flags, mo->kernel_opts);
543*9e564957SAndroid Build Coastguard Worker 	if (res == -1 && errno == ENODEV && mo->subtype) {
544*9e564957SAndroid Build Coastguard Worker 		/* Probably missing subtype support */
545*9e564957SAndroid Build Coastguard Worker 		strcpy(type, mo->blkdev ? "fuseblk" : "fuse");
546*9e564957SAndroid Build Coastguard Worker 		if (mo->fsname) {
547*9e564957SAndroid Build Coastguard Worker 			if (!mo->blkdev)
548*9e564957SAndroid Build Coastguard Worker 				sprintf(source, "%s#%s", mo->subtype,
549*9e564957SAndroid Build Coastguard Worker 					mo->fsname);
550*9e564957SAndroid Build Coastguard Worker 		} else {
551*9e564957SAndroid Build Coastguard Worker 			strcpy(source, type);
552*9e564957SAndroid Build Coastguard Worker 		}
553*9e564957SAndroid Build Coastguard Worker 		res = mount(source, mnt, type, mo->flags, mo->kernel_opts);
554*9e564957SAndroid Build Coastguard Worker 	}
555*9e564957SAndroid Build Coastguard Worker 	if (res == -1) {
556*9e564957SAndroid Build Coastguard Worker 		/*
557*9e564957SAndroid Build Coastguard Worker 		 * Maybe kernel doesn't support unprivileged mounts, in this
558*9e564957SAndroid Build Coastguard Worker 		 * case try falling back to fusermount3
559*9e564957SAndroid Build Coastguard Worker 		 */
560*9e564957SAndroid Build Coastguard Worker 		if (errno == EPERM) {
561*9e564957SAndroid Build Coastguard Worker 			res = -2;
562*9e564957SAndroid Build Coastguard Worker 		} else {
563*9e564957SAndroid Build Coastguard Worker 			int errno_save = errno;
564*9e564957SAndroid Build Coastguard Worker 			if (mo->blkdev && errno == ENODEV &&
565*9e564957SAndroid Build Coastguard Worker 			    !fuse_mnt_check_fuseblk())
566*9e564957SAndroid Build Coastguard Worker 				fuse_log(FUSE_LOG_ERR,
567*9e564957SAndroid Build Coastguard Worker 					"fuse: 'fuseblk' support missing\n");
568*9e564957SAndroid Build Coastguard Worker 			else
569*9e564957SAndroid Build Coastguard Worker 				fuse_log(FUSE_LOG_ERR, "fuse: mount failed: %s\n",
570*9e564957SAndroid Build Coastguard Worker 					strerror(errno_save));
571*9e564957SAndroid Build Coastguard Worker 		}
572*9e564957SAndroid Build Coastguard Worker 
573*9e564957SAndroid Build Coastguard Worker 		goto out_close;
574*9e564957SAndroid Build Coastguard Worker 	}
575*9e564957SAndroid Build Coastguard Worker 
576*9e564957SAndroid Build Coastguard Worker #ifndef IGNORE_MTAB
577*9e564957SAndroid Build Coastguard Worker 	if (geteuid() == 0) {
578*9e564957SAndroid Build Coastguard Worker 		char *newmnt = fuse_mnt_resolve_path("fuse", mnt);
579*9e564957SAndroid Build Coastguard Worker 		res = -1;
580*9e564957SAndroid Build Coastguard Worker 		if (!newmnt)
581*9e564957SAndroid Build Coastguard Worker 			goto out_umount;
582*9e564957SAndroid Build Coastguard Worker 
583*9e564957SAndroid Build Coastguard Worker 		res = fuse_mnt_add_mount("fuse", source, newmnt, type,
584*9e564957SAndroid Build Coastguard Worker 					 mnt_opts);
585*9e564957SAndroid Build Coastguard Worker 		free(newmnt);
586*9e564957SAndroid Build Coastguard Worker 		if (res == -1)
587*9e564957SAndroid Build Coastguard Worker 			goto out_umount;
588*9e564957SAndroid Build Coastguard Worker 	}
589*9e564957SAndroid Build Coastguard Worker #endif /* IGNORE_MTAB */
590*9e564957SAndroid Build Coastguard Worker 	free(type);
591*9e564957SAndroid Build Coastguard Worker 	free(source);
592*9e564957SAndroid Build Coastguard Worker 
593*9e564957SAndroid Build Coastguard Worker 	return fd;
594*9e564957SAndroid Build Coastguard Worker 
595*9e564957SAndroid Build Coastguard Worker out_umount:
596*9e564957SAndroid Build Coastguard Worker 	umount2(mnt, 2); /* lazy umount */
597*9e564957SAndroid Build Coastguard Worker out_close:
598*9e564957SAndroid Build Coastguard Worker 	free(type);
599*9e564957SAndroid Build Coastguard Worker 	free(source);
600*9e564957SAndroid Build Coastguard Worker 	close(fd);
601*9e564957SAndroid Build Coastguard Worker 	return res;
602*9e564957SAndroid Build Coastguard Worker }
603*9e564957SAndroid Build Coastguard Worker 
get_mnt_flag_opts(char ** mnt_optsp,int flags)604*9e564957SAndroid Build Coastguard Worker static int get_mnt_flag_opts(char **mnt_optsp, int flags)
605*9e564957SAndroid Build Coastguard Worker {
606*9e564957SAndroid Build Coastguard Worker 	int i;
607*9e564957SAndroid Build Coastguard Worker 
608*9e564957SAndroid Build Coastguard Worker 	if (!(flags & MS_RDONLY) && fuse_opt_add_opt(mnt_optsp, "rw") == -1)
609*9e564957SAndroid Build Coastguard Worker 		return -1;
610*9e564957SAndroid Build Coastguard Worker 
611*9e564957SAndroid Build Coastguard Worker 	for (i = 0; mount_flags[i].opt != NULL; i++) {
612*9e564957SAndroid Build Coastguard Worker 		if (mount_flags[i].on && (flags & mount_flags[i].flag) &&
613*9e564957SAndroid Build Coastguard Worker 		    fuse_opt_add_opt(mnt_optsp, mount_flags[i].opt) == -1)
614*9e564957SAndroid Build Coastguard Worker 			return -1;
615*9e564957SAndroid Build Coastguard Worker 	}
616*9e564957SAndroid Build Coastguard Worker 	return 0;
617*9e564957SAndroid Build Coastguard Worker }
618*9e564957SAndroid Build Coastguard Worker 
parse_mount_opts(struct fuse_args * args)619*9e564957SAndroid Build Coastguard Worker struct mount_opts *parse_mount_opts(struct fuse_args *args)
620*9e564957SAndroid Build Coastguard Worker {
621*9e564957SAndroid Build Coastguard Worker 	struct mount_opts *mo;
622*9e564957SAndroid Build Coastguard Worker 
623*9e564957SAndroid Build Coastguard Worker 	mo = (struct mount_opts*) malloc(sizeof(struct mount_opts));
624*9e564957SAndroid Build Coastguard Worker 	if (mo == NULL)
625*9e564957SAndroid Build Coastguard Worker 		return NULL;
626*9e564957SAndroid Build Coastguard Worker 
627*9e564957SAndroid Build Coastguard Worker 	memset(mo, 0, sizeof(struct mount_opts));
628*9e564957SAndroid Build Coastguard Worker 	mo->flags = MS_NOSUID | MS_NODEV;
629*9e564957SAndroid Build Coastguard Worker 
630*9e564957SAndroid Build Coastguard Worker 	if (args &&
631*9e564957SAndroid Build Coastguard Worker 	    fuse_opt_parse(args, mo, fuse_mount_opts, fuse_mount_opt_proc) == -1)
632*9e564957SAndroid Build Coastguard Worker 		goto err_out;
633*9e564957SAndroid Build Coastguard Worker 
634*9e564957SAndroid Build Coastguard Worker 	return mo;
635*9e564957SAndroid Build Coastguard Worker 
636*9e564957SAndroid Build Coastguard Worker err_out:
637*9e564957SAndroid Build Coastguard Worker 	destroy_mount_opts(mo);
638*9e564957SAndroid Build Coastguard Worker 	return NULL;
639*9e564957SAndroid Build Coastguard Worker }
640*9e564957SAndroid Build Coastguard Worker 
destroy_mount_opts(struct mount_opts * mo)641*9e564957SAndroid Build Coastguard Worker void destroy_mount_opts(struct mount_opts *mo)
642*9e564957SAndroid Build Coastguard Worker {
643*9e564957SAndroid Build Coastguard Worker 	free(mo->fsname);
644*9e564957SAndroid Build Coastguard Worker 	free(mo->subtype);
645*9e564957SAndroid Build Coastguard Worker 	free(mo->fusermount_opts);
646*9e564957SAndroid Build Coastguard Worker 	free(mo->subtype_opt);
647*9e564957SAndroid Build Coastguard Worker 	free(mo->kernel_opts);
648*9e564957SAndroid Build Coastguard Worker 	free(mo->mtab_opts);
649*9e564957SAndroid Build Coastguard Worker 	free(mo);
650*9e564957SAndroid Build Coastguard Worker }
651*9e564957SAndroid Build Coastguard Worker 
652*9e564957SAndroid Build Coastguard Worker 
fuse_kern_mount(const char * mountpoint,struct mount_opts * mo)653*9e564957SAndroid Build Coastguard Worker int fuse_kern_mount(const char *mountpoint, struct mount_opts *mo)
654*9e564957SAndroid Build Coastguard Worker {
655*9e564957SAndroid Build Coastguard Worker 	int res = -1;
656*9e564957SAndroid Build Coastguard Worker 	char *mnt_opts = NULL;
657*9e564957SAndroid Build Coastguard Worker 
658*9e564957SAndroid Build Coastguard Worker 	res = -1;
659*9e564957SAndroid Build Coastguard Worker 	if (get_mnt_flag_opts(&mnt_opts, mo->flags) == -1)
660*9e564957SAndroid Build Coastguard Worker 		goto out;
661*9e564957SAndroid Build Coastguard Worker 	if (mo->kernel_opts && fuse_opt_add_opt(&mnt_opts, mo->kernel_opts) == -1)
662*9e564957SAndroid Build Coastguard Worker 		goto out;
663*9e564957SAndroid Build Coastguard Worker 	if (mo->mtab_opts &&  fuse_opt_add_opt(&mnt_opts, mo->mtab_opts) == -1)
664*9e564957SAndroid Build Coastguard Worker 		goto out;
665*9e564957SAndroid Build Coastguard Worker 
666*9e564957SAndroid Build Coastguard Worker 	res = fuse_mount_sys(mountpoint, mo, mnt_opts);
667*9e564957SAndroid Build Coastguard Worker 	if (res >= 0 && mo->auto_unmount) {
668*9e564957SAndroid Build Coastguard Worker 		if(0 > setup_auto_unmount(mountpoint, 0)) {
669*9e564957SAndroid Build Coastguard Worker 			// Something went wrong, let's umount like in fuse_mount_sys.
670*9e564957SAndroid Build Coastguard Worker 			umount2(mountpoint, MNT_DETACH); /* lazy umount */
671*9e564957SAndroid Build Coastguard Worker 			res = -1;
672*9e564957SAndroid Build Coastguard Worker 		}
673*9e564957SAndroid Build Coastguard Worker 	} else if (res == -2) {
674*9e564957SAndroid Build Coastguard Worker 		if (mo->fusermount_opts &&
675*9e564957SAndroid Build Coastguard Worker 		    fuse_opt_add_opt(&mnt_opts, mo->fusermount_opts) == -1)
676*9e564957SAndroid Build Coastguard Worker 			goto out;
677*9e564957SAndroid Build Coastguard Worker 
678*9e564957SAndroid Build Coastguard Worker 		if (mo->subtype) {
679*9e564957SAndroid Build Coastguard Worker 			char *tmp_opts = NULL;
680*9e564957SAndroid Build Coastguard Worker 
681*9e564957SAndroid Build Coastguard Worker 			res = -1;
682*9e564957SAndroid Build Coastguard Worker 			if (fuse_opt_add_opt(&tmp_opts, mnt_opts) == -1 ||
683*9e564957SAndroid Build Coastguard Worker 			    fuse_opt_add_opt(&tmp_opts, mo->subtype_opt) == -1) {
684*9e564957SAndroid Build Coastguard Worker 				free(tmp_opts);
685*9e564957SAndroid Build Coastguard Worker 				goto out;
686*9e564957SAndroid Build Coastguard Worker 			}
687*9e564957SAndroid Build Coastguard Worker 
688*9e564957SAndroid Build Coastguard Worker 			res = fuse_mount_fusermount(mountpoint, mo, tmp_opts, 1);
689*9e564957SAndroid Build Coastguard Worker 			free(tmp_opts);
690*9e564957SAndroid Build Coastguard Worker 			if (res == -1)
691*9e564957SAndroid Build Coastguard Worker 				res = fuse_mount_fusermount(mountpoint, mo,
692*9e564957SAndroid Build Coastguard Worker 							    mnt_opts, 0);
693*9e564957SAndroid Build Coastguard Worker 		} else {
694*9e564957SAndroid Build Coastguard Worker 			res = fuse_mount_fusermount(mountpoint, mo, mnt_opts, 0);
695*9e564957SAndroid Build Coastguard Worker 		}
696*9e564957SAndroid Build Coastguard Worker 	}
697*9e564957SAndroid Build Coastguard Worker out:
698*9e564957SAndroid Build Coastguard Worker 	free(mnt_opts);
699*9e564957SAndroid Build Coastguard Worker 	return res;
700*9e564957SAndroid Build Coastguard Worker }
701