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);
   235 static int check_is_mount_child(
void *p)
   238         const char *last = a[0];
   239         const char *mnt = a[1];
   240         const char *type = a[2];
   242         const char *procmounts = 
"/proc/mounts";
   248         res = mount(
"", 
"/", 
"", MS_PRIVATE | MS_REC, NULL);
   250                 fprintf(stderr, 
"%s: failed to mark mounts private: %s\n",
   251                         progname, strerror(errno));
   255         fp = setmntent(procmounts, 
"r");
   257                 fprintf(stderr, 
"%s: failed to open %s: %s\n", progname,
   258                         procmounts, strerror(errno));
   263         while (getmntent(fp) != NULL)
   267         fp = setmntent(procmounts, 
"r");
   269                 fprintf(stderr, 
"%s: failed to open %s: %s\n", progname,
   270                         procmounts, strerror(errno));
   274         res = mount(
".", 
"/", 
"", MS_BIND | MS_REC, NULL);
   276                 fprintf(stderr, 
"%s: failed to bind parent to /: %s\n",
   277                         progname, strerror(errno));
   282         while ((entp = getmntent(fp)) != NULL) {
   287                 if (entp->mnt_dir[0] == 
'/' &&
   288                     strcmp(entp->mnt_dir + 1, last) == 0 &&
   289                     (!type || strcmp(entp->mnt_type, type) == 0)) {
   297                 fprintf(stderr, 
"%s: %s not mounted\n", progname, mnt);
   304 static pid_t clone_newns(
void *a)
   307         char *stack = buf + (
sizeof(buf) / 2 - ((
size_t) buf & 15));
   310         extern int __clone2(
int (*fn)(
void *),
   311                             void *child_stack_base, 
size_t stack_size,
   312                             int flags, 
void *arg, pid_t *ptid,
   313                             void *tls, pid_t *ctid);
   315         return __clone2(check_is_mount_child, stack, 
sizeof(buf) / 2,
   316                         CLONE_NEWNS, a, NULL, NULL, NULL);
   318         return clone(check_is_mount_child, stack, CLONE_NEWNS, a);
   322 static int check_is_mount(
const char *last, 
const char *mnt, 
const char *type)
   326         const char *a[3] = { last, mnt, type };
   328         pid = clone_newns((
void *) a);
   329         if (pid == (pid_t) -1) {
   330                 fprintf(stderr, 
"%s: failed to clone namespace: %s\n",
   331                         progname, strerror(errno));
   334         p = waitpid(pid, &status, __WCLONE);
   335         if (p == (pid_t) -1) {
   336                 fprintf(stderr, 
"%s: waitpid failed: %s\n",
   337                         progname, strerror(errno));
   340         if (!WIFEXITED(status)) {
   341                 fprintf(stderr, 
"%s: child terminated abnormally (status %i)\n",
   345         if (WEXITSTATUS(status) != 0)
   351 static int chdir_to_parent(
char *copy, 
const char **lastp)
   358         tmp = strrchr(copy, 
'/');
   359         if (tmp == NULL || tmp[1] == 
'\0') {
   360                 fprintf(stderr, 
"%s: internal error: invalid abs path: <%s>\n",
   368         } 
else if (tmp[1] != 
'\0') {
   378                 fprintf(stderr, 
"%s: failed to chdir to %s: %s\n",
   379                         progname, parent, strerror(errno));
   383         if (getcwd(buf, 
sizeof(buf)) == NULL) {
   384                 fprintf(stderr, 
"%s: failed to obtain current directory: %s\n",
   385                         progname, strerror(errno));
   388         if (strcmp(buf, parent) != 0) {
   389                 fprintf(stderr, 
"%s: mountpoint moved (%s -> %s)\n", progname,
   399 static int umount_nofollow_support(
void)
   401         int res = umount2(
"", UMOUNT_UNUSED);
   402         if (res != -1 || errno != EINVAL)
   405         res = umount2(
"", UMOUNT_NOFOLLOW);
   406         if (res != -1 || errno != ENOENT)
   412 static int unmount_fuse_locked(
const char *mnt, 
int quiet, 
int lazy)
   417         int umount_flags = lazy ? UMOUNT_DETACH : 0;
   420                 res = may_unmount(mnt, quiet);
   427                 fprintf(stderr, 
"%s: failed to allocate memory\n", progname);
   432         res = chdir_to_parent(copy, &last);
   437         if (umount_nofollow_support()) {
   438                 umount_flags |= UMOUNT_NOFOLLOW;
   440                 res = check_is_mount(last, mnt, NULL);
   445         res = umount2(last, umount_flags);
   446         if (res == -1 && !quiet) {
   447                 fprintf(stderr, 
"%s: failed to unmount %s: %s\n",
   448                         progname, mnt, strerror(errno));
   458                 fprintf(stderr, 
"%s: failed to chdir to '/'\n", progname);
   462         return fuse_mnt_remove_mount(progname, mnt);
   465 static int unmount_fuse(
const char *mnt, 
int quiet, 
int lazy)
   468         int mtablock = lock_umount();
   470         res = unmount_fuse_locked(mnt, quiet, lazy);
   471         unlock_umount(mtablock);
   476 static int count_fuse_fs(
void)
   480         const char *mtab = _PATH_MOUNTED;
   481         FILE *fp = setmntent(mtab, 
"r");
   483                 fprintf(stderr, 
"%s: failed to open %s: %s\n", progname, mtab,
   487         while ((entp = getmntent(fp)) != NULL) {
   488                 if (strcmp(entp->mnt_type, 
"fuse") == 0 ||
   489                     strncmp(entp->mnt_type, 
"fuse.", 5) == 0)
   498 static int count_fuse_fs(
void)
   503 static int add_mount(
const char *source, 
const char *mnt, 
const char *type,
   513 static int unmount_fuse(
const char *mnt, 
int quiet, 
int lazy)
   516         return fuse_mnt_umount(progname, mnt, mnt, lazy);
   520 static void strip_line(
char *line)
   522         char *s = strchr(line, 
'#');
   525         for (s = line + strlen(line) - 1;
   526              s >= line && isspace((
unsigned char) *s); s--);
   528         for (s = line; isspace((
unsigned char) *s); s++);
   530                 memmove(line, s, strlen(s)+1);
   533 static void parse_line(
char *line, 
int linenum)
   536         if (strcmp(line, 
"user_allow_other") == 0)
   537                 user_allow_other = 1;
   538         else if (sscanf(line, 
"mount_max = %i", &tmp) == 1)
   542                         "%s: unknown parameter in %s at line %i: '%s'\n",
   543                         progname, FUSE_CONF, linenum, line);
   546 static void read_conf(
void)
   548         FILE *fp = fopen(FUSE_CONF, 
"r");
   553                 while (fgets(line, 
sizeof(line), fp) != NULL) {
   555                                 if (line[strlen(line)-1] == 
'\n') {
   557                                         parse_line(line, linenum);
   561                         } 
else if(line[strlen(line)-1] == 
'\n') {
   562                                 fprintf(stderr, 
"%s: reading %s: line %i too long\n", progname, FUSE_CONF, linenum);
   570                         fprintf(stderr, 
"%s: reading %s: missing newline at end of file\n", progname, FUSE_CONF);
   574                         fprintf(stderr, 
"%s: reading %s: read failed\n", progname, FUSE_CONF);
   578         } 
else if (errno != ENOENT) {
   579                 bool fatal = (errno != EACCES && errno != ELOOP &&
   580                               errno != ENAMETOOLONG && errno != ENOTDIR &&
   582                 fprintf(stderr, 
"%s: failed to open %s: %s\n",
   583                         progname, FUSE_CONF, strerror(errno));
   589 static int begins_with(
const char *s, 
const char *beg)
   591         if (strncmp(s, beg, strlen(beg)) == 0)
   604 static struct mount_flags mount_flags[] = {
   605         {
"rw",      MS_RDONLY,      0, 1},
   606         {
"ro",      MS_RDONLY,      1, 1},
   607         {
"suid",    MS_NOSUID,      0, 0},
   608         {
"nosuid",  MS_NOSUID,      1, 1},
   609         {
"dev",     MS_NODEV,       0, 0},
   610         {
"nodev",   MS_NODEV,       1, 1},
   611         {
"exec",    MS_NOEXEC,      0, 1},
   612         {
"noexec",  MS_NOEXEC,      1, 1},
   613         {
"async",   MS_SYNCHRONOUS, 0, 1},
   614         {
"sync",    MS_SYNCHRONOUS, 1, 1},
   615         {
"atime",   MS_NOATIME,     0, 1},
   616         {
"noatime", MS_NOATIME,     1, 1},
   617         {
"dirsync", MS_DIRSYNC,     1, 1},
   621 static int find_mount_flag(
const char *s, 
unsigned len, 
int *on, 
int *flag)
   625         for (i = 0; mount_flags[i].opt != NULL; i++) {
   626                 const char *opt = mount_flags[i].opt;
   627                 if (strlen(opt) == len && strncmp(opt, s, len) == 0) {
   628                         *on = mount_flags[i].on;
   629                         *flag = mount_flags[i].flag;
   630                         if (!mount_flags[i].safe && getuid() != 0) {
   633                                         "%s: unsafe option %s ignored\n",
   642 static int add_option(
char **optsp, 
const char *opt, 
unsigned expand)
   646                 newopts = strdup(opt);
   648                 unsigned oldsize = strlen(*optsp);
   649                 unsigned newsize = oldsize + 1 + strlen(opt) + expand + 1;
   650                 newopts = (
char *) realloc(*optsp, newsize);
   652                         sprintf(newopts + oldsize, 
",%s", opt);
   654         if (newopts == NULL) {
   655                 fprintf(stderr, 
"%s: failed to allocate memory\n", progname);
   662 static int get_mnt_opts(
int flags, 
char *opts, 
char **mnt_optsp)
   667         if (!(flags & MS_RDONLY) && add_option(mnt_optsp, 
"rw", 0) == -1)
   670         for (i = 0; mount_flags[i].opt != NULL; i++) {
   671                 if (mount_flags[i].on && (flags & mount_flags[i].flag) &&
   672                     add_option(mnt_optsp, mount_flags[i].opt, 0) == -1)
   676         if (add_option(mnt_optsp, opts, 0) == -1)
   679         l = strlen(*mnt_optsp);
   680         if ((*mnt_optsp)[l-1] == 
',')
   681                 (*mnt_optsp)[l-1] = 
'\0';
   683                 const char *user = get_user_name();
   687                 if (add_option(mnt_optsp, 
"user=", strlen(user)) == -1)
   689                 strcat(*mnt_optsp, user);
   694 static int opt_eq(
const char *s, 
unsigned len, 
const char *opt)
   696         if(strlen(opt) == len && strncmp(s, opt, len) == 0)
   702 static int get_string_opt(
const char *s, 
unsigned len, 
const char *opt,
   706         unsigned opt_len = strlen(opt);
   711         *val = (
char *) malloc(len - opt_len + 1);
   713                 fprintf(stderr, 
"%s: failed to allocate memory\n", progname);
   720         for (i = 0; i < len; i++) {
   721                 if (s[i] == 
'\\' && i + 1 < len)
   734 static int mount_notrunc(
const char *source, 
const char *target,
   735                          const char *filesystemtype, 
unsigned long mountflags,
   737         if (strlen(data) > sysconf(_SC_PAGESIZE) - 1) {
   738                 fprintf(stderr, 
"%s: mount options too long\n", progname);
   742         return mount(source, target, filesystemtype, mountflags, data);
   746 static int do_mount(
const char *mnt, 
const char **typep, mode_t rootmode,
   747                     int fd, 
const char *opts, 
const char *dev, 
char **sourcep,
   751         int flags = MS_NOSUID | MS_NODEV;
   753         char *mnt_opts = NULL;
   757         char *subtype = NULL;
   762         optbuf = (
char *) malloc(strlen(opts) + 128);
   764                 fprintf(stderr, 
"%s: failed to allocate memory\n", progname);
   768         for (s = opts, d = optbuf; *s;) {
   770                 const char *fsname_str = 
"fsname=";
   771                 const char *subtype_str = 
"subtype=";
   772                 bool escape_ok = begins_with(s, fsname_str) ||
   773                                  begins_with(s, subtype_str);
   774                 for (len = 0; s[len]; len++) {
   775                         if (escape_ok && s[len] == 
'\\' && s[len + 1])
   777                         else if (s[len] == 
',')
   780                 if (begins_with(s, fsname_str)) {
   781                         if (!get_string_opt(s, len, fsname_str, &fsname))
   783                 } 
else if (begins_with(s, subtype_str)) {
   784                         if (!get_string_opt(s, len, subtype_str, &subtype))
   786                 } 
else if (opt_eq(s, len, 
"blkdev")) {
   789                                         "%s: option blkdev is privileged\n",
   794                 } 
else if (opt_eq(s, len, 
"auto_unmount")) {
   796                 } 
else if (!begins_with(s, 
"fd=") &&
   797                            !begins_with(s, 
"rootmode=") &&
   798                            !begins_with(s, 
"user_id=") &&
   799                            !begins_with(s, 
"group_id=")) {
   803                         if (opt_eq(s, len, 
"large_read")) {
   804                                 struct utsname utsname;
   806                                 res = uname(&utsname);
   808                                     sscanf(utsname.release, 
"%u.%u",
   809                                            &kmaj, &kmin) == 2 &&
   810                                     (kmaj > 2 || (kmaj == 2 && kmin > 4))) {
   811                                         fprintf(stderr, 
"%s: note: 'large_read' mount option is deprecated for %i.%i kernels\n", progname, kmaj, kmin);
   815                         if (getuid() != 0 && !user_allow_other &&
   816                             (opt_eq(s, len, 
"allow_other") ||
   817                              opt_eq(s, len, 
"allow_root"))) {
   818                                 fprintf(stderr, 
"%s: option %.*s only allowed if 'user_allow_other' is set in %s\n", progname, len, s, FUSE_CONF);
   822                                 if (find_mount_flag(s, len, &on, &flag)) {
   827                                 } 
else if (opt_eq(s, len, 
"default_permissions") ||
   828                                            opt_eq(s, len, 
"allow_other") ||
   829                                            begins_with(s, 
"max_read=") ||
   830                                            begins_with(s, 
"blksize=")) {
   835                                         fprintf(stderr, 
"%s: unknown option '%.*s'\n", progname, len, s);
   845         res = get_mnt_opts(flags, optbuf, &mnt_opts);
   849         sprintf(d, 
"fd=%i,rootmode=%o,user_id=%u,group_id=%u",
   850                 fd, rootmode, getuid(), getgid());
   852         source = malloc((fsname ? strlen(fsname) : 0) +
   853                         (subtype ? strlen(subtype) : 0) + strlen(dev) + 32);
   855         type = malloc((subtype ? strlen(subtype) : 0) + 32);
   856         if (!type || !source) {
   857                 fprintf(stderr, 
"%s: failed to allocate memory\n", progname);
   862                 sprintf(type, 
"%s.%s", blkdev ? 
"fuseblk" : 
"fuse", subtype);
   864                 strcpy(type, blkdev ? 
"fuseblk" : 
"fuse");
   867                 strcpy(source, fsname);
   869                 strcpy(source, subtype ? subtype : dev);
   871         res = mount_notrunc(source, mnt, type, flags, optbuf);
   872         if (res == -1 && errno == ENODEV && subtype) {
   874                 strcpy(type, blkdev ? 
"fuseblk" : 
"fuse");
   877                                 sprintf(source, 
"%s#%s", subtype, fsname);
   879                         strcpy(source, type);
   882                 res = mount_notrunc(source, mnt, type, flags, optbuf);
   884         if (res == -1 && errno == EINVAL) {
   886                 sprintf(d, 
"fd=%i,rootmode=%o,user_id=%u",
   887                         fd, rootmode, getuid());
   888                 res = mount_notrunc(source, mnt, type, flags, optbuf);
   891                 int errno_save = errno;
   892                 if (blkdev && errno == ENODEV && !fuse_mnt_check_fuseblk())
   893                         fprintf(stderr, 
"%s: 'fuseblk' support missing\n",
   896                         fprintf(stderr, 
"%s: mount failed: %s\n", progname,
   897                                 strerror(errno_save));
   902         *mnt_optsp = mnt_opts;
   918 static int check_perm(
const char **mntp, 
struct stat *stbuf, 
int *mountpoint_fd)
   921         const char *mnt = *mntp;
   922         const char *origmnt = mnt;
   923         struct statfs fs_buf;
   926         res = lstat(mnt, stbuf);
   928                 fprintf(stderr, 
"%s: failed to access mountpoint %s: %s\n",
   929                         progname, mnt, strerror(errno));
   937         if (S_ISDIR(stbuf->st_mode)) {
   941                                 "%s: failed to chdir to mountpoint: %s\n",
   942                                 progname, strerror(errno));
   946                 res = lstat(mnt, stbuf);
   949                                 "%s: failed to access mountpoint %s: %s\n",
   950                                 progname, origmnt, strerror(errno));
   954                 if ((stbuf->st_mode & S_ISVTX) && stbuf->st_uid != getuid()) {
   955                         fprintf(stderr, 
"%s: mountpoint %s not owned by user\n",
   960                 res = access(mnt, W_OK);
   962                         fprintf(stderr, 
"%s: user has no write access to mountpoint %s\n",
   966         } 
else if (S_ISREG(stbuf->st_mode)) {
   967                 static char procfile[256];
   968                 *mountpoint_fd = open(mnt, O_WRONLY);
   969                 if (*mountpoint_fd == -1) {
   970                         fprintf(stderr, 
"%s: failed to open %s: %s\n",
   971                                 progname, mnt, strerror(errno));
   974                 res = fstat(*mountpoint_fd, stbuf);
   977                                 "%s: failed to access mountpoint %s: %s\n",
   978                                 progname, mnt, strerror(errno));
   981                 if (!S_ISREG(stbuf->st_mode)) {
   983                                 "%s: mountpoint %s is no longer a regular file\n",
   988                 sprintf(procfile, 
"/proc/self/fd/%i", *mountpoint_fd);
   992                         "%s: mountpoint %s is not a directory or a regular file\n",
  1003         if (statfs(*mntp, &fs_buf)) {
  1004                 fprintf(stderr, 
"%s: failed to access mountpoint %s: %s\n",
  1005                         progname, mnt, strerror(errno));
  1014         typeof(fs_buf.f_type) f_type_whitelist[] = {
  1046         for (i = 0; i < 
sizeof(f_type_whitelist)/
sizeof(f_type_whitelist[0]); i++) {
  1047                 if (f_type_whitelist[i] == fs_buf.f_type)
  1051         fprintf(stderr, 
"%s: mounting over filesystem type %#010lx is forbidden\n",
  1052                 progname, (
unsigned long)fs_buf.f_type);
  1056 static int try_open(
const char *dev, 
char **devp, 
int silent)
  1058         int fd = open(dev, O_RDWR);
  1060                 *devp = strdup(dev);
  1061                 if (*devp == NULL) {
  1062                         fprintf(stderr, 
"%s: failed to allocate memory\n",
  1067         } 
else if (errno == ENODEV ||
  1071                 fprintf(stderr, 
"%s: failed to open %s: %s\n", progname, dev,
  1077 static int try_open_fuse_device(
char **devp)
  1082         fd = try_open(FUSE_DEV, devp, 0);
  1087 static int open_fuse_device(
char **devp)
  1089         int fd = try_open_fuse_device(devp);
  1094                 "%s: fuse device not found, try 'modprobe fuse' first\n",
  1101 static int mount_fuse(
const char *mnt, 
const char *opts, 
const char **type)
  1107         char *source = NULL;
  1108         char *mnt_opts = NULL;
  1109         const char *real_mnt = mnt;
  1110         int mountpoint_fd = -1;
  1112         fd = open_fuse_device(&dev);
  1119         if (getuid() != 0 && mount_max != -1) {
  1120                 int mount_count = count_fuse_fs();
  1121                 if (mount_count >= mount_max) {
  1122                         fprintf(stderr, 
"%s: too many FUSE filesystems mounted; mount_max=N can be set in %s\n", progname, FUSE_CONF);
  1127         res = check_perm(&real_mnt, &stbuf, &mountpoint_fd);
  1130                 res = do_mount(real_mnt, type, stbuf.st_mode & S_IFMT,
  1131                                fd, opts, dev, &source, &mnt_opts);
  1133         if (mountpoint_fd != -1)
  1134                 close(mountpoint_fd);
  1141                 fprintf(stderr, 
"%s: failed to chdir to '/'\n", progname);
  1145         if (geteuid() == 0) {
  1146                 res = add_mount(source, mnt, *type, mnt_opts);
  1166 static int send_fd(
int sock_fd, 
int fd)
  1170         struct cmsghdr *p_cmsg;
  1172         size_t cmsgbuf[CMSG_SPACE(
sizeof(fd)) / 
sizeof(size_t)];
  1176         msg.msg_control = cmsgbuf;
  1177         msg.msg_controllen = 
sizeof(cmsgbuf);
  1178         p_cmsg = CMSG_FIRSTHDR(&msg);
  1179         p_cmsg->cmsg_level = SOL_SOCKET;
  1180         p_cmsg->cmsg_type = SCM_RIGHTS;
  1181         p_cmsg->cmsg_len = CMSG_LEN(
sizeof(fd));
  1182         p_fds = (
int *) CMSG_DATA(p_cmsg);
  1184         msg.msg_controllen = p_cmsg->cmsg_len;
  1185         msg.msg_name = NULL;
  1186         msg.msg_namelen = 0;
  1192         vec.iov_base = &sendchar;
  1193         vec.iov_len = 
sizeof(sendchar);
  1194         while ((retval = sendmsg(sock_fd, &msg, 0)) == -1 && errno == EINTR);
  1196                 perror(
"sending file descriptor");
  1218 static int should_auto_unmount(
const char *mnt, 
const char *type)
  1227         fprintf(stderr, 
"%s: failed to allocate memory\n", progname);
  1231         if (chdir_to_parent(copy, &last) == -1)
  1233         if (check_is_mount(last, mnt, type) == -1)
  1236         fd = open(mnt, O_RDONLY);
  1240                 result = errno == ENOTCONN;
  1247 static void usage(
void)
  1249         printf(
"%s: [options] mountpoint\n"  1252                " -V                 print version\n"  1253                " -o opt[,opt...]   mount options\n"  1256                " -z                 lazy unmount\n",
  1261 static void show_version(
void)
  1263         printf(
"fusermount3 version: %s\n", PACKAGE_VERSION);
  1267 int main(
int argc, 
char *argv[])
  1275         static int unmount = 0;
  1276         static int lazy = 0;
  1277         static int quiet = 0;
  1280         const char *opts = 
"";
  1281         const char *type = NULL;
  1283         static const struct option long_opts[] = {
  1284                 {
"unmount", no_argument, NULL, 
'u'},
  1285                 {
"lazy",    no_argument, NULL, 
'z'},
  1286                 {
"quiet",   no_argument, NULL, 
'q'},
  1287                 {
"help",    no_argument, NULL, 
'h'},
  1288                 {
"version", no_argument, NULL, 
'V'},
  1291         progname = strdup(argv[0]);
  1292         if (progname == NULL) {
  1293                 fprintf(stderr, 
"%s: failed to allocate memory\n", argv[0]);
  1297         while ((ch = getopt_long(argc, argv, 
"hVo:uzq", long_opts,
  1329         if (lazy && !unmount) {
  1330                 fprintf(stderr, 
"%s: -z can only be used with -u\n", progname);
  1334         if (optind >= argc) {
  1335                 fprintf(stderr, 
"%s: missing mountpoint argument\n", progname);
  1337         } 
else if (argc > optind + 1) {
  1338                 fprintf(stderr, 
"%s: extra arguments after the mountpoint\n",
  1343         origmnt = argv[optind];
  1346         mnt = fuse_mnt_resolve_path(progname, origmnt);
  1350                         fprintf(stderr, 
"%s: failed to chdir to '/'\n", progname);
  1362         commfd = getenv(FUSE_COMMFD_ENV);
  1363         if (commfd == NULL) {
  1364                 fprintf(stderr, 
"%s: old style mounting not supported\n",
  1369         fd = mount_fuse(mnt, opts, &type);
  1374         res = send_fd(cfd, fd);
  1379         if (!auto_unmount) {
  1391                 fprintf(stderr, 
"%s: failed to chdir to '/'\n", progname);
  1395         sigfillset(&sigset);
  1396         sigprocmask(SIG_BLOCK, &sigset, NULL);
  1402                 unsigned char buf[16];
  1403                 int n = recv(cfd, buf, 
sizeof(buf), 0);
  1414         if (!should_auto_unmount(mnt, type)) {
  1420                 res = unmount_fuse(mnt, quiet, lazy);
  1422                 res = umount2(mnt, lazy ? UMOUNT_DETACH : 0);
  1423                 if (res == -1 && !quiet)
  1425                                 "%s: failed to unmount %s: %s\n",
  1426                                 progname, mnt, strerror(errno));