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/build.rb b/build.rb
new file mode 100755
index 0000000..b7a1d85
--- /dev/null
+++ b/build.rb
@@ -0,0 +1,54 @@
+#!/usr/bin/env ruby
+# Possible flags are:
+#   --debug       this builds distribuition with debug flags enabled
+#   --root DIR    install the binary into this directory. If this flag is not set - the script
+#                 redeploys kext to local machine and restarts it
+#   --static      build static sshfs binary, it dynamically links only with fuse4x library
+#   --clean       clean before build
+
+require 'fileutils'
+
+CWD = File.dirname(__FILE__)
+KEXT_DIR = '/System/Library/Extensions/'
+Dir.chdir(CWD)
+
+debug = ARGV.include?('--debug')
+clean = ARGV.include?('--clean')
+static = ARGV.include?('--static')
+root_dir = ARGV.index('--root') ? ARGV[ARGV.index('--root') + 1] : nil
+
+abort("root directory #{root_dir} does not exist") if ARGV.index('--root') and not File.exists?(root_dir)
+
+system('git clean -xdf') if clean
+
+unless File.exists?('Makefile') then
+  system("autoreconf -f -i -Wall,no-obsolete") or abort
+  system("./configure") or abort
+end
+
+tmp_dir = "/tmp/sshfsbuild-#{Process.pid}"
+Dir.mkdir(tmp_dir)
+
+ld_flags = ''
+dylibs = %w(iconv gthread-2.0 glib-2.0 intl)
+if static
+  # In case if we build the distribution we need statically link against
+  # macports libraries from the 'dylibs' list above.
+  # To do it - we trick the build system by adding temp path with static libraries.
+  for lib in dylibs do
+    `ln -s /opt/local/lib/lib#{lib}.a #{tmp_dir}/`
+  end
+
+  ld_flags = "LDFLAGS='-L#{tmp_dir} -framework CoreFoundation -framework CoreServices'"
+end
+
+system("make -s -j3 #{ld_flags}") or abort
+
+cmd = 'sudo make install'
+if root_dir
+  cmd = cmd + ' DESTDIR=' + root_dir
+end
+
+system(cmd)
+
+FileUtils.rm_rf(tmp_dir)
diff --git a/cache.c b/cache.c
index bb23f8f..5b635f2 100644
--- a/cache.c
+++ b/cache.c
@@ -559,6 +559,9 @@ struct fuse_operations *cache_init(struct fuse_cache_operations *oper)
 	cache.next_oper = oper;
 
 	cache_unity_fill(oper, &cache_oper);
+#ifdef __APPLE__
+	cache_enabled = cache.on;
+#endif
 	if (cache.on) {
 		cache_fill(oper, &cache_oper);
 		pthread_mutex_init(&cache.lock, NULL);
@@ -593,3 +596,7 @@ int cache_parse_options(struct fuse_args *args)
 
 	return fuse_opt_parse(args, &cache, cache_opts, NULL);
 }
+
+#ifdef __APPLE__
+int cache_enabled;
+#endif
diff --git a/cache.h b/cache.h
index cec9ca4..8ca0989 100644
--- a/cache.h
+++ b/cache.h
@@ -27,3 +27,7 @@ int cache_parse_options(struct fuse_args *args);
 void cache_add_attr(const char *path, const struct stat *stbuf, uint64_t wrctr);
 void cache_invalidate(const char *path);
 uint64_t cache_get_write_ctr(void);
+
+#ifdef __APPLE__
+extern int cache_enabled;
+#endif
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/configure.ac b/configure.ac
index 1cf48b3..f737b41 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,10 +1,10 @@
-AC_INIT(sshfs-fuse, 2.3)
+AC_INIT(sshfs-fuse, 2.3.0)
 AM_INIT_AUTOMAKE
 AM_CONFIG_HEADER(config.h)
 
 AC_PROG_CC
 AM_PROG_CC_C_O
-CFLAGS="$CFLAGS -Wall -W"
+CFLAGS="$CFLAGS -Wall -W -mmacosx-version-min=10.5"
 LIBS=
 AC_SEARCH_LIBS(dlsym, [dl])
 sshnodelay_libs=$LIBS
