diff -Naur old/Makefile.in new/Makefile.in --- old/Makefile.in 2008-04-23 05:18:30.000000000 -0700 +++ new/Makefile.in 2008-05-06 16:17:41.000000000 -0700 @@ -660,7 +660,11 @@ @SSH_NODELAY_SO_TRUE@ rm -f "$(DESTDIR)$(libdir)/sshnodelay.so" @SSH_NODELAY_SO_TRUE@sshnodelay.so: +ifeq "$(shell uname)" "Darwin" +@SSH_NODELAY_SO_TRUE@ $(CC) -Wall -dynamiclib $(CFLAGS) $(sshnodelay_libs) -install_name "$(DESTDIR)$(libdir)/sshnodelay.so" sshnodelay.c -o sshnodelay.so +else @SSH_NODELAY_SO_TRUE@ $(CC) -Wall -W -s --shared -fPIC $(sshnodelay_libs) sshnodelay.c -o sshnodelay.so +endif # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: diff -Naur old/README.MacFUSE new/README.MacFUSE --- old/README.MacFUSE 1969-12-31 16:00:00.000000000 -0800 +++ new/README.MacFUSE 2008-05-06 16:17:41.000000000 -0700 @@ -0,0 +1,9 @@ +MacFUSE Project Page: + +http://code.google.com/p/macfuse/ + +Making a Universal build of sshfs: + +0. Make sure dependencies (glib, MacFUSE) are installed +1. Run ./configure_for_macfuse.sh +2. Run make diff -Naur old/cache.c new/cache.c --- old/cache.c 2007-12-11 14:23:24.000000000 -0800 +++ new/cache.c 2008-05-06 16:23:45.000000000 -0700 @@ -28,6 +28,7 @@ GHashTable *table; pthread_mutex_t lock; time_t last_cleaned; + uint64_t write_ctr; }; static struct cache cache; @@ -47,6 +48,7 @@ fuse_dirh_t h; fuse_dirfil_t filler; GPtrArray *dir; + uint64_t wrctr; }; static void free_node(gpointer node_) @@ -108,6 +110,14 @@ pthread_mutex_unlock(&cache.lock); } +void cache_invalidate_write(const char *path) +{ + pthread_mutex_lock(&cache.lock); + cache_purge(path); + cache.write_ctr++; + pthread_mutex_unlock(&cache.lock); +} + static void cache_invalidate_dir(const char *path) { pthread_mutex_lock(&cache.lock); @@ -148,19 +158,21 @@ return node; } -void cache_add_attr(const char *path, const struct stat *stbuf) +void cache_add_attr(const char *path, const struct stat *stbuf, uint64_t wrctr) { struct node *node; time_t now; pthread_mutex_lock(&cache.lock); - node = cache_get(path); - now = time(NULL); - node->stat = *stbuf; - node->stat_valid = time(NULL) + cache.stat_timeout; - if (node->stat_valid > node->valid) - node->valid = node->stat_valid; - cache_clean(); + if (wrctr == cache.write_ctr) { + node = cache_get(path); + now = time(NULL); + node->stat = *stbuf; + node->stat_valid = time(NULL) + cache.stat_timeout; + if (node->stat_valid > node->valid) + node->valid = node->stat_valid; + cache_clean(); + } pthread_mutex_unlock(&cache.lock); } @@ -222,13 +234,25 @@ return err; } +uint64_t cache_get_write_ctr(void) +{ + uint64_t res; + + pthread_mutex_lock(&cache.lock); + res = cache.write_ctr; + pthread_mutex_unlock(&cache.lock); + + return res; +} + static int cache_getattr(const char *path, struct stat *stbuf) { int err = cache_get_attr(path, stbuf); if (err) { + uint64_t wrctr = cache_get_write_ctr(); err = cache.next_oper->oper.getattr(path, stbuf); if (!err) - cache_add_attr(path, stbuf); + cache_add_attr(path, stbuf, wrctr); } return err; } @@ -268,7 +292,7 @@ const char *basepath = !ch->path[1] ? "" : ch->path; fullpath = g_strdup_printf("%s/%s", basepath, name); - cache_add_attr(fullpath, stbuf); + cache_add_attr(fullpath, stbuf, ch->wrctr); g_free(fullpath); } } @@ -299,6 +323,7 @@ ch.h = h; ch.filler = filler; ch.dir = g_ptr_array_new(); + ch.wrctr = cache_get_write_ctr(); err = cache.next_oper->cache_getdir(path, &ch, cache_dirfill); g_ptr_array_add(ch.dir, NULL); dir = (char **) ch.dir->pdata; @@ -421,7 +446,7 @@ { int res = cache.next_oper->oper.write(path, buf, size, offset, fi); if (res >= 0) - cache_invalidate(path); + cache_invalidate_write(path); return res; } @@ -449,9 +474,10 @@ { int err = cache_get_attr(path, stbuf); if (err) { + uint64_t wrctr = cache_get_write_ctr(); err = cache.next_oper->oper.fgetattr(path, stbuf, fi); if (!err) - cache_add_attr(path, stbuf); + cache_add_attr(path, stbuf, wrctr); } return err; } @@ -527,6 +553,9 @@ cache.next_oper = oper; cache_unity_fill(oper, &cache_oper); +#if (__FreeBSD__ >= 10) + cache_enabled = cache.on; +#endif if (cache.on) { cache_fill(oper, &cache_oper); pthread_mutex_init(&cache.lock, NULL); @@ -561,3 +590,7 @@ return fuse_opt_parse(args, &cache, cache_opts, NULL); } + +#if (__FreeBSD__ >= 10) +int cache_enabled; +#endif diff -Naur old/cache.h new/cache.h --- old/cache.h 2006-02-20 03:43:23.000000000 -0800 +++ new/cache.h 2008-05-06 16:22:09.000000000 -0700 @@ -24,5 +24,10 @@ struct fuse_operations *cache_init(struct fuse_cache_operations *oper); int cache_parse_options(struct fuse_args *args); -void cache_add_attr(const char *path, const struct stat *stbuf); +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 (__FreeBSD__ >= 10) +extern int cache_enabled; +#endif diff -Naur old/sshfs.c new/sshfs.c --- old/sshfs.c 2008-04-22 09:02:42.000000000 -0700 +++ new/sshfs.c 2008-05-06 16:21:11.000000000 -0700 @@ -19,7 +19,12 @@ #include #include #include +#if !(__FreeBSD__ >= 10) #include +#else +#define MACFUSE_SSHFS_VERSION "1.5.0" +#include "fuse_darwin.h" +#endif #include #include #include @@ -33,9 +38,22 @@ #include #include #include +#if (__FreeBSD__ >= 10) +#include +#include +#endif #include "cache.h" +#ifndef MAP_LOCKED +#define MAP_LOCKED 0 +#endif + +#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON) +#define MAP_ANONYMOUS MAP_ANON +#endif + + #if FUSE_VERSION >= 23 #define SSHFS_USE_INIT #endif @@ -110,6 +128,16 @@ #define SSHNODELAY_SO "sshnodelay.so" +#if (__FreeBSD__ >= 10) + +#ifndef LIBDIR +#define LIBDIR "/usr/local/lib" +#endif + +static char sshfs_program_path[PATH_MAX] = { 0 }; + +#endif + struct buffer { uint8_t *p; size_t len; @@ -159,6 +187,9 @@ int connver; int modifver; int refs; +#if (__FreeBSD__ >= 10) + pthread_mutex_t file_lock; +#endif }; struct sshfs { @@ -198,6 +229,10 @@ int server_version; unsigned remote_uid; unsigned local_uid; +#if (__FreeBSD__ >= 10) + unsigned remote_gid; + unsigned local_gid; +#endif int remote_uid_detected; unsigned blksize; char *progname; @@ -629,8 +664,17 @@ } } +#if (__FreeBSD__ >= 10) + if (sshfs.remote_uid_detected) { + if (uid == sshfs.remote_uid) + uid = sshfs.local_uid; + if (gid == sshfs.remote_gid) + gid = sshfs.local_gid; + } +#else if (sshfs.remote_uid_detected && uid == sshfs.remote_uid) uid = sshfs.local_uid; +#endif memset(stbuf, 0, sizeof(struct stat)); stbuf->st_mode = mode; @@ -733,11 +777,33 @@ #ifdef SSH_NODELAY_WORKAROUND static int do_ssh_nodelay_workaround(void) { +#if (__FreeBSD__ >= 10) + char *oldpreload = getenv("DYLD_INSERT_LIBRARIES"); +#else char *oldpreload = getenv("LD_PRELOAD"); +#endif char *newpreload; char sopath[PATH_MAX]; int res; +#if (__FreeBSD__ >= 10) + 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 snprintf(sopath, sizeof(sopath), "%s/%s", LIBDIR, SSHNODELAY_SO); res = access(sopath, R_OK); if (res == -1) { @@ -762,16 +828,24 @@ return -1; } } +#if (__FreeBSD__ >= 10) +pathok: +#endif newpreload = g_strdup_printf("%s%s%s", oldpreload ? oldpreload : "", oldpreload ? " " : "", sopath); +#if (__FreeBSD__ >= 10) + if (!newpreload || setenv("DYLD_INSERT_LIBRARIES", newpreload, 1) == -1) + fprintf(stderr, "warning: failed set DYLD_INSERT_LIBRARIES for ssh nodelay workaround\n"); +#else if (!newpreload || setenv("LD_PRELOAD", newpreload, 1) == -1) { fprintf(stderr, "warning: failed set LD_PRELOAD " "for ssh nodelay workaround\n"); } +#endif g_free(newpreload); return 0; } @@ -1462,6 +1536,10 @@ sshfs.remote_uid = stbuf.st_uid; sshfs.local_uid = getuid(); +#if (__FreeBSD__ >= 10) + sshfs.remote_gid = stbuf.st_gid; + sshfs.local_gid = getgid(); +#endif sshfs.remote_uid_detected = 1; DEBUG("remote_uid = %i\n", sshfs.remote_uid); @@ -2056,6 +2134,14 @@ buf_init(&buf, 0); buf_add_path(&buf, path); buf_add_uint32(&buf, SSH_FILEXFER_ATTR_UIDGID); +#if (__FreeBSD__ >= 10) + if (sshfs.remote_uid_detected) { + if (uid == sshfs.local_uid) + uid = sshfs.remote_uid; + if (gid == sshfs.local_gid) + gid = sshfs.remote_gid; + } +#endif buf_add_uint32(&buf, uid); buf_add_uint32(&buf, gid); err = sftp_request(SSH_FXP_SETSTAT, &buf, SSH_FXP_STATUS, NULL); @@ -2116,6 +2202,7 @@ uint32_t pflags = 0; struct iovec iov; uint8_t type; + uint64_t wrctr = cache_get_write_ctr(); if ((fi->flags & O_ACCMODE) == O_RDONLY) pflags = SSH_FXF_READ; @@ -2138,6 +2225,9 @@ sf = g_new0(struct sshfs_file, 1); list_init(&sf->write_reqs); pthread_cond_init(&sf->write_finished, NULL); +#if (__FreeBSD__ >= 10) + pthread_mutex_init(&sf->file_lock, NULL); +#endif /* Assume random read after open */ sf->is_seq = 0; sf->refs = 1; @@ -2171,11 +2261,21 @@ } if (!err) { - cache_add_attr(path, &stbuf); +#if (__FreeBSD__ >= 10) + 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 { +#if (__FreeBSD__ >= 10) + if (cache_enabled) + cache_invalidate(path); +#else cache_invalidate(path); +#endif g_free(sf); } buf_free(&buf); @@ -2230,14 +2330,32 @@ static void sshfs_file_put(struct sshfs_file *sf) { +#if (__FreeBSD__ >= 10) + pthread_mutex_lock(&sf->file_lock); +#endif sf->refs--; +#if (__FreeBSD__ >= 10) + if (!sf->refs) { + pthread_mutex_unlock(&sf->file_lock); + g_free(sf); + } else { + pthread_mutex_unlock(&sf->file_lock); + } +#else if (!sf->refs) g_free(sf); +#endif } static void sshfs_file_get(struct sshfs_file *sf) { +#if (__FreeBSD__ >= 10) + pthread_mutex_lock(&sf->file_lock); +#endif sf->refs++; +#if (__FreeBSD__ >= 10) + pthread_mutex_unlock(&sf->file_lock); +#endif } static int sshfs_release(const char *path, struct fuse_file_info *fi) @@ -2920,7 +3038,12 @@ exit(1); case KEY_VERSION: +#if (__FreeBSD__ >= 10) + fprintf(stderr, "SSHFS version %s (MacFUSE SSHFS %s)\n", + PACKAGE_VERSION, MACFUSE_SSHFS_VERSION); +#else fprintf(stderr, "SSHFS version %s\n", PACKAGE_VERSION); +#endif #if FUSE_VERSION >= 25 fuse_opt_add_arg(outargs, "--version"); sshfs_fuse_main(outargs); @@ -3004,6 +3127,15 @@ perror("Failed to allocate locked page for password"); return -1; } +#if (__FreeBSD__ >= 10) + 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 /* __FreeBSD__ >= 10 */ /* Don't use fgets() because password might stay in memory */ for (n = 0; n < max_password; n++) { @@ -3069,8 +3201,17 @@ } } +#if (__FreeBSD__ >= 10) +int main(int argc, char *argv[], __unused char *envp[], char **exec_path) +#else int main(int argc, char *argv[]) +#endif { +#if (__FreeBSD__ >= 10) + if (!realpath(*exec_path, sshfs_program_path)) { + memset(sshfs_program_path, 0, PATH_MAX); + } +#endif int res; struct fuse_args args = FUSE_ARGS_INIT(argc, argv); char *tmp; @@ -3079,6 +3220,10 @@ const char *sftp_server; int libver; +#if (__FreeBSD__ >= 10) + /* Until this gets fixed somewhere else. */ + g_slice_set_config(G_SLICE_CONFIG_ALWAYS_MALLOC, TRUE); +#endif /* __FreeBSD__ >= 10 */ g_thread_init(NULL); sshfs.blksize = 4096; @@ -3086,7 +3231,11 @@ sshfs.max_write = 65536; sshfs.nodelay_workaround = 1; sshfs.nodelaysrv_workaround = 0; +#if (__FreeBSD__ >= 10) + sshfs.rename_workaround = 1; +#else sshfs.rename_workaround = 0; +#endif /* __FreeBSD__ >= 10 */ sshfs.truncate_workaround = 0; sshfs.buflimit_workaround = 1; sshfs.ssh_ver = 2; @@ -3099,6 +3248,10 @@ ssh_add_arg("-a"); ssh_add_arg("-oClearAllForwardings=yes"); +#if (__FreeBSD__ >= 10) + sshfs.detect_uid = 1; +#endif + if (fuse_opt_parse(&args, &sshfs, sshfs_opts, sshfs_opt_proc) == -1 || parse_workarounds() == -1) exit(1); diff -Naur old/sshnodelay.c new/sshnodelay.c --- old/sshnodelay.c 2007-12-11 14:23:29.000000000 -0800 +++ new/sshnodelay.c 2008-05-06 16:17:41.000000000 -0700 @@ -5,6 +5,32 @@ #include #include +#if (__FreeBSD__ >= 10) + +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 + int connect(int sock, const struct sockaddr *addr, socklen_t addrlen) { int (*next_connect)(int, const struct sockaddr *, socklen_t) = @@ -16,3 +42,5 @@ } return res; } + +#endif