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.
10 #include "mount_util.h"
21 #else /* __SOLARIS__ */
23 #include <sys/mount.h>
24 #include <sys/param.h>
25 #endif /* __SOLARIS__ */
29 char *mkdtemp(char *template);
32 #define _PATH_MOUNTED "/etc/mnttab"
33 #endif /* _PATH_MOUNTED */
36 static int mtab_needs_update(const char *mnt
)
40 /* If mtab is within new mount, don't touch it */
41 if (strncmp(mnt
, _PATH_MOUNTED
, strlen(mnt
)) == 0 &&
42 _PATH_MOUNTED
[strlen(mnt
)] == '/')
45 if (lstat(_PATH_MOUNTED
, &stbuf
) != -1 && S_ISLNK(stbuf
.st_mode
))
50 #endif /* IGNORE_MTAB */
52 int fuse_mnt_add_mount(const char *progname
, const char *fsname
,
53 const char *mnt
, const char *type
, const char *opts
)
59 if (!mtab_needs_update(mnt
))
61 #endif /* IGNORE_MTAB */
65 fprintf(stderr
, "%s: fork: %s\n", progname
, strerror(errno
));
69 char templ
[] = "/tmp/fusermountXXXXXX";
75 * hide in a directory, where mount isn't able to resolve
76 * fsname as a valid path
80 fprintf(stderr
, "%s: failed to create temporary directory\n",
85 fprintf(stderr
, "%s: failed to chdir to %s: %s\n",
86 progname
, tmp
, strerror(errno
));
90 execl("/sbin/mount", "/sbin/mount", "-F", type
, "-o", opts
,
92 fprintf(stderr
, "%s: failed to execute /sbin/mount: %s\n", progname
,
96 res
= waitpid(res
, &status
, 0);
98 fprintf(stderr
, "%s: waitpid: %s\n", progname
, strerror(errno
));
107 int fuse_mnt_umount(const char *progname
, const char *mnt
, int lazy
)
113 if (!mtab_needs_update(mnt
))
115 #endif /* IGNORE_MTAB */
119 fprintf(stderr
, "%s: fork: %s\n", progname
, strerror(errno
));
124 execl("/sbin/umount", "/sbin/umount", !lazy
? "-f" : NULL
, mnt
,
126 fprintf(stderr
, "%s: failed to execute /sbin/umount: %s\n", progname
,
130 res
= waitpid(res
, &status
, 0);
132 fprintf(stderr
, "%s: waitpid: %s\n", progname
, strerror(errno
));
141 char *fuse_mnt_resolve_path(const char *progname
, const char *orig
)
148 const char *toresolv
;
151 fprintf(stderr
, "%s: invalid mountpoint '%s'\n", progname
, orig
);
157 fprintf(stderr
, "%s: failed to allocate memory\n", progname
);
163 for (end
= copy
+ strlen(copy
) - 1; end
> copy
&& *end
== '/'; end
--);
167 tmp
= strrchr(copy
, '/');
176 if (strcmp(lastcomp
, ".") == 0 || strcmp(lastcomp
, "..") == 0) {
183 if (realpath(toresolv
, buf
) == NULL
) {
184 fprintf(stderr
, "%s: bad mount point %s: %s\n", progname
, orig
,
189 if (lastcomp
== NULL
)
192 dst
= (char *) malloc(strlen(buf
) + 1 + strlen(lastcomp
) + 1);
194 unsigned buflen
= strlen(buf
);
195 if (buflen
&& buf
[buflen
-1] == '/')
196 sprintf(dst
, "%s%s", buf
, lastcomp
);
198 sprintf(dst
, "%s/%s", buf
, lastcomp
);
203 fprintf(stderr
, "%s: failed to allocate memory\n", progname
);
207 int fuse_mnt_check_empty(const char *progname
, const char *mnt
,
208 mode_t rootmode
, off_t rootsize
)
212 if (S_ISDIR(rootmode
)) {
214 DIR *dp
= opendir(mnt
);
216 fprintf(stderr
, "%s: failed to open mountpoint for reading: %s\n",
217 progname
, strerror(errno
));
220 while ((ent
= readdir(dp
)) != NULL
) {
221 if (strcmp(ent
->d_name
, ".") != 0 &&
222 strcmp(ent
->d_name
, "..") != 0) {
232 fprintf(stderr
, "%s: mountpoint is not empty\n", progname
);
233 fprintf(stderr
, "%s: if you are sure this is safe, use the 'nonempty' mount option\n", progname
);
239 int fuse_mnt_check_fuseblk(void)
242 FILE *f
= fopen("/proc/filesystems", "r");
246 while (fgets(buf
, sizeof(buf
), f
))
247 if (strstr(buf
, "fuseblk\n")) {
256 #else /* __SOLARIS__ */
258 static int mtab_needs_update(const char *mnt
)
263 /* If mtab is within new mount, don't touch it */
264 if (strncmp(mnt
, _PATH_MOUNTED
, strlen(mnt
)) == 0 &&
265 _PATH_MOUNTED
[strlen(mnt
)] == '/')
269 * Skip mtab update if /etc/mtab:
273 * - is on a read-only filesystem.
275 res
= lstat(_PATH_MOUNTED
, &stbuf
);
280 if (S_ISLNK(stbuf
.st_mode
))
283 res
= access(_PATH_MOUNTED
, W_OK
);
284 if (res
== -1 && errno
== EROFS
)
291 int fuse_mnt_add_mount(const char *progname
, const char *fsname
,
292 const char *mnt
, const char *type
, const char *opts
)
296 if (!mtab_needs_update(mnt
))
301 fprintf(stderr
, "%s: fork: %s\n", progname
, strerror(errno
));
305 char templ
[] = "/tmp/fusermountXXXXXX";
311 * hide in a directory, where mount isn't able to resolve
312 * fsname as a valid path
314 tmp
= mkdtemp(templ
);
316 fprintf(stderr
, "%s: failed to create temporary directory\n",
321 fprintf(stderr
, "%s: failed to chdir to %s: %s\n",
322 progname
, tmp
, strerror(errno
));
326 execl("/bin/mount", "/bin/mount", "-i", "-f", "-t", type
, "-o", opts
,
328 fprintf(stderr
, "%s: failed to execute /bin/mount: %s\n", progname
,
335 int fuse_mnt_umount(const char *progname
, const char *mnt
, int lazy
)
340 if (!mtab_needs_update(mnt
)) {
341 res
= umount2(mnt
, lazy
? 2 : 0);
343 fprintf(stderr
, "%s: failed to unmount %s: %s\n", progname
,
344 mnt
, strerror(errno
));
350 fprintf(stderr
, "%s: fork: %s\n", progname
, strerror(errno
));
355 execl("/bin/umount", "/bin/umount", "-i", mnt
, lazy
? "-l" : NULL
,
357 fprintf(stderr
, "%s: failed to execute /bin/umount: %s\n", progname
,
361 res
= waitpid(res
, &status
, 0);
363 fprintf(stderr
, "%s: waitpid: %s\n", progname
, strerror(errno
));
372 char *fuse_mnt_resolve_path(const char *progname
, const char *orig
)
379 const char *toresolv
;
382 fprintf(stderr
, "%s: invalid mountpoint '%s'\n", progname
, orig
);
388 fprintf(stderr
, "%s: failed to allocate memory\n", progname
);
394 for (end
= copy
+ strlen(copy
) - 1; end
> copy
&& *end
== '/'; end
--);
398 tmp
= strrchr(copy
, '/');
407 if (strcmp(lastcomp
, ".") == 0 || strcmp(lastcomp
, "..") == 0) {
414 if (realpath(toresolv
, buf
) == NULL
) {
415 fprintf(stderr
, "%s: bad mount point %s: %s\n", progname
, orig
,
420 if (lastcomp
== NULL
)
423 dst
= (char *) malloc(strlen(buf
) + 1 + strlen(lastcomp
) + 1);
425 unsigned buflen
= strlen(buf
);
426 if (buflen
&& buf
[buflen
-1] == '/')
427 sprintf(dst
, "%s%s", buf
, lastcomp
);
429 sprintf(dst
, "%s/%s", buf
, lastcomp
);
434 fprintf(stderr
, "%s: failed to allocate memory\n", progname
);
438 int fuse_mnt_check_fuseblk(void)
441 FILE *f
= fopen("/proc/filesystems", "r");
445 while (fgets(buf
, sizeof(buf
), f
))
446 if (strstr(buf
, "fuseblk\n")) {
455 #endif /* __SOLARIS__ */