summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitmodules3
-rw-r--r--extra/gen.rc1
-rw-r--r--extra/sshfs/config.h11
-rw-r--r--extra/sshfs/gen.rc12
-rw-r--r--extra/sshfs/patch/0001-Add-nocache.c-stub.patch113
-rw-r--r--extra/sshfs/patch/0002-Use-a-compact-array-and-free-list-for-requests.patch292
-rw-r--r--extra/sshfs/patch/0003-Use-bool-instead-of-gboolean.patch33
-rw-r--r--extra/sshfs/patch/0004-Use-struct-list_head-instead-of-GList.patch62
-rw-r--r--extra/sshfs/patch/0005-Use-standard-C-functions.patch277
-rw-r--r--extra/sshfs/patch/0006-Add-missing-includes.patch34
-rw-r--r--extra/sshfs/patch/0007-Disable-uidmap-and-gidmap-support.patch127
-rw-r--r--extra/sshfs/patch/0008-Remove-remaining-uses-of-glib.patch36
m---------extra/sshfs/src0
13 files changed, 1001 insertions, 0 deletions
diff --git a/.gitmodules b/.gitmodules
index 1093bf78..9f47be58 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -67,6 +67,9 @@
[submodule "extra/libfuse/src"]
path = extra/libfuse/src
url = https://github.com/libfuse/libfuse
+[submodule "extra/sshfs/src"]
+ path = extra/sshfs/src
+ url = https://github.com/libfuse/sshfs
[submodule "extra/the_silver_searcher/src"]
path = extra/the_silver_searcher/src
url = https://github.com/ggreer/the_silver_searcher
diff --git a/extra/gen.rc b/extra/gen.rc
index 7f0fdb48..30739c4b 100644
--- a/extra/gen.rc
+++ b/extra/gen.rc
@@ -1,3 +1,4 @@
subgen libfuse
subgen pcre
+subgen sshfs
subgen the_silver_searcher
diff --git a/extra/sshfs/config.h b/extra/sshfs/config.h
new file mode 100644
index 00000000..b9c654f7
--- /dev/null
+++ b/extra/sshfs/config.h
@@ -0,0 +1,11 @@
+#define IDMAP_DEFAULT "none"
+
+#define PACKAGE "sshfs"
+#define PACKAGE_BUGREPORT ""
+#define PACKAGE_NAME "sshfs"
+#define PACKAGE_STRING "sshfs 2.7"
+#define PACKAGE_TARNAME "sshfs"
+#define PACKAGE_URL ""
+#define PACKAGE_VERSION "2.7"
+/* #undef SSH_NODELAY_WORKAROUND */
+#define VERSION "2.7"
diff --git a/extra/sshfs/gen.rc b/extra/sshfs/gen.rc
new file mode 100644
index 00000000..1d45d1f1
--- /dev/null
+++ b/extra/sshfs/gen.rc
@@ -0,0 +1,12 @@
+cflags\
+ -D '_FILE_OFFSET_BITS=64' \
+ -D 'FUSE_USE_VERSION=26' \
+ -I extra/libfuse/src/include\
+ -I '$dir'
+
+let expr 's,__UNMOUNT_COMMAND__,''fusermount -u'',' --\
+ build '$outdir'/sshfs.1 sed '$srcdir'/sshfs.1.in
+
+exe sshfs sshfs.c nocache.c '$builddir'/extra/libfuse/libfuse.a
+file bin/sshfs '$outdir'/sshfs 755
+file share/man/man1/sshfs.1 '$outdir'/sshfs.1 644
diff --git a/extra/sshfs/patch/0001-Add-nocache.c-stub.patch b/extra/sshfs/patch/0001-Add-nocache.c-stub.patch
new file mode 100644
index 00000000..18d5a503
--- /dev/null
+++ b/extra/sshfs/patch/0001-Add-nocache.c-stub.patch
@@ -0,0 +1,113 @@
+From 22ee03791d23693b273fa1489aabebca169a91c9 Mon Sep 17 00:00:00 2001
+From: Michael Forney <mforney@mforney.org>
+Date: Sun, 5 Jun 2016 17:13:58 -0700
+Subject: [PATCH] Add nocache.c stub
+
+---
+ nocache.c | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 94 insertions(+)
+ create mode 100644 nocache.c
+
+diff --git a/nocache.c b/nocache.c
+new file mode 100644
+index 0000000..58d7528
+--- /dev/null
++++ b/nocache.c
+@@ -0,0 +1,94 @@
++#include "cache.h"
++
++struct cache {
++ struct fuse_cache_operations *next_oper;
++};
++
++static struct cache cache;
++
++struct fuse_cache_dirhandle {
++ fuse_dirh_t h;
++ fuse_dirfil_t filler;
++};
++
++void cache_invalidate(const char *path)
++{
++}
++
++void cache_add_attr(const char *path, const struct stat *stbuf, uint64_t wrctr)
++{
++}
++
++uint64_t cache_get_write_ctr(void)
++{
++ return 0;
++}
++
++static int cache_unity_dirfill(fuse_cache_dirh_t ch, const char *name,
++ const struct stat *stbuf)
++{
++ (void) stbuf;
++ return ch->filler(ch->h, name, 0, 0);
++}
++
++static int cache_unity_getdir(const char *path, fuse_dirh_t h,
++ fuse_dirfil_t filler)
++{
++ struct fuse_cache_dirhandle ch;
++ ch.h = h;
++ ch.filler = filler;
++ return cache.next_oper->cache_getdir(path, &ch, cache_unity_dirfill);
++}
++
++static void cache_unity_fill(struct fuse_cache_operations *oper,
++ struct fuse_operations *cache_oper)
++{
++#if FUSE_VERSION >= 23
++ cache_oper->init = oper->oper.init;
++#endif
++ cache_oper->getattr = oper->oper.getattr;
++ cache_oper->access = oper->oper.access;
++ cache_oper->readlink = oper->oper.readlink;
++ cache_oper->getdir = cache_unity_getdir;
++ cache_oper->mknod = oper->oper.mknod;
++ cache_oper->mkdir = oper->oper.mkdir;
++ cache_oper->symlink = oper->oper.symlink;
++ cache_oper->unlink = oper->oper.unlink;
++ cache_oper->rmdir = oper->oper.rmdir;
++ cache_oper->rename = oper->oper.rename;
++ cache_oper->link = oper->oper.link;
++ cache_oper->chmod = oper->oper.chmod;
++ cache_oper->chown = oper->oper.chown;
++ cache_oper->truncate = oper->oper.truncate;
++ cache_oper->utime = oper->oper.utime;
++ cache_oper->open = oper->oper.open;
++ cache_oper->read = oper->oper.read;
++ cache_oper->write = oper->oper.write;
++ cache_oper->flush = oper->oper.flush;
++ cache_oper->release = oper->oper.release;
++ cache_oper->fsync = oper->oper.fsync;
++ cache_oper->statfs = oper->oper.statfs;
++ cache_oper->setxattr = oper->oper.setxattr;
++ cache_oper->getxattr = oper->oper.getxattr;
++ cache_oper->listxattr = oper->oper.listxattr;
++ cache_oper->removexattr = oper->oper.removexattr;
++#if FUSE_VERSION >= 25
++ cache_oper->create = oper->oper.create;
++ cache_oper->ftruncate = oper->oper.ftruncate;
++ cache_oper->fgetattr = oper->oper.fgetattr;
++#endif
++}
++
++struct fuse_operations *cache_init(struct fuse_cache_operations *oper)
++{
++ static struct fuse_operations cache_oper;
++ cache.next_oper = oper;
++
++ cache_unity_fill(oper, &cache_oper);
++ return &cache_oper;
++}
++
++int cache_parse_options(struct fuse_args *args)
++{
++ return 0;
++}
+--
+2.8.1
+
diff --git a/extra/sshfs/patch/0002-Use-a-compact-array-and-free-list-for-requests.patch b/extra/sshfs/patch/0002-Use-a-compact-array-and-free-list-for-requests.patch
new file mode 100644
index 00000000..f7b4da93
--- /dev/null
+++ b/extra/sshfs/patch/0002-Use-a-compact-array-and-free-list-for-requests.patch
@@ -0,0 +1,292 @@
+From fff5db303ec32476cf1457a1388110820b0b53e5 Mon Sep 17 00:00:00 2001
+From: Michael Forney <mforney@mforney.org>
+Date: Sun, 5 Jun 2016 17:25:36 -0700
+Subject: [PATCH] Use a compact array and free list for requests
+
+---
+ sshfs.c | 125 +++++++++++++++++++++++++++++++++++++++++-----------------------
+ 1 file changed, 80 insertions(+), 45 deletions(-)
+
+diff --git a/sshfs.c b/sshfs.c
+index ce30a0f..99dcc25 100644
+--- a/sshfs.c
++++ b/sshfs.c
+@@ -170,6 +170,17 @@ struct request {
+ struct list_head list;
+ };
+
++union request_entry {
++ struct request *req;
++ uintptr_t next;
++};
++
++struct request_table {
++ union request_entry *entries;
++ int len, cap;
++ uint32_t free;
++};
++
+ struct sshfs_io {
+ int num_reqs;
+ pthread_cond_t finished;
+@@ -244,7 +255,7 @@ struct sshfs {
+ int slave;
+ char *host;
+ char *base_path;
+- GHashTable *reqtab;
++ struct request_table reqtab;
+ pthread_mutex_t lock;
+ pthread_mutex_t lock_write;
+ int processing_thread_started;
+@@ -1239,12 +1250,6 @@ static int do_write(struct iovec *iov, size_t count)
+ return 0;
+ }
+
+-static uint32_t sftp_get_id(void)
+-{
+- static uint32_t idctr;
+- return idctr++;
+-}
+-
+ static void buf_to_iov(const struct buffer *buf, struct iovec *iov)
+ {
+ iov->iov_base = buf->p;
+@@ -1337,6 +1342,43 @@ static void request_free(struct request *req)
+ g_free(req);
+ }
+
++static int request_table_insert(struct request_table *reqtab, struct request *req)
++{
++ union request_entry *entries;
++ size_t cap;
++
++ if (reqtab->free) {
++ req->id = reqtab->free;
++ reqtab->free = reqtab->entries[req->id-1].next >> 1;
++ } else {
++ if (reqtab->len == reqtab->cap) {
++ cap = reqtab->cap * 2 + 1;
++ entries = realloc(reqtab->entries, cap * sizeof(reqtab->entries[0]));
++ if (!entries)
++ return -1;
++ reqtab->cap = cap;
++ reqtab->entries = entries;
++ }
++ req->id = ++reqtab->len;
++ }
++
++ reqtab->entries[req->id-1].req = req;
++ return 0;
++}
++
++static struct request *request_table_lookup(struct request_table *reqtab, uint32_t id)
++{
++ if (reqtab->entries[id-1].next & 1)
++ return NULL;
++ return reqtab->entries[id-1].req;
++}
++
++static void request_table_remove(struct request_table *reqtab, uint32_t id)
++{
++ reqtab->entries[id-1].next = (reqtab->free << 1) | 1;
++ reqtab->free = id;
++}
++
+ static void chunk_free(struct read_chunk *chunk)
+ {
+ while (!list_empty(&chunk->reqs)) {
+@@ -1366,21 +1408,6 @@ static void chunk_put_locked(struct read_chunk *chunk)
+ pthread_mutex_unlock(&sshfs.lock);
+ }
+
+-static int clean_req(void *key_, struct request *req)
+-{
+- (void) key_;
+-
+- req->error = -EIO;
+- if (req->want_reply)
+- sem_post(&req->ready);
+- else {
+- if (req->end_func)
+- req->end_func(req);
+- request_free(req);
+- }
+- return TRUE;
+-}
+-
+ static int process_one_request(void)
+ {
+ int res;
+@@ -1397,8 +1424,7 @@ static int process_one_request(void)
+ return -1;
+
+ pthread_mutex_lock(&sshfs.lock);
+- req = (struct request *)
+- g_hash_table_lookup(sshfs.reqtab, GUINT_TO_POINTER(id));
++ req = request_table_lookup(&sshfs.reqtab, id);
+ if (req == NULL)
+ fprintf(stderr, "request %i not found\n", id);
+ else {
+@@ -1410,7 +1436,7 @@ static int process_one_request(void)
+ sshfs.outstanding_len <= sshfs.max_outstanding_len) {
+ pthread_cond_broadcast(&sshfs.outstanding_cond);
+ }
+- g_hash_table_remove(sshfs.reqtab, GUINT_TO_POINTER(id));
++ request_table_remove(&sshfs.reqtab, id);
+ }
+ pthread_mutex_unlock(&sshfs.lock);
+ if (req != NULL) {
+@@ -1471,6 +1497,9 @@ static void close_conn(void)
+
+ static void *process_requests(void *data_)
+ {
++ int i;
++ struct request *req;
++
+ (void) data_;
+
+ while (1) {
+@@ -1481,7 +1510,20 @@ static void *process_requests(void *data_)
+ pthread_mutex_lock(&sshfs.lock);
+ sshfs.processing_thread_started = 0;
+ close_conn();
+- g_hash_table_foreach_remove(sshfs.reqtab, (GHRFunc) clean_req, NULL);
++ for (i = 0; i < sshfs.reqtab.len; ++i) {
++ if (sshfs.reqtab.entries[i].next & 1)
++ continue;
++ req = sshfs.reqtab.entries[i].req;
++ req->error = -EIO;
++ if (req->want_reply)
++ sem_post(&req->ready);
++ else {
++ if (req->end_func)
++ req->end_func(req);
++ request_free(req);
++ }
++ request_table_remove(&sshfs.reqtab, i + 1);
++ }
+ sshfs.connver ++;
+ sshfs.outstanding_len = 0;
+ pthread_cond_broadcast(&sshfs.outstanding_cond);
+@@ -1626,7 +1668,6 @@ static int sftp_error_to_errno(uint32_t error)
+ static void sftp_detect_uid()
+ {
+ int flags;
+- uint32_t id = sftp_get_id();
+ uint32_t replid;
+ uint8_t type;
+ struct buffer buf;
+@@ -1636,7 +1677,7 @@ static void sftp_detect_uid()
+ buf_init(&buf, 5);
+ buf_add_string(&buf, ".");
+ buf_to_iov(&buf, &iov[0]);
+- if (sftp_send_iov(SSH_FXP_STAT, id, iov, 1) == -1)
++ if (sftp_send_iov(SSH_FXP_STAT, 0, iov, 1) == -1)
+ goto out;
+ buf_clear(&buf);
+ if (sftp_read(&type, &buf) == -1)
+@@ -1647,7 +1688,7 @@ static void sftp_detect_uid()
+ }
+ if (buf_get_uint32(&buf, &replid) == -1)
+ goto out;
+- if (replid != id) {
++ if (replid != 0) {
+ fprintf(stderr, "bad reply ID\n");
+ goto out;
+ }
+@@ -1684,7 +1725,6 @@ out:
+ static int sftp_check_root(const char *base_path)
+ {
+ int flags;
+- uint32_t id = sftp_get_id();
+ uint32_t replid;
+ uint8_t type;
+ struct buffer buf;
+@@ -1696,7 +1736,7 @@ static int sftp_check_root(const char *base_path)
+ buf_init(&buf, 0);
+ buf_add_string(&buf, remote_dir);
+ buf_to_iov(&buf, &iov[0]);
+- if (sftp_send_iov(SSH_FXP_LSTAT, id, iov, 1) == -1)
++ if (sftp_send_iov(SSH_FXP_LSTAT, 0, iov, 1) == -1)
+ goto out;
+ buf_clear(&buf);
+ if (sftp_read(&type, &buf) == -1)
+@@ -1707,7 +1747,7 @@ static int sftp_check_root(const char *base_path)
+ }
+ if (buf_get_uint32(&buf, &replid) == -1)
+ goto out;
+- if (replid != id) {
++ if (replid != 0) {
+ fprintf(stderr, "bad reply ID\n");
+ goto out;
+ }
+@@ -1898,7 +1938,6 @@ static int sftp_request_send(uint8_t type, struct iovec *iov, size_t count,
+ struct request **reqp)
+ {
+ int err;
+- uint32_t id;
+ struct request *req = g_new0(struct request, 1);
+
+ req->want_reply = want_reply;
+@@ -1909,8 +1948,6 @@ static int sftp_request_send(uint8_t type, struct iovec *iov, size_t count,
+ pthread_mutex_lock(&sshfs.lock);
+ if (begin_func)
+ begin_func(req);
+- id = sftp_get_id();
+- req->id = id;
+ err = start_processing_thread();
+ if (err) {
+ pthread_mutex_unlock(&sshfs.lock);
+@@ -1921,21 +1958,24 @@ static int sftp_request_send(uint8_t type, struct iovec *iov, size_t count,
+ while (sshfs.outstanding_len > sshfs.max_outstanding_len)
+ pthread_cond_wait(&sshfs.outstanding_cond, &sshfs.lock);
+
+- g_hash_table_insert(sshfs.reqtab, GUINT_TO_POINTER(id), req);
++ if (request_table_insert(&sshfs.reqtab, req) < 0)
++ abort();
+ if (sshfs.debug) {
+ gettimeofday(&req->start, NULL);
+ sshfs.num_sent++;
+ sshfs.bytes_sent += req->len;
+ }
+- DEBUG("[%05i] %s\n", id, type_name(type));
++ DEBUG("[%05i] %s\n", req->id, type_name(type));
+ pthread_mutex_unlock(&sshfs.lock);
+
+ err = -EIO;
+- if (sftp_send_iov(type, id, iov, count) == -1) {
++ if (sftp_send_iov(type, req->id, iov, count) == -1) {
+ gboolean rmed;
+
+ pthread_mutex_lock(&sshfs.lock);
+- rmed = g_hash_table_remove(sshfs.reqtab, GUINT_TO_POINTER(id));
++ rmed = !!request_table_lookup(&sshfs.reqtab, req->id);
++ if (rmed)
++ request_table_remove(&sshfs.reqtab, req->id);
+ pthread_mutex_unlock(&sshfs.lock);
+
+ if (!rmed && !want_reply) {
+@@ -2125,7 +2165,7 @@ static int sftp_readdir_send(struct request **req, struct buffer *handle)
+
+ static int sshfs_req_pending(struct request *req)
+ {
+- if (g_hash_table_lookup(sshfs.reqtab, GUINT_TO_POINTER(req->id)))
++ if (request_table_lookup(&sshfs.reqtab, req->id))
+ return 1;
+ else
+ return 0;
+@@ -3314,11 +3354,6 @@ static int processing_init(void)
+ pthread_mutex_init(&sshfs.lock, NULL);
+ pthread_mutex_init(&sshfs.lock_write, NULL);
+ pthread_cond_init(&sshfs.outstanding_cond, NULL);
+- sshfs.reqtab = g_hash_table_new(NULL, NULL);
+- if (!sshfs.reqtab) {
+- fprintf(stderr, "failed to create hash table\n");
+- return -1;
+- }
+ return 0;
+ }
+
+--
+2.8.1
+
diff --git a/extra/sshfs/patch/0003-Use-bool-instead-of-gboolean.patch b/extra/sshfs/patch/0003-Use-bool-instead-of-gboolean.patch
new file mode 100644
index 00000000..01269089
--- /dev/null
+++ b/extra/sshfs/patch/0003-Use-bool-instead-of-gboolean.patch
@@ -0,0 +1,33 @@
+From d5a42cdc54068a731cd6a3803574dee4056e84fa Mon Sep 17 00:00:00 2001
+From: Michael Forney <mforney@mforney.org>
+Date: Sun, 5 Jun 2016 17:28:40 -0700
+Subject: [PATCH] Use bool instead of gboolean
+
+---
+ sshfs.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/sshfs.c b/sshfs.c
+index 99dcc25..6836cf4 100644
+--- a/sshfs.c
++++ b/sshfs.c
+@@ -16,6 +16,7 @@
+ # include <fuse_darwin.h>
+ #endif
+ #include <assert.h>
++#include <stdbool.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <unistd.h>
+@@ -1970,7 +1971,7 @@ static int sftp_request_send(uint8_t type, struct iovec *iov, size_t count,
+
+ err = -EIO;
+ if (sftp_send_iov(type, req->id, iov, count) == -1) {
+- gboolean rmed;
++ bool rmed;
+
+ pthread_mutex_lock(&sshfs.lock);
+ rmed = !!request_table_lookup(&sshfs.reqtab, req->id);
+--
+2.8.1
+
diff --git a/extra/sshfs/patch/0004-Use-struct-list_head-instead-of-GList.patch b/extra/sshfs/patch/0004-Use-struct-list_head-instead-of-GList.patch
new file mode 100644
index 00000000..95db227b
--- /dev/null
+++ b/extra/sshfs/patch/0004-Use-struct-list_head-instead-of-GList.patch
@@ -0,0 +1,62 @@
+From b119ab7e98c0ae325027c47515f9d360c9c10800 Mon Sep 17 00:00:00 2001
+From: Michael Forney <mforney@mforney.org>
+Date: Sun, 5 Jun 2016 17:30:20 -0700
+Subject: [PATCH] Use struct list_head instead of GList
+
+---
+ sshfs.c | 16 +++++++---------
+ 1 file changed, 7 insertions(+), 9 deletions(-)
+
+diff --git a/sshfs.c b/sshfs.c
+index 6836cf4..bb792ab 100644
+--- a/sshfs.c
++++ b/sshfs.c
+@@ -2175,13 +2175,13 @@ static int sshfs_req_pending(struct request *req)
+ static int sftp_readdir_async(struct buffer *handle, fuse_cache_dirh_t h,
+ fuse_cache_dirfil_t filler)
+ {
++ int done = 0;
+ int err = 0;
+ int outstanding = 0;
+ int max = READDIR_START;
+- GList *list = NULL;
+-
+- int done = 0;
++ struct list_head list;
+
++ list_init(&list);
+ while (!done || outstanding) {
+ struct request *req;
+ struct buffer name;
+@@ -2196,16 +2196,14 @@ static int sftp_readdir_async(struct buffer *handle, fuse_cache_dirh_t h,
+ break;
+ }
+
+- list = g_list_append(list, req);
++ list_add(&req->list, &list);
+ outstanding++;
+ }
+
+ if (outstanding) {
+- GList *first;
+ /* wait for response to next request */
+- first = g_list_first(list);
+- req = first->data;
+- list = g_list_delete_link(list, first);
++ req = list_entry(list.prev, struct request, list);
++ list_del(&req->list);
+ outstanding--;
+
+ if (done) {
+@@ -2239,7 +2237,7 @@ static int sftp_readdir_async(struct buffer *handle, fuse_cache_dirh_t h,
+ }
+ }
+ }
+- assert(list == NULL);
++ assert(list_empty(&list));
+
+ return err;
+ }
+--
+2.8.1
+
diff --git a/extra/sshfs/patch/0005-Use-standard-C-functions.patch b/extra/sshfs/patch/0005-Use-standard-C-functions.patch
new file mode 100644
index 00000000..e81f7cf2
--- /dev/null
+++ b/extra/sshfs/patch/0005-Use-standard-C-functions.patch
@@ -0,0 +1,277 @@
+From 6dd86c99ca057cd7a2c8450e7baa7ab69e8e0501 Mon Sep 17 00:00:00 2001
+From: Michael Forney <mforney@mforney.org>
+Date: Sun, 5 Jun 2016 17:42:29 -0700
+Subject: [PATCH] Use standard C functions
+
+---
+ sshfs.c | 101 ++++++++++++++++++++++++++++++++++++++--------------------------
+ 1 file changed, 60 insertions(+), 41 deletions(-)
+
+diff --git a/sshfs.c b/sshfs.c
+index bb792ab..22c18a7 100644
+--- a/sshfs.c
++++ b/sshfs.c
+@@ -635,25 +635,25 @@ static inline void buf_add_path(struct buffer *buf, const char *path)
+ if (sshfs.base_path[0]) {
+ if (path[1]) {
+ if (sshfs.base_path[strlen(sshfs.base_path)-1] != '/') {
+- realpath = g_strdup_printf("%s/%s",
+- sshfs.base_path,
+- path + 1);
++ if (asprintf(&realpath, "%s/%s", sshfs.base_path, path + 1) < 0)
++ abort();
+ } else {
+- realpath = g_strdup_printf("%s%s",
+- sshfs.base_path,
+- path + 1);
++ if (asprintf(&realpath, "%s%s", sshfs.base_path, path + 1) < 0)
++ abort();
+ }
+ } else {
+- realpath = g_strdup(sshfs.base_path);
++ realpath = strdup(sshfs.base_path);
+ }
+ } else {
+ if (path[1])
+- realpath = g_strdup(path + 1);
++ realpath = strdup(path + 1);
+ else
+- realpath = g_strdup(".");
++ realpath = strdup(".");
+ }
++ if (!realpath)
++ abort();
+ buf_add_string(buf, realpath);
+- g_free(realpath);
++ free(realpath);
+ }
+
+ static int buf_check_get(struct buffer *buf, size_t len)
+@@ -946,10 +946,9 @@ nobundle:
+ pathok:
+ #endif
+
+- newpreload = g_strdup_printf("%s%s%s",
+- oldpreload ? oldpreload : "",
+- oldpreload ? " " : "",
+- sopath);
++ if (asprintf(&newpreload, "%s%s%s",
++ oldpreload ? oldpreload : "", oldpreload ? " " : "", sopath) < 0)
++ abort();
+
+ #ifdef __APPLE__
+ if (!newpreload || setenv("DYLD_INSERT_LIBRARIES", newpreload, 1) == -1)
+@@ -960,7 +959,7 @@ pathok:
+ "for ssh nodelay workaround\n");
+ }
+ #endif /* __APPLE__ */
+- g_free(newpreload);
++ free(newpreload);
+ return 0;
+ }
+ #endif
+@@ -1340,7 +1339,7 @@ static void request_free(struct request *req)
+ {
+ buf_free(&req->reply);
+ sem_destroy(&req->ready);
+- g_free(req);
++ free(req);
+ }
+
+ static int request_table_insert(struct request_table *reqtab, struct request *req)
+@@ -1388,9 +1387,9 @@ static void chunk_free(struct read_chunk *chunk)
+ rreq = list_entry(chunk->reqs.prev, struct read_req, list);
+ list_del(&rreq->list);
+ buf_free(&rreq->data);
+- g_free(rreq);
++ free(rreq);
+ }
+- g_free(chunk);
++ free(chunk);
+ }
+
+ static void chunk_put(struct read_chunk *chunk)
+@@ -1939,8 +1938,10 @@ static int sftp_request_send(uint8_t type, struct iovec *iov, size_t count,
+ struct request **reqp)
+ {
+ int err;
+- struct request *req = g_new0(struct request, 1);
++ struct request *req = calloc(1, sizeof(struct request));
+
++ if (!req)
++ return -ENOMEM;
+ req->want_reply = want_reply;
+ req->end_func = end_func;
+ req->data = data;
+@@ -2581,7 +2582,9 @@ static int sshfs_open_common(const char *path, mode_t mode,
+ if (fi->flags & O_TRUNC)
+ pflags |= SSH_FXF_TRUNC;
+
+- sf = g_new0(struct sshfs_file, 1);
++ sf = calloc(1, sizeof(struct sshfs_file));
++ if (!sf)
++ return -ENOMEM;
+ list_init(&sf->write_reqs);
+ pthread_cond_init(&sf->write_finished, NULL);
+ /* Assume random read after open */
+@@ -2623,7 +2626,7 @@ static int sshfs_open_common(const char *path, mode_t mode,
+ fi->fh = (unsigned long) sf;
+ } else {
+ cache_invalidate(path);
+- g_free(sf);
++ free(sf);
+ }
+ buf_free(&buf);
+ return err;
+@@ -2679,7 +2682,7 @@ static void sshfs_file_put(struct sshfs_file *sf)
+ {
+ sf->refs--;
+ if (!sf->refs)
+- g_free(sf);
++ free(sf);
+ }
+
+ static void sshfs_file_get(struct sshfs_file *sf)
+@@ -2749,9 +2752,11 @@ static void sshfs_read_begin(struct request *req)
+ static struct read_chunk *sshfs_send_read(struct sshfs_file *sf, size_t size,
+ off_t offset)
+ {
+- struct read_chunk *chunk = g_new0(struct read_chunk, 1);
++ struct read_chunk *chunk = calloc(1, sizeof(struct read_chunk));
+ struct buffer *handle = &sf->handle;
+
++ if (!chunk)
++ abort();
+ pthread_cond_init(&chunk->sio.finished, NULL);
+ list_init(&chunk->reqs);
+ chunk->size = size;
+@@ -2765,7 +2770,9 @@ static struct read_chunk *sshfs_send_read(struct sshfs_file *sf, size_t size,
+ struct read_req *rreq;
+ size_t bsize = size < sshfs.max_read ? size : sshfs.max_read;
+
+- rreq = g_new0(struct read_req, 1);
++ rreq = calloc(1, sizeof(struct read_req));
++ if (!rreq)
++ abort();
+ rreq->sio = &chunk->sio;
+ rreq->size = bsize;
+ buf_init(&rreq->data, 0);
+@@ -2836,7 +2843,7 @@ static int wait_chunk(struct read_chunk *chunk, char *buf, size_t size)
+ size -= rreq->res;
+ list_del(&rreq->list);
+ buf_free(&rreq->data);
+- g_free(rreq);
++ free(rreq);
+ }
+ }
+
+@@ -3487,9 +3494,10 @@ static int sshfs_opt_proc(void *data, const char *arg, int key,
+ switch (key) {
+ case FUSE_OPT_KEY_OPT:
+ if (is_ssh_opt(arg)) {
+- tmp = g_strdup_printf("-o%s", arg);
++ if (asprintf(&tmp, "-o%s", arg) < 0)
++ abort();
+ ssh_add_arg(tmp);
+- g_free(tmp);
++ free(tmp);
+ return 0;
+ }
+ return 1;
+@@ -3502,9 +3510,10 @@ static int sshfs_opt_proc(void *data, const char *arg, int key,
+ return 1;
+
+ case KEY_PORT:
+- tmp = g_strdup_printf("-oPort=%s", arg + 2);
++ if (asprintf(&tmp, "-oPort=%s", arg + 2) < 0)
++ abort();
+ ssh_add_arg(tmp);
+- g_free(tmp);
++ free(tmp);
+ return 0;
+
+ case KEY_COMPRESS:
+@@ -3512,9 +3521,10 @@ static int sshfs_opt_proc(void *data, const char *arg, int key,
+ return 0;
+
+ case KEY_CONFIGFILE:
+- tmp = g_strdup_printf("-F%s", arg + 2);
++ if (asprintf(&tmp, "-F%s", arg + 2) < 0)
++ abort();
+ ssh_add_arg(tmp);
+- g_free(tmp);
++ free(tmp);
+ return 0;
+
+ case KEY_HELP:
+@@ -3729,17 +3739,19 @@ static void fsname_remove_commas(char *fsname)
+ #if FUSE_VERSION >= 27
+ static char *fsname_escape_commas(char *fsnameold)
+ {
+- char *fsname = g_malloc(strlen(fsnameold) * 2 + 1);
++ char *fsname = malloc(strlen(fsnameold) * 2 + 1);
+ char *d = fsname;
+ char *s;
+
++ if (!fsname)
++ abort();
+ for (s = fsnameold; *s; s++) {
+ if (*s == '\\' || *s == ',')
+ *d++ = '\\';
+ *d++ = *s;
+ }
+ *d = '\0';
+- g_free(fsnameold);
++ free(fsnameold);
+
+ return fsname;
+ }
+@@ -4055,15 +4067,20 @@ int main(int argc, char *argv[])
+ exit(1);
+ }
+
+- fsname = g_strdup(sshfs.host);
+- sshfs.base_path = g_strdup(find_base_path());
++ fsname = strdup(sshfs.host);
++ if (!fsname)
++ abort();
++ sshfs.base_path = strdup(find_base_path());
++ if (!sshfs.base_path)
++ abort();
+
+ if (sshfs.ssh_command)
+ set_ssh_command();
+
+- tmp = g_strdup_printf("-%i", sshfs.ssh_ver);
++ if (asprintf(&tmp, "-%i", sshfs.ssh_ver) < 0)
++ abort();
+ ssh_add_arg(tmp);
+- g_free(tmp);
++ free(tmp);
+ ssh_add_arg(sshfs.host);
+ if (sshfs.sftp_server)
+ sftp_server = sshfs.sftp_server;
+@@ -4099,14 +4116,16 @@ int main(int argc, char *argv[])
+ fsname = fsname_escape_commas(fsname);
+ else
+ fsname_remove_commas(fsname);
+- tmp = g_strdup_printf("-osubtype=sshfs,fsname=%s", fsname);
++ if (asprintf(&tmp, "-osubtype=sshfs,fsname=%s", fsname) < 0)
++ abort();
+ #else
+ fsname_remove_commas(fsname);
+- tmp = g_strdup_printf("-ofsname=sshfs#%s", fsname);
++ if (asprintf(&tmp, "-ofsname=sshfs#%s", fsname) < 0)
++ abort();
+ #endif
+ fuse_opt_insert_arg(&args, 1, tmp);
+- g_free(tmp);
+- g_free(fsname);
++ free(tmp);
++ free(fsname);
+ check_large_read(&args);
+
+ #if FUSE_VERSION >= 26
+--
+2.8.1
+
diff --git a/extra/sshfs/patch/0006-Add-missing-includes.patch b/extra/sshfs/patch/0006-Add-missing-includes.patch
new file mode 100644
index 00000000..9c8b49c6
--- /dev/null
+++ b/extra/sshfs/patch/0006-Add-missing-includes.patch
@@ -0,0 +1,34 @@
+From 27806ddaac633e9d71b061b57f74d02ff8aac889 Mon Sep 17 00:00:00 2001
+From: Michael Forney <mforney@mforney.org>
+Date: Sun, 5 Jun 2016 18:21:02 -0700
+Subject: [PATCH] Add missing includes
+
+stddef.h for offsetof
+sys/param.h for MIN
+---
+ sshfs.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/sshfs.c b/sshfs.c
+index 22c18a7..319bffe 100644
+--- a/sshfs.c
++++ b/sshfs.c
+@@ -17,6 +17,7 @@
+ #endif
+ #include <assert.h>
+ #include <stdbool.h>
++#include <stddef.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <unistd.h>
+@@ -37,6 +38,7 @@
+ #include <sys/socket.h>
+ #include <sys/utsname.h>
+ #include <sys/mman.h>
++#include <sys/param.h>
+ #include <sys/poll.h>
+ #include <netinet/in.h>
+ #include <netinet/tcp.h>
+--
+2.8.1
+
diff --git a/extra/sshfs/patch/0007-Disable-uidmap-and-gidmap-support.patch b/extra/sshfs/patch/0007-Disable-uidmap-and-gidmap-support.patch
new file mode 100644
index 00000000..2e4ff69b
--- /dev/null
+++ b/extra/sshfs/patch/0007-Disable-uidmap-and-gidmap-support.patch
@@ -0,0 +1,127 @@
+From ab229f7cec14fb428605585a1a0026339997d628 Mon Sep 17 00:00:00 2001
+From: Michael Forney <mforney@mforney.org>
+Date: Sun, 5 Jun 2016 18:24:16 -0700
+Subject: [PATCH] Disable uidmap and gidmap support
+
+---
+ sshfs.c | 16 ++++++++++++++++
+ 1 file changed, 16 insertions(+)
+
+diff --git a/sshfs.c b/sshfs.c
+index 319bffe..3448f4d 100644
+--- a/sshfs.c
++++ b/sshfs.c
+@@ -241,10 +241,12 @@ struct sshfs {
+ int disable_hardlink;
+ char *uid_file;
+ char *gid_file;
++#if 0
+ GHashTable *uid_map;
+ GHashTable *gid_map;
+ GHashTable *r_uid_map;
+ GHashTable *r_gid_map;
++#endif
+ unsigned max_read;
+ unsigned max_write;
+ unsigned ssh_ver;
+@@ -364,7 +366,9 @@ enum {
+ enum {
+ IDMAP_NONE,
+ IDMAP_USER,
++#if 0
+ IDMAP_FILE,
++#endif
+ };
+
+ enum {
+@@ -385,7 +389,9 @@ static struct fuse_opt sshfs_opts[] = {
+ SSHFS_OPT("workaround=%s", workarounds, 0),
+ SSHFS_OPT("idmap=none", idmap, IDMAP_NONE),
+ SSHFS_OPT("idmap=user", idmap, IDMAP_USER),
++#if 0
+ SSHFS_OPT("idmap=file", idmap, IDMAP_FILE),
++#endif
+ SSHFS_OPT("uidfile=%s", uid_file, 0),
+ SSHFS_OPT("gidfile=%s", gid_file, 0),
+ SSHFS_OPT("nomap=ignore", nomap, NOMAP_IGNORE),
+@@ -518,6 +524,7 @@ static int list_empty(const struct list_head *head)
+ return head->next == head;
+ }
+
++#if 0
+ /* given a pointer to the uid/gid, and the mapping table, remap the
+ * uid/gid, if necessary */
+ static inline int translate_id(uint32_t *id, GHashTable *map)
+@@ -535,6 +542,7 @@ static inline int translate_id(uint32_t *id, GHashTable *map)
+ abort();
+ }
+ }
++#endif
+
+ static inline void buf_init(struct buffer *buf, size_t size)
+ {
+@@ -782,12 +790,14 @@ static int buf_get_attrs(struct buffer *buf, struct stat *stbuf, int *flagsp)
+ if (sshfs.remote_uid_detected && uid == sshfs.remote_uid)
+ uid = sshfs.local_uid;
+ #endif /* __APPLE__ */
++#if 0
+ if (sshfs.idmap == IDMAP_FILE && sshfs.uid_map)
+ if (translate_id(&uid, sshfs.uid_map) == -1)
+ return -EPERM;
+ if (sshfs.idmap == IDMAP_FILE && sshfs.gid_map)
+ if (translate_id(&gid, sshfs.gid_map) == -1)
+ return -EPERM;
++#endif
+
+ memset(stbuf, 0, sizeof(struct stat));
+ stbuf->st_mode = mode;
+@@ -2481,12 +2491,14 @@ static int sshfs_chown(const char *path, uid_t uid, gid_t gid)
+ if (sshfs.remote_uid_detected && uid == sshfs.local_uid)
+ uid = sshfs.remote_uid;
+ #endif /* __APPLE__ */
++#if 0
+ if (sshfs.idmap == IDMAP_FILE && sshfs.r_uid_map)
+ if(translate_id(&uid, sshfs.r_uid_map) == -1)
+ return -EPERM;
+ if (sshfs.idmap == IDMAP_FILE && sshfs.r_gid_map)
+ if (translate_id(&gid, sshfs.r_gid_map) == -1)
+ return -EPERM;
++#endif
+
+ buf_init(&buf, 0);
+ buf_add_path(&buf, path);
+@@ -3779,6 +3791,7 @@ static int ssh_connect(void)
+ return 0;
+ }
+
++#if 0
+ /* number of ':' separated fields in a passwd/group file that we care
+ * about */
+ #define IDMAP_FIELDS 3
+@@ -3953,6 +3966,7 @@ static inline void load_gid_map(void)
+ {
+ read_id_map(sshfs.gid_file, &groupname_to_gid, "gid", &sshfs.gid_map, &sshfs.r_gid_map);
+ }
++#endif
+
+ #ifdef __APPLE__
+ int main(int argc, char *argv[], __unused char *envp[], char **exec_path)
+@@ -4020,6 +4034,7 @@ int main(int argc, char *argv[])
+
+ if (sshfs.idmap == IDMAP_USER)
+ sshfs.detect_uid = 1;
++#if 0
+ else if (sshfs.idmap == IDMAP_FILE) {
+ sshfs.uid_map = NULL;
+ sshfs.gid_map = NULL;
+@@ -4034,6 +4049,7 @@ int main(int argc, char *argv[])
+ if (sshfs.gid_file)
+ load_gid_map();
+ }
++#endif
+ free(sshfs.uid_file);
+ free(sshfs.gid_file);
+
+--
+2.8.1
+
diff --git a/extra/sshfs/patch/0008-Remove-remaining-uses-of-glib.patch b/extra/sshfs/patch/0008-Remove-remaining-uses-of-glib.patch
new file mode 100644
index 00000000..203dfafb
--- /dev/null
+++ b/extra/sshfs/patch/0008-Remove-remaining-uses-of-glib.patch
@@ -0,0 +1,36 @@
+From e1b37bd0bbb61e8b425972ee0321ba501b1d4ea2 Mon Sep 17 00:00:00 2001
+From: Michael Forney <mforney@mforney.org>
+Date: Sun, 5 Jun 2016 18:24:31 -0700
+Subject: [PATCH] Remove remaining uses of glib
+
+---
+ sshfs.c | 5 -----
+ 1 file changed, 5 deletions(-)
+
+diff --git a/sshfs.c b/sshfs.c
+index 3448f4d..d548c98 100644
+--- a/sshfs.c
++++ b/sshfs.c
+@@ -42,7 +42,6 @@
+ #include <sys/poll.h>
+ #include <netinet/in.h>
+ #include <netinet/tcp.h>
+-#include <glib.h>
+ #include <pwd.h>
+ #include <grp.h>
+ #include <limits.h>
+@@ -3985,11 +3984,7 @@ int main(int argc, char *argv[])
+ 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;
+ /* SFTP spec says all servers should allow at least 32k I/O */
+--
+2.8.1
+
diff --git a/extra/sshfs/src b/extra/sshfs/src
new file mode 160000
+Subproject a9a1cc004675f35df34c68f3e134c2194311943