summaryrefslogtreecommitdiff
path: root/filesystems
diff options
context:
space:
mode:
authorpho <pho@pkgsrc.org>2021-12-02 07:28:40 +0000
committerpho <pho@pkgsrc.org>2021-12-02 07:28:40 +0000
commita695ed42edde952e841ed827188cadb34b59076f (patch)
tree8147e80d9f9c4c6f5e65a55500b1722c73b85e5b /filesystems
parent2ded0ceef98b3ff9cc87ebb55939e27828569114 (diff)
downloadpkgsrc-a695ed42edde952e841ed827188cadb34b59076f.tar.gz
Update to sshfs-3.7.2
I have added a lot of unpleasant hacks to the code in order to make it work with NetBSD librefuse. We really should fix it. I will probably do it later. Release notes from the upstream are as follows: Release 3.7.2 (2021-06-08) -------------------------- * Added a secondary check so if a mkdir request fails with EPERM an access request will be tried - returning EEXIST if the access was successful. Fixes: https://github.com/libfuse/sshfs/issues/243 Release 3.7.1 (2020-11-09) -------------------------- * Minor bugfixes. Release 3.7.0 (2020-01-03) -------------------------- * New max_conns option enables the use of multiple connections to improve responsiveness during large file transfers. Thanks to Timo Savola for doing most of the implementation work, and thanks to CEA.fr for sponsoring remaining bugfixes and cleanups! * The `buflimit` workaround is now disabled by default. The corresponding bug in OpenSSH has been fixed in 2007 (cf. https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=365541#37), so this shouldn't be needed anymore. If you depend on this workaround, please let the SSHFS maintainers know, otherwise support for the workaround will be removed completely in a future version. Release 3.6.0 (2019-11-03) -------------------------- * Added "-o direct_io" option. This option disables the use of page cache in kernel. This is useful for example if the file size is not known before reading it. For example if you mount /proc dir from a remote host without the direct_io option, the read always will return zero bytes instead of actual data. * Added --verbose option. * Fixed a number of compiler warnings. * Improved performance under OS X. Release 3.5.2 (2019-04-13) -------------------------- * Fixed "-o idmap=user" to map both UID and GID on all OSs. * Fixed improper handling of sequential spaces spaces in "ssh_command" option Release 3.5.1 (2018-12-22) -------------------------- * Documentation updates * Build system updates * Added "BindInterface" as valid "-o" option. Release 3.5.0 (2018-08-28) -------------------------- * Fixed error code returned by rename(), allowing proper fallback. * Port to Cygwin. Release 3.4.0 (2018-06-29) -------------------------- * Make utimens(NULL) result in timestamp "now" -- no more touched files dated 1970-01-01 * New `createmode` workaround. * Fix `fstat` workaround regression. Release 3.3.2 (2018-04-29) -------------------------- * New `renamexdev` workaround. Release 3.3.1 (2017-10-25) -------------------------- * Manpage is now installed in correct directory. * SSHFS now supports (or rather: ignores) some options that it may receive as result of being mounted from ``/etc/mtab``. This includes things like ``user``, ``netdev``, or ``auto``. SSHFS 3.3.0 (2017-09-20) ------------------------ * Dropped support for writeback caching (and, as a consequence, "unreliable append" operation). As of kernel 4.14, the FUSE module's writeback implementation is not compatible with network filesystems and there are no imminent plans to change that. * Add support for mounting from /etc/fstab * Dropped support for building with autotools. * Added missing options to man page. Release 3.2.0 (2017-08-06) -------------------------- * Re-enabled writeback cache. * SSHFS now supports O_APPEND. Release 3.1.0 (2017-08-04) -------------------------- * Temporarily disabled the writeback cache feature, since there have been reports of dataloss when appending to files when writeback caching is enabled. * Fixed a crash due to a race condition when listing directory contents. * For improved backwards compatibility, SSHFS now also silently accepts the old ``-o cache_*`` options. Release 3.0.0 (2017-07-08) -------------------------- * sshfs now requires libfuse 3.1.0 or newer. * When supported by the kernel, sshfs now uses writeback caching. * The `cache` option has been renamed to `dir_cache` for clarity. * Added unit tests * --debug now behaves like -o debug_sshfs, i.e. it enables sshfs debugging messages rather than libfuse debugging messages. * Documented limited hardlink support. * Added support for building with Meson. * Added support for more SSH options. * Dropped support for the *nodelay* workaround - the last OpenSSH version for which this was useful was released in 2006. * Dropped support for the *nodelaysrv* workaround. The same effect (enabling NODELAY on the server side *and* enabling X11 forwarding) can be achieved by explicitly passing `-o ForwardX11` * Removed support for `-o workaround=all`. Workarounds should always enabled explicitly and only when needed. There is no point in always enabling a potentially changing set of workarounds. Release 2.9 (2017-04-17) ------------------------ * Improved support for Cygwin. * Various small bugfixes. Release 2.8 (2016-06-22) ------------------------ * Added support for the "fsync" extension. * Fixed a build problem with bitbake
Diffstat (limited to 'filesystems')
-rw-r--r--filesystems/fuse-sshfs/Makefile10
-rw-r--r--filesystems/fuse-sshfs/PLIST4
-rw-r--r--filesystems/fuse-sshfs/distinfo12
-rw-r--r--filesystems/fuse-sshfs/patches/patch-cache.c227
-rw-r--r--filesystems/fuse-sshfs/patches/patch-meson.build19
-rw-r--r--filesystems/fuse-sshfs/patches/patch-sshfs.c420
-rw-r--r--filesystems/fuse-sshfs/patches/patch-utils_install__helper.sh18
7 files changed, 699 insertions, 11 deletions
diff --git a/filesystems/fuse-sshfs/Makefile b/filesystems/fuse-sshfs/Makefile
index bcb15a64d1c..76869660fdb 100644
--- a/filesystems/fuse-sshfs/Makefile
+++ b/filesystems/fuse-sshfs/Makefile
@@ -1,25 +1,23 @@
-# $NetBSD: Makefile,v 1.3 2020/03/08 16:49:31 wiz Exp $
+# $NetBSD: Makefile,v 1.4 2021/12/02 07:28:40 pho Exp $
#
-DISTNAME= sshfs-2.7
+DISTNAME= sshfs-3.7.2
PKGNAME= fuse-${DISTNAME}
-PKGREVISION= 1
CATEGORIES= filesystems
MASTER_SITES= ${MASTER_SITE_GITHUB:=libfuse/}
GITHUB_PROJECT= sshfs
GITHUB_RELEASE= ${DISTNAME}
+EXTRACT_SUFX= .tar.xz
MAINTAINER= pkgsrc-users@NetBSD.org
HOMEPAGE= https://github.com/libfuse/sshfs/
COMMENT= File system client based on the SFTP protocol
LICENSE= gnu-gpl-v2
-ONLY_FOR_PLATFORM= Darwin-*-* Linux-*-*
-
-GNU_CONFIGURE= yes
USE_LANGUAGES= c
USE_TOOLS= pkg-config
.include "../../devel/glib2/buildlink3.mk"
+.include "../../devel/meson/build.mk"
.include "../../mk/fuse.buildlink3.mk"
.include "../../mk/bsd.pkg.mk"
diff --git a/filesystems/fuse-sshfs/PLIST b/filesystems/fuse-sshfs/PLIST
index 93685f4121b..92a303fdbd4 100644
--- a/filesystems/fuse-sshfs/PLIST
+++ b/filesystems/fuse-sshfs/PLIST
@@ -1,3 +1,5 @@
-@comment $NetBSD: PLIST,v 1.1 2016/03/01 11:30:07 jmmv Exp $
+@comment $NetBSD: PLIST,v 1.2 2021/12/02 07:28:40 pho Exp $
bin/sshfs
man/man1/sshfs.1
+sbin/mount.fuse.sshfs
+sbin/mount.sshfs
diff --git a/filesystems/fuse-sshfs/distinfo b/filesystems/fuse-sshfs/distinfo
index c7a7030ef47..763ec2be66d 100644
--- a/filesystems/fuse-sshfs/distinfo
+++ b/filesystems/fuse-sshfs/distinfo
@@ -1,5 +1,9 @@
-$NetBSD: distinfo,v 1.4 2021/10/26 10:25:28 nia Exp $
+$NetBSD: distinfo,v 1.5 2021/12/02 07:28:40 pho Exp $
-BLAKE2s (sshfs-2.7.tar.gz) = 127adb5052b76f8d0a3d54fe83b2ac9acde72b788f113baccabaec09bdcd42df
-SHA512 (sshfs-2.7.tar.gz) = e8b00bc3661140d59c6735f1f76d1bd4c63ebc04b578cbcebca88c2f1df8b2cea18c86ff24bef5d40ce286319b55d906632bea53e6b37aff76744072250aec1b
-Size (sshfs-2.7.tar.gz) = 153014 bytes
+BLAKE2s (sshfs-3.7.2.tar.xz) = a770780be6c0d5b26ebb9b7b43c35c8a689e226a619f03cdaee847598c81d025
+SHA512 (sshfs-3.7.2.tar.xz) = 1612d515869a8b38c0bc3d79eaf80e8b4da1a9710c9668e6ec23e6b77313063ae0bee66ab9e9e0f70d98eaa1334425b2087dd93cc4618af3ac6ac191acf7f838
+Size (sshfs-3.7.2.tar.xz) = 53160 bytes
+SHA1 (patch-cache.c) = 9a089852ab3ad77d2b77c4323c5d65ed9f05036a
+SHA1 (patch-meson.build) = dd9549c3d099a4137089757bd743c8c0bbb63b35
+SHA1 (patch-sshfs.c) = 4f06a3c945de2f4b3b8e5935b28c6fca0d50a355
+SHA1 (patch-utils_install__helper.sh) = 7e31f031ecf40731acb4a96b0c23543b7015c290
diff --git a/filesystems/fuse-sshfs/patches/patch-cache.c b/filesystems/fuse-sshfs/patches/patch-cache.c
new file mode 100644
index 00000000000..5f0221c8faf
--- /dev/null
+++ b/filesystems/fuse-sshfs/patches/patch-cache.c
@@ -0,0 +1,227 @@
+$NetBSD: patch-cache.c,v 1.1 2021/12/02 07:28:40 pho Exp $
+
+Impedance adjustment with librefuse. Never send this to the
+upstream. It's our code that needs to be fixed, not theirs!
+
+TODO: This patch should *really* be gone, except for one thing (see
+comments). Update librefuse.
+
+--- cache.c.orig 2021-06-08 08:52:08.000000000 +0000
++++ cache.c
+@@ -251,6 +251,12 @@ uint64_t cache_get_write_ctr(void)
+ return res;
+ }
+
++#if defined(__NetBSD__) && FUSE_MAJOR_VERSION < 3
++static void *cache_init(struct fuse_conn_info *conn __attribute__((__unused__)))
++{
++ return cache.next_oper->init(NULL);
++}
++#else
+ static void *cache_init(struct fuse_conn_info *conn,
+ struct fuse_config *cfg)
+ {
+@@ -262,14 +268,23 @@ static void *cache_init(struct fuse_conn
+
+ return res;
+ }
++#endif
+
++#if FUSE_MAJOR_VERSION < 3
++static int cache_getattr(const char *path, struct stat *stbuf)
++#else
+ static int cache_getattr(const char *path, struct stat *stbuf,
+ struct fuse_file_info *fi)
++#endif
+ {
+ int err = cache_get_attr(path, stbuf);
+ if (err) {
+ uint64_t wrctr = cache_get_write_ctr();
++#if FUSE_MAJOR_VERSION < 3
++ err = cache.next_oper->getattr(path, stbuf);
++#else
+ err = cache.next_oper->getattr(path, stbuf, fi);
++#endif
+ if (!err)
+ cache_add_attr(path, stbuf, wrctr);
+ }
+@@ -331,15 +346,24 @@ static int cache_releasedir(const char *
+ return err;
+ }
+
++#if FUSE_MAJOR_VERSION < 3
++static int cache_dirfill (void *buf, const char *name,
++ const struct stat *stbuf, off_t off)
++#else
+ static int cache_dirfill (void *buf, const char *name,
+ const struct stat *stbuf, off_t off,
+ enum fuse_fill_dir_flags flags)
++#endif
+ {
+ int err;
+ struct readdir_handle *ch;
+
+ ch = (struct readdir_handle*) buf;
++#if FUSE_MAJOR_VERSION < 3
++ err = ch->filler(ch->buf, name, stbuf, off);
++#else
+ err = ch->filler(ch->buf, name, stbuf, off, flags);
++#endif
+ if (!err) {
+ g_ptr_array_add(ch->dir, g_strdup(name));
+ if (stbuf->st_mode & S_IFMT) {
+@@ -354,9 +378,14 @@ static int cache_dirfill (void *buf, con
+ return err;
+ }
+
++#if FUSE_MAJOR_VERSION < 3
++static int cache_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
++ off_t offset, struct fuse_file_info *fi)
++#else
+ static int cache_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
+ off_t offset, struct fuse_file_info *fi,
+ enum fuse_readdir_flags flags)
++#endif
+ {
+ struct readdir_handle ch;
+ struct file_handle *cfi;
+@@ -373,7 +402,11 @@ static int cache_readdir(const char *pat
+ if (node->dir_valid - now >= 0) {
+ for(dir = node->dir; *dir != NULL; dir++)
+ // FIXME: What about st_mode?
++#if FUSE_MAJOR_VERSION < 3
++ filler(buf, *dir, NULL, 0);
++#else
+ filler(buf, *dir, NULL, 0, 0);
++#endif
+ pthread_mutex_unlock(&cache.lock);
+ return 0;
+ }
+@@ -398,7 +431,19 @@ static int cache_readdir(const char *pat
+ ch.filler = filler;
+ ch.dir = g_ptr_array_new();
+ ch.wrctr = cache_get_write_ctr();
++#if FUSE_MAJOR_VERSION < 3
++ err = cache.next_oper->readdir(path, &ch, cache_dirfill, offset, fi);
++#else
+ err = cache.next_oper->readdir(path, &ch, cache_dirfill, offset, fi, flags);
++#endif
++ /* fi->fh is set to an underlying file handle at this
++ * point. We must set it back to the cache file_handle or
++ * otherwise cache_releasedir() will dereference a wrong
++ * pointer. I believe this is an upstream bug but have no idea
++ * why it works on Linux. FUSE doesn't call releasedir()
++ * perhaps? */
++ fi->fh = (unsigned long) cfi;
++
+ g_ptr_array_add(ch.dir, NULL);
+ dir = (char **) ch.dir->pdata;
+ if (!err) {
+@@ -451,6 +496,15 @@ static int cache_symlink(const char *fro
+ return err;
+ }
+
++#if FUSE_MAJOR_VERSION < 3
++static int cache_rename(const char *from, const char *to)
++{
++ int err = cache.next_oper->rename(from, to);
++ if (!err)
++ cache_do_rename(from, to);
++ return err;
++}
++#else
+ static int cache_rename(const char *from, const char *to, unsigned int flags)
+ {
+ int err = cache.next_oper->rename(from, to, flags);
+@@ -458,6 +512,7 @@ static int cache_rename(const char *from
+ cache_do_rename(from, to);
+ return err;
+ }
++#endif
+
+ static int cache_link(const char *from, const char *to)
+ {
+@@ -469,6 +524,15 @@ static int cache_link(const char *from,
+ return err;
+ }
+
++#if FUSE_MAJOR_VERSION < 3
++static int cache_chmod(const char *path, mode_t mode)
++{
++ int err = cache.next_oper->chmod(path, mode);
++ if (!err)
++ cache_invalidate(path);
++ return err;
++}
++#else
+ static int cache_chmod(const char *path, mode_t mode,
+ struct fuse_file_info *fi)
+ {
+@@ -477,7 +541,17 @@ static int cache_chmod(const char *path,
+ cache_invalidate(path);
+ return err;
+ }
++#endif
+
++#if FUSE_MAJOR_VERSION < 3
++static int cache_chown(const char *path, uid_t uid, gid_t gid)
++{
++ int err = cache.next_oper->chown(path, uid, gid);
++ if (!err)
++ cache_invalidate(path);
++ return err;
++}
++#else
+ static int cache_chown(const char *path, uid_t uid, gid_t gid,
+ struct fuse_file_info *fi)
+ {
+@@ -486,7 +560,17 @@ static int cache_chown(const char *path,
+ cache_invalidate(path);
+ return err;
+ }
++#endif
+
++#if FUSE_MAJOR_VERSION < 3
++static int cache_utimens(const char *path, const struct timespec tv[2])
++{
++ int err = cache.next_oper->utimens(path, tv);
++ if (!err)
++ cache_invalidate(path);
++ return err;
++}
++#else
+ static int cache_utimens(const char *path, const struct timespec tv[2],
+ struct fuse_file_info *fi)
+ {
+@@ -495,6 +579,7 @@ static int cache_utimens(const char *pat
+ cache_invalidate(path);
+ return err;
+ }
++#endif
+
+ static int cache_write(const char *path, const char *buf, size_t size,
+ off_t offset, struct fuse_file_info *fi)
+@@ -514,6 +599,15 @@ static int cache_create(const char *path
+ return err;
+ }
+
++#if FUSE_MAJOR_VERSION < 3
++static int cache_truncate(const char *path, off_t size)
++{
++ int err = cache.next_oper->truncate(path, size);
++ if (!err)
++ cache_invalidate(path);
++ return err;
++}
++#else
+ static int cache_truncate(const char *path, off_t size,
+ struct fuse_file_info *fi)
+ {
+@@ -522,6 +616,7 @@ static int cache_truncate(const char *pa
+ cache_invalidate(path);
+ return err;
+ }
++#endif
+
+ static void cache_fill(struct fuse_operations *oper,
+ struct fuse_operations *cache_oper)
diff --git a/filesystems/fuse-sshfs/patches/patch-meson.build b/filesystems/fuse-sshfs/patches/patch-meson.build
new file mode 100644
index 00000000000..fa753175f87
--- /dev/null
+++ b/filesystems/fuse-sshfs/patches/patch-meson.build
@@ -0,0 +1,19 @@
+$NetBSD: patch-meson.build,v 1.1 2021/12/02 07:28:40 pho Exp $
+
+Impedance adjustment with librefuse. Never send this to the
+upstream. It's our code that needs to be fixed, not theirs!
+
+TODO: This patch should *really* be gone. Update librefuse.
+
+--- meson.build.orig 2021-12-01 17:06:20.555815467 +0000
++++ meson.build
+@@ -44,7 +44,8 @@ endif
+ configure_file(output: 'config.h',
+ configuration : cfg)
+
+-sshfs_deps = [ dependency('fuse3', version: '>= 3.1.0'),
++sshfs_deps = [ dependency('fuse3', version: '>= 3.1.0', required: false),
++ dependency('fuse' , version: '>= 2.6.0', required: false),
+ dependency('glib-2.0'),
+ dependency('gthread-2.0') ]
+
diff --git a/filesystems/fuse-sshfs/patches/patch-sshfs.c b/filesystems/fuse-sshfs/patches/patch-sshfs.c
new file mode 100644
index 00000000000..6c14b656114
--- /dev/null
+++ b/filesystems/fuse-sshfs/patches/patch-sshfs.c
@@ -0,0 +1,420 @@
+$NetBSD: patch-sshfs.c,v 1.1 2021/12/02 07:28:40 pho Exp $
+
+Impedance adjustment with librefuse. Never send this to the
+upstream. It's our code that needs to be fixed, not theirs!
+
+TODO: This patch should *really* be gone. Update librefuse.
+
+--- sshfs.c.orig 2021-06-08 08:52:08.000000000 +0000
++++ sshfs.c
+@@ -980,7 +980,11 @@ static int buf_get_entries(struct buffer
+ S_ISLNK(stbuf.st_mode)) {
+ stbuf.st_mode = 0;
+ }
++#if FUSE_MAJOR_VERSION < 3
++ filler(dbuf, name, &stbuf, 0);
++#else
+ filler(dbuf, name, &stbuf, 0, 0);
++#endif
+ }
+ }
+ free(name);
+@@ -1884,6 +1888,21 @@ static int start_processing_thread(struc
+ return 0;
+ }
+
++#if FUSE_MAJOR_VERSION < 3
++static void *sshfs_init(struct fuse_conn_info *conn __attribute__((__unused__)))
++{
++ sshfs.sync_read = 1;
++
++ /* Don't start the processing thread here. This is a
++ * workaround for a broken op->init() handing: librefuse calls
++ * it inside fuse_new(), before we start the main
++ * loop. Already fixed in HEAD. */
++ //if (!sshfs.delay_connect)
++ // start_processing_thread(&sshfs.conns[0]);
++
++ return NULL;
++}
++#else
+ static void *sshfs_init(struct fuse_conn_info *conn,
+ struct fuse_config *cfg)
+ {
+@@ -1909,6 +1928,7 @@ static void *sshfs_init(struct fuse_conn
+
+ return NULL;
+ }
++#endif
+
+ static int sftp_request_wait(struct request *req, uint8_t type,
+ uint8_t expect_type, struct buffer *outbuf)
+@@ -2069,7 +2089,11 @@ static int sshfs_access(const char *path
+ int err = 0;
+
+ if (mask & X_OK) {
++#if FUSE_MAJOR_VERSION < 3
++ err = sshfs.op->getattr(path, &stbuf);
++#else
+ err = sshfs.op->getattr(path, &stbuf, NULL);
++#endif
+ if (!err) {
+ if (S_ISREG(stbuf.st_mode) &&
+ !(stbuf.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)))
+@@ -2323,11 +2347,15 @@ static int sshfs_opendir(const char *pat
+ return err;
+ }
+
+-static int sshfs_readdir(const char *path, void *dbuf, fuse_fill_dir_t filler,
++#if FUSE_MAJOR_VERSION < 3
++static int sshfs_readdir(const char *path __attribute__((__unused__)), void *dbuf, fuse_fill_dir_t filler,
++ off_t offset, struct fuse_file_info *fi)
++#else
++static int sshfs_readdir(const char *path __attribute__((__unused__)), void *dbuf, fuse_fill_dir_t filler,
+ off_t offset, struct fuse_file_info *fi,
+- enum fuse_readdir_flags flags)
++ enum fuse_readdir_flags flags __attribute__((__unused__)))
++#endif
+ {
+- (void) path; (void) flags;
+ int err;
+ struct dir_handle *handle;
+
+@@ -2491,13 +2519,19 @@ static void random_string(char *str, int
+ *str = '\0';
+ }
+
++#if FUSE_MAJOR_VERSION < 3
++static int sshfs_rename(const char *from, const char *to)
++#else
+ static int sshfs_rename(const char *from, const char *to, unsigned int flags)
++#endif
+ {
+ int err;
+ struct conntab_entry *ce;
+
++#if FUSE_MAJOR_VERSION >= 3
+ if(flags != 0)
+ return -EINVAL;
++#endif
+
+ if (sshfs.ext_posix_rename)
+ err = sshfs_ext_posix_rename(from, to);
+@@ -2572,19 +2606,24 @@ static inline struct sshfs_file *get_ssh
+ return (struct sshfs_file *) (uintptr_t) fi->fh;
+ }
+
++#if FUSE_MAJOR_VERSION < 3
++static int sshfs_chmod(const char *path, mode_t mode)
++#else
+ static int sshfs_chmod(const char *path, mode_t mode,
+ struct fuse_file_info *fi)
++#endif
+ {
+- (void) fi;
+ int err;
+ struct buffer buf;
+ struct sshfs_file *sf = NULL;
+
++#if FUSE_MAJOR_VERSION >= 3
+ if (fi != NULL) {
+ sf = get_sshfs_file(fi);
+ if (!sshfs_file_is_conn(sf))
+ return -EIO;
+ }
++#endif
+
+ buf_init(&buf, 0);
+ if (sf == NULL)
+@@ -2605,19 +2644,24 @@ static int sshfs_chmod(const char *path,
+ return err;
+ }
+
++#if FUSE_MAJOR_VERSION < 3
++static int sshfs_chown(const char *path, uid_t uid, gid_t gid)
++#else
+ static int sshfs_chown(const char *path, uid_t uid, gid_t gid,
+ struct fuse_file_info *fi)
++#endif
+ {
+- (void) fi;
+ int err;
+ struct buffer buf;
+ struct sshfs_file *sf = NULL;
+
++#if FUSE_MAJOR_VERSION >= 3
+ if (fi != NULL) {
+ sf = get_sshfs_file(fi);
+ if (!sshfs_file_is_conn(sf))
+ return -EIO;
+ }
++#endif
+
+ if (sshfs.remote_uid_detected) {
+ if (uid == sshfs.local_uid)
+@@ -2650,8 +2694,12 @@ static int sshfs_chown(const char *path,
+ return err;
+ }
+
++#if FUSE_MAJOR_VERSION < 3
++static int sshfs_truncate_workaround(const char *path, off_t size);
++#else
+ static int sshfs_truncate_workaround(const char *path, off_t size,
+ struct fuse_file_info *fi);
++#endif
+
+ static void sshfs_inc_modifver(void)
+ {
+@@ -2660,10 +2708,13 @@ static void sshfs_inc_modifver(void)
+ pthread_mutex_unlock(&sshfs.lock);
+ }
+
++#if FUSE_MAJOR_VERSION < 3
++static int sshfs_utimens(const char *path, const struct timespec tv[2])
++#else
+ static int sshfs_utimens(const char *path, const struct timespec tv[2],
+ struct fuse_file_info *fi)
++#endif
+ {
+- (void) fi;
+ int err;
+ struct buffer buf;
+ struct sshfs_file *sf = NULL;
+@@ -2676,11 +2727,13 @@ static int sshfs_utimens(const char *pat
+ if (msec == 0)
+ msec = now.tv_sec;
+
++#if FUSE_MAJOR_VERSION >= 3
+ if (fi != NULL) {
+ sf = get_sshfs_file(fi);
+ if (!sshfs_file_is_conn(sf))
+ return -EIO;
+ }
++#endif
+
+ buf_init(&buf, 0);
+ if (sf == NULL)
+@@ -3338,22 +3391,32 @@ static int sshfs_create(const char *path
+ return sshfs_open_common(path, mode, fi);
+ }
+
++#if FUSE_MAJOR_VERSION < 3
++static int sshfs_truncate(const char *path, off_t size)
++#else
+ static int sshfs_truncate(const char *path, off_t size,
+ struct fuse_file_info *fi)
++#endif
+ {
+ int err;
+ struct buffer buf;
+ struct sshfs_file *sf = NULL;
+
++#if FUSE_MAJOR_VERSION >= 3
+ if (fi != NULL) {
+ sf = get_sshfs_file(fi);
+ if (!sshfs_file_is_conn(sf))
+ return -EIO;
+ }
++#endif
+
+ sshfs_inc_modifver();
+ if (sshfs.truncate_workaround)
++#if FUSE_MAJOR_VERSION < 3
++ return sshfs_truncate_workaround(path, size);
++#else
+ return sshfs_truncate_workaround(path, size, fi);
++#endif
+
+ buf_init(&buf, 0);
+
+@@ -3372,19 +3435,38 @@ static int sshfs_truncate(const char *pa
+ return err;
+ }
+
++#if defined(__NetBSD__) && FUSE_MAJOR_VERSION < 3
++/* Workaround for a librefuse issue. fuse_mount() calls
++ * fuse_operations::getattr() before we are ready for that. The
++ * resulting struct stat isn't even used apparently. librefuse really
++ * shouldn't do that. */
++static int sshfs_initialized = 0;
++#endif
++
++#if FUSE_MAJOR_VERSION < 3
++static int sshfs_getattr(const char *path, struct stat *stbuf)
++#else
+ static int sshfs_getattr(const char *path, struct stat *stbuf,
+ struct fuse_file_info *fi)
++#endif
+ {
+ int err;
+ struct buffer buf;
+ struct buffer outbuf;
+ struct sshfs_file *sf = NULL;
+
++#if FUSE_MAJOR_VERSION < 3
++ if (!sshfs_initialized)
++ return -EIO;
++#endif
++
++#if FUSE_MAJOR_VERSION >= 3
+ if (fi != NULL && !sshfs.fstat_workaround) {
+ sf = get_sshfs_file(fi);
+ if (!sshfs_file_is_conn(sf))
+ return -EIO;
+ }
++#endif
+
+ buf_init(&buf, 0);
+ if(sf == NULL) {
+@@ -3508,15 +3590,23 @@ static int sshfs_truncate_extend(const c
+ * If new size is greater than current size, then write a zero byte to
+ * the new end of the file.
+ */
++#if FUSE_MAJOR_VERSION < 3
++static int sshfs_truncate_workaround(const char *path, off_t size)
++#else
+ static int sshfs_truncate_workaround(const char *path, off_t size,
+ struct fuse_file_info *fi)
++#endif
+ {
+ if (size == 0)
+ return sshfs_truncate_zero(path);
+ else {
+ struct stat stbuf;
+ int err;
++#if FUSE_MAJOR_VERSION < 3
++ err = sshfs_getattr(path, &stbuf);
++#else
+ err = sshfs_getattr(path, &stbuf, fi);
++#endif
+ if (err)
+ return err;
+ if (stbuf.st_size == size)
+@@ -3524,7 +3614,11 @@ static int sshfs_truncate_workaround(con
+ else if (stbuf.st_size > size)
+ return sshfs_truncate_shrink(path, size);
+ else
++#if FUSE_MAJOR_VERSION < 3
++ return sshfs_truncate_extend(path, size, NULL);
++#else
+ return sshfs_truncate_extend(path, size, fi);
++#endif
+ }
+ }
+
+@@ -4156,7 +4250,9 @@ int main(int argc, char *argv[])
+ char *fsname;
+ const char *sftp_server;
+ struct fuse *fuse;
++#if FUSE_MAJOR_VERSION >= 3
+ struct fuse_session *se;
++#endif
+ int i;
+
+ #ifdef __APPLE__
+@@ -4216,7 +4312,11 @@ int main(int argc, char *argv[])
+
+ if (sshfs.show_version) {
+ printf("SSHFS version %s\n", PACKAGE_VERSION);
++#if FUSE_MAJOR_VERSION < 3
++ printf("FUSE library version %d\n", fuse_version());
++#else
+ printf("FUSE library version %s\n", fuse_pkgversion());
++#endif
+ #if !defined(__CYGWIN__)
+ fuse_lowlevel_version();
+ #endif
+@@ -4225,7 +4325,11 @@ int main(int argc, char *argv[])
+
+ if (sshfs.show_help) {
+ usage(args.argv[0]);
++#if FUSE_MAJOR_VERSION < 3
++ fuse_cmdline_help();
++#else
+ fuse_lib_help(&args);
++#endif
+ exit(0);
+ } else if (!sshfs.host) {
+ fprintf(stderr, "missing host\n");
+@@ -4359,20 +4463,16 @@ int main(int argc, char *argv[])
+ sizeof(struct fuse_operations), NULL);
+ if(fuse == NULL)
+ exit(1);
++#if FUSE_MAJOR_VERSION >= 3
+ se = fuse_get_session(fuse);
+ res = fuse_set_signal_handlers(se);
+ if (res != 0) {
+ fuse_destroy(fuse);
+ exit(1);
+ }
++#endif
+
+- res = fuse_mount(fuse, sshfs.mountpoint);
+- if (res != 0) {
+- fuse_destroy(fuse);
+- exit(1);
+- }
+-
+-#if !defined(__CYGWIN__)
++#if !defined(__CYGWIN__) && FUSE_MAJOR_VERSION >= 3
+ res = fcntl(fuse_session_fd(se), F_SETFD, FD_CLOEXEC);
+ if (res == -1)
+ perror("WARNING: failed to set FD_CLOEXEC on fuse device");
+@@ -4384,29 +4484,55 @@ int main(int argc, char *argv[])
+ */
+ res = ssh_connect();
+ if (res == -1) {
+- fuse_unmount(fuse);
+ fuse_destroy(fuse);
+ exit(1);
+ }
+
++#if FUSE_MAJOR_VERSION < 3
++ if (!sshfs.foreground)
++ res = fuse_daemonize(fuse);
++#else
+ res = fuse_daemonize(sshfs.foreground);
++#endif
+ if (res == -1) {
+- fuse_unmount(fuse);
+ fuse_destroy(fuse);
+ exit(1);
+ }
+
++ /* NetBSD librefuse (actually libpuffs) requires that
++ * applications call fuse_daemonize() before calling
++ * fuse_mount(), otherwise the daemonizing parent process will
++ * deadlock. FUSE on the other hand defines no specific order
++ * of calling these two functions. pho@ thinks puffs_daemon()
++ * waiting for the completion of fuse_mount() is actually
++ * helpful and not a bug to be fixed, but it should at least
++ * not deadlock. That is, fuse_daemonize() should immediately
++ * kill the parent if the filesystem is already mounted. Until
++ * the change is made, we reorder function calls here. */
++ res = fuse_mount(fuse, sshfs.mountpoint);
++ if (res != 0) {
++ fuse_destroy(fuse);
++ exit(1);
++ }
++
++ sshfs_initialized = 1;
++#if FUSE_MAJOR_VERSION >= 3
+ if (sshfs.singlethread)
+ res = fuse_loop(fuse);
+ else
+ res = fuse_loop_mt(fuse, 0);
++#else
++ res = fuse_loop(fuse);
++#endif
+
+ if (res != 0)
+ res = 1;
+ else
+ res = 0;
+
++#if FUSE_MAJOR_VERSION >= 3
+ fuse_remove_signal_handlers(se);
++#endif
+ fuse_unmount(fuse);
+ fuse_destroy(fuse);
+
diff --git a/filesystems/fuse-sshfs/patches/patch-utils_install__helper.sh b/filesystems/fuse-sshfs/patches/patch-utils_install__helper.sh
new file mode 100644
index 00000000000..741cecdb148
--- /dev/null
+++ b/filesystems/fuse-sshfs/patches/patch-utils_install__helper.sh
@@ -0,0 +1,18 @@
+$NetBSD: patch-utils_install__helper.sh,v 1.1 2021/12/02 07:28:40 pho Exp $
+
+`ln --relative' is a Linux-only thing. Do not use it. There should be
+no reason we can't just use hard links here.
+
+--- utils/install_helper.sh.orig 2021-06-08 08:52:08.000000000 +0000
++++ utils/install_helper.sh
+@@ -12,8 +12,8 @@ prefix="${MESON_INSTALL_DESTDIR_PREFIX}"
+
+ mkdir -p "${prefix}/${sbindir}"
+
+-ln -svf --relative "${prefix}/${bindir}/sshfs" \
++ln -vf "${prefix}/${bindir}/sshfs" \
+ "${prefix}/${sbindir}/mount.sshfs"
+
+-ln -svf --relative "${prefix}/${bindir}/sshfs" \
++ln -vf "${prefix}/${bindir}/sshfs" \
+ "${prefix}/${sbindir}/mount.fuse.sshfs"