Compare commits

...

28 Commits

Author SHA1 Message Date
Nikolaus Rath 695cd8916f Released 3.5.2 2019-04-13 09:25:45 +01:00
mssalvatore 7364b73e80 Gracefully handle multiple spaces in ssh_command option (#169)
When using the "ssh_command" option, commands with multiple spaces in a
row will not be properly parsed. Example:

Properly parsed:
    ssh_command = "ssh -o IdentityFile=~/.ssh/id_rsa"

Improperly parsed:
    ssh_command = "ssh -o      IdentityFile=~/.ssh/id_rsa"

This commit changes the ssh_command parsing logic so that both of the
above examples are considered valid and properly handled. 

Fixes: #114.
2019-04-08 21:50:10 +01:00
DrDaveD 1dbc89f959 allow /dev/fd/N as a mountpoint (#166) 2019-03-31 04:57:21 -04:00
Nikolaus Rath d299217510 Travis CI: Use Xenial instead of Trusty. 2019-02-27 21:27:39 +00:00
mssalvatore fda6c8f862 Update clean_req() to match the definition of GHRFunc (#160)
The current definition of the clean_req() function produces a compiler
warning as it expects 2 parameters but GHRFunc expects 3. This commit
resolves issue #157.
2019-02-25 21:00:53 +00:00
Clayton G. Hobbs 6b10b3c8c0 Also remap GID under non-MacOS
The manpage says that -o idmap=user maps the UID and GID, but it
apparently only mapped the UID.  The code was in place to map the GID as
well, but it was hidden behind #ifdef __APPLE__.  This commit removes
those #ifdefs, and in a couple of cases the code inside an #else, to
make the option behave as documented.
2019-01-04 19:39:47 +00:00
Nikolaus Rath d3c6c338ae Bump meson dependency
build_by_default arg in custom_target needs 0.40.0
2018-12-22 14:34:39 +00:00
Nikolaus Rath 93c052a3cd Released 3.5.1 2018-12-22 14:33:52 +00:00
Nikolaus Rath 76d11fa6f4 Use fusermount3 instead of fusermount
We're using libfuse3, so we should be using its fusermount command.
2018-12-22 14:31:52 +00:00
Nikolaus Rath 9ced6ca681 Kill filesystem process on test cleanup. 2018-12-22 14:31:52 +00:00
Tim Harder de11ec091e meson: fallback to looking for rst2man.py
As that's what upstream docutils installs by default.
2018-12-22 14:22:24 +00:00
smheidrich 37b79d06f8 Docs: add section on interrupted connections
Also rename "SSHFS hangs" section to something more specific to
differentiate it from this new section.

Cf. issues #77 and #3.
2018-12-22 14:22:01 +00:00
S. D. Cloudt 2f1147c7d6 Added "BindInterface" as valid "-o" option. 2018-12-22 14:20:54 +00:00
Nikolaus Rath b5d1484314 Released 3.5.0 2018-08-28 14:58:39 +01:00
Bill Zissimopoulos d0c5fa3ed6 Add AppVeyor CI for Cygwin 2018-08-11 10:33:42 +01:00
Bill Zissimopoulos eac420791c Port SSHFS to Cygwin 2018-08-01 14:39:23 +01:00
Quentin Rameau 6480b66bd6 Fix error return value from rename()
Fuse operations expect negated errno values.
2018-07-25 11:03:01 +01:00
Nikolaus Rath 30a2668b99 Released 3.4.0 2018-06-29 09:34:57 +01:00
Samuel Murray 4ed15c4c04 Update README.rst
OS-X is now called macOS
2018-06-28 20:08:50 +01:00
Rian Hunter fc7a57f0dc Correct workaround condition for not using handle in sshfs_getattr (#127)
In libfuse<3, when `fstat_workaround` was true, that meant to always
use the `path` argument to resolve fgetattr instead of the supplied
handle.  Before this change, the logic was interpreting
`fstat_workaround` to not use the `path` argument when it was
true. This change reverts to the libfuse<3 behavior.
2018-06-20 20:31:53 +01:00
Daniel Lublin f0452119e0 Make utimens(NULL) work correctly 2018-06-18 19:12:38 +01:00
Josh Triplett fb174704dd Add workaround to always pass a 0 mode when creating a file (#128)
Add workaround to always pass a 0 mode when creating a file

This works around servers that produce an error for any non-zero mode.
2018-06-09 11:28:55 +01:00
Nikolaus Rath 39663c8288 Released 3.3.2 2018-04-29 18:06:03 +01:00
Nikolaus Rath 646a3c417b Fix Travis build environment.
Newest Meson requires Python 3.5.which isn't available in Trusty.
Pip version pin no longer necessary.
2018-03-31 13:26:15 +01:00
G.raud Meyer 303126bad9 New workaround renamexdev to enable moving files across remote filesystems
sshfs.rst: update the documentation.
2018-03-28 19:48:02 +01:00
Nikolaus Rath f0a0cc2b7e Fix rst markup 2017-11-27 19:55:09 +00:00
Brandon Carter 2c7c667576 change make directory command in readme 2017-11-17 18:17:41 +00:00
Nikolaus Rath 1846b685c4 Updated professional support information. 2017-11-13 20:09:54 +00:00
12 changed files with 281 additions and 73 deletions
+19
View File
@@ -0,0 +1,19 @@
version: '{build}'
install:
# install WinFsp
- appveyor DownloadFile https://github.com/billziss-gh/winfsp/releases/download/v1.4B2/winfsp-1.4.18211.msi
- for %%f in ("winfsp-*.msi") do start /wait msiexec /i %%f /qn INSTALLLEVEL=1000
# install FUSE for Cygwin (64-bit and 32-bit)
- C:\cygwin64\bin\env.exe -i PATH=/bin bash "%ProgramFiles(x86)%\WinFsp\opt\cygfuse\install.sh"
- C:\cygwin\bin\env.exe -i PATH=/bin bash "%ProgramFiles(x86)%\WinFsp\opt\cygfuse\install.sh"
# install additional Cygwin packages (64-bit and 32-bit)
- C:\cygwin64\setup-x86_64.exe -qnNdO -R C:\cygwin64 -s http://cygwin.mirror.constant.com -l C:\cygwin64\var\cache\setup -P libglib2.0-devel -P meson
- C:\cygwin\setup-x86.exe -qnNdO -R C:\cygwin -s http://cygwin.mirror.constant.com -l C:\cygwin\var\cache\setup -P libglib2.0-devel -P meson
build_script:
- C:\cygwin64\bin\env.exe -i PATH=/bin bash test\appveyor-build.sh
- C:\cygwin\bin\env.exe -i PATH=/bin bash test\appveyor-build.sh
+3 -3
View File
@@ -1,5 +1,5 @@
sudo: required
dist: trusty
dist: xenial
language:
- c
@@ -14,8 +14,8 @@ addons:
- gcc-6
- python-docutils
- python3-pip
before_install:
- sudo -H python3 -m pip install pip==8.1.1
- python3-setuptools
- ninja-build
install: test/travis-install.sh
script: test/travis-build.sh
+13
View File
@@ -19,21 +19,34 @@ Anatol Pomozov <anatol.pomozov@gmail.com>
Benjamin Fleischer <fleiben@gmail.com>
Berserker <berserker.troll@yandex.com>
Bill Zissimopoulos <billziss@navimatics.com>
Brandon Carter <b-carter@users.noreply.github.com>
Chris Wolfe <cwolfe@chromium.org>
Clayton G. Hobbs <clay@lakeserv.net>
Daniel Lublin <daniel@lublin.se>
DrDaveD <2129743+DrDaveD@users.noreply.github.com>
gala <gala132@users.noreply.github.com>
George Vlahavas <vlahavas@gmail.com>
G.raud Meyer <graud@gmx.com>
harrim4n <git@harrim4n.com>
Jakub Jelen <jjelen@redhat.com>
Josh Triplett <josh@joshtriplett.org>
Julio Merino <jmmv@google.com>
Julio Merino <jmmv@meroh.net>
Mike Kelly <mike@pair.com>
Miklos Szeredi <miklos@szeredi.hu>
Miklos Szeredi <mszeredi@suse.cz>
mssalvatore <mike.s.salvatore@gmail.com>
Nikolaus Rath <Nikolaus@rath.org>
Percy Jahn <email@percyjahn.de>
Qais Patankar <qaisjp@gmail.com>
Quentin Rameau <quinq@fifth.space>
Reid Wagner <wagnerreid@gmail.com>
Rian Hunter <rian@alum.mit.edu>
Rian Hunter <rianhunter@users.noreply.github.com>
Samuel Murray <samuel.murray@outlook.com>
S. D. Cloudt <s.d.cloudt@student.tue.nl>
smheidrich <smheidrich@weltenfunktion.de>
Tim Harder <radhermit@gmail.com>
Timo Savola <timo.savola@iki.fi>
tpoindessous <thomas@poindessous.com>
Zoltan Kuscsik <zoltan.kuscsik@linaro.org>
+32
View File
@@ -1,3 +1,35 @@
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)
--------------------------
+7 -5
View File
@@ -32,7 +32,7 @@ To unmount the filesystem::
fusermount -u mountpoint
On BSD and OS-X, to unmount the filesystem::
On BSD and macOS, to unmount the filesystem::
umount mountpoint
@@ -42,7 +42,7 @@ Installation
First, download the latest SSHFS release from
https://github.com/libfuse/sshfs/releases. On Linux and BSD, you will
also need to install libfuse_ 3.1.0 or newer. On OS-X, you need
also need to install libfuse_ 3.1.0 or newer. On macOS, you need
OSXFUSE_ instead. Finally, you need the Glib_ library with development
headers (which should be available from your operating system's
package manager).
@@ -51,7 +51,7 @@ To build and install, we recommend to use Meson_ (version 0.38 or
newer) and Ninja_. After extracting the sshfs tarball, create a
(temporary) build directory and run Meson::
$ md build; cd build
$ mkdir build; cd build
$ meson ..
Normally, the default build options will work fine. If you
@@ -85,8 +85,10 @@ https://lists.sourceforge.net/lists/listinfo/fuse-sshfs).
Please report any bugs on the GitHub issue tracker at
https://github.com/libfuse/libfuse/issues.
Professional Support
--------------------
Professional support is available. Please contact Nikolaus Rath
<Nikolaus@rath.org> for details.
Professional support is offered via `Rath Consulting`_.
.. _`Rath Consulting`: http://www.rath-consulting.biz
+3 -3
View File
@@ -1,5 +1,5 @@
project('sshfs', 'c', version: '3.3.1',
meson_version: '>= 0.38',
project('sshfs', 'c', version: '3.5.2',
meson_version: '>= 0.40',
default_options: [ 'buildtype=debugoptimized' ])
add_global_arguments('-D_REENTRANT', '-DHAVE_CONFIG_H',
@@ -25,7 +25,7 @@ if not cc.compiles(code, args: [ '-O0', '-Werror=unused-result' ])
endif
rst2man = find_program('rst2man', required: false)
rst2man = find_program('rst2man', 'rst2man.py', required: false)
cfg = configuration_data()
+127 -50
View File
@@ -12,7 +12,7 @@
#include <fuse.h>
#include <fuse_opt.h>
#if !defined(__CYGWIN__)
#include <fuse_lowlevel.h>
# include <fuse_lowlevel.h>
#endif
#ifdef __APPLE__
# include <fuse_darwin.h>
@@ -214,10 +214,12 @@ struct sshfs {
struct fuse_args ssh_args;
char *workarounds;
int rename_workaround;
int renamexdev_workaround;
int truncate_workaround;
int buflimit_workaround;
int unrel_append;
int fstat_workaround;
int createmode_workaround;
int transform_symlinks;
int follow_symlinks;
int no_check_root;
@@ -262,10 +264,8 @@ 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;
@@ -298,6 +298,7 @@ static const char *ssh_opts[] = {
"AddressFamily",
"BatchMode",
"BindAddress",
"BindInterface",
"CertificateFile",
"ChallengeResponseAuthentication",
"CheckHostIP",
@@ -446,12 +447,16 @@ static struct fuse_opt workaround_opts[] = {
SSHFS_OPT("none", fstat_workaround, 0),
SSHFS_OPT("rename", rename_workaround, 1),
SSHFS_OPT("norename", rename_workaround, 0),
SSHFS_OPT("renamexdev", renamexdev_workaround, 1),
SSHFS_OPT("norenamexdev", renamexdev_workaround, 0),
SSHFS_OPT("truncate", truncate_workaround, 1),
SSHFS_OPT("notruncate", truncate_workaround, 0),
SSHFS_OPT("buflimit", buflimit_workaround, 1),
SSHFS_OPT("nobuflimit", buflimit_workaround, 0),
SSHFS_OPT("fstat", fstat_workaround, 1),
SSHFS_OPT("nofstat", fstat_workaround, 0),
SSHFS_OPT("createmode", createmode_workaround, 1),
SSHFS_OPT("nocreatemode", createmode_workaround, 0),
FUSE_OPT_END
};
@@ -782,17 +787,12 @@ 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;
@@ -1289,9 +1289,10 @@ static void chunk_put_locked(struct read_chunk *chunk)
pthread_mutex_unlock(&sshfs.lock);
}
static int clean_req(void *key_, struct request *req)
static int clean_req(void *key_, struct request *req, gpointer user_data_)
{
(void) key_;
(void) user_data_;
req->error = -EIO;
if (req->want_reply)
@@ -1593,10 +1594,8 @@ 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);
@@ -2310,7 +2309,7 @@ static int sshfs_rename(const char *from, const char *to, unsigned int flags)
int err;
if(flags != 0)
return EINVAL;
return -EINVAL;
if (sshfs.ext_posix_rename)
err = sshfs_ext_posix_rename(from, to);
@@ -2333,6 +2332,8 @@ static int sshfs_rename(const char *from, const char *to, unsigned int flags)
}
}
}
if (err == -EPERM && sshfs.renamexdev_workaround)
err = -EXDEV;
return err;
}
@@ -2415,17 +2416,12 @@ static int sshfs_chown(const char *path, uid_t uid, gid_t gid,
return -EIO;
}
#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;
@@ -2465,6 +2461,14 @@ static int sshfs_utimens(const char *path, const struct timespec tv[2],
int err;
struct buffer buf;
struct sshfs_file *sf = NULL;
time_t asec = tv[0].tv_sec, msec = tv[1].tv_sec;
struct timeval now;
gettimeofday(&now, NULL);
if (asec == 0)
asec = now.tv_sec;
if (msec == 0)
msec = now.tv_sec;
if (fi != NULL) {
sf = get_sshfs_file(fi);
@@ -2478,8 +2482,8 @@ static int sshfs_utimens(const char *path, const struct timespec tv[2],
else
buf_add_buf(&buf, &sf->handle);
buf_add_uint32(&buf, SSH_FILEXFER_ATTR_ACMODTIME);
buf_add_uint32(&buf, tv[0].tv_sec);
buf_add_uint32(&buf, tv[1].tv_sec);
buf_add_uint32(&buf, asec);
buf_add_uint32(&buf, msec);
err = sftp_request(sf == NULL ? SSH_FXP_SETSTAT : SSH_FXP_FSETSTAT,
&buf, SSH_FXP_STATUS, NULL);
@@ -3095,6 +3099,9 @@ static int sshfs_statfs(const char *path, struct statvfs *buf)
static int sshfs_create(const char *path, mode_t mode,
struct fuse_file_info *fi)
{
if (sshfs.createmode_workaround)
mode = 0;
return sshfs_open_common(path, mode, fi);
}
@@ -3139,7 +3146,7 @@ static int sshfs_getattr(const char *path, struct stat *stbuf,
struct buffer outbuf;
struct sshfs_file *sf = NULL;
if (fi != NULL || sshfs.fstat_workaround) {
if (fi != NULL && !sshfs.fstat_workaround) {
sf = get_sshfs_file(fi);
if (!sshfs_file_is_conn(sf))
return -EIO;
@@ -3365,9 +3372,11 @@ static void usage(const char *progname)
" -o workaround=LIST colon separated list of workarounds\n"
" none no workarounds enabled\n"
" [no]rename fix renaming to existing file (default: off)\n"
" [no]renamexdev fix moving across filesystems (default: off)\n"
" [no]truncate fix truncate for old servers (default: off)\n"
" [no]buflimit fix buffer fillup bug in server (default: on)\n"
" [no]fstat always use stat() instead of fstat() (default: off)\n"
" [no]createmode always pass mode 0 to create (default: off)\n"
" -o idmap=TYPE user/group ID mapping (default: " IDMAP_DEFAULT ")\n"
" none no translation of the ID space\n"
" user only translate UID/GID of connecting user\n"
@@ -3431,7 +3440,51 @@ static int sshfs_opt_proc(void *data, const char *arg, int key,
return 0;
}
else if (!sshfs.mountpoint) {
sshfs.mountpoint = realpath(arg, NULL);
#if defined(__CYGWIN__)
/*
* On FUSE for Cygwin the mountpoint may be a drive or directory.
* Furthermore the mountpoint must NOT exist prior to mounting.
* So we cannot use realpath(3).
*/
if ((('A' <= arg[0] && arg[0] <= 'Z') || ('a' <= arg[0] && arg[0] <= 'z'))
&& ':' == arg[1] && '\0' == arg[2]) {
/* drive: make a copy */
sshfs.mountpoint = strdup(arg);
} else {
/* path: split into dirname, basename and check dirname */
char *dir;
const char *base;
const char *slash = strrchr(arg, '/');
if (slash) {
char *tmp = strndup(arg, slash == arg ? 1 : slash - arg);
dir = tmp ? realpath(tmp, NULL) : 0;
base = slash + 1;
free(tmp);
} else {
dir = realpath(".", NULL);
base = arg;
}
if (dir) {
slash = '/' == dir[0] && '\0' == dir[1] ? "" : "/";
asprintf(&sshfs.mountpoint, "%s%s%s", dir, slash, base);
free(dir);
}
}
#else
int fd, len;
if (sscanf(arg, "/dev/fd/%u%n", &fd, &len) == 1 &&
len == strlen(arg)) {
/*
* Allow /dev/fd/N unchanged; it can be
* use for pre-mounting a generic fuse
* mountpoint to later be completely
* unprivileged with libfuse >= 3.3.0.
*/
sshfs.mountpoint = arg;
} else {
sshfs.mountpoint = realpath(arg, NULL);
}
#endif
if (!sshfs.mountpoint) {
fprintf(stderr, "sshfs: bad mount point `%s': %s\n",
arg, strerror(errno));
@@ -3543,40 +3596,60 @@ static int read_password(void)
return 0;
}
// Behaves similarly to strtok(), but allows for the ' ' delimiter to be escaped
// by '\ '.
static char *tokenize_on_space(char *str)
{
static char *pos = NULL;
char *start = NULL;
if (str)
pos = str;
if (!pos)
return NULL;
// trim any leading spaces
while (*pos == ' ')
pos++;
start = pos;
while (pos && *pos != '\0') {
// break on space, but not on '\ '
if (*pos == ' ' && *(pos - 1) != '\\') {
break;
}
pos++;
}
if (*pos == '\0') {
pos = NULL;
}
else {
*pos = '\0';
pos++;
}
return start;
}
static void set_ssh_command(void)
{
char *s;
char *d;
char *token = NULL;
int i = 0;
int end = 0;
d = sshfs.ssh_command;
s = sshfs.ssh_command;
while (!end) {
switch (*s) {
case '\0':
end = 1;
case ' ':
*d = '\0';
if (i == 0) {
replace_arg(&sshfs.ssh_args.argv[0],
sshfs.ssh_command);
} else {
if (fuse_opt_insert_arg(&sshfs.ssh_args, i,
sshfs.ssh_command) == -1)
_exit(1);
}
i++;
d = sshfs.ssh_command;
break;
case '\\':
if (s[1])
s++;
default:
*d++ = *s;
token = tokenize_on_space(sshfs.ssh_command);
while (token != NULL) {
if (i == 0) {
replace_arg(&sshfs.ssh_args.argv[0], token);
} else {
if (fuse_opt_insert_arg(&sshfs.ssh_args, i, token) == -1)
_exit(1);
}
s++;
i++;
token = tokenize_on_space(NULL);
}
}
@@ -3851,8 +3924,10 @@ int main(int argc, char *argv[])
#else
sshfs.rename_workaround = 0;
#endif
sshfs.renamexdev_workaround = 0;
sshfs.truncate_workaround = 0;
sshfs.buflimit_workaround = 1;
sshfs.createmode_workaround = 0;
sshfs.ssh_ver = 2;
sshfs.progname = argv[0];
sshfs.rfd = -1;
@@ -3889,7 +3964,9 @@ int main(int argc, char *argv[])
if (sshfs.show_version) {
printf("SSHFS version %s\n", PACKAGE_VERSION);
printf("FUSE library version %s\n", fuse_pkgversion());
#if !defined(__CYGWIN__)
fuse_lowlevel_version();
#endif
exit(0);
}
+45 -2
View File
@@ -107,12 +107,16 @@ Options
:rename: Emulate overwriting an existing file by deleting and
renaming.
:renamexdev: Make rename fail with EXDEV instead of the default EPERM
to allow moving files across remote filesystems.
:truncate: Work around servers that don't support truncate by
coping the whole file, truncating it locally, and sending it
back.
:fstat: Work around broken servers that don't support *fstat()* by
using *stat* instead.
:buflimit: Work around OpenSSH "buffer fillup" bug.
:createmode: Work around broken servers that produce an error when passing a
non-zero mode to create, by always passing a mode of 0.
-o idmap=TYPE
How to map remote UID/GIDs to local values. Possible values are:
@@ -228,8 +232,19 @@ removed it, but before SSHFS had the time to rename the old file. In
this case, the rename will still fail.
SSHFS hangs
~~~~~~~~~~~
Permission denied when moving files across remote filesystems
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Most SFTP servers return only a generic "failure" when failing to rename
across filesystem boundaries (EXDEV). sshfs normally converts this generic
failure to a permission denied error (EPERM). If the option ``-o
workaround=renamexdev`` is given, generic failures will be considered EXDEV
errors which will make programs like `mv(1)` attempt to actually move the
file after the failed rename.
SSHFS hangs for no apparent reason
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In some cases, attempts to access the SSHFS mountpoint may freeze if
no filesystem activity has occured for some time. This is typically
@@ -238,6 +253,34 @@ without SSHFS being informed about that. As a workaround, you can try
to mount with ``-o ServerAliveInterval=15``. This will force the SSH
connection to stay alive even if you have no activity.
SSHFS hangs after the connection was interrupted
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
By default, network operations in SSHFS run without timeouts, mirroring the
default behavior of SSH itself. As a consequence, if the connection to the
remote host is interrupted (e.g. because a network cable was removed),
operations on files or directories under the mountpoint will block until the
connection is either restored or closed altogether (e.g. manually).
Applications that try to access such files or directories will generally appear
to "freeze" when this happens.
If it is acceptable to discard data being read or written, a quick workaround
is to kill the responsible ``sshfs`` process, which will make any blocking
operations on the mounted filesystem error out and thereby "unfreeze" the
relevant applications. Note that force unmounting with ``fusermount -zu``, on
the other hand, does not help in this case and will leave read/write operations
in the blocking state.
For a more automatic solution, one can use the ``-o ServerAliveInterval=15``
option mentioned above, which will drop the connection after not receiving a
response for 3 * 15 = 45 seconds from the remote host. By also supplying ``-o
reconnect``, one can ensure that the connection is re-established as soon as
possible afterwards. As before, this will naturally lead to loss of data that
was in the process of being read or written at the time when the connection was
interrupted.
Mounting from /etc/fstab
========================
+7
View File
@@ -0,0 +1,7 @@
#!/bin/bash
machine=$(uname -m)
mkdir build-$machine
cd build-$machine
meson ..
ninja
+14 -1
View File
@@ -102,13 +102,14 @@ def test_sshfs(tmpdir, debug, cache_timeout, sync_rd, capfd):
# SSHFS only supports one second resolution when setting
# file timestamps.
tst_utimens(mnt_dir, tol=1)
tst_utimens_now(mnt_dir)
tst_link(mnt_dir, cache_timeout)
tst_truncate_path(mnt_dir)
tst_truncate_fd(mnt_dir)
tst_open_unlink(mnt_dir)
except:
cleanup(mnt_dir)
cleanup(mount_process, mnt_dir)
raise
else:
umount(mount_process, mnt_dir)
@@ -403,6 +404,18 @@ def tst_utimens(mnt_dir, tol=0):
assert abs(fstat.st_atime_ns - atime_ns) < tol*1e9
assert abs(fstat.st_mtime_ns - mtime_ns) < tol*1e9
def tst_utimens_now(mnt_dir):
fullname = pjoin(mnt_dir, name_generator())
fd = os.open(fullname, os.O_CREAT | os.O_RDWR)
os.close(fd)
os.utime(fullname, None)
fstat = os.lstat(fullname)
# We should get now-timestamps
assert fstat.st_atime != 0
assert fstat.st_mtime != 0
def tst_passthrough(src_dir, mnt_dir, cache_timeout):
name = name_generator()
src_name = pjoin(src_dir, name)
+3 -7
View File
@@ -2,12 +2,8 @@
set -e
sudo python3 -m pip install pytest meson
wget https://github.com/ninja-build/ninja/releases/download/v1.7.2/ninja-linux.zip
unzip ninja-linux.zip
chmod 755 ninja
sudo chown root:root ninja
sudo mv -fv ninja /usr/local/bin
# Meson 0.45 requires Python 3.5 or newer
sudo python3 -m pip install pytest meson==0.44
valgrind --version
ninja --version
meson --version
@@ -28,7 +24,7 @@ ls -d1 /usr/local/lib/*-linux-gnu | sudo tee /etc/ld.so.conf.d/usrlocal.conf
sudo ldconfig
# Setup ssh
ssh-keygen -b 768 -t rsa -f ~/.ssh/id_rsa -P ''
ssh-keygen -b 1024 -t rsa -f ~/.ssh/id_rsa -P ''
cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
ssh -o "StrictHostKeyChecking=no" localhost echo "SSH connection succeeded"
+8 -2
View File
@@ -20,13 +20,19 @@ def wait_for_mount(mount_process, mnt_dir,
elapsed += 0.1
pytest.fail("mountpoint failed to come up")
def cleanup(mnt_dir):
def cleanup(mount_process, mnt_dir):
subprocess.call(['fusermount', '-z', '-u', mnt_dir],
stdout=subprocess.DEVNULL,
stderr=subprocess.STDOUT)
mount_process.terminate()
try:
mount_process.wait(1)
except subprocess.TimeoutExpired:
mount_process.kill()
def umount(mount_process, mnt_dir):
subprocess.check_call(['fusermount', '-z', '-u', mnt_dir ])
subprocess.check_call(['fusermount3', '-z', '-u', mnt_dir ])
assert not os.path.ismount(mnt_dir)
# Give mount process a little while to terminate. Popen.wait(timeout)