summaryrefslogtreecommitdiffstats
path: root/contrib/macfuse/mount_darwin.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/macfuse/mount_darwin.c')
-rw-r--r--contrib/macfuse/mount_darwin.c264
1 files changed, 264 insertions, 0 deletions
diff --git a/contrib/macfuse/mount_darwin.c b/contrib/macfuse/mount_darwin.c
new file mode 100644
index 00000000000..d1d1c34e761
--- /dev/null
+++ b/contrib/macfuse/mount_darwin.c
@@ -0,0 +1,264 @@
+/*
+ * Derived from mount_bsd.c from the fuse distribution.
+ *
+ * FUSE: Filesystem in Userspace
+ * Copyright (C) 2005-2006 Csaba Henk <csaba.henk@creo.hu>
+ * Copyright (C) 2007-2009 Amit Singh <asingh@gmail.com>
+ * Copyright (c) 2010 Gluster, Inc. <http://www.gluster.com>
+ *
+ * This program can be distributed under the terms of the GNU LGPLv2.
+ * See the file COPYING.LIB.
+ */
+
+#undef _POSIX_C_SOURCE
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <sys/sysctl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stddef.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <paths.h>
+
+#include <libproc.h>
+#include <sys/utsname.h>
+
+#include <sys/param.h>
+#include <sys/mount.h>
+#include <AssertMacros.h>
+
+#include "fuse_param.h"
+#include "fuse_ioctl.h"
+
+#include "glusterfs/glusterfs.h"
+#include "glusterfs/logging.h"
+#include "glusterfs/common-utils.h"
+
+#define GFFUSE_LOGERR(...) \
+ gf_log ("glusterfs-fuse", GF_LOG_ERROR, ## __VA_ARGS__)
+
+int
+gf_fuse_mount (const char *mountpoint, char *fsname, char *mnt_param,
+ pid_t *mnt_pid, int status_fd) /* Not used on OS X */
+{
+ int fd = 0;
+ int pid = 0;
+ int ret = 0;
+ char *fdnam = NULL;
+ char *dev = NULL;
+ char vstr[4];
+ unsigned vval = 0;
+ int i = 0;
+
+ const char *mountprog = OSXFUSE_MOUNT_PROG;
+ sig_t chldf = SIG_ERR;
+ char version[MAXHOSTNAMELEN + 1] = { 0 };
+ size_t version_len = MAXHOSTNAMELEN;
+ size_t version_len_desired = 0;
+ int r = 0;
+ char devpath[MAXPATHLEN] = { 0 };;
+
+ if (!mountpoint) {
+ gf_log ("glustefs-fuse", GF_LOG_ERROR,
+ "missing or invalid mount point");
+ goto err;
+ }
+
+ /* 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);
+
+ chldf = signal(SIGCHLD, SIG_DFL); /* So that we can wait4() below. */
+
+ if (chldf == SIG_ERR) {
+ gf_log ("glusterfs-fuse", GF_LOG_ERROR,
+ "signal() returned SIG_ERR: %s",
+ strerror(errno));
+ goto err;
+ }
+
+ /* check for user<->kernel match. */
+ ret = sysctlbyname(SYSCTL_OSXFUSE_VERSION_NUMBER, version,
+ &version_len, NULL, (size_t)0);
+ if (ret != 0) {
+ gf_log ("glustefs-fuse", GF_LOG_ERROR,
+ "sysctlbyname() returned error: %s",
+ strerror(errno));
+ goto err;
+ }
+
+ /* sysctlbyname() includes the trailing '\0' in version_len */
+ version_len_desired = sizeof ("2.x.y");
+
+ if (version_len != version_len_desired) {
+ gf_log ("glusterfs-fuse", GF_LOG_ERROR,
+ "version length mismatch for OSXFUSE %s",
+ version);
+ ret = -1;
+ goto err;
+ }
+
+ for (i = 0; i < 3; i++)
+ vstr[i] = version[2*i];
+ vstr[3] = '\0';
+
+ vval = strtoul(vstr, NULL, 10);
+ if (vval < 264) {
+ GFFUSE_LOGERR("OSXFUSE version %s is not supported", version);
+ ret = -1;
+ goto err;
+ }
+
+ gf_log("glusterfs-fuse", GF_LOG_INFO,
+ "OSXFUSE kext version supported %s", version);
+
+ fdnam = getenv("FUSE_DEV_FD");
+ if (fdnam) {
+ fd = strtol(fdnam, NULL, 10);
+ if (fd < 0) {
+ GFFUSE_LOGERR("invalid value given in FUSE_DEV_FD");
+ ret = -1;
+ goto err;
+ }
+ goto mount;
+ }
+
+ dev = getenv("FUSE_DEV_NAME");
+ if (!dev) {
+ for (r = 0; r < OSXFUSE_NDEVICES; r++) {
+ snprintf(devpath, MAXPATHLEN - 1,
+ _PATH_DEV OSXFUSE_DEVICE_BASENAME "%d", r);
+ if ((fd = open(devpath, O_RDWR)) < 0) {
+ GFFUSE_LOGERR("failed to open device %s (%s)",
+ devpath,
+ strerror(errno));
+ goto err;
+ }
+ dev = devpath;
+ goto mount;
+ }
+ }
+
+ fd = open(dev, O_RDWR);
+ if (fd < 0) {
+ GFFUSE_LOGERR("failed to open device %s (%s)", dev,
+ strerror(errno));
+ ret = -1;
+ goto err;
+ }
+
+mount:
+ signal(SIGCHLD, chldf);
+
+ pid = fork();
+ if (pid == -1) {
+ GFFUSE_LOGERR("fork() failed (%s)", strerror(errno));
+ ret = -1;
+ goto err;
+ }
+
+ if (pid == 0) {
+ pid = fork();
+ if (pid == -1) {
+ GFFUSE_LOGERR("fork() failed (%s)", strerror(errno));
+ ret = -1;
+ goto err;
+ }
+
+ if (pid == 0) {
+ const char *argv[32];
+ int a = 0;
+ char *opts = NULL;
+
+ if (asprintf(&opts, "%s,fssubtype=glusterfs",
+ mnt_param) == -1) {
+ GFFUSE_LOGERR("asprintf() error: %s",
+ strerror(errno));
+ ret = -1;
+ goto err;
+ }
+
+ 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("OSXFUSE: failed to exec mount"
+ " program (%s)", strerror(errno));
+ _exit(1);
+ }
+ _exit(0);
+ }
+ ret = fd;
+err:
+ if (ret == -1) {
+ if (fd > 0) {
+ close(fd);
+ }
+ }
+ return ret;
+}
+
+void
+gf_fuse_unmount(const char *mountpoint, int fd)
+{
+ int ret;
+ struct stat sbuf;
+ char dev[128];
+ char resolved_path[PATH_MAX];
+ char *ep, *rp = NULL;
+
+ unsigned int hs_complete = 0;
+
+ ret = ioctl(fd, FUSEDEVIOCGETHANDSHAKECOMPLETE, &hs_complete);
+ if (ret || !hs_complete) {
+ return;
+ }
+
+ if (fstat(fd, &sbuf) == -1) {
+ return;
+ }
+
+ devname_r(sbuf.st_rdev, S_IFCHR, dev, 128);
+
+ if (strncmp(dev, OSXFUSE_DEVICE_BASENAME,
+ sizeof(OSXFUSE_DEVICE_BASENAME) - 1)) {
+ return;
+ }
+
+ strtol(dev + sizeof(OSXFUSE_DEVICE_BASENAME) - 1, &ep, 10);
+ if (*ep != '\0') {
+ return;
+ }
+
+ rp = realpath(mountpoint, resolved_path);
+ if (rp) {
+ ret = unmount(resolved_path, 0);
+ }
+
+ close(fd);
+ return;
+}