Ejemplo n.º 1
0
int
gf_fuse_mount (const char *mountpoint, char *fsname,
               unsigned long mountflags, char *mnt_param,
               pid_t *mnt_pid, int status_fd)
{
        int   fd  = -1;
        pid_t pid = -1;
        int   ret = -1;

        fd = open ("/dev/fuse", O_RDWR);
        if (fd == -1) {
                GFFUSE_LOGERR ("cannot open /dev/fuse (%s)",
                                strerror (errno));
                return -1;
        }

        /* start mount agent */
        pid = fork();
        switch (pid) {
        case 0:
                /* hello it's mount agent */
                if (!mnt_pid) {
                        /* daemonize mount agent, caller is
                         * not interested in waiting for it
                         */
                        pid = fork ();
                        if (pid)
                                exit (pid == -1 ? 1 : 0);
                }

                ret = fuse_mount_sys (mountpoint, fsname, mountflags, mnt_param,
                                      fd);
                if (ret == -1) {
                        gf_log ("glusterfs-fuse", GF_LOG_INFO,
                                "direct mount failed (%s) errno %d, "
                                "retry to mount via fusermount",
                                strerror (errno), errno);

                        ret = fuse_mount_fusermount (mountpoint, fsname,
                                                     mountflags, mnt_param, fd);
                }

                if (ret == -1)
                        GFFUSE_LOGERR ("mount of %s to %s (%s) failed",
                                       fsname, mountpoint, mnt_param);

                if (status_fd >= 0)
                        (void)write (status_fd, &ret, sizeof (ret));
                exit (!!ret);
                /* bye mount agent */
        case -1:
                close (fd);
                fd = -1;
        }

        if (mnt_pid)
               *mnt_pid = pid;

        return fd;
}
Ejemplo n.º 2
0
/* FUSE: to support some changes that were reverted since
 * then, it was split in two (fuse_mnt_umount() and
 * exec_umount()); however the actual code is same as here
 * since 0197ce40
 */
