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"
24 #include <sys/mount.h>
25 #include <sys/param.h>
28 #define umount2(mnt, flags) unmount(mnt, (flags == 2) ? MNT_FORCE : 0)
29 #define mtab_needs_update(mnt) 0
31 static int mtab_needs_update(const char *mnt)
36 /* If mtab is within new mount, don't touch it */
37 if (strncmp(mnt, _PATH_MOUNTED, strlen(mnt)) == 0 &&
38 _PATH_MOUNTED[strlen(mnt)] == '/')
42 * Skip mtab update if /etc/mtab:
46 * - is on a read-only filesystem.
48 res = lstat(_PATH_MOUNTED, &stbuf);
56 if (S_ISLNK(stbuf.st_mode))
63 res = access(_PATH_MOUNTED, W_OK);
64 err = (res == -1) ? errno : 0;
74 #endif /* __NetBSD__ */
76 static int add_mount(const char *progname, const char *fsname,
77 const char *mnt, const char *type, const char *opts)
84 sigemptyset(&blockmask);
85 sigaddset(&blockmask, SIGCHLD);
86 res = sigprocmask(SIG_BLOCK, &blockmask, &oldmask);
88 fprintf(stderr, "%s: sigprocmask: %s\n", progname, strerror(errno));
94 fprintf(stderr, "%s: fork: %s\n", progname, strerror(errno));
98 sigprocmask(SIG_SETMASK, &oldmask, NULL);
100 execl("/bin/mount", "/bin/mount", "--no-canonicalize", "-i",
101 "-f", "-t", type, "-o", opts, fsname, mnt, NULL);
102 fprintf(stderr, "%s: failed to execute /bin/mount: %s\n",
103 progname, strerror(errno));
106 res = waitpid(res, &status, 0);
108 fprintf(stderr, "%s: waitpid: %s\n", progname, strerror(errno));
114 sigprocmask(SIG_SETMASK, &oldmask, NULL);
119 int fuse_mnt_add_mount(const char *progname, const char *fsname,
120 const char *mnt, const char *type, const char *opts)
122 if (!mtab_needs_update(mnt))
125 return add_mount(progname, fsname, mnt, type, opts);
128 static int exec_umount(const char *progname, const char *rel_mnt, int lazy)
135 sigemptyset(&blockmask);
136 sigaddset(&blockmask, SIGCHLD);
137 res = sigprocmask(SIG_BLOCK, &blockmask, &oldmask);
139 fprintf(stderr, "%s: sigprocmask: %s\n", progname, strerror(errno));
145 fprintf(stderr, "%s: fork: %s\n", progname, strerror(errno));
149 sigprocmask(SIG_SETMASK, &oldmask, NULL);
151 execl("/bin/umount", "/bin/umount", "-i", rel_mnt,
152 lazy ? "-l" : NULL, NULL);
153 fprintf(stderr, "%s: failed to execute /bin/umount: %s\n",
154 progname, strerror(errno));
157 res = waitpid(res, &status, 0);
159 fprintf(stderr, "%s: waitpid: %s\n", progname, strerror(errno));
166 sigprocmask(SIG_SETMASK, &oldmask, NULL);
171 int fuse_mnt_umount(const char *progname, const char *abs_mnt,
172 const char *rel_mnt, int lazy)
176 if (!mtab_needs_update(abs_mnt)) {
177 res = umount2(rel_mnt, lazy ? 2 : 0);
179 fprintf(stderr, "%s: failed to unmount %s: %s\n",
180 progname, abs_mnt, strerror(errno));
184 return exec_umount(progname, rel_mnt, lazy);
187 static int remove_mount(const char *progname, const char *mnt)
194 sigemptyset(&blockmask);
195 sigaddset(&blockmask, SIGCHLD);
196 res = sigprocmask(SIG_BLOCK, &blockmask, &oldmask);
198 fprintf(stderr, "%s: sigprocmask: %s\n", progname, strerror(errno));
204 fprintf(stderr, "%s: fork: %s\n", progname, strerror(errno));
208 sigprocmask(SIG_SETMASK, &oldmask, NULL);
210 execl("/bin/umount", "/bin/umount", "--no-canonicalize", "-i",
211 "--fake", mnt, NULL);
212 fprintf(stderr, "%s: failed to execute /bin/umount: %s\n",
213 progname, strerror(errno));
216 res = waitpid(res, &status, 0);
218 fprintf(stderr, "%s: waitpid: %s\n", progname, strerror(errno));
224 sigprocmask(SIG_SETMASK, &oldmask, NULL);
228 int fuse_mnt_remove_mount(const char *progname, const char *mnt)
230 if (!mtab_needs_update(mnt))
233 return remove_mount(progname, mnt);
236 char *fuse_mnt_resolve_path(const char *progname, const char *orig)
243 const char *toresolv;
246 fprintf(stderr, "%s: invalid mountpoint '%s'\n", progname,
253 fprintf(stderr, "%s: failed to allocate memory\n", progname);
259 for (end = copy + strlen(copy) - 1; end > copy && *end == '/'; end --);
263 tmp = strrchr(copy, '/');
272 if (strcmp(lastcomp, ".") == 0 || strcmp(lastcomp, "..") == 0) {
279 if (realpath(toresolv, buf) == NULL) {
280 fprintf(stderr, "%s: bad mount point %s: %s\n", progname, orig,
285 if (lastcomp == NULL)
288 dst = (char *) malloc(strlen(buf) + 1 + strlen(lastcomp) + 1);
290 unsigned buflen = strlen(buf);
291 if (buflen && buf[buflen-1] == '/')
292 sprintf(dst, "%s%s", buf, lastcomp);
294 sprintf(dst, "%s/%s", buf, lastcomp);
299 fprintf(stderr, "%s: failed to allocate memory\n", progname);
303 int fuse_mnt_check_empty(const char *progname, const char *mnt,
304 mode_t rootmode, off_t rootsize)
308 if (S_ISDIR(rootmode)) {
310 DIR *dp = opendir(mnt);
313 "%s: failed to open mountpoint for reading: %s\n",
314 progname, strerror(errno));
317 while ((ent = readdir(dp)) != NULL) {
318 if (strcmp(ent->d_name, ".") != 0 &&
319 strcmp(ent->d_name, "..") != 0) {
329 fprintf(stderr, "%s: mountpoint is not empty\n", progname);
330 fprintf(stderr, "%s: if you are sure this is safe, use the 'nonempty' mount option\n", progname);
336 int fuse_mnt_check_fuseblk(void)
339 FILE *f = fopen("/proc/filesystems", "r");
343 while (fgets(buf, sizeof(buf), f))
344 if (strstr(buf, "fuseblk\n")) {