11#include "fuse_config.h"
12#include "mount_util.h"
25#if !defined( __NetBSD__) && !defined(__FreeBSD__) && !defined(__DragonFly__) && !defined(__ANDROID__)
33#include "fuse_mount_compat.h"
37#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__)
38#define umount2(mnt, flags) unmount(mnt, ((flags) == 2) ? MNT_FORCE : 0)
42#define mtab_needs_update(mnt) 0
44static int mtab_needs_update(
const char *mnt)
50 if (strncmp(mnt, _PATH_MOUNTED, strlen(mnt)) == 0 &&
51 _PATH_MOUNTED[strlen(mnt)] ==
'/')
60 res = lstat(_PATH_MOUNTED, &stbuf);
72 res = access(_PATH_MOUNTED, W_OK);
73 err = (res == -1) ? errno : 0;
80 res = access(
"/run/mount/utab", F_OK);
97static int unsafe_operand(
const char *value)
99 return value == NULL || value[0] ==
'-';
102static int add_mount(
const char *progname,
const char *fsname,
103 const char *mnt,
const char *type,
const char *opts)
110 if (unsafe_operand(fsname) || unsafe_operand(mnt) ||
111 unsafe_operand(type) || unsafe_operand(opts)) {
113 "%s: option-like mount argument, skipping mtab update\n",
118 sigemptyset(&blockmask);
119 sigaddset(&blockmask, SIGCHLD);
120 res = sigprocmask(SIG_BLOCK, &blockmask, &oldmask);
122 fprintf(stderr,
"%s: sigprocmask: %s\n", progname, strerror(errno));
128 fprintf(stderr,
"%s: fork: %s\n", progname, strerror(errno));
134 sigprocmask(SIG_SETMASK, &oldmask, NULL);
136 if(setuid(geteuid()) == -1) {
137 fprintf(stderr,
"%s: setuid: %s\n", progname, strerror(errno));
148 execle(
"/bin/mount",
"/bin/mount",
"--no-canonicalize",
"-i",
149 "-f",
"-t", type,
"-o", opts,
"--", fsname, mnt, NULL,
151 fprintf(stderr,
"%s: failed to execute /bin/mount: %s\n",
152 progname, strerror(errno));
155 res = waitpid(res, &status, 0);
157 fprintf(stderr,
"%s: waitpid: %s\n", progname, strerror(errno));
163 sigprocmask(SIG_SETMASK, &oldmask, NULL);
168int fuse_mnt_add_mount(
const char *progname,
const char *fsname,
169 const char *mnt,
const char *type,
const char *opts)
171 if (!mtab_needs_update(mnt))
174 return add_mount(progname, fsname, mnt, type, opts);
177static int exec_umount(
const char *progname,
const char *rel_mnt,
int lazy)
184 sigemptyset(&blockmask);
185 sigaddset(&blockmask, SIGCHLD);
186 res = sigprocmask(SIG_BLOCK, &blockmask, &oldmask);
188 fprintf(stderr,
"%s: sigprocmask: %s\n", progname, strerror(errno));
194 fprintf(stderr,
"%s: fork: %s\n", progname, strerror(errno));
200 sigprocmask(SIG_SETMASK, &oldmask, NULL);
202 if(setuid(geteuid()) == -1) {
203 fprintf(stderr,
"%s: setuid: %s\n", progname, strerror(errno));
209 execle(
"/bin/umount",
"/bin/umount",
"-i",
"-l",
210 "--", rel_mnt, NULL, &env);
212 execle(
"/bin/umount",
"/bin/umount",
"-i",
213 "--", rel_mnt, NULL, &env);
215 fprintf(stderr,
"%s: failed to execute /bin/umount: %s\n",
216 progname, strerror(errno));
219 res = waitpid(res, &status, 0);
221 fprintf(stderr,
"%s: waitpid: %s\n", progname, strerror(errno));
228 sigprocmask(SIG_SETMASK, &oldmask, NULL);
233int fuse_mnt_umount(
const char *progname,
const char *abs_mnt,
234 const char *rel_mnt,
int lazy)
242 if (!mtab_needs_update(abs_mnt) || unsafe_operand(rel_mnt)) {
243 res = umount2(rel_mnt, lazy ? 2 : 0);
245 fprintf(stderr,
"%s: failed to unmount %s: %s\n",
246 progname, abs_mnt, strerror(errno));
250 return exec_umount(progname, rel_mnt, lazy);
253static int remove_mount(
const char *progname,
const char *mnt)
260 if (unsafe_operand(mnt))
263 sigemptyset(&blockmask);
264 sigaddset(&blockmask, SIGCHLD);
265 res = sigprocmask(SIG_BLOCK, &blockmask, &oldmask);
267 fprintf(stderr,
"%s: sigprocmask: %s\n", progname, strerror(errno));
273 fprintf(stderr,
"%s: fork: %s\n", progname, strerror(errno));
279 sigprocmask(SIG_SETMASK, &oldmask, NULL);
281 if(setuid(geteuid()) == -1) {
282 fprintf(stderr,
"%s: setuid: %s\n", progname, strerror(errno));
287 execle(
"/bin/umount",
"/bin/umount",
"--no-canonicalize",
"-i",
288 "--fake",
"--", mnt, NULL, &env);
289 fprintf(stderr,
"%s: failed to execute /bin/umount: %s\n",
290 progname, strerror(errno));
293 res = waitpid(res, &status, 0);
295 fprintf(stderr,
"%s: waitpid: %s\n", progname, strerror(errno));
301 sigprocmask(SIG_SETMASK, &oldmask, NULL);
305int fuse_mnt_remove_mount(
const char *progname,
const char *mnt)
307 if (!mtab_needs_update(mnt))
310 return remove_mount(progname, mnt);
313char *fuse_mnt_resolve_path(
const char *progname,
const char *orig)
320 const char *toresolv;
323 fprintf(stderr,
"%s: invalid mountpoint '%s'\n", progname,
330 fprintf(stderr,
"%s: failed to allocate memory\n", progname);
336 for (end = copy + strlen(copy) - 1; end > copy && *end ==
'/'; end --);
340 tmp = strrchr(copy,
'/');
349 if (strcmp(lastcomp,
".") == 0 || strcmp(lastcomp,
"..") == 0) {
356 if (realpath(toresolv, buf) == NULL) {
357 fprintf(stderr,
"%s: bad mount point %s: %s\n", progname, orig,
362 if (lastcomp == NULL)
365 dst = (
char *) malloc(strlen(buf) + 1 + strlen(lastcomp) + 1);
367 unsigned buflen = strlen(buf);
368 if (buflen && buf[buflen-1] ==
'/')
369 sprintf(dst,
"%s%s", buf, lastcomp);
371 sprintf(dst,
"%s/%s", buf, lastcomp);
376 fprintf(stderr,
"%s: failed to allocate memory\n", progname);
380int fuse_mnt_check_fuseblk(
void)
383 FILE *f = fopen(
"/proc/filesystems",
"r");
387 while (fgets(buf,
sizeof(buf), f))
388 if (strstr(buf,
"fuseblk\n")) {
397int fuse_mnt_parse_fuse_fd(
const char *mountpoint)
402 if (mountpoint == NULL) {
403 fprintf(stderr,
"Invalid null-ptr mount-point!\n");
407 if (sscanf(mountpoint,
"/dev/fd/%u%n", &fd, &len) == 1 &&
408 len == strlen(mountpoint)) {
void fuse_log(enum fuse_log_level level, const char *fmt,...) __attribute__((format(printf