xref: /aosp_15_r20/external/libfuse/lib/mount_util.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-independent mounting code.
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 #include "fuse_config.h"
12*9e564957SAndroid Build Coastguard Worker #include "mount_util.h"
13*9e564957SAndroid Build Coastguard Worker 
14*9e564957SAndroid Build Coastguard Worker #include <stdio.h>
15*9e564957SAndroid Build Coastguard Worker #include <unistd.h>
16*9e564957SAndroid Build Coastguard Worker #include <stdlib.h>
17*9e564957SAndroid Build Coastguard Worker #include <string.h>
18*9e564957SAndroid Build Coastguard Worker #include <signal.h>
19*9e564957SAndroid Build Coastguard Worker #include <dirent.h>
20*9e564957SAndroid Build Coastguard Worker #include <errno.h>
21*9e564957SAndroid Build Coastguard Worker #include <fcntl.h>
22*9e564957SAndroid Build Coastguard Worker #include <limits.h>
23*9e564957SAndroid Build Coastguard Worker #include <paths.h>
24*9e564957SAndroid Build Coastguard Worker #if !defined( __NetBSD__) && !defined(__FreeBSD__) && !defined(__DragonFly__) && !defined(__ANDROID__)
25*9e564957SAndroid Build Coastguard Worker #include <mntent.h>
26*9e564957SAndroid Build Coastguard Worker #else
27*9e564957SAndroid Build Coastguard Worker #define IGNORE_MTAB
28*9e564957SAndroid Build Coastguard Worker #endif
29*9e564957SAndroid Build Coastguard Worker #include <sys/stat.h>
30*9e564957SAndroid Build Coastguard Worker #include <sys/wait.h>
31*9e564957SAndroid Build Coastguard Worker 
32*9e564957SAndroid Build Coastguard Worker #include "fuse_mount_compat.h"
33*9e564957SAndroid Build Coastguard Worker 
34*9e564957SAndroid Build Coastguard Worker #include <sys/param.h>
35*9e564957SAndroid Build Coastguard Worker 
36*9e564957SAndroid Build Coastguard Worker #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__)
37*9e564957SAndroid Build Coastguard Worker #define umount2(mnt, flags) unmount(mnt, ((flags) == 2) ? MNT_FORCE : 0)
38*9e564957SAndroid Build Coastguard Worker #endif
39*9e564957SAndroid Build Coastguard Worker 
40*9e564957SAndroid Build Coastguard Worker #ifdef IGNORE_MTAB
41*9e564957SAndroid Build Coastguard Worker #define mtab_needs_update(mnt) 0
42*9e564957SAndroid Build Coastguard Worker #else
mtab_needs_update(const char * mnt)43*9e564957SAndroid Build Coastguard Worker static int mtab_needs_update(const char *mnt)
44*9e564957SAndroid Build Coastguard Worker {
45*9e564957SAndroid Build Coastguard Worker 	int res;
46*9e564957SAndroid Build Coastguard Worker 	struct stat stbuf;
47*9e564957SAndroid Build Coastguard Worker 
48*9e564957SAndroid Build Coastguard Worker 	/* If mtab is within new mount, don't touch it */
49*9e564957SAndroid Build Coastguard Worker 	if (strncmp(mnt, _PATH_MOUNTED, strlen(mnt)) == 0 &&
50*9e564957SAndroid Build Coastguard Worker 	    _PATH_MOUNTED[strlen(mnt)] == '/')
51*9e564957SAndroid Build Coastguard Worker 		return 0;
52*9e564957SAndroid Build Coastguard Worker 
53*9e564957SAndroid Build Coastguard Worker 	/*
54*9e564957SAndroid Build Coastguard Worker 	 * Skip mtab update if /etc/mtab:
55*9e564957SAndroid Build Coastguard Worker 	 *
56*9e564957SAndroid Build Coastguard Worker 	 *  - doesn't exist,
57*9e564957SAndroid Build Coastguard Worker 	 *  - is on a read-only filesystem.
58*9e564957SAndroid Build Coastguard Worker 	 */
59*9e564957SAndroid Build Coastguard Worker 	res = lstat(_PATH_MOUNTED, &stbuf);
60*9e564957SAndroid Build Coastguard Worker 	if (res == -1) {
61*9e564957SAndroid Build Coastguard Worker 		if (errno == ENOENT)
62*9e564957SAndroid Build Coastguard Worker 			return 0;
63*9e564957SAndroid Build Coastguard Worker 	} else {
64*9e564957SAndroid Build Coastguard Worker 		uid_t ruid;
65*9e564957SAndroid Build Coastguard Worker 		int err;
66*9e564957SAndroid Build Coastguard Worker 
67*9e564957SAndroid Build Coastguard Worker 		ruid = getuid();
68*9e564957SAndroid Build Coastguard Worker 		if (ruid != 0)
69*9e564957SAndroid Build Coastguard Worker 			setreuid(0, -1);
70*9e564957SAndroid Build Coastguard Worker 
71*9e564957SAndroid Build Coastguard Worker 		res = access(_PATH_MOUNTED, W_OK);
72*9e564957SAndroid Build Coastguard Worker 		err = (res == -1) ? errno : 0;
73*9e564957SAndroid Build Coastguard Worker 		if (ruid != 0)
74*9e564957SAndroid Build Coastguard Worker 			setreuid(ruid, -1);
75*9e564957SAndroid Build Coastguard Worker 
76*9e564957SAndroid Build Coastguard Worker 		if (err == EROFS)
77*9e564957SAndroid Build Coastguard Worker 			return 0;
78*9e564957SAndroid Build Coastguard Worker 	}
79*9e564957SAndroid Build Coastguard Worker 
80*9e564957SAndroid Build Coastguard Worker 	return 1;
81*9e564957SAndroid Build Coastguard Worker }
82*9e564957SAndroid Build Coastguard Worker #endif /* IGNORE_MTAB */
83*9e564957SAndroid Build Coastguard Worker 
add_mount(const char * progname,const char * fsname,const char * mnt,const char * type,const char * opts)84*9e564957SAndroid Build Coastguard Worker static int add_mount(const char *progname, const char *fsname,
85*9e564957SAndroid Build Coastguard Worker 		       const char *mnt, const char *type, const char *opts)
86*9e564957SAndroid Build Coastguard Worker {
87*9e564957SAndroid Build Coastguard Worker 	int res;
88*9e564957SAndroid Build Coastguard Worker 	int status;
89*9e564957SAndroid Build Coastguard Worker 	sigset_t blockmask;
90*9e564957SAndroid Build Coastguard Worker 	sigset_t oldmask;
91*9e564957SAndroid Build Coastguard Worker 
92*9e564957SAndroid Build Coastguard Worker 	sigemptyset(&blockmask);
93*9e564957SAndroid Build Coastguard Worker 	sigaddset(&blockmask, SIGCHLD);
94*9e564957SAndroid Build Coastguard Worker 	res = sigprocmask(SIG_BLOCK, &blockmask, &oldmask);
95*9e564957SAndroid Build Coastguard Worker 	if (res == -1) {
96*9e564957SAndroid Build Coastguard Worker 		fprintf(stderr, "%s: sigprocmask: %s\n", progname, strerror(errno));
97*9e564957SAndroid Build Coastguard Worker 		return -1;
98*9e564957SAndroid Build Coastguard Worker 	}
99*9e564957SAndroid Build Coastguard Worker 
100*9e564957SAndroid Build Coastguard Worker 	res = fork();
101*9e564957SAndroid Build Coastguard Worker 	if (res == -1) {
102*9e564957SAndroid Build Coastguard Worker 		fprintf(stderr, "%s: fork: %s\n", progname, strerror(errno));
103*9e564957SAndroid Build Coastguard Worker 		goto out_restore;
104*9e564957SAndroid Build Coastguard Worker 	}
105*9e564957SAndroid Build Coastguard Worker 	if (res == 0) {
106*9e564957SAndroid Build Coastguard Worker 		char *env = NULL;
107*9e564957SAndroid Build Coastguard Worker 
108*9e564957SAndroid Build Coastguard Worker 		sigprocmask(SIG_SETMASK, &oldmask, NULL);
109*9e564957SAndroid Build Coastguard Worker 
110*9e564957SAndroid Build Coastguard Worker 		if(setuid(geteuid()) == -1) {
111*9e564957SAndroid Build Coastguard Worker 			fprintf(stderr, "%s: setuid: %s\n", progname, strerror(errno));
112*9e564957SAndroid Build Coastguard Worker 			res = -1;
113*9e564957SAndroid Build Coastguard Worker 			goto out_restore;
114*9e564957SAndroid Build Coastguard Worker 		}
115*9e564957SAndroid Build Coastguard Worker 
116*9e564957SAndroid Build Coastguard Worker 		execle("/bin/mount", "/bin/mount", "--no-canonicalize", "-i",
117*9e564957SAndroid Build Coastguard Worker 		       "-f", "-t", type, "-o", opts, fsname, mnt, NULL, &env);
118*9e564957SAndroid Build Coastguard Worker 		fprintf(stderr, "%s: failed to execute /bin/mount: %s\n",
119*9e564957SAndroid Build Coastguard Worker 			progname, strerror(errno));
120*9e564957SAndroid Build Coastguard Worker 		exit(1);
121*9e564957SAndroid Build Coastguard Worker 	}
122*9e564957SAndroid Build Coastguard Worker 	res = waitpid(res, &status, 0);
123*9e564957SAndroid Build Coastguard Worker 	if (res == -1)
124*9e564957SAndroid Build Coastguard Worker 		fprintf(stderr, "%s: waitpid: %s\n", progname, strerror(errno));
125*9e564957SAndroid Build Coastguard Worker 
126*9e564957SAndroid Build Coastguard Worker 	if (status != 0)
127*9e564957SAndroid Build Coastguard Worker 		res = -1;
128*9e564957SAndroid Build Coastguard Worker 
129*9e564957SAndroid Build Coastguard Worker  out_restore:
130*9e564957SAndroid Build Coastguard Worker 	sigprocmask(SIG_SETMASK, &oldmask, NULL);
131*9e564957SAndroid Build Coastguard Worker 
132*9e564957SAndroid Build Coastguard Worker 	return res;
133*9e564957SAndroid Build Coastguard Worker }
134*9e564957SAndroid Build Coastguard Worker 
fuse_mnt_add_mount(const char * progname,const char * fsname,const char * mnt,const char * type,const char * opts)135*9e564957SAndroid Build Coastguard Worker int fuse_mnt_add_mount(const char *progname, const char *fsname,
136*9e564957SAndroid Build Coastguard Worker 		       const char *mnt, const char *type, const char *opts)
137*9e564957SAndroid Build Coastguard Worker {
138*9e564957SAndroid Build Coastguard Worker 	if (!mtab_needs_update(mnt))
139*9e564957SAndroid Build Coastguard Worker 		return 0;
140*9e564957SAndroid Build Coastguard Worker 
141*9e564957SAndroid Build Coastguard Worker 	return add_mount(progname, fsname, mnt, type, opts);
142*9e564957SAndroid Build Coastguard Worker }
143*9e564957SAndroid Build Coastguard Worker 
exec_umount(const char * progname,const char * rel_mnt,int lazy)144*9e564957SAndroid Build Coastguard Worker static int exec_umount(const char *progname, const char *rel_mnt, int lazy)
145*9e564957SAndroid Build Coastguard Worker {
146*9e564957SAndroid Build Coastguard Worker 	int res;
147*9e564957SAndroid Build Coastguard Worker 	int status;
148*9e564957SAndroid Build Coastguard Worker 	sigset_t blockmask;
149*9e564957SAndroid Build Coastguard Worker 	sigset_t oldmask;
150*9e564957SAndroid Build Coastguard Worker 
151*9e564957SAndroid Build Coastguard Worker 	sigemptyset(&blockmask);
152*9e564957SAndroid Build Coastguard Worker 	sigaddset(&blockmask, SIGCHLD);
153*9e564957SAndroid Build Coastguard Worker 	res = sigprocmask(SIG_BLOCK, &blockmask, &oldmask);
154*9e564957SAndroid Build Coastguard Worker 	if (res == -1) {
155*9e564957SAndroid Build Coastguard Worker 		fprintf(stderr, "%s: sigprocmask: %s\n", progname, strerror(errno));
156*9e564957SAndroid Build Coastguard Worker 		return -1;
157*9e564957SAndroid Build Coastguard Worker 	}
158*9e564957SAndroid Build Coastguard Worker 
159*9e564957SAndroid Build Coastguard Worker 	res = fork();
160*9e564957SAndroid Build Coastguard Worker 	if (res == -1) {
161*9e564957SAndroid Build Coastguard Worker 		fprintf(stderr, "%s: fork: %s\n", progname, strerror(errno));
162*9e564957SAndroid Build Coastguard Worker 		goto out_restore;
163*9e564957SAndroid Build Coastguard Worker 	}
164*9e564957SAndroid Build Coastguard Worker 	if (res == 0) {
165*9e564957SAndroid Build Coastguard Worker 		char *env = NULL;
166*9e564957SAndroid Build Coastguard Worker 
167*9e564957SAndroid Build Coastguard Worker 		sigprocmask(SIG_SETMASK, &oldmask, NULL);
168*9e564957SAndroid Build Coastguard Worker 
169*9e564957SAndroid Build Coastguard Worker 		if(setuid(geteuid()) == -1) {
170*9e564957SAndroid Build Coastguard Worker 			fprintf(stderr, "%s: setuid: %s\n", progname, strerror(errno));
171*9e564957SAndroid Build Coastguard Worker 			res = -1;
172*9e564957SAndroid Build Coastguard Worker 			goto out_restore;
173*9e564957SAndroid Build Coastguard Worker 		}
174*9e564957SAndroid Build Coastguard Worker 
175*9e564957SAndroid Build Coastguard Worker 		if (lazy) {
176*9e564957SAndroid Build Coastguard Worker 			execle("/bin/umount", "/bin/umount", "-i", rel_mnt,
177*9e564957SAndroid Build Coastguard Worker 			       "-l", NULL, &env);
178*9e564957SAndroid Build Coastguard Worker 		} else {
179*9e564957SAndroid Build Coastguard Worker 			execle("/bin/umount", "/bin/umount", "-i", rel_mnt,
180*9e564957SAndroid Build Coastguard Worker 			       NULL, &env);
181*9e564957SAndroid Build Coastguard Worker 		}
182*9e564957SAndroid Build Coastguard Worker 		fprintf(stderr, "%s: failed to execute /bin/umount: %s\n",
183*9e564957SAndroid Build Coastguard Worker 			progname, strerror(errno));
184*9e564957SAndroid Build Coastguard Worker 		exit(1);
185*9e564957SAndroid Build Coastguard Worker 	}
186*9e564957SAndroid Build Coastguard Worker 	res = waitpid(res, &status, 0);
187*9e564957SAndroid Build Coastguard Worker 	if (res == -1)
188*9e564957SAndroid Build Coastguard Worker 		fprintf(stderr, "%s: waitpid: %s\n", progname, strerror(errno));
189*9e564957SAndroid Build Coastguard Worker 
190*9e564957SAndroid Build Coastguard Worker 	if (status != 0) {
191*9e564957SAndroid Build Coastguard Worker 		res = -1;
192*9e564957SAndroid Build Coastguard Worker 	}
193*9e564957SAndroid Build Coastguard Worker 
194*9e564957SAndroid Build Coastguard Worker  out_restore:
195*9e564957SAndroid Build Coastguard Worker 	sigprocmask(SIG_SETMASK, &oldmask, NULL);
196*9e564957SAndroid Build Coastguard Worker 	return res;
197*9e564957SAndroid Build Coastguard Worker 
198*9e564957SAndroid Build Coastguard Worker }
199*9e564957SAndroid Build Coastguard Worker 
fuse_mnt_umount(const char * progname,const char * abs_mnt,const char * rel_mnt,int lazy)200*9e564957SAndroid Build Coastguard Worker int fuse_mnt_umount(const char *progname, const char *abs_mnt,
201*9e564957SAndroid Build Coastguard Worker 		    const char *rel_mnt, int lazy)
202*9e564957SAndroid Build Coastguard Worker {
203*9e564957SAndroid Build Coastguard Worker 	int res;
204*9e564957SAndroid Build Coastguard Worker 
205*9e564957SAndroid Build Coastguard Worker 	if (!mtab_needs_update(abs_mnt)) {
206*9e564957SAndroid Build Coastguard Worker 		res = umount2(rel_mnt, lazy ? 2 : 0);
207*9e564957SAndroid Build Coastguard Worker 		if (res == -1)
208*9e564957SAndroid Build Coastguard Worker 			fprintf(stderr, "%s: failed to unmount %s: %s\n",
209*9e564957SAndroid Build Coastguard Worker 				progname, abs_mnt, strerror(errno));
210*9e564957SAndroid Build Coastguard Worker 		return res;
211*9e564957SAndroid Build Coastguard Worker 	}
212*9e564957SAndroid Build Coastguard Worker 
213*9e564957SAndroid Build Coastguard Worker 	return exec_umount(progname, rel_mnt, lazy);
214*9e564957SAndroid Build Coastguard Worker }
215*9e564957SAndroid Build Coastguard Worker 
remove_mount(const char * progname,const char * mnt)216*9e564957SAndroid Build Coastguard Worker static int remove_mount(const char *progname, const char *mnt)
217*9e564957SAndroid Build Coastguard Worker {
218*9e564957SAndroid Build Coastguard Worker 	int res;
219*9e564957SAndroid Build Coastguard Worker 	int status;
220*9e564957SAndroid Build Coastguard Worker 	sigset_t blockmask;
221*9e564957SAndroid Build Coastguard Worker 	sigset_t oldmask;
222*9e564957SAndroid Build Coastguard Worker 
223*9e564957SAndroid Build Coastguard Worker 	sigemptyset(&blockmask);
224*9e564957SAndroid Build Coastguard Worker 	sigaddset(&blockmask, SIGCHLD);
225*9e564957SAndroid Build Coastguard Worker 	res = sigprocmask(SIG_BLOCK, &blockmask, &oldmask);
226*9e564957SAndroid Build Coastguard Worker 	if (res == -1) {
227*9e564957SAndroid Build Coastguard Worker 		fprintf(stderr, "%s: sigprocmask: %s\n", progname, strerror(errno));
228*9e564957SAndroid Build Coastguard Worker 		return -1;
229*9e564957SAndroid Build Coastguard Worker 	}
230*9e564957SAndroid Build Coastguard Worker 
231*9e564957SAndroid Build Coastguard Worker 	res = fork();
232*9e564957SAndroid Build Coastguard Worker 	if (res == -1) {
233*9e564957SAndroid Build Coastguard Worker 		fprintf(stderr, "%s: fork: %s\n", progname, strerror(errno));
234*9e564957SAndroid Build Coastguard Worker 		goto out_restore;
235*9e564957SAndroid Build Coastguard Worker 	}
236*9e564957SAndroid Build Coastguard Worker 	if (res == 0) {
237*9e564957SAndroid Build Coastguard Worker 		char *env = NULL;
238*9e564957SAndroid Build Coastguard Worker 
239*9e564957SAndroid Build Coastguard Worker 		sigprocmask(SIG_SETMASK, &oldmask, NULL);
240*9e564957SAndroid Build Coastguard Worker 
241*9e564957SAndroid Build Coastguard Worker 		if(setuid(geteuid()) == -1) {
242*9e564957SAndroid Build Coastguard Worker 			fprintf(stderr, "%s: setuid: %s\n", progname, strerror(errno));
243*9e564957SAndroid Build Coastguard Worker 			res = -1;
244*9e564957SAndroid Build Coastguard Worker 			goto out_restore;
245*9e564957SAndroid Build Coastguard Worker 		}
246*9e564957SAndroid Build Coastguard Worker 
247*9e564957SAndroid Build Coastguard Worker 		execle("/bin/umount", "/bin/umount", "--no-canonicalize", "-i",
248*9e564957SAndroid Build Coastguard Worker 		       "--fake", mnt, NULL, &env);
249*9e564957SAndroid Build Coastguard Worker 		fprintf(stderr, "%s: failed to execute /bin/umount: %s\n",
250*9e564957SAndroid Build Coastguard Worker 			progname, strerror(errno));
251*9e564957SAndroid Build Coastguard Worker 		exit(1);
252*9e564957SAndroid Build Coastguard Worker 	}
253*9e564957SAndroid Build Coastguard Worker 	res = waitpid(res, &status, 0);
254*9e564957SAndroid Build Coastguard Worker 	if (res == -1)
255*9e564957SAndroid Build Coastguard Worker 		fprintf(stderr, "%s: waitpid: %s\n", progname, strerror(errno));
256*9e564957SAndroid Build Coastguard Worker 
257*9e564957SAndroid Build Coastguard Worker 	if (status != 0)
258*9e564957SAndroid Build Coastguard Worker 		res = -1;
259*9e564957SAndroid Build Coastguard Worker 
260*9e564957SAndroid Build Coastguard Worker  out_restore:
261*9e564957SAndroid Build Coastguard Worker 	sigprocmask(SIG_SETMASK, &oldmask, NULL);
262*9e564957SAndroid Build Coastguard Worker 	return res;
263*9e564957SAndroid Build Coastguard Worker }
264*9e564957SAndroid Build Coastguard Worker 
fuse_mnt_remove_mount(const char * progname,const char * mnt)265*9e564957SAndroid Build Coastguard Worker int fuse_mnt_remove_mount(const char *progname, const char *mnt)
266*9e564957SAndroid Build Coastguard Worker {
267*9e564957SAndroid Build Coastguard Worker 	if (!mtab_needs_update(mnt))
268*9e564957SAndroid Build Coastguard Worker 		return 0;
269*9e564957SAndroid Build Coastguard Worker 
270*9e564957SAndroid Build Coastguard Worker 	return remove_mount(progname, mnt);
271*9e564957SAndroid Build Coastguard Worker }
272*9e564957SAndroid Build Coastguard Worker 
fuse_mnt_resolve_path(const char * progname,const char * orig)273*9e564957SAndroid Build Coastguard Worker char *fuse_mnt_resolve_path(const char *progname, const char *orig)
274*9e564957SAndroid Build Coastguard Worker {
275*9e564957SAndroid Build Coastguard Worker 	char buf[PATH_MAX];
276*9e564957SAndroid Build Coastguard Worker 	char *copy;
277*9e564957SAndroid Build Coastguard Worker 	char *dst;
278*9e564957SAndroid Build Coastguard Worker 	char *end;
279*9e564957SAndroid Build Coastguard Worker 	char *lastcomp;
280*9e564957SAndroid Build Coastguard Worker 	const char *toresolv;
281*9e564957SAndroid Build Coastguard Worker 
282*9e564957SAndroid Build Coastguard Worker 	if (!orig[0]) {
283*9e564957SAndroid Build Coastguard Worker 		fprintf(stderr, "%s: invalid mountpoint '%s'\n", progname,
284*9e564957SAndroid Build Coastguard Worker 			orig);
285*9e564957SAndroid Build Coastguard Worker 		return NULL;
286*9e564957SAndroid Build Coastguard Worker 	}
287*9e564957SAndroid Build Coastguard Worker 
288*9e564957SAndroid Build Coastguard Worker 	copy = strdup(orig);
289*9e564957SAndroid Build Coastguard Worker 	if (copy == NULL) {
290*9e564957SAndroid Build Coastguard Worker 		fprintf(stderr, "%s: failed to allocate memory\n", progname);
291*9e564957SAndroid Build Coastguard Worker 		return NULL;
292*9e564957SAndroid Build Coastguard Worker 	}
293*9e564957SAndroid Build Coastguard Worker 
294*9e564957SAndroid Build Coastguard Worker 	toresolv = copy;
295*9e564957SAndroid Build Coastguard Worker 	lastcomp = NULL;
296*9e564957SAndroid Build Coastguard Worker 	for (end = copy + strlen(copy) - 1; end > copy && *end == '/'; end --);
297*9e564957SAndroid Build Coastguard Worker 	if (end[0] != '/') {
298*9e564957SAndroid Build Coastguard Worker 		char *tmp;
299*9e564957SAndroid Build Coastguard Worker 		end[1] = '\0';
300*9e564957SAndroid Build Coastguard Worker 		tmp = strrchr(copy, '/');
301*9e564957SAndroid Build Coastguard Worker 		if (tmp == NULL) {
302*9e564957SAndroid Build Coastguard Worker 			lastcomp = copy;
303*9e564957SAndroid Build Coastguard Worker 			toresolv = ".";
304*9e564957SAndroid Build Coastguard Worker 		} else {
305*9e564957SAndroid Build Coastguard Worker 			lastcomp = tmp + 1;
306*9e564957SAndroid Build Coastguard Worker 			if (tmp == copy)
307*9e564957SAndroid Build Coastguard Worker 				toresolv = "/";
308*9e564957SAndroid Build Coastguard Worker 		}
309*9e564957SAndroid Build Coastguard Worker 		if (strcmp(lastcomp, ".") == 0 || strcmp(lastcomp, "..") == 0) {
310*9e564957SAndroid Build Coastguard Worker 			lastcomp = NULL;
311*9e564957SAndroid Build Coastguard Worker 			toresolv = copy;
312*9e564957SAndroid Build Coastguard Worker 		}
313*9e564957SAndroid Build Coastguard Worker 		else if (tmp)
314*9e564957SAndroid Build Coastguard Worker 			tmp[0] = '\0';
315*9e564957SAndroid Build Coastguard Worker 	}
316*9e564957SAndroid Build Coastguard Worker 	if (realpath(toresolv, buf) == NULL) {
317*9e564957SAndroid Build Coastguard Worker 		fprintf(stderr, "%s: bad mount point %s: %s\n", progname, orig,
318*9e564957SAndroid Build Coastguard Worker 			strerror(errno));
319*9e564957SAndroid Build Coastguard Worker 		free(copy);
320*9e564957SAndroid Build Coastguard Worker 		return NULL;
321*9e564957SAndroid Build Coastguard Worker 	}
322*9e564957SAndroid Build Coastguard Worker 	if (lastcomp == NULL)
323*9e564957SAndroid Build Coastguard Worker 		dst = strdup(buf);
324*9e564957SAndroid Build Coastguard Worker 	else {
325*9e564957SAndroid Build Coastguard Worker 		dst = (char *) malloc(strlen(buf) + 1 + strlen(lastcomp) + 1);
326*9e564957SAndroid Build Coastguard Worker 		if (dst) {
327*9e564957SAndroid Build Coastguard Worker 			unsigned buflen = strlen(buf);
328*9e564957SAndroid Build Coastguard Worker 			if (buflen && buf[buflen-1] == '/')
329*9e564957SAndroid Build Coastguard Worker 				sprintf(dst, "%s%s", buf, lastcomp);
330*9e564957SAndroid Build Coastguard Worker 			else
331*9e564957SAndroid Build Coastguard Worker 				sprintf(dst, "%s/%s", buf, lastcomp);
332*9e564957SAndroid Build Coastguard Worker 		}
333*9e564957SAndroid Build Coastguard Worker 	}
334*9e564957SAndroid Build Coastguard Worker 	free(copy);
335*9e564957SAndroid Build Coastguard Worker 	if (dst == NULL)
336*9e564957SAndroid Build Coastguard Worker 		fprintf(stderr, "%s: failed to allocate memory\n", progname);
337*9e564957SAndroid Build Coastguard Worker 	return dst;
338*9e564957SAndroid Build Coastguard Worker }
339*9e564957SAndroid Build Coastguard Worker 
fuse_mnt_check_fuseblk(void)340*9e564957SAndroid Build Coastguard Worker int fuse_mnt_check_fuseblk(void)
341*9e564957SAndroid Build Coastguard Worker {
342*9e564957SAndroid Build Coastguard Worker 	char buf[256];
343*9e564957SAndroid Build Coastguard Worker 	FILE *f = fopen("/proc/filesystems", "r");
344*9e564957SAndroid Build Coastguard Worker 	if (!f)
345*9e564957SAndroid Build Coastguard Worker 		return 1;
346*9e564957SAndroid Build Coastguard Worker 
347*9e564957SAndroid Build Coastguard Worker 	while (fgets(buf, sizeof(buf), f))
348*9e564957SAndroid Build Coastguard Worker 		if (strstr(buf, "fuseblk\n")) {
349*9e564957SAndroid Build Coastguard Worker 			fclose(f);
350*9e564957SAndroid Build Coastguard Worker 			return 1;
351*9e564957SAndroid Build Coastguard Worker 		}
352*9e564957SAndroid Build Coastguard Worker 
353*9e564957SAndroid Build Coastguard Worker 	fclose(f);
354*9e564957SAndroid Build Coastguard Worker 	return 0;
355*9e564957SAndroid Build Coastguard Worker }
356*9e564957SAndroid Build Coastguard Worker 
fuse_mnt_parse_fuse_fd(const char * mountpoint)357*9e564957SAndroid Build Coastguard Worker int fuse_mnt_parse_fuse_fd(const char *mountpoint)
358*9e564957SAndroid Build Coastguard Worker {
359*9e564957SAndroid Build Coastguard Worker 	int fd = -1;
360*9e564957SAndroid Build Coastguard Worker 	int len = 0;
361*9e564957SAndroid Build Coastguard Worker 
362*9e564957SAndroid Build Coastguard Worker 	if (sscanf(mountpoint, "/dev/fd/%u%n", &fd, &len) == 1 &&
363*9e564957SAndroid Build Coastguard Worker 	    len == strlen(mountpoint)) {
364*9e564957SAndroid Build Coastguard Worker 		return fd;
365*9e564957SAndroid Build Coastguard Worker 	}
366*9e564957SAndroid Build Coastguard Worker 
367*9e564957SAndroid Build Coastguard Worker 	return -1;
368*9e564957SAndroid Build Coastguard Worker }
369