diff --git a/Makefile.am b/Makefile.am
index a80788b..99e1dc8 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -2,14 +2,14 @@
 
 bin_PROGRAMS = sshfs
 
-sshfs_SOURCES = sshfs.c cache.c cache.h
+sshfs_SOURCES = sshfs.c cache.c cache.h compat/darwin_semaphore.h compat/darwin_semaphore.c
 if FUSE_OPT_COMPAT
 sshfs_SOURCES += compat/fuse_opt.c compat/fuse_opt.h
 endif
 
 sshfs_LDADD = $(SSHFS_LIBS)
 sshfs_CFLAGS = $(SSHFS_CFLAGS)
-sshfs_CPPFLAGS = -D_REENTRANT -DFUSE_USE_VERSION=26 -DLIBDIR=\"$(libdir)\"
+sshfs_CPPFLAGS = -D_REENTRANT -DFUSE_USE_VERSION=26 -DLIBDIR=\"$(libdir)\" -Icompat
 
 EXTRA_DIST = sshnodelay.c FAQ.txt
 CLEANFILES = sshnodelay.so
diff --git a/compat/darwin_semaphore.c b/compat/darwin_semaphore.c
new file mode 100644
index 0000000..e45fd9a
--- /dev/null
+++ b/compat/darwin_semaphore.c
@@ -0,0 +1,229 @@
+/*
+ * Copyright (C) 2000,02 Free Software Foundation, Inc.
+ * This file is part of the GNU C Library.
+ * Written by Ga<EB>l Le Mignot <address@hidden>
+ *
+ * The GNU C Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * The GNU C Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with the GNU C Library; see the file COPYING.LIB.  If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "darwin_semaphore.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <sys/types.h>
+
+#define __SEM_ID_NONE  0x0
+#define __SEM_ID_LOCAL 0xcafef00d
+
+/* http://www.opengroup.org/onlinepubs/007908799/xsh/sem_init.html */
+int
+compat_sem_init(compat_sem_t *sem, int pshared, unsigned int value)
+{
+    if (pshared) {
+        errno = ENOSYS;
+        return -1;
+    }
+
+    sem->id = __SEM_ID_NONE;
+
+    if (pthread_cond_init(&sem->__data.local.count_cond, NULL)) {
+        goto cond_init_fail;
+    }
+
+    if (pthread_mutex_init(&sem->__data.local.count_lock, NULL)) {
+        goto mutex_init_fail;
+    }
+
+    sem->__data.local.count = value;
+    sem->id = __SEM_ID_LOCAL;
+
+    return 0;
+
+mutex_init_fail:
+
+    pthread_cond_destroy(&sem->__data.local.count_cond);
+
+cond_init_fail:
+
+    return -1;
+}
+
+/* http://www.opengroup.org/onlinepubs/007908799/xsh/sem_destroy.html */
+int
+compat_sem_destroy(compat_sem_t *sem)
+{
+    int res = 0;
+
+    pthread_mutex_lock(&sem->__data.local.count_lock);
+
+    sem->id = __SEM_ID_NONE;
+    pthread_cond_broadcast(&sem->__data.local.count_cond);
+
+    if (pthread_cond_destroy(&sem->__data.local.count_cond)) {
+        res = -1;
+    }
+
+    pthread_mutex_unlock(&sem->__data.local.count_lock);
+
+    if (pthread_mutex_destroy(&sem->__data.local.count_lock)) {
+        res = -1;
+    }
+
+    return res;
+}
+
+int
+compat_sem_getvalue(compat_sem_t *sem, unsigned int *sval)
+{
+    int res = 0;
+
+    pthread_mutex_lock(&sem->__data.local.count_lock);
+
+    if (sem->id != __SEM_ID_LOCAL) {
+        res = -1;
+        errno = EINVAL;
+    } else {
+        *sval = sem->__data.local.count;
+    }
+
+    pthread_mutex_unlock(&sem->__data.local.count_lock);
+
+    return res;
+}
+
+/* http://www.opengroup.org/onlinepubs/007908799/xsh/sem_post.html */
+int
+compat_sem_post(compat_sem_t *sem)
+{
+    int res = 0;
+
+    pthread_mutex_lock(&sem->__data.local.count_lock);
+
+    if (sem->id != __SEM_ID_LOCAL) {
+        res = -1;
+        errno = EINVAL;
+    } else if (sem->__data.local.count < COMPAT_SEM_VALUE_MAX) {
+        sem->__data.local.count++;
+	if (sem->__data.local.count == 1) {
+            pthread_cond_signal(&sem->__data.local.count_cond);
+        }
+    } else {
+        errno = ERANGE;
+        res = -1;
+    }
+
+    pthread_mutex_unlock(&sem->__data.local.count_lock);
+
+    return res;
+}
+
+/* http://www.opengroup.org/onlinepubs/009695399/functions/sem_timedwait.html */
+int
+compat_sem_timedwait(compat_sem_t *sem, const struct timespec *abs_timeout)
+{
+    int res = 0;
+
+    if (abs_timeout &&
+        (abs_timeout->tv_nsec < 0 || abs_timeout->tv_nsec >= 1000000000)) {
+       errno = EINVAL;
+       return -1;
+    }
+
+    pthread_cleanup_push((void(*)(void*))&pthread_mutex_unlock,
+                         &sem->__data.local.count_lock);
+
+    pthread_mutex_lock(&sem->__data.local.count_lock);
+
+    if (sem->id != __SEM_ID_LOCAL) {
+        errno = EINVAL;
+        res = -1;
+    } else {
+        if (!sem->__data.local.count) {
+            res = pthread_cond_timedwait(&sem->__data.local.count_cond,
+                                         &sem->__data.local.count_lock,
+                                         abs_timeout);
+        }
+        if (res) {
+            assert(res == ETIMEDOUT);
+            res = -1;
+            errno = ETIMEDOUT;
+        } else if (sem->id != __SEM_ID_LOCAL) {
+	    res = -1;
+            errno = EINVAL;
+	} else {
+            sem->__data.local.count--;
+        }
+    }
+
+    pthread_cleanup_pop(1);
+
+    return res;
+}
+
+/* http://www.opengroup.org/onlinepubs/007908799/xsh/sem_trywait.html */
+int
+compat_sem_trywait(compat_sem_t *sem)
+{
+    int res = 0;
+
+    pthread_mutex_lock(&sem->__data.local.count_lock);
+
+    if (sem->id != __SEM_ID_LOCAL) {
+        res = -1;
+        errno = EINVAL;
+    } else if (sem->__data.local.count) {
+        sem->__data.local.count--;
+    } else {
+        res = -1;
+        errno = EAGAIN;
+    }
+
+    pthread_mutex_unlock (&sem->__data.local.count_lock);
+
+    return res;
+}
+
+/* http://www.opengroup.org/onlinepubs/007908799/xsh/sem_wait.html */
+int
+compat_sem_wait(compat_sem_t *sem)
+{
+    int res = 0;
+
+    pthread_cleanup_push((void(*)(void*))&pthread_mutex_unlock,
+                          &sem->__data.local.count_lock);
+
+    pthread_mutex_lock(&sem->__data.local.count_lock);
+
+    if (sem->id != __SEM_ID_LOCAL) {
+        errno = EINVAL;
+        res = -1;
+    } else {
+        while (!sem->__data.local.count) {
+            pthread_cond_wait(&sem->__data.local.count_cond,
+                              &sem->__data.local.count_lock);
+        }
+        if (sem->id != __SEM_ID_LOCAL) {
+	    res = -1;
+            errno = EINVAL;
+	} else {
+            sem->__data.local.count--;
+        }
+    }
+
+    pthread_cleanup_pop(1);
+
+    return res;
+}
diff --git a/compat/darwin_semaphore.h b/compat/darwin_semaphore.h
new file mode 100644
index 0000000..3f03e41
--- /dev/null
+++ b/compat/darwin_semaphore.h
@@ -0,0 +1,69 @@
+/* Copyright (C) 2000,02 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Written by Gaël Le Mignot <address@hidden>
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+// This implementation is based on libsem http://lists.debian.org/debian-devel/2004/08/msg00612.html
+
+#ifndef _SEMAPHORE_H_
+#define _SEMAPHORE_H_
+
+/* Caller must not include <semaphore.h> */
+
+#include <pthread.h>
+
+struct __local_sem_t
+{
+    unsigned int    count;
+    pthread_mutex_t count_lock;
+    pthread_cond_t  count_cond;
+};
+
+typedef struct compat_sem {
+    unsigned int id;
+    union {
+        struct __local_sem_t local;
+    } __data;
+} compat_sem_t;
+
+#define COMPAT_SEM_VALUE_MAX ((int32_t)32767)
+
+int compat_sem_init(compat_sem_t *sem, int pshared, unsigned int value);
+int compat_sem_destroy(compat_sem_t *sem);
+int compat_sem_getvalue(compat_sem_t *sem, unsigned int *value);
+int compat_sem_post(compat_sem_t *sem);
+int compat_sem_timedwait(compat_sem_t *sem, const struct timespec *abs_timeout);
+int compat_sem_trywait(compat_sem_t *sem);
+int compat_sem_wait(compat_sem_t *sem);
+
+
+/* Redefine semaphores. Caller must not include <semaphore.h> */
+
+typedef compat_sem_t sem_t;
+
+#define sem_init(s, p, v)   compat_sem_init(s, p, v)
+#define sem_destroy(s)      compat_sem_destroy(s)
+#define sem_getvalue(s, v)  compat_sem_getvalue(s, v)
+#define sem_post(s)         compat_sem_post(s)
+#define sem_timedwait(s, t) compat_sem_timedwait(s, t)
+#define sem_trywait(s)      compat_sem_trywait(s)
+#define sem_wait(s)         compat_sem_wait(s)
+
+#define SEM_VALUE_MAX       COMPAT_SEM_VALUE_MAX
+
+
+#endif /* semaphore.h */
diff --git a/sshfs.c b/sshfs.c
index 8a8e858..9220b70 100644
--- a/sshfs.c.orig	2011-07-23 18:00:48.000000000 -0400
+++ a/sshfs.c	2011-07-23 19:28:43.000000000 -0400
@@ -19,12 +19,18 @@
 #include <string.h>
 #include <stdint.h>
 #include <errno.h>
