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:
Julio Merino 2016-02-08 11:12:22 -05:00 committed by Julio Merino
commit ddbe3bee44
10 changed files with 524 additions and 5 deletions

1
.gitignore vendored
View File

@ -20,6 +20,7 @@ Makefile
*.m4
stamp-h*
config.*
sshfs.1
/sshfs
/ltmain.sh
/configure

View File

@ -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

View File

@ -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

View File

@ -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

246
compat/darwin_compat.c Normal file
View File

@ -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;
}

49
compat/darwin_compat.h Normal file
View File

@ -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_ */

View File

@ -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

View File

@ -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
View File

@ -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");

View File

@ -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__ */