diff --git a/sshfs.c b/sshfs.c
index 22bda6b..9698c74 100644
--- a/sshfs.c
+++ b/sshfs.c
@@ -20,7 +20,11 @@
 #include <string.h>
 #include <stdint.h>
 #include <errno.h>
+#ifdef __APPLE__
+#include <darwin_semaphore.h>
+#else
 #include <semaphore.h>
+#endif
 #include <pthread.h>
 #include <netdb.h>
 #include <signal.h>
@@ -35,6 +39,10 @@
 #include <netinet/in.h>
 #include <netinet/tcp.h>
 #include <glib.h>
+#ifdef __APPLE__
+#include <libgen.h>
+#include <strings.h>
+#endif
 
 #include "cache.h"
 
@@ -118,6 +126,16 @@
 
 #define SSHNODELAY_SO "sshnodelay.so"
 
+#ifdef __APPLE__
+
+#ifndef LIBDIR
+#define LIBDIR "/usr/local/lib"
+#endif
+
+static char sshfs_program_path[PATH_MAX] = { 0 };
+
+#endif
+
 struct buffer {
 	uint8_t *p;
 	size_t len;
@@ -167,6 +185,9 @@ struct sshfs_file {
 	int connver;
 	int modifver;
 	int refs;
+#ifdef __APPLE__
+	pthread_mutex_t file_lock;
+#endif
 };
 
 struct sshfs {
@@ -207,6 +228,10 @@ struct sshfs {
 	int server_version;
 	unsigned remote_uid;
 	unsigned local_uid;
+#ifdef __APPLE__
+	unsigned remote_gid;
+	unsigned local_gid;
+#endif
 	int remote_uid_detected;
 	unsigned blksize;
 	char *progname;
@@ -661,8 +686,17 @@ static int buf_get_attrs(struct buffer *buf, struct stat *stbuf, int *flagsp)
 		}
 	}
 
+#ifdef __APPLE__
+	if (sshfs.remote_uid_detected) {
+		if (uid == sshfs.remote_uid)
+			uid = sshfs.local_uid;
+		if (gid == sshfs.remote_gid)
+			gid = sshfs.local_gid;
+	}
+#else
 	if (sshfs.remote_uid_detected && uid == sshfs.remote_uid)
 		uid = sshfs.local_uid;
+#endif
 
 	memset(stbuf, 0, sizeof(struct stat));
 	stbuf->st_mode = mode;
@@ -765,11 +799,33 @@ static void ssh_add_arg(const char *arg)
 #ifdef SSH_NODELAY_WORKAROUND
 static int do_ssh_nodelay_workaround(void)
 {
+#ifdef __APPLE__
+	char *oldpreload = getenv("DYLD_INSERT_LIBRARIES");
+#else
 	char *oldpreload = getenv("LD_PRELOAD");
+#endif
 	char *newpreload;
 	char sopath[PATH_MAX];
 	int res;
 
+#ifdef __APPLE__
+	char *sshfs_program_path_base = NULL;
+	if (!sshfs_program_path[0]) {
+		goto nobundle;
+	}
+	sshfs_program_path_base = dirname(sshfs_program_path);
+	if (!sshfs_program_path_base) {
+		goto nobundle;
+	}
+	snprintf(sopath, sizeof(sopath), "%s/%s", sshfs_program_path_base,
+		SSHNODELAY_SO);
+	res = access(sopath, R_OK);
+	if (res == -1) {
+		goto nobundle;
+	}
+	goto pathok;
+nobundle:
+#endif
 	snprintf(sopath, sizeof(sopath), "%s/%s", LIBDIR, SSHNODELAY_SO);
 	res = access(sopath, R_OK);
 	if (res == -1) {
@@ -794,16 +850,24 @@ static int do_ssh_nodelay_workaround(void)
 			return -1;
 		}
 	}
+#ifdef __APPLE__
+pathok:
+#endif
 
 	newpreload = g_strdup_printf("%s%s%s",
 				     oldpreload ? oldpreload : "",
 				     oldpreload ? " " : "",
 				     sopath);
 
+#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
 	if (!newpreload || setenv("LD_PRELOAD", newpreload, 1) == -1) {
 		fprintf(stderr, "warning: failed set LD_PRELOAD "
 			"for ssh nodelay workaround\n");
 	}
+#endif
 	g_free(newpreload);
 	return 0;
 }
