12 #include "mount_util.h" 27 #include <sys/mount.h> 28 #include <sys/fsuid.h> 29 #include <sys/socket.h> 30 #include <sys/utsname.h> 35 #define FUSE_COMMFD_ENV "_FUSE_COMMFD" 37 #define FUSE_DEV "/dev/fuse" 40 #define MS_DIRSYNC 128 46 #define MS_PRIVATE (1<<18) 50 #define UMOUNT_DETACH 0x00000002 52 #ifndef UMOUNT_NOFOLLOW 53 #define UMOUNT_NOFOLLOW 0x00000008 56 #define UMOUNT_UNUSED 0x80000000 59 static const char *progname;
61 static int user_allow_other = 0;
62 static int mount_max = 1000;
64 static int auto_unmount = 0;
66 static const char *get_user_name(
void)
68 struct passwd *pw = getpwuid(getuid());
69 if (pw != NULL && pw->pw_name != NULL)
72 fprintf(stderr,
"%s: could not determine username\n", progname);
77 static uid_t oldfsuid;
78 static gid_t oldfsgid;
80 static void drop_privs(
void)
83 oldfsuid = setfsuid(getuid());
84 oldfsgid = setfsgid(getgid());
88 static void restore_privs(
void)
100 static int lock_umount(
void)
102 const char *mtab_lock = _PATH_MOUNTED
".fuselock";
105 struct stat mtab_stat;
108 if (lstat(_PATH_MOUNTED, &mtab_stat) == 0 && S_ISLNK(mtab_stat.st_mode))
111 mtablock = open(mtab_lock, O_RDWR | O_CREAT, 0600);
112 if (mtablock == -1) {
113 fprintf(stderr,
"%s: unable to open fuse lock file: %s\n",
114 progname, strerror(errno));
117 res = lockf(mtablock, F_LOCK, 0);
119 fprintf(stderr,
"%s: error getting lock: %s\n", progname,
128 static void unlock_umount(
int mtablock)
133 res = lockf(mtablock, F_ULOCK, 0);
135 fprintf(stderr,
"%s: error releasing lock: %s\n",
136 progname, strerror(errno));
142 static int add_mount(
const char *source,
const char *mnt,
const char *type,
145 return fuse_mnt_add_mount(progname, source, mnt, type, opts);
148 static int may_unmount(
const char *mnt,
int quiet)
152 const char *user = NULL;
156 const char *mtab = _PATH_MOUNTED;
158 user = get_user_name();
162 fp = setmntent(mtab,
"r");
164 fprintf(stderr,
"%s: failed to open %s: %s\n", progname, mtab,
169 uidlen = sprintf(uidstr,
"%u", getuid());
172 while ((entp = getmntent(fp)) != NULL) {
173 if (!found && strcmp(entp->mnt_dir, mnt) == 0 &&
174 (strcmp(entp->mnt_type,
"fuse") == 0 ||
175 strcmp(entp->mnt_type,
"fuseblk") == 0 ||
176 strncmp(entp->mnt_type,
"fuse.", 5) == 0 ||
177 strncmp(entp->mnt_type,
"fuseblk.", 8) == 0)) {
178 char *p = strstr(entp->mnt_opts,
"user=");
180 (p == entp->mnt_opts || *(p-1) ==
',') &&
181 strcmp(p + 5, user) == 0) {
188 strstr(entp->mnt_opts,
"user_id=")) &&
189 (p == entp->mnt_opts ||
191 strncmp(p + 8, uidstr, uidlen) == 0 &&
192 (*(p+8+uidlen) ==
',' ||
193 *(p+8+uidlen) ==
'\0')) {
204 "%s: entry for %s not found in %s\n",
205 progname, mnt, mtab);
236 static int check_is_mount_child(
void *p)
239 const char *last = a[0];
240 const char *mnt = a[1];
241 const char *type = a[2];
243 const char *procmounts =
"/proc/mounts";
249 res = mount(
"",
"/",
"", MS_PRIVATE | MS_REC, NULL);
251 fprintf(stderr,
"%s: failed to mark mounts private: %s\n",
252 progname, strerror(errno));
256 fp = setmntent(procmounts,
"r");
258 fprintf(stderr,
"%s: failed to open %s: %s\n", progname,
259 procmounts, strerror(errno));
264 while (getmntent(fp) != NULL)
268 fp = setmntent(procmounts,
"r");
270 fprintf(stderr,
"%s: failed to open %s: %s\n", progname,
271 procmounts, strerror(errno));
275 res = mount(
".",
"/",
"", MS_BIND | MS_REC, NULL);
277 fprintf(stderr,
"%s: failed to bind parent to /: %s\n",
278 progname, strerror(errno));
283 while ((entp = getmntent(fp)) != NULL) {
288 if (entp->mnt_dir[0] ==
'/' &&
289 strcmp(entp->mnt_dir + 1, last) == 0 &&
290 (!type || strcmp(entp->mnt_type, type) == 0)) {
298 fprintf(stderr,
"%s: %s not mounted\n", progname, mnt);
305 static pid_t clone_newns(
void *a)
308 char *stack = buf + (
sizeof(buf) / 2 - ((
size_t) buf & 15));
311 extern int __clone2(
int (*fn)(
void *),
312 void *child_stack_base,
size_t stack_size,
313 int flags,
void *arg, pid_t *ptid,
314 void *tls, pid_t *ctid);
316 return __clone2(check_is_mount_child, stack,
sizeof(buf) / 2,
317 CLONE_NEWNS, a, NULL, NULL, NULL);
319 return clone(check_is_mount_child, stack, CLONE_NEWNS, a);
323 static int check_is_mount(
const char *last,
const char *mnt,
const char *type)
327 const char *a[3] = { last, mnt, type };
329 pid = clone_newns((
void *) a);
330 if (pid == (pid_t) -1) {
331 fprintf(stderr,
"%s: failed to clone namespace: %s\n",
332 progname, strerror(errno));
335 p = waitpid(pid, &status, __WCLONE);
336 if (p == (pid_t) -1) {
337 fprintf(stderr,
"%s: waitpid failed: %s\n",
338 progname, strerror(errno));
341 if (!WIFEXITED(status)) {
342 fprintf(stderr,
"%s: child terminated abnormally (status %i)\n",
346 if (WEXITSTATUS(status) != 0)
352 static int chdir_to_parent(
char *copy,
const char **lastp)
359 tmp = strrchr(copy,
'/');
360 if (tmp == NULL || tmp[1] ==
'\0') {
361 fprintf(stderr,
"%s: internal error: invalid abs path: <%s>\n",
369 }
else if (tmp[1] !=
'\0') {
379 fprintf(stderr,
"%s: failed to chdir to %s: %s\n",
380 progname, parent, strerror(errno));
384 if (getcwd(buf,
sizeof(buf)) == NULL) {
385 fprintf(stderr,
"%s: failed to obtain current directory: %s\n",
386 progname, strerror(errno));
389 if (strcmp(buf, parent) != 0) {
390 fprintf(stderr,
"%s: mountpoint moved (%s -> %s)\n", progname,
401 static int umount_nofollow_support(
void)
403 int res = umount2(
"", UMOUNT_UNUSED);
404 if (res != -1 || errno != EINVAL)
407 res = umount2(
"", UMOUNT_NOFOLLOW);
408 if (res != -1 || errno != ENOENT)
414 static int unmount_fuse_locked(
const char *mnt,
int quiet,
int lazy)
419 int umount_flags = lazy ? UMOUNT_DETACH : 0;
422 res = may_unmount(mnt, quiet);
429 fprintf(stderr,
"%s: failed to allocate memory\n", progname);
434 res = chdir_to_parent(copy, &last);
439 if (umount_nofollow_support()) {
440 umount_flags |= UMOUNT_NOFOLLOW;
442 res = check_is_mount(last, mnt, NULL);
447 res = umount2(last, umount_flags);
448 if (res == -1 && !quiet) {
449 fprintf(stderr,
"%s: failed to unmount %s: %s\n",
450 progname, mnt, strerror(errno));
460 fprintf(stderr,
"%s: failed to chdir to '/'\n", progname);
464 return fuse_mnt_remove_mount(progname, mnt);
467 static int unmount_fuse(
const char *mnt,
int quiet,
int lazy)
470 int mtablock = lock_umount();
472 res = unmount_fuse_locked(mnt, quiet, lazy);
473 unlock_umount(mtablock);
478 static int count_fuse_fs(
void)
482 const char *mtab = _PATH_MOUNTED;
483 FILE *fp = setmntent(mtab,
"r");
485 fprintf(stderr,
"%s: failed to open %s: %s\n", progname, mtab,
489 while ((entp = getmntent(fp)) != NULL) {
490 if (strcmp(entp->mnt_type,
"fuse") == 0 ||
491 strncmp(entp->mnt_type,
"fuse.", 5) == 0)
500 static int count_fuse_fs(
void)
505 static int add_mount(
const char *source,
const char *mnt,
const char *type,
515 static int unmount_fuse(
const char *mnt,
int quiet,
int lazy)
518 return fuse_mnt_umount(progname, mnt, mnt, lazy);
522 static void strip_line(
char *line)
524 char *s = strchr(line,
'#');
527 for (s = line + strlen(line) - 1;
528 s >= line && isspace((
unsigned char) *s); s--);
530 for (s = line; isspace((
unsigned char) *s); s++);
532 memmove(line, s, strlen(s)+1);
535 static void parse_line(
char *line,
int linenum)
538 if (strcmp(line,
"user_allow_other") == 0)
539 user_allow_other = 1;
540 else if (sscanf(line,
"mount_max = %i", &tmp) == 1)
544 "%s: unknown parameter in %s at line %i: '%s'\n",
545 progname, FUSE_CONF, linenum, line);
548 static void read_conf(
void)
550 FILE *fp = fopen(FUSE_CONF,
"r");
555 while (fgets(line,
sizeof(line), fp) != NULL) {
557 if (line[strlen(line)-1] ==
'\n') {
559 parse_line(line, linenum);
563 }
else if(line[strlen(line)-1] ==
'\n') {
564 fprintf(stderr,
"%s: reading %s: line %i too long\n", progname, FUSE_CONF, linenum);
572 fprintf(stderr,
"%s: reading %s: missing newline at end of file\n", progname, FUSE_CONF);
576 fprintf(stderr,
"%s: reading %s: read failed\n", progname, FUSE_CONF);
580 }
else if (errno != ENOENT) {
581 bool fatal = (errno != EACCES && errno != ELOOP &&
582 errno != ENAMETOOLONG && errno != ENOTDIR &&
584 fprintf(stderr,
"%s: failed to open %s: %s\n",
585 progname, FUSE_CONF, strerror(errno));
591 static int begins_with(
const char *s,
const char *beg)
593 if (strncmp(s, beg, strlen(beg)) == 0)
606 static struct mount_flags mount_flags[] = {
607 {
"rw", MS_RDONLY, 0, 1},
608 {
"ro", MS_RDONLY, 1, 1},
609 {
"suid", MS_NOSUID, 0, 0},
610 {
"nosuid", MS_NOSUID, 1, 1},
611 {
"dev", MS_NODEV, 0, 0},
612 {
"nodev", MS_NODEV, 1, 1},
613 {
"exec", MS_NOEXEC, 0, 1},
614 {
"noexec", MS_NOEXEC, 1, 1},
615 {
"async", MS_SYNCHRONOUS, 0, 1},
616 {
"sync", MS_SYNCHRONOUS, 1, 1},
617 {
"atime", MS_NOATIME, 0, 1},
618 {
"noatime", MS_NOATIME, 1, 1},
619 {
"dirsync", MS_DIRSYNC, 1, 1},
623 static int find_mount_flag(
const char *s,
unsigned len,
int *on,
int *flag)
627 for (i = 0; mount_flags[i].opt != NULL; i++) {
628 const char *opt = mount_flags[i].opt;
629 if (strlen(opt) == len && strncmp(opt, s, len) == 0) {
630 *on = mount_flags[i].on;
631 *flag = mount_flags[i].flag;
632 if (!mount_flags[i].safe && getuid() != 0) {
635 "%s: unsafe option %s ignored\n",
644 static int add_option(
char **optsp,
const char *opt,
unsigned expand)
648 newopts = strdup(opt);
650 unsigned oldsize = strlen(*optsp);
651 unsigned newsize = oldsize + 1 + strlen(opt) + expand + 1;
652 newopts = (
char *) realloc(*optsp, newsize);
654 sprintf(newopts + oldsize,
",%s", opt);
656 if (newopts == NULL) {
657 fprintf(stderr,
"%s: failed to allocate memory\n", progname);
664 static int get_mnt_opts(
int flags,
char *opts,
char **mnt_optsp)
669 if (!(flags & MS_RDONLY) && add_option(mnt_optsp,
"rw", 0) == -1)
672 for (i = 0; mount_flags[i].opt != NULL; i++) {
673 if (mount_flags[i].on && (flags & mount_flags[i].flag) &&
674 add_option(mnt_optsp, mount_flags[i].opt, 0) == -1)
678 if (add_option(mnt_optsp, opts, 0) == -1)
681 l = strlen(*mnt_optsp);
682 if ((*mnt_optsp)[l-1] ==
',')
683 (*mnt_optsp)[l-1] =
'\0';
685 const char *user = get_user_name();
689 if (add_option(mnt_optsp,
"user=", strlen(user)) == -1)
691 strcat(*mnt_optsp, user);
696 static int opt_eq(
const char *s,
unsigned len,
const char *opt)
698 if(strlen(opt) == len && strncmp(s, opt, len) == 0)
704 static int get_string_opt(
const char *s,
unsigned len,
const char *opt,
708 unsigned opt_len = strlen(opt);
713 *val = (
char *) malloc(len - opt_len + 1);
715 fprintf(stderr,
"%s: failed to allocate memory\n", progname);
722 for (i = 0; i < len; i++) {
723 if (s[i] ==
'\\' && i + 1 < len)
736 static int mount_notrunc(
const char *source,
const char *target,
737 const char *filesystemtype,
unsigned long mountflags,
739 if (strlen(data) > sysconf(_SC_PAGESIZE) - 1) {
740 fprintf(stderr,
"%s: mount options too long\n", progname);
744 return mount(source, target, filesystemtype, mountflags, data);
748 static int do_mount(
const char *mnt,
const char **typep, mode_t rootmode,
749 int fd,
const char *opts,
const char *dev,
char **sourcep,
753 int flags = MS_NOSUID | MS_NODEV;
755 char *mnt_opts = NULL;
759 char *subtype = NULL;
764 optbuf = (
char *) malloc(strlen(opts) + 128);
766 fprintf(stderr,
"%s: failed to allocate memory\n", progname);
770 for (s = opts, d = optbuf; *s;) {
772 const char *fsname_str =
"fsname=";
773 const char *subtype_str =
"subtype=";
774 bool escape_ok = begins_with(s, fsname_str) ||
775 begins_with(s, subtype_str);
776 for (len = 0; s[len]; len++) {
777 if (escape_ok && s[len] ==
'\\' && s[len + 1])
779 else if (s[len] ==
',')
782 if (begins_with(s, fsname_str)) {
783 if (!get_string_opt(s, len, fsname_str, &fsname))
785 }
else if (begins_with(s, subtype_str)) {
786 if (!get_string_opt(s, len, subtype_str, &subtype))
788 }
else if (opt_eq(s, len,
"blkdev")) {
791 "%s: option blkdev is privileged\n",
796 }
else if (opt_eq(s, len,
"auto_unmount")) {
798 }
else if (!begins_with(s,
"fd=") &&
799 !begins_with(s,
"rootmode=") &&
800 !begins_with(s,
"user_id=") &&
801 !begins_with(s,
"group_id=")) {
805 if (opt_eq(s, len,
"large_read")) {
806 struct utsname utsname;
808 res = uname(&utsname);
810 sscanf(utsname.release,
"%u.%u",
811 &kmaj, &kmin) == 2 &&
812 (kmaj > 2 || (kmaj == 2 && kmin > 4))) {
813 fprintf(stderr,
"%s: note: 'large_read' mount option is deprecated for %i.%i kernels\n", progname, kmaj, kmin);
817 if (getuid() != 0 && !user_allow_other &&
818 (opt_eq(s, len,
"allow_other") ||
819 opt_eq(s, len,
"allow_root"))) {
820 fprintf(stderr,
"%s: option %.*s only allowed if 'user_allow_other' is set in %s\n", progname, len, s, FUSE_CONF);
824 if (find_mount_flag(s, len, &on, &flag)) {
829 }
else if (opt_eq(s, len,
"default_permissions") ||
830 opt_eq(s, len,
"allow_other") ||
831 begins_with(s,
"max_read=") ||
832 begins_with(s,
"blksize=")) {
837 fprintf(stderr,
"%s: unknown option '%.*s'\n", progname, len, s);
847 res = get_mnt_opts(flags, optbuf, &mnt_opts);
851 sprintf(d,
"fd=%i,rootmode=%o,user_id=%u,group_id=%u",
852 fd, rootmode, getuid(), getgid());
854 source = malloc((fsname ? strlen(fsname) : 0) +
855 (subtype ? strlen(subtype) : 0) + strlen(dev) + 32);
857 type = malloc((subtype ? strlen(subtype) : 0) + 32);
858 if (!type || !source) {
859 fprintf(stderr,
"%s: failed to allocate memory\n", progname);
864 sprintf(type,
"%s.%s", blkdev ?
"fuseblk" :
"fuse", subtype);
866 strcpy(type, blkdev ?
"fuseblk" :
"fuse");
869 strcpy(source, fsname);
871 strcpy(source, subtype ? subtype : dev);
873 res = mount_notrunc(source, mnt, type, flags, optbuf);
874 if (res == -1 && errno == ENODEV && subtype) {
876 strcpy(type, blkdev ?
"fuseblk" :
"fuse");
879 sprintf(source,
"%s#%s", subtype, fsname);
881 strcpy(source, type);
884 res = mount_notrunc(source, mnt, type, flags, optbuf);
886 if (res == -1 && errno == EINVAL) {
888 sprintf(d,
"fd=%i,rootmode=%o,user_id=%u",
889 fd, rootmode, getuid());
890 res = mount_notrunc(source, mnt, type, flags, optbuf);
893 int errno_save = errno;
894 if (blkdev && errno == ENODEV && !fuse_mnt_check_fuseblk())
895 fprintf(stderr,
"%s: 'fuseblk' support missing\n",
898 fprintf(stderr,
"%s: mount failed: %s\n", progname,
899 strerror(errno_save));
904 *mnt_optsp = mnt_opts;
920 static int check_perm(
const char **mntp,
struct stat *stbuf,
int *mountpoint_fd)
923 const char *mnt = *mntp;
924 const char *origmnt = mnt;
925 struct statfs fs_buf;
928 res = lstat(mnt, stbuf);
930 fprintf(stderr,
"%s: failed to access mountpoint %s: %s\n",
931 progname, mnt, strerror(errno));
939 if (S_ISDIR(stbuf->st_mode)) {
943 "%s: failed to chdir to mountpoint: %s\n",
944 progname, strerror(errno));
948 res = lstat(mnt, stbuf);
951 "%s: failed to access mountpoint %s: %s\n",
952 progname, origmnt, strerror(errno));
956 if ((stbuf->st_mode & S_ISVTX) && stbuf->st_uid != getuid()) {
957 fprintf(stderr,
"%s: mountpoint %s not owned by user\n",
962 res = access(mnt, W_OK);
964 fprintf(stderr,
"%s: user has no write access to mountpoint %s\n",
968 }
else if (S_ISREG(stbuf->st_mode)) {
969 static char procfile[256];
970 *mountpoint_fd = open(mnt, O_WRONLY);
971 if (*mountpoint_fd == -1) {
972 fprintf(stderr,
"%s: failed to open %s: %s\n",
973 progname, mnt, strerror(errno));
976 res = fstat(*mountpoint_fd, stbuf);
979 "%s: failed to access mountpoint %s: %s\n",
980 progname, mnt, strerror(errno));
983 if (!S_ISREG(stbuf->st_mode)) {
985 "%s: mountpoint %s is no longer a regular file\n",
990 sprintf(procfile,
"/proc/self/fd/%i", *mountpoint_fd);
994 "%s: mountpoint %s is not a directory or a regular file\n",
1005 if (statfs(*mntp, &fs_buf)) {
1006 fprintf(stderr,
"%s: failed to access mountpoint %s: %s\n",
1007 progname, mnt, strerror(errno));
1016 typeof(fs_buf.f_type) f_type_whitelist[] = {
1045 0x736675005346544e ,
1049 for (i = 0; i <
sizeof(f_type_whitelist)/
sizeof(f_type_whitelist[0]); i++) {
1050 if (f_type_whitelist[i] == fs_buf.f_type)
1054 fprintf(stderr,
"%s: mounting over filesystem type %#010lx is forbidden\n",
1055 progname, (
unsigned long)fs_buf.f_type);
1059 static int try_open(
const char *dev,
char **devp,
int silent)
1061 int fd = open(dev, O_RDWR);
1063 *devp = strdup(dev);
1064 if (*devp == NULL) {
1065 fprintf(stderr,
"%s: failed to allocate memory\n",
1070 }
else if (errno == ENODEV ||
1074 fprintf(stderr,
"%s: failed to open %s: %s\n", progname, dev,
1080 static int try_open_fuse_device(
char **devp)
1085 fd = try_open(FUSE_DEV, devp, 0);
1090 static int open_fuse_device(
char **devp)
1092 int fd = try_open_fuse_device(devp);
1097 "%s: fuse device not found, try 'modprobe fuse' first\n",
1104 static int mount_fuse(
const char *mnt,
const char *opts,
const char **type)
1110 char *source = NULL;
1111 char *mnt_opts = NULL;
1112 const char *real_mnt = mnt;
1113 int mountpoint_fd = -1;
1115 fd = open_fuse_device(&dev);
1122 if (getuid() != 0 && mount_max != -1) {
1123 int mount_count = count_fuse_fs();
1124 if (mount_count >= mount_max) {
1125 fprintf(stderr,
"%s: too many FUSE filesystems mounted; mount_max=N can be set in %s\n", progname, FUSE_CONF);
1130 res = check_perm(&real_mnt, &stbuf, &mountpoint_fd);
1133 res = do_mount(real_mnt, type, stbuf.st_mode & S_IFMT,
1134 fd, opts, dev, &source, &mnt_opts);
1136 if (mountpoint_fd != -1)
1137 close(mountpoint_fd);
1144 fprintf(stderr,
"%s: failed to chdir to '/'\n", progname);
1148 if (geteuid() == 0) {
1149 res = add_mount(source, mnt, *type, mnt_opts);
1169 static int send_fd(
int sock_fd,
int fd)
1173 struct cmsghdr *p_cmsg;
1175 size_t cmsgbuf[CMSG_SPACE(
sizeof(fd)) /
sizeof(size_t)];
1179 msg.msg_control = cmsgbuf;
1180 msg.msg_controllen =
sizeof(cmsgbuf);
1181 p_cmsg = CMSG_FIRSTHDR(&msg);
1182 p_cmsg->cmsg_level = SOL_SOCKET;
1183 p_cmsg->cmsg_type = SCM_RIGHTS;
1184 p_cmsg->cmsg_len = CMSG_LEN(
sizeof(fd));
1185 p_fds = (
int *) CMSG_DATA(p_cmsg);
1187 msg.msg_controllen = p_cmsg->cmsg_len;
1188 msg.msg_name = NULL;
1189 msg.msg_namelen = 0;
1195 vec.iov_base = &sendchar;
1196 vec.iov_len =
sizeof(sendchar);
1197 while ((retval = sendmsg(sock_fd, &msg, 0)) == -1 && errno == EINTR);
1199 perror(
"sending file descriptor");
1221 static int should_auto_unmount(
const char *mnt,
const char *type)
1230 fprintf(stderr,
"%s: failed to allocate memory\n", progname);
1234 if (chdir_to_parent(copy, &last) == -1)
1236 if (check_is_mount(last, mnt, type) == -1)
1239 fd = open(mnt, O_RDONLY);
1243 result = errno == ENOTCONN;
1250 static void usage(
void)
1252 printf(
"%s: [options] mountpoint\n" 1255 " -V print version\n" 1256 " -o opt[,opt...] mount options\n" 1259 " -z lazy unmount\n",
1264 static void show_version(
void)
1266 printf(
"fusermount3 version: %s\n", PACKAGE_VERSION);
1270 int main(
int argc,
char *argv[])
1278 static int unmount = 0;
1279 static int lazy = 0;
1280 static int quiet = 0;
1283 const char *opts =
"";
1284 const char *type = NULL;
1286 static const struct option long_opts[] = {
1287 {
"unmount", no_argument, NULL,
'u'},
1288 {
"lazy", no_argument, NULL,
'z'},
1289 {
"quiet", no_argument, NULL,
'q'},
1290 {
"help", no_argument, NULL,
'h'},
1291 {
"version", no_argument, NULL,
'V'},
1294 progname = strdup(argv[0]);
1295 if (progname == NULL) {
1296 fprintf(stderr,
"%s: failed to allocate memory\n", argv[0]);
1300 while ((ch = getopt_long(argc, argv,
"hVo:uzq", long_opts,
1332 if (lazy && !unmount) {
1333 fprintf(stderr,
"%s: -z can only be used with -u\n", progname);
1337 if (optind >= argc) {
1338 fprintf(stderr,
"%s: missing mountpoint argument\n", progname);
1340 }
else if (argc > optind + 1) {
1341 fprintf(stderr,
"%s: extra arguments after the mountpoint\n",
1346 origmnt = argv[optind];
1349 mnt = fuse_mnt_resolve_path(progname, origmnt);
1353 fprintf(stderr,
"%s: failed to chdir to '/'\n", progname);
1365 commfd = getenv(FUSE_COMMFD_ENV);
1366 if (commfd == NULL) {
1367 fprintf(stderr,
"%s: old style mounting not supported\n",
1372 fd = mount_fuse(mnt, opts, &type);
1377 res = send_fd(cfd, fd);
1382 if (!auto_unmount) {
1394 fprintf(stderr,
"%s: failed to chdir to '/'\n", progname);
1398 sigfillset(&sigset);
1399 sigprocmask(SIG_BLOCK, &sigset, NULL);
1405 unsigned char buf[16];
1406 int n = recv(cfd, buf,
sizeof(buf), 0);
1417 if (!should_auto_unmount(mnt, type)) {
1423 res = unmount_fuse(mnt, quiet, lazy);
1425 res = umount2(mnt, lazy ? UMOUNT_DETACH : 0);
1426 if (res == -1 && !quiet)
1428 "%s: failed to unmount %s: %s\n",
1429 progname, mnt, strerror(errno));