-#if !(__FreeBSD__ >= 10)
-#include <semaphore.h>
+#ifdef __APPLE__
+/* OS X does not support named semaphores; need some sort of emulation */
+#if (__FreeBSD__ >= 10)
+/* MacFUSE provides a semaphore emulation layer */
+#include <fuse_darwin.h>
 #else
-#define MACFUSE_SSHFS_VERSION "2.2.0"
-#include "fuse_darwin.h"
-#endif
+/* Fuse4X doesn't; use our own */
+#include "darwin_semaphore.h"
+#endif  /* (__FreeBSD__ >= 10) */
+#else
+#include <semaphore.h>
+#endif  /* __APPLE__ */
 #include <pthread.h>
 #include <netdb.h>
 #include <signal.h>
@@ -39,7 +45,7 @@
 #include <netinet/in.h>
 #include <netinet/tcp.h>
 #include <glib.h>
-#if (__FreeBSD__ >= 10)
+#ifdef __APPLE__
 #include <libgen.h>
 #include <strings.h>
 #endif
@@ -129,7 +135,7 @@
 
 #define SSHNODELAY_SO "sshnodelay.so"
 
-#if (__FreeBSD__ >= 10)
+#ifdef __APPLE__
 
 #ifndef LIBDIR
 #define LIBDIR "/usr/local/lib"
