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.
This commit is contained in:
commit
ddbe3bee44
|
|
@ -20,6 +20,7 @@ Makefile
|
|||
*.m4
|
||||
stamp-h*
|
||||
config.*
|
||||
sshfs.1
|
||||
/sshfs
|
||||
/ltmain.sh
|
||||
/configure
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
7
cache.c
7
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
|
||||
|
|
|
|||
4
cache.h
4
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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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_ */
|
||||
12
configure.ac
12
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
|
||||
|
|
|
|||
|
|
@ -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).
|
||||
|
||||
|
||||
158
sshfs.c
158
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");
|
||||
|
|
|
|||
28
sshnodelay.c
28
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__ */
|
||||
|
|
|
|||
Loading…
Reference in New Issue