aboutsummaryrefslogtreecommitdiff
path: root/sshfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'sshfs.c')
-rw-r--r--sshfs.c158
1 files changed, 157 insertions, 1 deletions
diff --git a/sshfs.c b/sshfs.c
index 96b98a5..d43ebc5 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.4.1"
+#endif
+
#ifndef MAP_LOCKED
#define MAP_LOCKED 0
#endif
@@ -125,6 +139,16 @@
#define READDIR_START 2
#define READDIR_MAX 32
+#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;
@@ -188,6 +212,9 @@ struct sshfs_file {
int connver;
int modifver;
int refs;
+#ifdef __APPLE__
+ pthread_mutex_t file_lock;
+#endif
};
struct sshfs {
@@ -241,6 +268,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;
@@ -736,8 +767,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;
@@ -846,11 +886,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) {
@@ -876,15 +940,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;
}
@@ -1604,6 +1677,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);
@@ -2345,8 +2422,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;
@@ -2453,6 +2539,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;
@@ -2487,11 +2576,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);
@@ -2546,14 +2645,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)
@@ -3297,8 +3414,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"
@@ -3389,7 +3511,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);
@@ -3473,6 +3600,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++) {
@@ -3798,7 +3934,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);
@@ -3807,6 +3947,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;
@@ -3815,7 +3963,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;
@@ -3827,7 +3979,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");