@@ -188,7 +194,7 @@
 	int connver;
 	int modifver;
 	int refs;
-#if (__FreeBSD__ >= 10)
+#ifdef __APPLE__
 	pthread_mutex_t file_lock;
 #endif
 };
@@ -230,7 +236,7 @@
 	int server_version;
 	unsigned remote_uid;
 	unsigned local_uid;
-#if (__FreeBSD__ >= 10)
+#ifdef __APPLE__
 	unsigned remote_gid;
 	unsigned local_gid;
 #endif
@@ -667,7 +673,7 @@
 		}
 	}
 
-#if (__FreeBSD__ >= 10)
+#ifdef __APPLE__
 	if (sshfs.remote_uid_detected) {
 		if (uid == sshfs.remote_uid)
 			uid = sshfs.local_uid;
@@ -780,7 +786,7 @@
 #ifdef SSH_NODELAY_WORKAROUND
 static int do_ssh_nodelay_workaround(void)
 {
-#if (__FreeBSD__ >= 10)
+#ifdef __APPLE__
 	char *oldpreload = getenv("DYLD_INSERT_LIBRARIES");
 #else
 	char *oldpreload = getenv("LD_PRELOAD");
@@ -789,7 +795,7 @@
 	char sopath[PATH_MAX];
 	int res;
 
-#if (__FreeBSD__ >= 10)
+#ifdef __APPLE__
 	char *sshfs_program_path_base = NULL;
 	if (!sshfs_program_path[0]) {
 		goto nobundle;
@@ -831,7 +837,7 @@
 			return -1;
 		}
 	}
-#if (__FreeBSD__ >= 10)
+#ifdef __APPLE__
 pathok:
 #endif
 
@@ -840,7 +846,7 @@
 				     oldpreload ? " " : "",
 				     sopath);
 