int
fuse_mnt_umount (const char *progname, const char *abs_mnt,
                 const char *rel_mnt, int lazy)
{
        int res;
        int status;
        sigset_t blockmask;
        sigset_t oldmask;

        if (!mtab_needs_update (abs_mnt)) {
                res = umount2 (rel_mnt, lazy ? 2 : 0);
                if (res == -1)
                        GFFUSE_LOGERR ("%s: failed to unmount %s: %s",
                                       progname, abs_mnt, strerror (errno));
                return res;
        }

        sigemptyset (&blockmask);
        sigaddset (&blockmask, SIGCHLD);
        res = sigprocmask (SIG_BLOCK, &blockmask, &oldmask);
        if (res == -1) {
                GFFUSE_LOGERR ("%s: sigprocmask: %s", progname,
                               strerror (errno));
                return -1;
        }

        res = fork ();
        if (res == -1) {
                GFFUSE_LOGERR ("%s: fork: %s", progname, strerror (errno));
                goto out_restore;
        }
        if (res == 0) {
                sigprocmask (SIG_SETMASK, &oldmask, NULL);
                setuid (geteuid ());
                execl ("/bin/umount", "/bin/umount", "-i", rel_mnt,
                      lazy ? "-l" : NULL, NULL);
                GFFUSE_LOGERR ("%s: failed to execute /bin/umount: %s",
                               progname, strerror (errno));
                exit (1);
        }
        res = waitpid (res, &status, 0);
        if (res == -1)
                GFFUSE_LOGERR ("%s: waitpid: %s", progname, strerror (errno));

        if (status != 0)
                res = -1;

 out_restore:
        sigprocmask (SIG_SETMASK, &oldmask, NULL);
        return res;
}
Ejemplo n.º 3
0
int
gf_fuse_mount (const char *mountpoint, char *fsname, char *mnt_param)
{
    int fd, pid;
    int result;
    char *fdnam, *dev;
    const char *mountprog = MACFUSE_MOUNT_PROG;
    sig_t chldf;

    /* mount_fusefs should not try to spawn the daemon */
    setenv("MOUNT_FUSEFS_SAFE", "1", 1);

    /* to notify mount_fusefs it's called from lib */
    setenv("MOUNT_FUSEFS_CALL_BY_LIB", "1", 1);

    if (!mountpoint) {
        fprintf(stderr, "missing or invalid mount point\n");
        return -1;
    }

    if (fuse_running_under_rosetta()) {
        fprintf(stderr, "MacFUSE does not work under Rosetta\n");
        return -1;
    }

    chldf = signal(SIGCHLD, SIG_DFL); /* So that we can wait4() below. */

    result = loadkmod();
    if (result == EINVAL)
        GFFUSE_LOGERR("OS X >= 10.5 (at least Leopard) required");
    else if (result == 0 || result == ENOENT || result == EBUSY) {
        /* Module loaded, but now need to check for user<->kernel match. */

        char   version[MAXHOSTNAMELEN + 1] = { 0 };
        size_t version_len = MAXHOSTNAMELEN;
        size_t version_len_desired = 0;

        result = sysctlbyname(SYSCTL_MACFUSE_VERSION_NUMBER, version,
                              &version_len, NULL, (size_t)0);
        if (result == 0) {
            /* sysctlbyname() includes the trailing '\0' in version_len */
            version_len_desired = strlen("2.x.y") + 1;

            if (version_len != version_len_desired)
                result = -1;
        } else
            strcpy(version, "?.?.?");
        if (result == 0) {
            char *ep;
            char vstr[4];
            unsigned vval;
            int i;

            for (i = 0; i < 3; i++)
                vstr[i] = version[2*i];
            vstr[3] = '\0';

            vval = strtoul(vstr, &ep, 10);
            if (*ep || vval < 203 || vval > 217)
                result = -1;
            else
                gf_log("glusterfs-fuse", GF_LOG_INFO,
                       "MacFUSE kext version %s", version);
        }
        if (result != 0)
            GFFUSE_LOGERR("MacFUSE version %s is not supported", version);
    } else
        GFFUSE_LOGERR("cannot load MacFUSE kext");
    if (result != 0)
        return -1;

    fdnam = getenv("FUSE_DEV_FD");

    if (fdnam) {
        char *ep;

        fd = strtol(fdnam, &ep, 10);
        if (*ep != '\0' || fd < 0) {
            GFFUSE_LOGERR("invalid value given in FUSE_DEV_FD");
            return -1;
        }

        goto mount;
    }

    dev = getenv("FUSE_DEV_NAME");
    if (dev) {
        if ((fd = open(dev, O_RDWR)) < 0) {
            GFFUSE_LOGERR("failed to open device (%s)", strerror(errno));
            return -1;
        }
    } else {
        int r, devidx = -1;
        char devpath[MAXPATHLEN];

        for (r = 0; r < MACFUSE_NDEVICES; r++) {
            snprintf(devpath, MAXPATHLEN - 1,
                     _PATH_DEV MACFUSE_DEVICE_BASENAME "%d", r);
            fd = open(devpath, O_RDWR);
            if (fd >= 0) {
                dev = devpath;
                devidx = r;
                break;
            }
        }
        if (devidx == -1) {
            GFFUSE_LOGERR("failed to open device (%s)", strerror(errno));
            return -1;
        }
    }

mount:
    if (getenv("FUSE_NO_MOUNT") || ! mountpoint)
        goto out;

    signal(SIGCHLD, chldf);

    pid = fork();

    if (pid == -1) {
        GFFUSE_LOGERR("fork() failed (%s)", strerror(errno));
        close(fd);
        return -1;
    }

    if (pid == 0) {

        pid = fork();
        if (pid == -1) {
            GFFUSE_LOGERR("fork() failed (%s)", strerror(errno));
            close(fd);
            exit(1);
        }

        if (pid == 0) {
            const char *argv[32];
            int a = 0;
            char *opts = NULL;

            if (asprintf(&opts, "%s,fssubtype=glusterfs", mnt_param) == -1) {
                GFFUSE_LOGERR("Out of memory");
		exit(1);
            }

            if (! fdnam)
                asprintf(&fdnam, "%d", fd);

            argv[a++] = mountprog;
            if (opts) {
                argv[a++] = "-o";
                argv[a++] = opts;
            }
            argv[a++] = fdnam;
            argv[a++] = mountpoint;
            argv[a++] = NULL;

            {
                char title[MAXPATHLEN + 1] = { 0 };
                u_int32_t len = MAXPATHLEN;
                int ret = proc_pidpath(getpid(), title, len);
                if (ret) {
                    setenv("MOUNT_FUSEFS_DAEMON_PATH", title, 1);
                }
            }
            execvp(mountprog, (char **) argv);
            GFFUSE_LOGERR("MacFUSE: failed to exec mount program (%s)", strerror(errno));
            exit(1);
        }

        _exit(0);
    }

out:
    return fd;
}
Ejemplo n.º 4
0
static int
fuse_mount_sys (const char *mountpoint, char *fsname,
                unsigned long mountflags, char *mnt_param, int fd)
{
        int ret = -1;
        unsigned mounted = 0;
        char *mnt_param_mnt = NULL;
        char *fstype = "fuse.glusterfs";
        char *source = fsname;

        ret = asprintf (&mnt_param_mnt,
                        "%s,fd=%i,rootmode=%o,user_id=%i,group_id=%i",
                        mnt_param, fd, S_IFDIR, getuid (), getgid ());
        if (ret == -1) {
                GFFUSE_LOGERR ("Out of memory");

                goto out;
        }

#ifdef __FreeBSD__
        struct iovec *iov = NULL;
        int iovlen = 0;
        build_iovec (&iov, &iovlen, "fstype", "fusefs", -1);
        build_iovec (&iov, &iovlen, "subtype", "glusterfs", -1);
        build_iovec (&iov, &iovlen, "fspath", mountpoint, -1);
        build_iovec (&iov, &iovlen, "from", "/dev/fuse", -1);
        build_iovec (&iov, &iovlen, "volname", source, -1);
        build_iovec_argf (&iov, &iovlen, "fd", "%d", fd);
        build_iovec_argf (&iov, &iovlen, "user_id", "%d", getuid());
        build_iovec_argf (&iov, &iovlen, "group_id", "%d", getgid());
        ret = nmount (iov, iovlen, mountflags);
#else
        ret = mount (source, mountpoint, fstype, mountflags,
                     mnt_param_mnt);
#endif /* __FreeBSD__ */
#ifdef GF_LINUX_HOST_OS
        if (ret == -1 && errno == ENODEV) {
                /* fs subtype support was added by 79c0b2df aka
                   v2.6.21-3159-g79c0b2d. Probably we have an
                   older kernel ... */
                fstype = "fuse";
                ret = asprintf (&source, "glusterfs#%s", fsname);
                if (ret == -1) {
                        GFFUSE_LOGERR ("Out of memory");

                        goto out;
                }
                ret = mount (source, mountpoint, fstype, mountflags,
                             mnt_param_mnt);
        }
#endif /* GF_LINUX_HOST_OS */
        if (ret == -1)
                goto out;
        else
                mounted = 1;

#ifdef GF_LINUX_HOST_OS
        if (geteuid () == 0) {
                char *newmnt = fuse_mnt_resolve_path ("fuse", mountpoint);
                char *mnt_param_mtab = NULL;

                if (!newmnt) {
                        ret = -1;

                        goto out;
                }

                ret = asprintf (&mnt_param_mtab, "%s%s",
                                mountflags & MS_RDONLY ? "ro," : "",
                                mnt_param);
                if (ret == -1)
                        GFFUSE_LOGERR ("Out of memory");
                else {
                        ret = fuse_mnt_add_mount ("fuse", source, newmnt,
                                                  fstype, mnt_param_mtab);
                        FREE (mnt_param_mtab);
                }

                FREE (newmnt);
                if (ret == -1) {
                        GFFUSE_LOGERR ("failed to add mtab entry");

                        goto out;
                }
        }
#endif /* GF_LINUX_HOST_OS */

out:
        if (ret == -1) {
                GFFUSE_LOGERR("ret = -1\n");
                if (mounted)
                        umount2 (mountpoint, 2); /* lazy umount */
        }
        FREE (mnt_param_mnt);
        if (source != fsname)
                FREE (source);

        return ret;
}
Ejemplo n.º 5
0
static int
fuse_mount_fusermount (const char *mountpoint, char *fsname,
                       unsigned long mountflags, char *mnt_param,
                       int fd)
{
        int  pid = -1;
        int  res = 0;
        int  ret = -1;
        char *fm_mnt_params = NULL;
        char *efsname = NULL;

#ifndef GF_FUSERMOUNT
        GFFUSE_LOGERR ("Mounting via helper utility "
                       "(unprivileged mounting) is supported "
                       "only if glusterfs is compiled with "
                       "--enable-fusermount");
        return -1;
#endif

        efsname = escape (fsname);
        if (!efsname) {
                GFFUSE_LOGERR ("Out of memory");

                return -1;
        }
        ret = asprintf (&fm_mnt_params,
                        "%s%s,fsname=%s,nonempty,subtype=glusterfs",
                        (mountflags & MS_RDONLY) ? "ro," : "",
                        mnt_param, efsname);
        FREE (efsname);
        if (ret == -1) {
                GFFUSE_LOGERR ("Out of memory");

                goto out;
        }

        /* fork to exec fusermount */
        pid = fork ();
        if (pid == -1) {
                GFFUSE_LOGERR ("fork() failed: %s", strerror (errno));
                ret = -1;
                goto out;
        }

        if (pid == 0) {
                char env[10];
                const char *argv[32];
                int a = 0;

                argv[a++] = FUSERMOUNT_PROG;
                argv[a++] = "-o";
                argv[a++] = fm_mnt_params;
                argv[a++] = "--";
                argv[a++] = mountpoint;
                argv[a++] = NULL;

                snprintf (env, sizeof (env), "%i", fd);
                setenv (FUSE_DEVFD_ENV, env, 1);
                execvp (FUSERMOUNT_PROG, (char **)argv);
                GFFUSE_LOGERR ("failed to exec fusermount: %s",
                               strerror (errno));
                _exit (1);
        }

        ret = waitpid (pid, &res, 0);
        ret = (ret == pid && res == 0) ? 0 : -1;
 out:
        FREE (fm_mnt_params);
        return ret;
}
Ejemplo n.º 6
0
/* FUSE: called add_mount_legacy(); R.I.P. as of cbd3a2a8 */
int
fuse_mnt_add_mount (const char *progname, const char *fsname,
                    const char *mnt, const char *type, const char *opts)
{
        int res;
        int status;
        sigset_t blockmask;
        sigset_t oldmask;

        if (!mtab_needs_update (mnt))
                return 0;

        sigemptyset (&blockmask);
        sigaddset (&blockmask, SIGCHLD);
        res = sigprocmask (SIG_BLOCK, &blockmask, &oldmask);
        if (res == -1) {
                GFFUSE_LOGERR ("%s: sigprocmask: %s",
                               progname, strerror (errno));
                return -1;
        }

        res = fork ();
        if (res == -1) {
                GFFUSE_LOGERR ("%s: fork: %s", progname, strerror (errno));
                goto out_restore;
        }
        if (res == 0) {
                char templ[] = "/tmp/fusermountXXXXXX";
                char *tmp;

                sigprocmask (SIG_SETMASK, &oldmask, NULL);
                setuid (geteuid ());

                /*
                 * hide in a directory, where mount isn't able to resolve
                 * fsname as a valid path
                 */
                tmp = mkdtemp (templ);
                if (!tmp) {
                        GFFUSE_LOGERR ("%s: failed to create temporary directory",
                                       progname);
                        exit (1);
                }
                if (chdir (tmp)) {
                        GFFUSE_LOGERR ("%s: failed to chdir to %s: %s",
                                       progname, tmp, strerror (errno));
                        exit (1);
                }
                rmdir (tmp);
                execl (_PATH_MOUNT, _PATH_MOUNT, "-i", "-f", "-t", type,
                       "-o", opts, fsname, mnt, NULL);
                GFFUSE_LOGERR ("%s: failed to execute %s: %s",
                               progname, _PATH_MOUNT, strerror (errno));
                exit (1);
        }

        res = waitpid (res, &status, 0);
        if (res == -1)
                GFFUSE_LOGERR ("%s: waitpid: %s", progname, strerror (errno));
        res = (res != -1 && status == 0) ? 0 : -1;

 out_restore:
        sigprocmask (SIG_SETMASK, &oldmask, NULL);
        return res;
}
Ejemplo n.º 7
0
char *
fuse_mnt_resolve_path (const char *progname, const char *orig)
{
        char buf[PATH_MAX];
        char *copy;
        char *dst;
        char *end;
        char *lastcomp;
        const char *toresolv;

        if (!orig[0]) {
                GFFUSE_LOGERR ("%s: invalid mountpoint '%s'", progname, orig);
                return NULL;
        }

        copy = strdup (orig);
        if (copy == NULL) {
                GFFUSE_LOGERR ("%s: failed to allocate memory", progname);
                return NULL;
        }

        toresolv = copy;
        lastcomp = NULL;
        for (end = copy + strlen (copy) - 1; end > copy && *end == '/'; end --);
        if (end[0] != '/') {
                char *tmp;
                end[1] = '\0';
                tmp = strrchr (copy, '/');
                if (tmp == NULL) {
                        lastcomp = copy;
                        toresolv = ".";
                } else {
                        lastcomp = tmp + 1;
                        if (tmp == copy)
                                toresolv = "/";
                }
                if (strcmp (lastcomp, ".") == 0 || strcmp (lastcomp, "..") == 0) {
                        lastcomp = NULL;
                        toresolv = copy;
                }
                else if (tmp)
                        tmp[0] = '\0';
        }
        if (realpath (toresolv, buf) == NULL) {
                GFFUSE_LOGERR ("%s: bad mount point %s: %s", progname, orig,
                               strerror (errno));
                FREE (copy);
                return NULL;
        }
        if (lastcomp == NULL)
                dst = strdup (buf);
        else {
                dst = (char *) MALLOC (strlen (buf) + 1 + strlen (lastcomp) + 1);
                if (dst) {
                        unsigned buflen = strlen (buf);
                        if (buflen && buf[buflen-1] == '/')
                                sprintf (dst, "%s%s", buf, lastcomp);
                        else
                                sprintf (dst, "%s/%s", buf, lastcomp);
                }
        }
        FREE (copy);
        if (dst == NULL)
                GFFUSE_LOGERR ("%s: failed to allocate memory", progname);
        return dst;
}