Compare commits
25 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5d64c08f69 | |||
| 586ad60414 | |||
| 0bb569557e | |||
| da3a3f5bd1 | |||
| d141ea44c1 | |||
| 6ac4046bee | |||
| 95c65a6246 | |||
| f8df458f23 | |||
| e2a4bc904e | |||
| 70acee8c4b | |||
| fc63c64602 | |||
| 1e6e067fdf | |||
| 44a56f0cac | |||
| 653de120c8 | |||
| 63300fd564 | |||
| 45710c81d7 | |||
| 161ece55a3 | |||
| db149d1d87 | |||
| 861d308a03 | |||
| 319f0dde18 | |||
| 82766d1093 | |||
| 6f6491cd13 | |||
| 03a693d295 | |||
| 55eb1f00e6 | |||
| 37b6969067 |
+2
-1
@@ -1,6 +1,5 @@
|
||||
sudo: required
|
||||
dist: trusty
|
||||
group: deprecated-2017Q2
|
||||
|
||||
language:
|
||||
- c
|
||||
@@ -13,6 +12,8 @@ addons:
|
||||
- clang
|
||||
- gcc
|
||||
- gcc-6
|
||||
before_install:
|
||||
- pip install pip==8.1.1 && pip3 install pip==8.1.1
|
||||
install: test/travis-install.sh
|
||||
script: test/travis-build.sh
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ Bill Zissimopoulos <billziss@navimatics.com>
|
||||
Chris Wolfe <cwolfe@chromium.org>
|
||||
gala <gala132@users.noreply.github.com>
|
||||
George Vlahavas <vlahavas@gmail.com>
|
||||
harrim4n <git@harrim4n.com>
|
||||
Jakub Jelen <jjelen@redhat.com>
|
||||
Julio Merino <jmmv@google.com>
|
||||
Julio Merino <jmmv@meroh.net>
|
||||
|
||||
@@ -1,3 +1,22 @@
|
||||
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)
|
||||
--------------------------
|
||||
|
||||
|
||||
@@ -6,30 +6,26 @@ SSHFS FAQ
|
||||
2. Advantage of sshfs over NFS and Samba
|
||||
3. Create the device node
|
||||
4. mv fails with "Operation not permitted"
|
||||
5. cvs fails with "cvs [status aborted]: cannot get working
|
||||
directory: No such file or directory" in a sshfs mounted directory
|
||||
6. Changes on the server are not immediately visible in the
|
||||
mounted directory.
|
||||
7. Configuring the ssh connection
|
||||
8. What are the no_readahead and sshfs_sync options for?
|
||||
9. Why does df return strange values on partitions mounted via
|
||||
5. Configuring the ssh connection
|
||||
6. What are the no_readahead and sshfs_sync options for?
|
||||
7. Why does df return strange values on partitions mounted via
|
||||
sshfs?
|
||||
10. How do I specify the remote mount point (since the example
|
||||
8. How do I specify the remote mount point (since the example
|
||||
defaults to the home directory)
|
||||
11. sshfs hangs after a while
|
||||
12. Following symlinks on the server side
|
||||
13. Making absolute symlinks work
|
||||
14. Mounting as root
|
||||
15. Exporting via NFS
|
||||
16. Automatical mounting using /etc/fstab
|
||||
17. Why does SVN (etc...) fail with permission denied?
|
||||
18. Why does SVN (etc...) fail to rename files?
|
||||
19. Is there some neat way to do it in reverse?
|
||||
20. Might it be reasonable to disallow loops?
|
||||
21. How to mount through an intermediary ssh server, eg:
|
||||
9. sshfs hangs after a while
|
||||
10. Following symlinks on the server side
|
||||
11. Making absolute symlinks work
|
||||
12. Mounting as root
|
||||
13. Exporting via NFS
|
||||
14. Automatical mounting using /etc/fstab
|
||||
15. Why does SVN (etc...) fail with permission denied?
|
||||
16. Why does SVN (etc...) fail to rename files?
|
||||
17. Is there some neat way to do it in reverse?
|
||||
18. Might it be reasonable to disallow loops?
|
||||
19. How to mount through an intermediary ssh server, eg:
|
||||
localhost -> A -> B; mount B from localhost
|
||||
22. Alternative Solution
|
||||
23. I seem to have successfully mounted a remote directory, but
|
||||
20. Alternative Solution
|
||||
21. I seem to have successfully mounted a remote directory, but
|
||||
performing an `ls -l` on the directory above the mount point shows
|
||||
the mount point's attributes as `? ? ? ? ? ?`. Nothing shows up in
|
||||
the directory either. What am I doing wrong?
|
||||
@@ -82,80 +78,63 @@ SSHFS FAQ
|
||||
|
||||
Use -o workaround=rename (requires sshfs version >= 1.3).
|
||||
|
||||
5. cvs fails with "cvs status aborted?: cannot get working directory: No such
|
||||
file or directory" in a sshfs mounted directory
|
||||
|
||||
Use the -oreaddir_ino option. Example:
|
||||
sshfs -oreaddir_ino hostname:remote_dir mount_point
|
||||
|
||||
6. Changes on the server are not immediately visible in the mounted directory.
|
||||
|
||||
By default, sshfs caches things for 20 seconds, use -o cache_timeout=N
|
||||
to change the default cache timeout (in seconds) or -o cache=no for
|
||||
disabling the cache.
|
||||
|
||||
You can also control cache timeouts for directory listing etc with
|
||||
-o cache_stat_timeout=N,
|
||||
-o cache_dir_timout=N, and
|
||||
-o cache_link_timout=N.
|
||||
|
||||
7. Configuring the ssh connection
|
||||
5. Configuring the ssh connection
|
||||
|
||||
In addition to flags like -C, -p, and -o SSHOPT...=, you may find it
|
||||
easier to edit your /.ssh/config file. You can add an entry with any
|
||||
customization you want, test it with ssh, and finally use it with
|
||||
sshfs. As a bonus, you get a short mnemonic for your configuration.
|
||||
|
||||
8. What are the no_readahead and sshfs_sync options for?
|
||||
6. What are the no_readahead and sshfs_sync options for?
|
||||
|
||||
These disable read and write optimizations respectively. They don't
|
||||
really make sense unless you're doing something special.
|
||||
|
||||
9. Why does df return strange values on partitions mounted via sshfs?
|
||||
7. Why does df return strange values on partitions mounted via sshfs?
|
||||
|
||||
Because the SFTP protocol doesn't have a statfs operation this is
|
||||
currently not possible to display proper usage on remote partition.
|
||||
|
||||
10. How do I specfy the remote mount point (since the example defaults to the
|
||||
home directory)
|
||||
8. How do I specfy the remote mount point (since the example defaults to the
|
||||
home directory)
|
||||
|
||||
The example shows:
|
||||
sshfs hostname: mountpoint
|
||||
The example shows:
|
||||
sshfs hostname: mountpoint
|
||||
|
||||
To specify a remote mount point use:
|
||||
sshfs hostname:remotemountpoint mountpoint
|
||||
To specify a remote mount point use:
|
||||
sshfs hostname:remotemountpoint mountpoint
|
||||
|
||||
This might be obvious to others, but I ended up looking up the
|
||||
interface to sftp to see if I could learn how to specify the remote
|
||||
mount point, then thought about the way that scp specifies the remote
|
||||
directory, and it worked.
|
||||
This might be obvious to others, but I ended up looking up the
|
||||
interface to sftp to see if I could learn how to specify the remote
|
||||
mount point, then thought about the way that scp specifies the remote
|
||||
directory, and it worked.
|
||||
|
||||
11. sshfs hangs after a while
|
||||
9. sshfs hangs after a while
|
||||
|
||||
Mounting works fine, I can use the files in Mountpoint as good as any
|
||||
other files on my system, but after bit of time, changing nothing on
|
||||
the remote files sshfs crashes. This means, I can not cd into the
|
||||
Mountpoint (xterm hangs, nautilus hangs... every program trying to
|
||||
access the Mountpoint gets stuck, and won't return).
|
||||
Mounting works fine, I can use the files in Mountpoint as good as any
|
||||
other files on my system, but after bit of time, changing nothing on
|
||||
the remote files sshfs crashes. This means, I can not cd into the
|
||||
Mountpoint (xterm hangs, nautilus hangs... every program trying to
|
||||
access the Mountpoint gets stuck, and won't return).
|
||||
|
||||
Solution: add
|
||||
ServerAliveInterval 15
|
||||
Solution: add
|
||||
ServerAliveInterval 15
|
||||
|
||||
in your .ssh/config (or use -o ServerAliveInterval=15 on the sshfs
|
||||
command line but I did not test that solution). This will force the
|
||||
ssh connection to stay alive even if you have no activity.
|
||||
in your .ssh/config (or use -o ServerAliveInterval=15 on the sshfs
|
||||
command line but I did not test that solution). This will force the
|
||||
ssh connection to stay alive even if you have no activity.
|
||||
|
||||
12. Following symlinks on the server side
|
||||
10. Following symlinks on the server side
|
||||
|
||||
The -o follow_symlinks option will enable this.
|
||||
|
||||
13. Making absolute symlinks work
|
||||
11. Making absolute symlinks work
|
||||
|
||||
Use the -o transform_symlinks option, which will transform absolute
|
||||
symlinks (ones which point somewhere inside the mount) into relative
|
||||
ones.
|
||||
|
||||
14. Mounting as root
|
||||
12. Mounting as root
|
||||
|
||||
Generally it's not possible to use an sshfs mount as a "real"
|
||||
filesystem shared between multiple users. Some of this functionality
|
||||
@@ -163,11 +142,11 @@ SSHFS FAQ
|
||||
options, but files will not be created with the correct ownership,
|
||||
etc...
|
||||
|
||||
15. Exporting via NFS
|
||||
13. Exporting via NFS
|
||||
|
||||
Use the userspace NFS daemon http://sourceforge.net/projects/unfs
|
||||
|
||||
16. Automatical mounting using /etc/fstab
|
||||
14. Automatical mounting using /etc/fstab
|
||||
|
||||
A line in /etc/fstab has the following format:
|
||||
sshfs#USERNAME@REMOTE_HOST:REMOTE_PATH MOUNT_POINT fuse SSHFS_OPTIONS 0 0
|
||||
@@ -176,7 +155,7 @@ SSHFS FAQ
|
||||
sshfs#guest@guest.login.com:data /mnt/guest fuse \
|
||||
uid=1003,gid=100,umask=0,allow_other 0 0
|
||||
|
||||
17. Why does SVN (etc...) fail with permission denied?
|
||||
15. Why does SVN (etc...) fail with permission denied?
|
||||
|
||||
This is a bug that happens when an application creates a read-only
|
||||
file opened for writing (e.g. open("foo", O_WRONLY|O_CREAT, 0444))
|
||||
@@ -184,7 +163,7 @@ SSHFS FAQ
|
||||
It has been fixed in sshfs version 1.3, but also requires FUSE version
|
||||
>=2.5.X and Linux kernel version >=2.6.15.
|
||||
|
||||
18. Why does SVN (etc...) fail to rename files?
|
||||
16. Why does SVN (etc...) fail to rename files?
|
||||
|
||||
$ svn co svn://anonsvn.kde.org/home/kde/trunk/KDE/kdelibs
|
||||
svn: Can't move 'kdelibs/.svn/tmp/entries' to 'kdelibs/.svn/entries':
|
||||
@@ -200,7 +179,7 @@ SSHFS FAQ
|
||||
semantics, but it cannot guarantee atomicity. In most of the cases
|
||||
this doesn't matter, and things will work fine with this option.
|
||||
|
||||
19. Is there some neat way to do it in reverse?
|
||||
17. Is there some neat way to do it in reverse?
|
||||
|
||||
You want to mount a USB thumb drive onto a file server that is rather
|
||||
remote.
|
||||
@@ -214,13 +193,13 @@ SSHFS FAQ
|
||||
(Now, is there is there a smarter way that does not involve port
|
||||
opening login permissions in an undesireable direction?)
|
||||
|
||||
20. Might it be reasonable to disallow loops?
|
||||
18. Might it be reasonable to disallow loops?
|
||||
|
||||
sshfs localhost:/mnt /mnt
|
||||
|
||||
This seems to produce undesirable results. --JoshuaRodman
|
||||
|
||||
21. How to mount through an intermediary ssh server, eg: localhost -> A -> B;
|
||||
19. How to mount through an intermediary ssh server, eg: localhost -> A -> B;
|
||||
mount B from localhost
|
||||
|
||||
Start by mounting the folder you need that is on "a" to a folder on
|
||||
@@ -230,7 +209,7 @@ SSHFS FAQ
|
||||
A mounts B:/home/x on /mnt/Bx
|
||||
localhost mounts A:/mnt/Bx on ~/mydir
|
||||
|
||||
22. Alternative Solution:
|
||||
20. Alternative Solution:
|
||||
|
||||
1) Create a shell script to wrap the tunneling of one ssh command over
|
||||
another,
|
||||
@@ -244,7 +223,7 @@ SSHFS FAQ
|
||||
normal but using this script as the ssh command.
|
||||
$ sshfs -o ssh_command='Atunnel' B: ~/mydir
|
||||
|
||||
23. I seem to have successfully mounted a remote directory, but performing an
|
||||
21. I seem to have successfully mounted a remote directory, but performing an
|
||||
`ls -l` on the directory above the mount point shows the mount point's
|
||||
attributes as `? ? ? ? ? ?`. Nothing shows up in the directory either. What
|
||||
am I doing wrong?
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@ sshfs_CFLAGS = $(SSHFS_CFLAGS)
|
||||
sshfs_CPPFLAGS = -D_REENTRANT -DFUSE_USE_VERSION=31 -DLIBDIR=\"$(libdir)\" \
|
||||
-DIDMAP_DEFAULT="\"$(IDMAP_DEFAULT)\""
|
||||
|
||||
EXTRA_DIST = sshfs.1.in meson.build
|
||||
EXTRA_DIST = sshfs.1.in meson.build ChangeLog.rst
|
||||
CLEANFILES = sshfs.1 sshfs.1.tmp
|
||||
|
||||
dist_man_MANS = sshfs.1
|
||||
|
||||
+10
@@ -116,6 +116,16 @@ individual files when seen through an SSHFS mount, i.e. they will
|
||||
appear to have different inodes and an *st_nlink* value of 1.
|
||||
|
||||
|
||||
O_APPEND
|
||||
~~~~~~~~
|
||||
|
||||
When writeback caching is enabled, SSHFS cannot reliably support the
|
||||
``O_APPEND`` open flag and thus signals an error on open. To enable
|
||||
support for unreliable ``O_APPEND`` (which may overwrite data if the
|
||||
file changes on the server at a bad time), mount the file system with
|
||||
``-o unreliable_append``.
|
||||
|
||||
|
||||
Getting Help
|
||||
------------
|
||||
|
||||
|
||||
@@ -586,6 +586,19 @@ static const struct fuse_opt cache_opts[] = {
|
||||
clean_interval_secs), 0 },
|
||||
{ "dcache_min_clean_interval=%u", offsetof(struct cache,
|
||||
min_clean_interval_secs), 0 },
|
||||
|
||||
/* For backwards compatibility */
|
||||
{ "cache_timeout=%u", offsetof(struct cache, stat_timeout_secs), 0 },
|
||||
{ "cache_timeout=%u", offsetof(struct cache, dir_timeout_secs), 0 },
|
||||
{ "cache_timeout=%u", offsetof(struct cache, link_timeout_secs), 0 },
|
||||
{ "cache_stat_timeout=%u", offsetof(struct cache, stat_timeout_secs), 0 },
|
||||
{ "cache_dir_timeout=%u", offsetof(struct cache, dir_timeout_secs), 0 },
|
||||
{ "cache_link_timeout=%u", offsetof(struct cache, link_timeout_secs), 0 },
|
||||
{ "cache_max_size=%u", offsetof(struct cache, max_size), 0 },
|
||||
{ "cache_clean_interval=%u", offsetof(struct cache,
|
||||
clean_interval_secs), 0 },
|
||||
{ "cache_min_clean_interval=%u", offsetof(struct cache,
|
||||
min_clean_interval_secs), 0 },
|
||||
FUSE_OPT_END
|
||||
};
|
||||
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
AC_INIT(sshfs, 3.0.0)
|
||||
AC_INIT(sshfs, 3.2.0)
|
||||
AC_CANONICAL_TARGET
|
||||
AM_INIT_AUTOMAKE([foreign subdir-objects])
|
||||
AM_CONFIG_HEADER(config.h)
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
project('sshfs', 'c', version: '3.0.0',
|
||||
project('sshfs', 'c', version: '3.1.0',
|
||||
meson_version: '>= 0.38',
|
||||
default_options: [ 'buildtype=plain' ])
|
||||
|
||||
|
||||
-45
@@ -64,15 +64,6 @@ synchronous readdir
|
||||
\fB\-o\fR sshfs_debug
|
||||
print some debugging information
|
||||
.TP
|
||||
\fB\-o\fR cache=BOOL
|
||||
enable caching {yes,no} (default: yes)
|
||||
.TP
|
||||
\fB\-o\fR cache_timeout=N
|
||||
sets timeout for caches in seconds (default: 20)
|
||||
.TP
|
||||
\fB\-o\fR cache_X_timeout=N
|
||||
sets timeout for {stat,dir,link} cache
|
||||
.TP
|
||||
\fB\-o\fR workaround=LIST
|
||||
colon separated list of workarounds
|
||||
.RS 8
|
||||
@@ -80,9 +71,6 @@ colon separated list of workarounds
|
||||
none
|
||||
no workarounds enabled
|
||||
.TP
|
||||
all
|
||||
all workarounds enabled
|
||||
.TP
|
||||
[no]rename
|
||||
fix renaming to existing file (default: off)
|
||||
.TP
|
||||
@@ -180,9 +168,6 @@ allow access to other users
|
||||
.TP
|
||||
\fB\-o\fR allow_root
|
||||
allow access to root
|
||||
.TP
|
||||
\fB\-o\fR nonempty
|
||||
allow mounts over non\-empty file/dir
|
||||
.HP
|
||||
\fB\-o\fR default_permissions
|
||||
enable permission checking by kernel
|
||||
@@ -193,24 +178,9 @@ set filesystem name
|
||||
\fB\-o\fR subtype=NAME
|
||||
set filesystem type
|
||||
.TP
|
||||
\fB\-o\fR large_read
|
||||
issue large read requests (2.4 only)
|
||||
.TP
|
||||
\fB\-o\fR max_read=N
|
||||
set maximum size of read requests
|
||||
.TP
|
||||
\fB\-o\fR hard_remove
|
||||
immediate removal (don't hide files)
|
||||
.TP
|
||||
\fB\-o\fR use_ino
|
||||
let filesystem set inode numbers
|
||||
.TP
|
||||
\fB\-o\fR readdir_ino
|
||||
try to fill in d_ino in readdir
|
||||
.TP
|
||||
\fB\-o\fR direct_io
|
||||
use direct I/O
|
||||
.TP
|
||||
\fB\-o\fR kernel_cache
|
||||
cache files in kernel
|
||||
.TP
|
||||
@@ -238,26 +208,11 @@ cache timeout for attributes (1.0s)
|
||||
\fB\-o\fR ac_attr_timeout=T
|
||||
auto cache timeout for attributes (attr_timeout)
|
||||
.TP
|
||||
\fB\-o\fR intr
|
||||
allow requests to be interrupted
|
||||
.TP
|
||||
\fB\-o\fR intr_signal=NUM
|
||||
signal to send on interrupt (10)
|
||||
.TP
|
||||
\fB\-o\fR modules=M1[:M2...]
|
||||
names of modules to push onto filesystem stack
|
||||
.TP
|
||||
\fB\-o\fR max_write=N
|
||||
set maximum size of write requests
|
||||
.TP
|
||||
\fB\-o\fR max_readahead=N
|
||||
set maximum readahead
|
||||
.TP
|
||||
\fB\-o\fR async_read
|
||||
perform reads asynchronously (default)
|
||||
.TP
|
||||
\fB\-o\fR sync_read
|
||||
perform reads synchronously
|
||||
.SS "Module options:"
|
||||
.TP
|
||||
[subdir]
|
||||
|
||||
@@ -216,6 +216,7 @@ struct sshfs {
|
||||
int rename_workaround;
|
||||
int truncate_workaround;
|
||||
int buflimit_workaround;
|
||||
int unrel_append;
|
||||
int fstat_workaround;
|
||||
int transform_symlinks;
|
||||
int follow_symlinks;
|
||||
@@ -279,7 +280,6 @@ struct sshfs {
|
||||
int ext_statvfs;
|
||||
int ext_hardlink;
|
||||
int ext_fsync;
|
||||
mode_t mnt_mode;
|
||||
struct fuse_operations *op;
|
||||
|
||||
/* statistics */
|
||||
@@ -410,6 +410,7 @@ static struct fuse_opt sshfs_opts[] = {
|
||||
SSHFS_OPT("dir_cache=no", dir_cache, 0),
|
||||
SSHFS_OPT("writeback_cache=yes", writeback_cache, 1),
|
||||
SSHFS_OPT("writeback_cache=no", writeback_cache, 0),
|
||||
SSHFS_OPT("unreliable_append", unrel_append, 1),
|
||||
|
||||
SSHFS_OPT("-h", show_help, 1),
|
||||
SSHFS_OPT("--help", show_help, 1),
|
||||
@@ -423,7 +424,13 @@ static struct fuse_opt sshfs_opts[] = {
|
||||
FUSE_OPT_KEY("-p ", KEY_PORT),
|
||||
FUSE_OPT_KEY("-C", KEY_COMPRESS),
|
||||
FUSE_OPT_KEY("-F ", KEY_CONFIGFILE),
|
||||
|
||||
/* For backwards compatibility */
|
||||
SSHFS_OPT("cache=yes", dir_cache, 1),
|
||||
SSHFS_OPT("cache=no", dir_cache, 0),
|
||||
|
||||
FUSE_OPT_END
|
||||
|
||||
};
|
||||
|
||||
static struct fuse_opt workaround_opts[] = {
|
||||
@@ -1644,16 +1651,11 @@ static int sftp_check_root(const char *base_path)
|
||||
if (!(flags & SSH_FILEXFER_ATTR_PERMISSIONS))
|
||||
goto out;
|
||||
|
||||
if (S_ISDIR(sshfs.mnt_mode) && !S_ISDIR(stbuf.st_mode)) {
|
||||
if (!S_ISDIR(stbuf.st_mode)) {
|
||||
fprintf(stderr, "%s:%s: Not a directory\n", sshfs.host,
|
||||
remote_dir);
|
||||
goto out;
|
||||
}
|
||||
if ((sshfs.mnt_mode ^ stbuf.st_mode) & S_IFMT) {
|
||||
fprintf(stderr, "%s:%s: type of file differs from mountpoint\n",
|
||||
sshfs.host, remote_dir);
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = 0;
|
||||
|
||||
@@ -2073,11 +2075,16 @@ static int sftp_readdir_async(struct buffer *handle, void *buf, off_t offset,
|
||||
outstanding--;
|
||||
|
||||
if (done) {
|
||||
/* We need to cache want_reply, since processing
|
||||
thread may free req right after unlock() if
|
||||
want_reply == 0 */
|
||||
int want_reply;
|
||||
pthread_mutex_lock(&sshfs.lock);
|
||||
if (sshfs_req_pending(req))
|
||||
req->want_reply = 0;
|
||||
want_reply = req->want_reply;
|
||||
pthread_mutex_unlock(&sshfs.lock);
|
||||
if (!req->want_reply)
|
||||
if (!want_reply)
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -2490,11 +2497,29 @@ static int sshfs_open_common(const char *path, mode_t mode,
|
||||
uint32_t pflags = 0;
|
||||
struct iovec iov;
|
||||
uint8_t type;
|
||||
uint64_t wrctr;
|
||||
uint64_t wrctr = 0;
|
||||
|
||||
if (sshfs.dir_cache)
|
||||
wrctr = cache_get_write_ctr();
|
||||
|
||||
/* With writeback cache, kernel may send read requests even
|
||||
when userspace opened write-only */
|
||||
if (sshfs.writeback_cache &&
|
||||
(fi->flags & O_ACCMODE) == O_WRONLY) {
|
||||
fi->flags &= ~O_ACCMODE;
|
||||
fi->flags |= O_RDWR;
|
||||
}
|
||||
|
||||
/* Having the kernel handle O_APPEND doesn't work reliably, if
|
||||
the file changes on the server at the wrong time, we will
|
||||
overwrite data instead of appending. */
|
||||
if ((fi->flags & O_APPEND) && sshfs.writeback_cache) {
|
||||
if(sshfs.unrel_append)
|
||||
fi->flags &= ~O_APPEND;
|
||||
else
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((fi->flags & O_ACCMODE) == O_RDONLY)
|
||||
pflags = SSH_FXF_READ;
|
||||
else if((fi->flags & O_ACCMODE) == O_WRONLY)
|
||||
@@ -2513,6 +2538,9 @@ static int sshfs_open_common(const char *path, mode_t mode,
|
||||
if (fi->flags & O_TRUNC)
|
||||
pflags |= SSH_FXF_TRUNC;
|
||||
|
||||
if (fi->flags & O_APPEND)
|
||||
pflags |= SSH_FXF_APPEND;
|
||||
|
||||
sf = g_new0(struct sshfs_file, 1);
|
||||
list_init(&sf->write_reqs);
|
||||
pthread_cond_init(&sf->write_finished, NULL);
|
||||
@@ -3145,6 +3173,9 @@ static int sshfs_getattr(const char *path, struct stat *stbuf,
|
||||
}
|
||||
if (!err) {
|
||||
err = buf_get_attrs(&outbuf, stbuf, NULL);
|
||||
#ifdef __APPLE__
|
||||
stbuf->st_blksize = 0;
|
||||
#endif
|
||||
buf_free(&outbuf);
|
||||
}
|
||||
buf_free(&buf);
|
||||
@@ -3333,6 +3364,7 @@ static void usage(const char *progname)
|
||||
" -o sshfs_sync synchronous writes\n"
|
||||
" -o no_readahead synchronous reads (no speculative readahead)\n"
|
||||
" -o sync_readdir synchronous readdir\n"
|
||||
" -o unreliable_append Enable (unreliable) O_APPEND support\n"
|
||||
" -d, --debug print some debugging information (implies -f)\n"
|
||||
" -o writeback_cache=BOOL enable writeback cache {yes,no} (default: yes)\n"
|
||||
" -o dir_cache=BOOL enable caching of directory contents (names,\n"
|
||||
@@ -3820,9 +3852,6 @@ int main(int argc, char *argv[])
|
||||
const char *sftp_server;
|
||||
struct fuse *fuse;
|
||||
struct fuse_session *se;
|
||||
#if !defined(__CYGWIN__)
|
||||
struct stat st;
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
if (!realpath(*exec_path, sshfs_program_path)) {
|
||||
@@ -3848,6 +3877,7 @@ int main(int argc, char *argv[])
|
||||
sshfs.ptyfd = -1;
|
||||
sshfs.dir_cache = 1;
|
||||
sshfs.writeback_cache = 1;
|
||||
sshfs.unrel_append = 0;
|
||||
sshfs.show_help = 0;
|
||||
sshfs.show_version = 0;
|
||||
sshfs.singlethread = 0;
|
||||
@@ -3895,7 +3925,7 @@ int main(int argc, char *argv[])
|
||||
fprintf(stderr, "see `%s -h' for usage\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
if (sshfs.idmap == IDMAP_USER)
|
||||
sshfs.detect_uid = 1;
|
||||
else if (sshfs.idmap == IDMAP_FILE) {
|
||||
@@ -3984,18 +4014,6 @@ int main(int argc, char *argv[])
|
||||
g_free(tmp);
|
||||
g_free(fsname);
|
||||
|
||||
|
||||
#if !defined(__CYGWIN__)
|
||||
res = stat(sshfs.mountpoint, &st);
|
||||
if (res == -1) {
|
||||
perror(sshfs.mountpoint);
|
||||
exit(1);
|
||||
}
|
||||
sshfs.mnt_mode = st.st_mode;
|
||||
#elif defined(__CYGWIN__)
|
||||
sshfs.mnt_mode = S_IFDIR | 0755;
|
||||
#endif
|
||||
|
||||
if(sshfs.dir_cache)
|
||||
sshfs.op = cache_wrap(&sshfs_oper);
|
||||
else
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@ test_scripts = [ 'conftest.py', 'pytest.ini', 'test_sshfs.py',
|
||||
'util.py' ]
|
||||
custom_target('test_scripts', input: test_scripts,
|
||||
output: test_scripts, build_by_default: true,
|
||||
command: ['cp', '-fPu', '--preserve=mode',
|
||||
command: ['cp', '-fP', '--preserve=mode',
|
||||
'@INPUT@', meson.current_build_dir() ])
|
||||
|
||||
# Provide something helpful when running 'ninja test'
|
||||
|
||||
+50
-2
@@ -13,6 +13,7 @@ import stat
|
||||
import shutil
|
||||
import filecmp
|
||||
import errno
|
||||
from contextlib import contextmanager
|
||||
from tempfile import NamedTemporaryFile
|
||||
from util import (wait_for_mount, umount, cleanup, base_cmdline,
|
||||
basename, fuse_test_marker, safe_sleep)
|
||||
@@ -32,7 +33,9 @@ def name_generator(__ctr=[0]):
|
||||
@pytest.mark.parametrize("debug", (False, True))
|
||||
@pytest.mark.parametrize("cache_timeout", (0,1))
|
||||
@pytest.mark.parametrize("sync_rd", (True, False))
|
||||
def test_sshfs(tmpdir, debug, cache_timeout, sync_rd, capfd):
|
||||
@pytest.mark.parametrize("writeback", (False, True))
|
||||
def test_sshfs(tmpdir, debug, cache_timeout, sync_rd,
|
||||
writeback, capfd):
|
||||
|
||||
# Avoid false positives from debug messages
|
||||
#if debug:
|
||||
@@ -61,7 +64,13 @@ def test_sshfs(tmpdir, debug, cache_timeout, sync_rd, capfd):
|
||||
|
||||
if sync_rd:
|
||||
cmdline += [ '-o', 'sync_readdir' ]
|
||||
|
||||
|
||||
if writeback:
|
||||
cmdline += [ '-o', 'writeback_cache=yes',
|
||||
'-o', 'unreliable_append' ]
|
||||
else:
|
||||
cmdline += [ '-o', 'writeback_cache=no' ]
|
||||
|
||||
# SSHFS Cache
|
||||
if cache_timeout == 0:
|
||||
cmdline += [ '-o', 'dir_cache=no' ]
|
||||
@@ -87,6 +96,8 @@ def test_sshfs(tmpdir, debug, cache_timeout, sync_rd, capfd):
|
||||
tst_readdir(src_dir, mnt_dir)
|
||||
tst_open_read(src_dir, mnt_dir)
|
||||
tst_open_write(src_dir, mnt_dir)
|
||||
tst_append(src_dir, mnt_dir)
|
||||
tst_seek(src_dir, mnt_dir)
|
||||
tst_create(mnt_dir)
|
||||
tst_passthrough(src_dir, mnt_dir, cache_timeout)
|
||||
tst_mkdir(mnt_dir)
|
||||
@@ -110,6 +121,17 @@ def test_sshfs(tmpdir, debug, cache_timeout, sync_rd, capfd):
|
||||
else:
|
||||
umount(mount_process, mnt_dir)
|
||||
|
||||
@contextmanager
|
||||
def os_open(name, flags):
|
||||
fd = os.open(name, flags)
|
||||
try:
|
||||
yield fd
|
||||
finally:
|
||||
os.close(fd)
|
||||
|
||||
def os_create(name):
|
||||
os.close(os.open(name, os.O_CREAT | os.O_RDWR))
|
||||
|
||||
def tst_unlink(src_dir, mnt_dir, cache_timeout):
|
||||
name = name_generator()
|
||||
fullname = mnt_dir + "/" + name
|
||||
@@ -215,6 +237,32 @@ def tst_open_write(src_dir, mnt_dir):
|
||||
|
||||
assert filecmp.cmp(fullname, TEST_FILE, False)
|
||||
|
||||
def tst_append(src_dir, mnt_dir):
|
||||
name = name_generator()
|
||||
os_create(pjoin(src_dir, name))
|
||||
fullname = pjoin(mnt_dir, name)
|
||||
with os_open(fullname, os.O_WRONLY) as fd:
|
||||
os.write(fd, b'foo\n')
|
||||
with os_open(fullname, os.O_WRONLY|os.O_APPEND) as fd:
|
||||
os.write(fd, b'bar\n')
|
||||
|
||||
with open(fullname, 'rb') as fh:
|
||||
assert fh.read() == b'foo\nbar\n'
|
||||
|
||||
def tst_seek(src_dir, mnt_dir):
|
||||
name = name_generator()
|
||||
os_create(pjoin(src_dir, name))
|
||||
fullname = pjoin(mnt_dir, name)
|
||||
with os_open(fullname, os.O_WRONLY) as fd:
|
||||
os.lseek(fd, 1, os.SEEK_SET)
|
||||
os.write(fd, b'foobar\n')
|
||||
with os_open(fullname, os.O_WRONLY) as fd:
|
||||
os.lseek(fd, 4, os.SEEK_SET)
|
||||
os.write(fd, b'com')
|
||||
|
||||
with open(fullname, 'rb') as fh:
|
||||
assert fh.read() == b'\0foocom\n'
|
||||
|
||||
def tst_open_unlink(mnt_dir):
|
||||
name = pjoin(mnt_dir, name_generator())
|
||||
data1 = b'foo'
|
||||
|
||||
@@ -14,16 +14,19 @@ ninja --version
|
||||
meson --version
|
||||
|
||||
# Install fuse
|
||||
wget https://github.com/libfuse/libfuse/releases/download/fuse-3.0.2/fuse-3.0.2.tar.gz
|
||||
tar xzf fuse-3.0.2.tar.gz
|
||||
cd fuse-3.0.2
|
||||
wget https://github.com/libfuse/libfuse/archive/master.zip
|
||||
unzip master.zip
|
||||
cd libfuse-master
|
||||
mkdir build
|
||||
cd build
|
||||
export CC=gcc-6
|
||||
meson ..
|
||||
ninja
|
||||
sudo ninja install
|
||||
test -e /usr/local/lib/pkgconfig || sudo mkdir /usr/local/lib/pkgconfig
|
||||
sudo mv /usr/local/lib/*/pkgconfig/* /usr/local/lib/pkgconfig/
|
||||
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 ''
|
||||
|
||||
Reference in New Issue
Block a user