-#if (__FreeBSD__ >= 10)
+#ifdef __APPLE__
 	if (!newpreload || setenv("DYLD_INSERT_LIBRARIES", newpreload, 1) == -1)
 		fprintf(stderr, "warning: failed set DYLD_INSERT_LIBRARIES for ssh nodelay workaround\n");
 #else
@@ -1541,7 +1547,7 @@
 
 	sshfs.remote_uid = stbuf.st_uid;
 	sshfs.local_uid = getuid();
-#if (__FreeBSD__ >= 10)
+#ifdef __APPLE__
 	sshfs.remote_gid = stbuf.st_gid;
 	sshfs.local_gid = getgid();
 #endif
@@ -2139,7 +2145,7 @@
 	buf_init(&buf, 0);
 	buf_add_path(&buf, path);
 	buf_add_uint32(&buf, SSH_FILEXFER_ATTR_UIDGID);
-#if (__FreeBSD__ >= 10)
+#ifdef __APPLE__
 	if (sshfs.remote_uid_detected) {
 		if (uid == sshfs.local_uid)
 			uid = sshfs.remote_uid;
@@ -2230,7 +2236,7 @@
 	sf = g_new0(struct sshfs_file, 1);
 	list_init(&sf->write_reqs);
 	pthread_cond_init(&sf->write_finished, NULL);
-#if (__FreeBSD__ >= 10)
+#ifdef __APPLE__
 	pthread_mutex_init(&sf->file_lock, NULL);
 #endif
 	/* Assume random read after open */
@@ -2266,7 +2272,7 @@
 	}
 
 	if (!err) {
-#if (__FreeBSD__ >= 10)
+#ifdef __APPLE__
 		if (cache_enabled)
 			cache_add_attr(path, &stbuf, wrctr);
 #else
@@ -2275,7 +2281,7 @@
 		buf_finish(&sf->handle);
 		fi->fh = (unsigned long) sf;
 	} else {
-#if (__FreeBSD__ >= 10)
+#ifdef __APPLE__
 		if (cache_enabled)
 			cache_invalidate(path);
 #else
@@ -2335,11 +2341,11 @@
 
 static void sshfs_file_put(struct sshfs_file *sf)
 {
-#if (__FreeBSD__ >= 10)
+#ifdef __APPLE__
 	pthread_mutex_lock(&sf->file_lock);
 #endif
 	sf->refs--;
-#if (__FreeBSD__ >= 10)
+#ifdef __APPLE__
 	if (!sf->refs) {
 		pthread_mutex_unlock(&sf->file_lock);
 		g_free(sf);
@@ -2354,11 +2360,11 @@
 
 static void sshfs_file_get(struct sshfs_file *sf)
 {
-#if (__FreeBSD__ >= 10)
+#ifdef __APPLE__
 	pthread_mutex_lock(&sf->file_lock);
 #endif
 	sf->refs++;
-#if (__FreeBSD__ >= 10)
+#ifdef __APPLE__
 	pthread_mutex_unlock(&sf->file_lock);
 #endif
 }
@@ -3050,12 +3056,7 @@
 		exit(1);
 
 	case KEY_VERSION:
-#if (__FreeBSD__ >= 10)
-		fprintf(stderr, "SSHFS version %s (MacFUSE SSHFS %s)\n",
-			PACKAGE_VERSION, MACFUSE_SSHFS_VERSION);
-#else
 		fprintf(stderr, "SSHFS version %s\n", PACKAGE_VERSION);
-#endif
 #if FUSE_VERSION >= 25
 		fuse_opt_add_arg(outargs, "--version");
 		sshfs_fuse_main(outargs);
@@ -3139,7 +3140,7 @@
 		perror("Failed to allocate locked page for password");
 		return -1;
 	}
-#if (__FreeBSD__ >= 10)
+#ifdef __APPLE__
 	if (mlock(sshfs.password, size) != 0) {
 		memset(sshfs.password, 0, size);
 		munmap(sshfs.password, size);
@@ -3147,7 +3148,7 @@
 		perror("Failed to allocate locked page for password");
 		return -1;
 	}
-#endif /* __FreeBSD__ >= 10 */
+#endif /* __APPLE__ */
 
 	/* Don't use fgets() because password might stay in memory */
 	for (n = 0; n < max_password; n++) {
@@ -3279,13 +3280,13 @@
 }
 #endif
 
-#if (__FreeBSD__ >= 10)
+#ifdef __APPLE__
 int main(int argc, char *argv[], __unused char *envp[], char **exec_path)
 #else
 int main(int argc, char *argv[])
 #endif
 {
-#if (__FreeBSD__ >= 10)
+#ifdef __APPLE__
 	if (!realpath(*exec_path, sshfs_program_path)) {
 		memset(sshfs_program_path, 0, PATH_MAX);
 	}
@@ -3298,10 +3299,10 @@
 	const char *sftp_server;
 	int libver;
 
-#if (__FreeBSD__ >= 10)
+#ifdef __APPLE__
 	/* Until this gets fixed somewhere else. */
 	g_slice_set_config(G_SLICE_CONFIG_ALWAYS_MALLOC, TRUE);
-#endif /* __FreeBSD__ >= 10 */
+#endif /* __APPLE__ */
 	g_thread_init(NULL);
 
 	sshfs.blksize = 4096;
@@ -3309,11 +3310,11 @@
 	sshfs.max_write = 65536;
 	sshfs.nodelay_workaround = 1;
 	sshfs.nodelaysrv_workaround = 0;
-#if (__FreeBSD__ >= 10)
+#ifdef __APPLE__
 	sshfs.rename_workaround = 1;
 #else
 	sshfs.rename_workaround = 0;
-#endif /* __FreeBSD__ >= 10 */
+#endif /* __APPLE__ */
 	sshfs.truncate_workaround = 0;
 	sshfs.buflimit_workaround = 1;
 	sshfs.ssh_ver = 2;
@@ -3326,7 +3327,7 @@
 	ssh_add_arg("-a");
 	ssh_add_arg("-oClearAllForwardings=yes");
 
-#if (__FreeBSD__ >= 10)
+#ifdef __APPLE__
 	sshfs.detect_uid = 1;
 #endif
 
--- sshfs-fuse-2.2/cache.h.orig	2011-07-23 19:42:35.000000000 -0400
+++ sshfs-fuse-2.2/cache.h	2011-07-23 19:48:15.000000000 -0400
@@ -28,6 +28,6 @@
 void cache_invalidate(const char *path);
 uint64_t cache_get_write_ctr(void);
 
-#if (__FreeBSD__ >= 10)
+#ifdef __APPLE__
 extern int cache_enabled;
 #endif
--- sshfs-fuse-2.2/cache.c.orig	2011-07-23 19:42:33.000000000 -0400
+++ sshfs-fuse-2.2/cache.c	2011-07-23 19:47:52.000000000 -0400
@@ -559,7 +559,7 @@
 	cache.next_oper = oper;
 
 	cache_unity_fill(oper, &cache_oper);
-#if (__FreeBSD__ >= 10)
+#ifdef __APPLE__
 	cache_enabled = cache.on;
 #endif
 	if (cache.on) {
@@ -597,6 +597,6 @@
 	return fuse_opt_parse(args, &cache, cache_opts, NULL);
 }
 
-#if (__FreeBSD__ >= 10)
+#ifdef __APPLE__
 int cache_enabled;
 #endif
