aboutsummaryrefslogtreecommitdiff
path: root/sshfs.c
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 /sshfs.c
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.
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 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");