aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulio Merino <jmmv@google.com>2016-02-08 11:12:22 -0500
committerJulio Merino <jmmv@meroh.net>2016-02-08 20:46:37 -0500
commitddbe3bee444909420049a68f7891563f0e431669 (patch)
tree1273577a0fd0fa7ce54b426688938b785b442666
parentb10d21db3185a2b25e3bd35579f57d3c7b8d882e (diff)
parent9bcb98945405db3d64cd8dca409aa18990ff1929 (diff)
downloadsshfs-ddbe3bee444909420049a68f7891563f0e431669.tar
sshfs-ddbe3bee444909420049a68f7891563f0e431669.tar.gz
sshfs-ddbe3bee444909420049a68f7891563f0e431669.tar.bz2
sshfs-ddbe3bee444909420049a68f7891563f0e431669.zip
Merge remote-tracking branch 'osxfuse/master' into merge-osxfuse
Pull in all changes from osxfuse's fork of sshfs into libfuse's sshfs. There need not be two different copies of this codebase, particularly because libfuse's version is already autoconf-ified and can support multiple platforms. The merge is mostly clean with just a few manual edits to resolve conflicts.
-rw-r--r--.gitignore1
-rw-r--r--Makefile.am8
-rw-r--r--cache.c7
-rw-r--r--cache.h4
-rw-r--r--compat/darwin_compat.c246
-rw-r--r--compat/darwin_compat.h49
-rw-r--r--configure.ac12
-rw-r--r--sshfs.1.in (renamed from sshfs.1)16
-rw-r--r--sshfs.c158
-rw-r--r--sshnodelay.c28
10 files changed, 524 insertions, 5 deletions
diff --git a/.gitignore b/.gitignore
index daba941..f39c637 100644
--- a/.gitignore
+++ b/.gitignore
@@ -20,6 +20,7 @@ Makefile
*.m4
stamp-h*
config.*
+sshfs.1
/sshfs
/ltmain.sh
/configure
diff --git a/Makefile.am b/Makefile.am
index e1e5510..c5b92f0 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -6,16 +6,22 @@ sshfs_SOURCES = sshfs.c cache.c cache.h
if FUSE_OPT_COMPAT
sshfs_SOURCES += compat/fuse_opt.c compat/fuse_opt.h
endif
+if DARWIN_COMPAT
+sshfs_SOURCES += compat/darwin_compat.c compat/darwin_compat.h
+endif
sshfs_LDADD = $(SSHFS_LIBS)
sshfs_CFLAGS = $(SSHFS_CFLAGS)
sshfs_CPPFLAGS = -D_REENTRANT -DFUSE_USE_VERSION=26 -DLIBDIR=\"$(libdir)\"
EXTRA_DIST = sshnodelay.c
-CLEANFILES = sshnodelay.so
+CLEANFILES = sshnodelay.so sshfs.1
dist_man_MANS = sshfs.1
+sshfs.1:
+ $(CPP) $(CPPFLAGS) -P -xassembler-with-cpp sshfs.1.in | sed -e '/^$$/d' > sshfs.1
+
if SSH_NODELAY_SO
all-local: sshnodelay.so
diff --git a/cache.c b/cache.c
index 6e93157..ffdf71d 100644
--- a/cache.c
+++ b/cache.c
@@ -554,6 +554,9 @@ struct fuse_operations *cache_init(struct fuse_cache_operations *oper)
cache.next_oper = oper;
cache_unity_fill(oper, &cache_oper);
+#if __APPLE__
+ cache_enabled = cache.on;
+#endif
if (cache.on) {
cache_fill(oper, &cache_oper);
pthread_mutex_init(&cache.lock, NULL);
@@ -588,3 +591,7 @@ int cache_parse_options(struct fuse_args *args)
return fuse_opt_parse(args, &cache, cache_opts, NULL);
}
+
+#if __APPLE__
+int cache_enabled;
+#endif
diff --git a/cache.h b/cache.h
index cec9ca4..23ff970 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);
+
+#if __APPLE__
+extern int cache_enabled;
+#endif
diff --git a/compat/darwin_compat.c b/compat/darwin_compat.c
new file mode 100644
index 0000000..9b23be2
--- /dev/null
+++ b/compat/darwin_compat.c
@@ -0,0 +1,246 @@
+/*
+ * Copyright (c) 2006-2008 Amit Singh/Google Inc.
+ * Copyright (c) 2012 Anatol Pomozov
+ * Copyright (c) 2011-2013 Benjamin Fleischer
+ */
+
+#include "darwin_compat.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <sys/types.h>
+
+/*
+ * Semaphore implementation based on:
+ *
+ * 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.
+ */
+
+/* Semaphores */
+
+#define __SEM_ID_NONE ((int)0x0)
+#define __SEM_ID_LOCAL ((int)0xcafef00d)
+
+/* http://www.opengroup.org/onlinepubs/007908799/xsh/sem_init.html */
+int
+darwin_sem_init(darwin_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
+darwin_sem_destroy(darwin_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
+darwin_sem_getvalue(darwin_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
+darwin_sem_post(darwin_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 < DARWIN_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
+darwin_sem_timedwait(darwin_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
+darwin_sem_trywait(darwin_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
+darwin_sem_wait(darwin_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 {
+ if (!sem->__data.local.count) {
+ pthread_cond_wait(&sem->__data.local.count_cond,
+ &sem->__data.local.count_lock);
+ if (!sem->__data.local.count) {
+ /* spurious wakeup, assume it is an interruption */
+ res = -1;
+ errno = EINTR;
+ goto out;
+ }
+ }
+ if (sem->id != __SEM_ID_LOCAL) {
+ res = -1;
+ errno = EINVAL;
+ } else {
+ sem->__data.local.count--;
+ }
+ }
+
+out:
+ pthread_cleanup_pop(1);
+
+ return res;
+}
diff --git a/compat/darwin_compat.h b/compat/darwin_compat.h
new file mode 100644
index 0000000..0a16471
--- /dev/null
+++ b/compat/darwin_compat.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2006-2008 Amit Singh/Google Inc.
+ * Copyright (c) 2011-2013 Benjamin Fleischer
+ */
+
+#ifndef _DARWIN_COMPAT_
+#define _DARWIN_COMPAT_
+
+#include <pthread.h>
+
+/* Semaphores */
+
+typedef struct darwin_sem {
+ int id;
+ union {
+ struct
+ {
+ unsigned int count;
+ pthread_mutex_t count_lock;
+ pthread_cond_t count_cond;
+ } local;
+ } __data;
+} darwin_sem_t;
+
+#define DARWIN_SEM_VALUE_MAX ((int32_t)32767)
+
+int darwin_sem_init(darwin_sem_t *sem, int pshared, unsigned int value);
+int darwin_sem_destroy(darwin_sem_t *sem);
+int darwin_sem_getvalue(darwin_sem_t *sem, unsigned int *value);
+int darwin_sem_post(darwin_sem_t *sem);
+int darwin_sem_timedwait(darwin_sem_t *sem, const struct timespec *abs_timeout);
+int darwin_sem_trywait(darwin_sem_t *sem);
+int darwin_sem_wait(darwin_sem_t *sem);
+
+/* Caller must not include <semaphore.h> */
+
+typedef darwin_sem_t sem_t;
+
+#define sem_init(s, p, v) darwin_sem_init(s, p, v)
+#define sem_destroy(s) darwin_sem_destroy(s)
+#define sem_getvalue(s, v) darwin_sem_getvalue(s, v)
+#define sem_post(s) darwin_sem_post(s)
+#define sem_timedwait(s, t) darwin_sem_timedwait(s, t)
+#define sem_trywait(s) darwin_sem_trywait(s)
+#define sem_wait(s) darwin_sem_wait(s)
+
+#define SEM_VALUE_MAX DARWIN_SEM_VALUE_MAX
+
+#endif /* _DARWIN_COMPAT_ */
diff --git a/configure.ac b/configure.ac
index 4d7e23c..d0ee2eb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,4 +1,5 @@
AC_INIT(sshfs, 2.6)
+AC_CANONICAL_TARGET
AM_INIT_AUTOMAKE([foreign subdir-objects])
AM_CONFIG_HEADER(config.h)
@@ -11,6 +12,14 @@ sshnodelay_libs=$LIBS
AC_SUBST(sshnodelay_libs)
LIBS=
+case $target_os in
+ *linux*) arch=linux;;
+ *netbsd*) arch=netbsd;;
+ *bsd*) arch=bsd;;
+ *darwin*) arch=darwin;;
+ *) arch=unknown;;
+esac
+
AC_ARG_ENABLE(sshnodelay,
[ --disable-sshnodelay Don't compile NODELAY workaround for ssh])
@@ -43,10 +52,11 @@ oldlibs="$LIBS"
LIBS="$LIBS $SSHFS_LIBS"
AC_CHECK_FUNC([fuse_opt_parse], [have_fuse_opt_parse=yes])
LIBS="$oldlibs"
-if test "$have_fuse_opt_parse" = no; then
+if test "$have_fuse_opt_parse" = no -o "$arch" = darwin; then
CFLAGS="$CFLAGS -Icompat"
fi
AM_CONDITIONAL(FUSE_OPT_COMPAT, test "$have_fuse_opt_parse" = no)
+AM_CONDITIONAL(DARWIN_COMPAT, test "$arch" = darwin)
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
diff --git a/sshfs.1 b/sshfs.1.in
index 0bad826..7d431ed 100644
--- a/sshfs.1
+++ b/sshfs.1.in
@@ -7,7 +7,11 @@ SSHFS \- filesystem client based on ssh
\fBsshfs\fP [\fIuser\fP@]\fBhost\fP:[\fIdir\fP] \fBmountpoint\fP [\fIoptions\fP]
.SS unmounting
.TP
+#ifdef __APPLE__
+\fBumount mountpoint\fP
+#else
\fBfusermount -u mountpoint\fP
+#endif
.SH DESCRIPTION
SSHFS (Secure SHell FileSystem) is a file system for Linux (and other
operating systems with a FUSE implementation, such as Mac OS X or FreeBSD)
@@ -101,10 +105,18 @@ user/group ID mapping, possible types are:
.RS 8
.TP
none
+#ifdef __APPLE__
+no translation of the ID space
+#else
no translation of the ID space (default)
+#endif
.TP
user
+#ifdef __APPLE__
+only translate UID/GID of connecting user (default)
+#else
only translate UID of connecting user
+#endif
.TP
file
translate UIDs/GIDs based upon the contents of \fBuidfile \fR and
@@ -141,6 +153,8 @@ path to sftp server or subsystem (default: sftp)
.TP
\fB\-o\fR directport=PORT
directly connect to PORT bypassing ssh
+\fB\-o\fR slave
+communicate over stdin and stdout bypassing network
.TP
\fB\-o\fR slave
communicate over stdin and stdout bypassing network
@@ -282,5 +296,3 @@ SSHFS has been written by Miklos Szeredi <miklos@szeredi.hu>.
.LP
This man page was written by Bartosz Fenski <fenio@debian.org> for the
Debian GNU/Linux distribution (but it may be used by others).
-
-
diff --git a/sshfs.c b/sshfs.c
index 3904a50..eab48c9 100644
--- a/sshfs.c
+++ b/sshfs.c
@@ -12,6 +12,9 @@
#include <fuse.h>
#include <fuse_opt.h>
#include <fuse_lowlevel.h>
+#ifdef __APPLE__
+# include <fuse_darwin.h>
+#endif
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
@@ -20,7 +23,9 @@
#include <string.h>
#include <stdint.h>
#include <errno.h>
-#include <semaphore.h>
+#ifndef __APPLE__
+# include <semaphore.h>
+#endif
#include <pthread.h>
#include <netdb.h>
#include <signal.h>
@@ -38,9 +43,18 @@
#include <pwd.h>
#include <grp.h>
#include <limits.h>
+#ifdef __APPLE__
+# include <strings.h>
+# include <libgen.h>
+# include <darwin_compat.h>
+#endif
#include "cache.h"
+#ifdef __APPLE__
+# define OSXFUSE_SSHFS_VERSION "2.5.0"
+#endif
+
#ifndef MAP_LOCKED
#define MAP_LOCKED 0
#endif
@@ -127,6 +141,16 @@
#define MAX_PASSWORD 1024
+#ifdef __APPLE__
+
+#ifndef LIBDIR
+# define LIBDIR "/usr/local/lib"
+#endif
+
+static char sshfs_program_path[PATH_MAX] = { 0 };
+
+#endif /* __APPLE__ */
+
struct buffer {
uint8_t *p;
size_t len;
@@ -190,6 +214,9 @@ struct sshfs_file {
int connver;
int modifver;
int refs;
+#ifdef __APPLE__
+ pthread_mutex_t file_lock;
+#endif
};
struct sshfs {
@@ -243,6 +270,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;
@@ -739,8 +770,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 /* !__APPLE__ */
if (sshfs.remote_uid_detected && uid == sshfs.remote_uid)
uid = sshfs.local_uid;
+#endif /* __APPLE__ */
if (sshfs.idmap == IDMAP_FILE && sshfs.uid_map)
if (translate_id(&uid, sshfs.uid_map) == -1)
return -EPERM;
@@ -849,11 +889,35 @@ 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 /* __APPLE__ */
+
snprintf(sopath, sizeof(sopath), "%s/%s", LIBDIR, SSHNODELAY_SO);
res = access(sopath, R_OK);
if (res == -1) {
@@ -879,15 +943,24 @@ static int do_ssh_nodelay_workaround(void)
}
}
+#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 /* !__APPLE__ */
if (!newpreload || setenv("LD_PRELOAD", newpreload, 1) == -1) {
fprintf(stderr, "warning: failed set LD_PRELOAD "
"for ssh nodelay workaround\n");
}
+#endif /* __APPLE__ */
g_free(newpreload);
return 0;
}
@@ -1607,6 +1680,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);
@@ -2364,8 +2441,17 @@ static int sshfs_chown(const char *path, uid_t uid, gid_t gid)
int err;
struct buffer buf;
+#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;
+ }
+#else /* !__APPLE__ */
if (sshfs.remote_uid_detected && uid == sshfs.local_uid)
uid = sshfs.remote_uid;
+#endif /* __APPLE__ */
if (sshfs.idmap == IDMAP_FILE && sshfs.r_uid_map)
if(translate_id(&uid, sshfs.r_uid_map) == -1)
return -EPERM;
@@ -2472,6 +2558,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;
@@ -2506,11 +2595,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);
@@ -2565,14 +2664,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 /* !__APPLE__ */
if (!sf->refs)
g_free(sf);
+#endif /* __APPLE__ */
}
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)
@@ -3317,8 +3434,13 @@ static void usage(const char *progname)
" [no]truncate fix truncate for old servers (default: off)\n"
" [no]buflimit fix buffer fillup bug in server (default: on)\n"
" -o idmap=TYPE user/group ID mapping, possible types are:\n"
+#ifdef __APPLE__
+" none no translation of the ID space\n"
+" user only translate UID/GID of connecting user (default)\n"
+#else
" none no translation of the ID space (default)\n"
" user only translate UID of connecting user\n"
+#endif
" file translate UIDs/GIDs contained in uidfile/gidfile\n"
" -o uidfile=FILE file containing username:remote_uid mappings\n"
" -o gidfile=FILE file containing groupname:remote_gid mappings\n"
@@ -3410,7 +3532,12 @@ static int sshfs_opt_proc(void *data, const char *arg, int key,
exit(1);
case KEY_VERSION:
+#ifdef __APPLE__
+ printf("SSHFS version %s (OSXFUSE SSHFS %s)\n",
+ PACKAGE_VERSION, OSXFUSE_SSHFS_VERSION);
+#else
printf("SSHFS version %s\n", PACKAGE_VERSION);
+#endif
#if FUSE_VERSION >= 25
fuse_opt_add_arg(outargs, "--version");
sshfs_fuse_main(outargs);
@@ -3494,6 +3621,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++) {
@@ -3819,7 +3955,11 @@ static inline void load_gid_map(void)
read_id_map(sshfs.gid_file, &groupname_to_gid, "gid", &sshfs.gid_map, &sshfs.r_gid_map);
}
+#ifdef __APPLE__
+int main(int argc, char *argv[], __unused char *envp[], char **exec_path)
+#else
int main(int argc, char *argv[])
+#endif
{
int res;
struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
@@ -3828,6 +3968,14 @@ int main(int argc, char *argv[])
const char *sftp_server;
int libver;
+#ifdef __APPLE__
+ if (!realpath(*exec_path, sshfs_program_path)) {
+ memset(sshfs_program_path, 0, PATH_MAX);
+ }
+
+ /* 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;
@@ -3836,7 +3984,11 @@ int main(int argc, char *argv[])
sshfs.max_write = 32768;
sshfs.nodelay_workaround = 1;
sshfs.nodelaysrv_workaround = 0;
+#ifdef __APPLE__
+ sshfs.rename_workaround = 1;
+#else
sshfs.rename_workaround = 0;
+#endif
sshfs.truncate_workaround = 0;
sshfs.buflimit_workaround = 1;
sshfs.ssh_ver = 2;
@@ -3848,7 +4000,11 @@ int main(int argc, char *argv[])
sshfs.delay_connect = 0;
sshfs.slave = 0;
sshfs.detect_uid = 0;
+#ifdef __APPLE__
+ sshfs.idmap = IDMAP_USER;
+#else
sshfs.idmap = IDMAP_NONE;
+#endif
sshfs.nomap = NOMAP_ERROR;
ssh_add_arg("ssh");
ssh_add_arg("-x");
diff --git a/sshnodelay.c b/sshnodelay.c
index 7518089..e1d9220 100644
--- a/sshnodelay.c
+++ b/sshnodelay.c
@@ -5,6 +5,32 @@
#include <netinet/in.h>
#include <netinet/tcp.h>
+#if __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 /* !__APPLE__ */
+
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 /* !__APPLE__ */