@@ -1500,6 +1564,10 @@ static void sftp_detect_uid()
 
 	sshfs.remote_uid = stbuf.st_uid;
 	sshfs.local_uid = getuid();
+#ifdef __APPLE__
+	sshfs.remote_gid = stbuf.st_gid;
+	sshfs.local_gid = getgid();
+#endif
 	sshfs.remote_uid_detected = 1;
 	DEBUG("remote_uid = %i\n", sshfs.remote_uid);
 
@@ -2120,6 +2188,14 @@ static int sshfs_chown(const char *path, uid_t uid, gid_t gid)
 	buf_init(&buf, 0);
 	buf_add_path(&buf, path);
 	buf_add_uint32(&buf, SSH_FILEXFER_ATTR_UIDGID);
+#ifdef __APPLE__
+	if (sshfs.remote_uid_detected) {
+		if (uid == sshfs.local_uid)
+			uid = sshfs.remote_uid;
+		if (gid == sshfs.local_gid)
+			gid = sshfs.remote_gid;
+	}
+#endif
 	buf_add_uint32(&buf, uid);
 	buf_add_uint32(&buf, gid);
 	err = sftp_request(SSH_FXP_SETSTAT, &buf, SSH_FXP_STATUS, NULL);
@@ -2203,6 +2279,9 @@ static int sshfs_open_common(const char *path, mode_t mode,
 	sf = g_new0(struct sshfs_file, 1);
 	list_init(&sf->write_reqs);
 	pthread_cond_init(&sf->write_finished, NULL);
+#ifdef __APPLE__
+	pthread_mutex_init(&sf->file_lock, NULL);
+#endif
 	/* Assume random read after open */
 	sf->is_seq = 0;
 	sf->refs = 1;
@@ -2236,11 +2315,21 @@ static int sshfs_open_common(const char *path, mode_t mode,
 	}
 
 	if (!err) {
+#ifdef __APPLE__
+		if (cache_enabled)
+			cache_add_attr(path, &stbuf, wrctr);
+#else
 		cache_add_attr(path, &stbuf, wrctr);
+#endif
 		buf_finish(&sf->handle);
 		fi->fh = (unsigned long) sf;
 	} else {
+#ifdef __APPLE__
+		if (cache_enabled)
+			cache_invalidate(path);
+#else
 		cache_invalidate(path);
+#endif
 		g_free(sf);
 	}
 	buf_free(&buf);
@@ -2295,14 +2384,32 @@ static int sshfs_fsync(const char *path, int isdatasync,
 
 static void sshfs_file_put(struct sshfs_file *sf)
 {
+#ifdef __APPLE__
+	pthread_mutex_lock(&sf->file_lock);
+#endif
 	sf->refs--;
+#ifdef __APPLE__
+	if (!sf->refs) {
+		pthread_mutex_unlock(&sf->file_lock);
+		g_free(sf);
+	} else {
+		pthread_mutex_unlock(&sf->file_lock);
+	}
+#else
 	if (!sf->refs)
 		g_free(sf);
+#endif
 }
 
 static void sshfs_file_get(struct sshfs_file *sf)
 {
+#ifdef __APPLE__
+	pthread_mutex_lock(&sf->file_lock);
+#endif
 	sf->refs++;
+#ifdef __APPLE__
+	pthread_mutex_unlock(&sf->file_lock);
+#endif
 }
 
 static int sshfs_release(const char *path, struct fuse_file_info *fi)
@@ -3076,6 +3183,15 @@ static int read_password(void)
 		perror("Failed to allocate locked page for password");
 		return -1;
 	}
+#ifdef __APPLE__
+	if (mlock(sshfs.password, size) != 0) {
+		memset(sshfs.password, 0, size);
+		munmap(sshfs.password, size);
+		sshfs.password = NULL;
+		perror("Failed to allocate locked page for password");
+		return -1;
+	}
+#endif /* __APPLE__ */
 
 	/* Don't use fgets() because password might stay in memory */
 	for (n = 0; n < max_password; n++) {
@@ -3123,7 +3239,7 @@ static void set_ssh_command(void)
 				replace_arg(&sshfs.ssh_args.argv[0],
 					    sshfs.ssh_command);
 			} else {
-				if (fuse_opt_insert_arg(&sshfs.ssh_args, i, 
+				if (fuse_opt_insert_arg(&sshfs.ssh_args, i,
 						sshfs.ssh_command) == -1)
 					_exit(1);
 			}
@@ -3227,8 +3343,13 @@ static int ssh_connect(void)
 	return 0;
 }
 
-int main(int argc, char *argv[])
+int main(int argc, char *argv[], __unused char *envp[], char **exec_path)
 {
+#ifdef __APPLE__
+	if (!realpath(*exec_path, sshfs_program_path)) {
+		memset(sshfs_program_path, 0, PATH_MAX);
+	}
+#endif
 	int res;
 	struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
 	char *tmp;
@@ -3236,6 +3357,10 @@ int main(int argc, char *argv[])
 	const char *sftp_server;
 	int libver;
 
+#ifdef __APPLE__
+	/* Until this gets fixed somewhere else. */
+	g_slice_set_config(G_SLICE_CONFIG_ALWAYS_MALLOC, TRUE);
+#endif /* __APPLE__ */
 	g_thread_init(NULL);
 
 	sshfs.blksize = 4096;
@@ -3243,7 +3368,11 @@ int main(int argc, char *argv[])
 	sshfs.max_write = 65536;
 	sshfs.nodelay_workaround = 1;
 	sshfs.nodelaysrv_workaround = 0;
+#ifdef __APPLE__
+	sshfs.rename_workaround = 1;
+#else
 	sshfs.rename_workaround = 0;
+#endif /* __APPLE__ */
 	sshfs.truncate_workaround = 0;
 	sshfs.buflimit_workaround = 1;
 	sshfs.ssh_ver = 2;
@@ -3257,6 +3386,10 @@ int main(int argc, char *argv[])
 	ssh_add_arg("-a");
 	ssh_add_arg("-oClearAllForwardings=yes");
 
+#ifdef __APPLE__
+	sshfs.detect_uid = 1;
+#endif
+
 	if (fuse_opt_parse(&args, &sshfs, sshfs_opts, sshfs_opt_proc) == -1 ||
 	    parse_workarounds() == -1)
 		exit(1);
diff --git a/sshfs.xcodeproj/project.pbxproj b/sshfs.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..b114fe3
--- /dev/null
+++ b/sshfs.xcodeproj/project.pbxproj
@@ -0,0 +1,229 @@
+// !$*UTF8*$!
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 46;
+	objects = {
+
+/* Begin PBXBuildFile section */
+		DE0F21EB139A7AFF003CBAC9 /* sshfs.c in Sources */ = {isa = PBXBuildFile; fileRef = DE0F21EA139A7AFF003CBAC9 /* sshfs.c */; };
+		DE0F21EF139A7B0A003CBAC9 /* cache.c in Sources */ = {isa = PBXBuildFile; fileRef = DE0F21ED139A7B0A003CBAC9 /* cache.c */; };
+		DE0F21F1139A7B11003CBAC9 /* sshnodelay.c in Sources */ = {isa = PBXBuildFile; fileRef = DE0F21F0139A7B11003CBAC9 /* sshnodelay.c */; };
+		DE37D32813CF7B660027D6F9 /* darwin_semaphore.c in Sources */ = {isa = PBXBuildFile; fileRef = DE37D32413CF7B660027D6F9 /* darwin_semaphore.c */; };
+		DE37D32913CF7B660027D6F9 /* fuse_opt.c in Sources */ = {isa = PBXBuildFile; fileRef = DE37D32613CF7B660027D6F9 /* fuse_opt.c */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+		DE0F21D3139A7ABB003CBAC9 /* CopyFiles */ = {
+			isa = PBXCopyFilesBuildPhase;
+			buildActionMask = 2147483647;
+			dstPath = /usr/share/man/man1/;
+			dstSubfolderSpec = 0;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 1;
+		};
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+		DE0F21D5139A7ABB003CBAC9 /* sshfs */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = sshfs; sourceTree = BUILT_PRODUCTS_DIR; };
+		DE0F21E9139A7AFF003CBAC9 /* sshfs.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; path = sshfs.1; sourceTree = "<group>"; };
+		DE0F21EA139A7AFF003CBAC9 /* sshfs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sshfs.c; sourceTree = "<group>"; };
+		DE0F21ED139A7B0A003CBAC9 /* cache.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cache.c; sourceTree = "<group>"; };
+		DE0F21EE139A7B0A003CBAC9 /* cache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cache.h; sourceTree = "<group>"; };
+		DE0F21F0139A7B11003CBAC9 /* sshnodelay.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sshnodelay.c; sourceTree = "<group>"; };
+		DE0F21F2139A7B1D003CBAC9 /* config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = config.h; sourceTree = "<group>"; };
+		DE0F21FC139B1EC3003CBAC9 /* configure.ac */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = configure.ac; sourceTree = "<group>"; };
+		DE0F21FE139B1ECB003CBAC9 /* Makefile.am */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Makefile.am; sourceTree = "<group>"; };
+		DE37D32413CF7B660027D6F9 /* darwin_semaphore.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = darwin_semaphore.c; sourceTree = "<group>"; };
+		DE37D32513CF7B660027D6F9 /* darwin_semaphore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = darwin_semaphore.h; sourceTree = "<group>"; };
+		DE37D32613CF7B660027D6F9 /* fuse_opt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fuse_opt.c; sourceTree = "<group>"; };
+		DE37D32713CF7B660027D6F9 /* fuse_opt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fuse_opt.h; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+		DE0F21D2139A7ABB003CBAC9 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+		DE0F21CA139A7ABB003CBAC9 = {
+			isa = PBXGroup;
+			children = (
+				DE37D32313CF7B660027D6F9 /* compat */,
+				DE0F21FE139B1ECB003CBAC9 /* Makefile.am */,
+				DE0F21FC139B1EC3003CBAC9 /* configure.ac */,
+				DE0F21F2139A7B1D003CBAC9 /* config.h */,
+				DE0F21F0139A7B11003CBAC9 /* sshnodelay.c */,
+				DE0F21ED139A7B0A003CBAC9 /* cache.c */,
+				DE0F21EE139A7B0A003CBAC9 /* cache.h */,
+				DE0F21E9139A7AFF003CBAC9 /* sshfs.1 */,
+				DE0F21EA139A7AFF003CBAC9 /* sshfs.c */,
+				DE0F21D6139A7ABB003CBAC9 /* Products */,
+			);
+			sourceTree = "<group>";
+		};
+		DE0F21D6139A7ABB003CBAC9 /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				DE0F21D5139A7ABB003CBAC9 /* sshfs */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		DE37D32313CF7B660027D6F9 /* compat */ = {
+			isa = PBXGroup;
+			children = (
+				DE37D32413CF7B660027D6F9 /* darwin_semaphore.c */,
+				DE37D32513CF7B660027D6F9 /* darwin_semaphore.h */,
+				DE37D32613CF7B660027D6F9 /* fuse_opt.c */,
+				DE37D32713CF7B660027D6F9 /* fuse_opt.h */,
+			);
+			path = compat;
+			sourceTree = "<group>";
+		};
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+		DE0F21D4139A7ABB003CBAC9 /* sshfs */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = DE0F21DE139A7ABB003CBAC9 /* Build configuration list for PBXNativeTarget "sshfs" */;
+			buildPhases = (
+				DE0F21D1139A7ABB003CBAC9 /* Sources */,
+				DE0F21D2139A7ABB003CBAC9 /* Frameworks */,
+				DE0F21D3139A7ABB003CBAC9 /* CopyFiles */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = sshfs;
+			productName = sshfs;
+			productReference = DE0F21D5139A7ABB003CBAC9 /* sshfs */;
+			productType = "com.apple.product-type.tool";
+		};
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+		DE0F21CC139A7ABB003CBAC9 /* Project object */ = {
+			isa = PBXProject;
+			buildConfigurationList = DE0F21CF139A7ABB003CBAC9 /* Build configuration list for PBXProject "sshfs" */;
+			compatibilityVersion = "Xcode 3.2";
+			developmentRegion = English;
+			hasScannedForEncodings = 0;
+			knownRegions = (
+				en,
+			);
+			mainGroup = DE0F21CA139A7ABB003CBAC9;
+			productRefGroup = DE0F21D6139A7ABB003CBAC9 /* Products */;
+			projectDirPath = "";
+			projectRoot = "";
+			targets = (
+				DE0F21D4139A7ABB003CBAC9 /* sshfs */,
+			);
+		};
+/* End PBXProject section */
+
+/* Begin PBXSourcesBuildPhase section */
+		DE0F21D1139A7ABB003CBAC9 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				DE0F21EB139A7AFF003CBAC9 /* sshfs.c in Sources */,
+				DE0F21EF139A7B0A003CBAC9 /* cache.c in Sources */,
+				DE0F21F1139A7B11003CBAC9 /* sshnodelay.c in Sources */,
+				DE37D32813CF7B660027D6F9 /* darwin_semaphore.c in Sources */,
+				DE37D32913CF7B660027D6F9 /* fuse_opt.c in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+		DE0F21DC139A7ABB003CBAC9 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				GCC_PREPROCESSOR_DEFINITIONS = DEBUG;
+				GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+				GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				MACOSX_DEPLOYMENT_TARGET = 10.6;
+				ONLY_ACTIVE_ARCH = YES;
+				SDKROOT = macosx;
+			};
+			name = Debug;
+		};
+		DE0F21DD139A7ABB003CBAC9 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				MACOSX_DEPLOYMENT_TARGET = 10.6;
+				SDKROOT = macosx;
+			};
+			name = Release;
+		};
+		DE0F21DF139A7ABB003CBAC9 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				COPY_PHASE_STRIP = NO;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_ENABLE_OBJC_EXCEPTIONS = YES;
+				MACOSX_DEPLOYMENT_TARGET = 10.5;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+			};
+			name = Debug;
+		};
+		DE0F21E0139A7ABB003CBAC9 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				COPY_PHASE_STRIP = YES;
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				GCC_ENABLE_OBJC_EXCEPTIONS = YES;
+				MACOSX_DEPLOYMENT_TARGET = 10.5;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+			};
+			name = Release;
+		};
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+		DE0F21CF139A7ABB003CBAC9 /* Build configuration list for PBXProject "sshfs" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				DE0F21DC139A7ABB003CBAC9 /* Debug */,
+				DE0F21DD139A7ABB003CBAC9 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		DE0F21DE139A7ABB003CBAC9 /* Build configuration list for PBXNativeTarget "sshfs" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				DE0F21DF139A7ABB003CBAC9 /* Debug */,
+				DE0F21E0139A7ABB003CBAC9 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+/* End XCConfigurationList section */
+	};
+	rootObject = DE0F21CC139A7ABB003CBAC9 /* Project object */;
+}
diff --git a/sshfs.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/sshfs.xcodeproj/project.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 0000000..3adcdb4
--- /dev/null
+++ b/sshfs.xcodeproj/project.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Workspace
+   version = "1.0">
+   <FileRef
+      location = "self:sshfs.xcodeproj">
+   </FileRef>
+</Workspace>
diff --git a/sshnodelay.c b/sshnodelay.c
index 7518089..efe393c 100644
--- a/sshnodelay.c
+++ b/sshnodelay.c
@@ -5,6 +5,32 @@
 #include <netinet/in.h>
 #include <netinet/tcp.h>
 
+#ifdef __APPLE__
+
+int custom_connect(int sock, const struct sockaddr *addr, socklen_t addrlen);
+
+typedef struct interpose_s {
+	void *new_func;
+	void *orig_func;
+} interpose_t;
+
+static const interpose_t interposers[] \
+	__attribute__ ((section("__DATA, __interpose"))) = {
+	{ (void *)custom_connect,  (void *)connect  },
+};
+
+int custom_connect(int sock, const struct sockaddr *addr, socklen_t addrlen)
+{
+	int res = connect(sock, addr, addrlen);
+	if (!res && addr->sa_family == AF_INET) {
+		int opt = 1;
+		setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt));
+	}
+	return res;
+}
+
+#else
+
 int connect(int sock, const struct sockaddr *addr, socklen_t addrlen)
 {
 	int (*next_connect)(int, const struct sockaddr *, socklen_t) =
@@ -16,3 +42,5 @@ int connect(int sock, const struct sockaddr *addr, socklen_t addrlen)
 	}
 	return res;
 }
+
+#endif
