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.
9 #include "mount_util.h"
25 #include <sys/mount.h>
26 #include <sys/param.h>
29 #define umount2(mnt, flags) unmount(mnt, (flags == 2) ? MNT_FORCE : 0)
30 #define mtab_needs_update(mnt) 0
32 static int mtab_needs_update(const char *mnt)
37 /* If mtab is within new mount, don't touch it */
38 if (strncmp(mnt, _PATH_MOUNTED, strlen(mnt)) == 0 &&
39 _PATH_MOUNTED[strlen(mnt)] == '/')
43 * Skip mtab update if /etc/mtab:
47 * - is on a read-only filesystem.
49 res = lstat(_PATH_MOUNTED, &stbuf);
57 if (S_ISLNK(stbuf.st_mode))
64 res = access(_PATH_MOUNTED, W_OK);
65 err = (res == -1) ? errno : 0;
75 #endif /* __NetBSD__ */
77 static int add_mount(const char *progname, const char *fsname,
78 const char *mnt, const char *type, const char *opts)
85 sigemptyset(&blockmask);
86 sigaddset(&blockmask, SIGCHLD);
87 res = sigprocmask(SIG_BLOCK, &blockmask, &oldmask);
89 fprintf(stderr, "%s: sigprocmask: %s\n", progname, strerror(errno));
95 fprintf(stderr, "%s: fork: %s\n", progname, strerror(errno));
101 sigprocmask(SIG_SETMASK, &oldmask, NULL);
103 execle("/bin/mount", "/bin/mount", "--no-canonicalize", "-i",
104 "-f", "-t", type, "-o", opts, fsname, mnt, NULL, &env);
105 fprintf(stderr, "%s: failed to execute /bin/mount: %s\n",
106 progname, strerror(errno));
109 res = waitpid(res, &status, 0);
111 fprintf(stderr, "%s: waitpid: %s\n", progname, strerror(errno));
117 sigprocmask(SIG_SETMASK, &oldmask, NULL);
122 int fuse_mnt_add_mount(const char *progname, const char *fsname,
123 const char *mnt, const char *type, const char *opts)
125 if (!mtab_needs_update(mnt))
128 return add_mount(progname, fsname, mnt, type, opts);
131 static int exec_umount(const char *progname, const char *rel_mnt, int lazy)
138 sigemptyset(&blockmask);
139 sigaddset(&blockmask, SIGCHLD);
140 res = sigprocmask(SIG_BLOCK, &blockmask, &oldmask);
142 fprintf(stderr, "%s: sigprocmask: %s\n", progname, strerror(errno));
148 fprintf(stderr, "%s: fork: %s\n", progname, strerror(errno));
154 sigprocmask(SIG_SETMASK, &oldmask, NULL);
157 execle("/bin/umount", "/bin/umount", "-i", rel_mnt,
160 execle("/bin/umount", "/bin/umount", "-i", rel_mnt,
163 fprintf(stderr, "%s: failed to execute /bin/umount: %s\n",
164 progname, strerror(errno));
167 res = waitpid(res, &status, 0);
169 fprintf(stderr, "%s: waitpid: %s\n", progname, strerror(errno));
176 sigprocmask(SIG_SETMASK, &oldmask, NULL);
181 int fuse_mnt_umount(const char *progname, const char *abs_mnt,
182 const char *rel_mnt, int lazy)
186 if (!mtab_needs_update(abs_mnt)) {
187 res = umount2(rel_mnt, lazy ? 2 : 0);
189 fprintf(stderr, "%s: failed to unmount %s: %s\n",
190 progname, abs_mnt, strerror(errno));
194 return exec_umount(progname, rel_mnt, lazy);
197 static int remove_mount(const char *progname, const char *mnt)
204 sigemptyset(&blockmask);
205 sigaddset(&blockmask, SIGCHLD);
206 res = sigprocmask(SIG_BLOCK, &blockmask, &oldmask);
208 fprintf(stderr, "%s: sigprocmask: %s\n", progname, strerror(errno));
214 fprintf(stderr, "%s: fork: %s\n", progname, strerror(errno));
220 sigprocmask(SIG_SETMASK, &oldmask, NULL);
222 execle("/bin/umount", "/bin/umount", "--no-canonicalize", "-i",
223 "--fake", mnt, NULL, &env);
224 fprintf(stderr, "%s: failed to execute /bin/umount: %s\n",
225 progname, strerror(errno));
228 res = waitpid(res, &status, 0);
230 fprintf(stderr, "%s: waitpid: %s\n", progname, strerror(errno));
236 sigprocmask(SIG_SETMASK, &oldmask, NULL);
240 int fuse_mnt_remove_mount(const char *progname, const char *mnt)
242 if (!mtab_needs_update(mnt))
245 return remove_mount(progname, mnt);
248 char *fuse_mnt_resolve_path(const char *progname, const char *orig)
255 const char *toresolv;
258 fprintf(stderr, "%s: invalid mountpoint '%s'\n", progname,
265 fprintf(stderr, "%s: failed to allocate memory\n", progname);
271 for (end = copy + strlen(copy) - 1; end > copy && *end == '/'; end --);
275 tmp = strrchr(copy, '/');
284 if (strcmp(lastcomp, ".") == 0 || strcmp(lastcomp, "..") == 0) {
291 if (realpath(toresolv, buf) == NULL) {
292 fprintf(stderr, "%s: bad mount point %s: %s\n", progname, orig,
297 if (lastcomp == NULL)
300 dst = (char *) malloc(strlen(buf) + 1 + strlen(lastcomp) + 1);
302 unsigned buflen = strlen(buf);
303 if (buflen && buf[buflen-1] == '/')
304 sprintf(dst, "%s%s", buf, lastcomp);
306 sprintf(dst, "%s/%s", buf, lastcomp);
311 fprintf(stderr, "%s: failed to allocate memory\n", progname);
315 int fuse_mnt_check_empty(const char *progname, const char *mnt,
316 mode_t rootmode, off_t rootsize)
320 if (S_ISDIR(rootmode)) {
322 DIR *dp = opendir(mnt);
325 "%s: failed to open mountpoint for reading: %s\n",
326 progname, strerror(errno));
329 while ((ent = readdir(dp)) != NULL) {
330 if (strcmp(ent->d_name, ".") != 0 &&
331 strcmp(ent->d_name, "..") != 0) {
341 fprintf(stderr, "%s: mountpoint is not empty\n", progname);
342 fprintf(stderr, "%s: if you are sure this is safe, use the 'nonempty' mount option\n", progname);
348 int fuse_mnt_check_fuseblk(void)
351 FILE *f = fopen("/proc/filesystems", "r");
355 while (fgets(buf, sizeof(buf), f))
356 if (strstr(buf, "fuseblk\n")) {