Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6b4415ada4 | |||
| 6a2d06e36f | |||
| 334e9e6a27 | |||
| 91c1f2ba9e | |||
| c1d62f2032 | |||
| 61524cd1e8 | |||
| 9f4ba56b52 | |||
| ce6753c88f |
@@ -1,3 +1,27 @@
|
||||
2014-01-14 Miklos Szeredi <miklos@szeredi.hu>
|
||||
|
||||
* Released 2.5
|
||||
|
||||
2014-01-08 Miklos Szeredi <miklos@szeredi.hu>
|
||||
|
||||
* Add -o disable_hardlink option (debian bug #670926). Reported
|
||||
by Louis-David Mitterrand
|
||||
|
||||
* Optimize readdir by sending multiple requests in parallel. Add
|
||||
-o sync_readdir to restore old behavior. Patch by Alexander
|
||||
Neumann
|
||||
|
||||
2014-01-07 Miklos Szeredi <miklos@szeredi.hu>
|
||||
|
||||
* Map SSH2_FX_FAILURE to ENOTEMPTY for rmdir. Reported by Ross
|
||||
Lagerwall
|
||||
|
||||
2012-05-14 Miklos Szeredi <miklos@szeredi.hu>
|
||||
|
||||
* When checking root directory use LSTAT not STAT. This prevents
|
||||
I/O error being returned after a successful mount if a symlink is
|
||||
mounted. Reported by Bart Friederichs
|
||||
|
||||
2012-03-08 Miklos Szeredi <miklos@szeredi.hu>
|
||||
|
||||
* Released 2.4
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
AC_INIT(sshfs-fuse, 2.4)
|
||||
AC_INIT(sshfs-fuse, 2.5)
|
||||
AM_INIT_AUTOMAKE
|
||||
AM_CONFIG_HEADER(config.h)
|
||||
|
||||
|
||||
@@ -58,6 +58,9 @@ synchronous writes
|
||||
\fB\-o\fR no_readahead
|
||||
synchronous reads (no speculative readahead)
|
||||
.TP
|
||||
\fB\-o\fR sync_readdir
|
||||
synchronous readdir
|
||||
.TP
|
||||
\fB\-o\fR sshfs_debug
|
||||
print some debugging information
|
||||
.TP
|
||||
@@ -138,9 +141,15 @@ path to sftp server or subsystem (default: sftp)
|
||||
.TP
|
||||
\fB\-o\fR directport=PORT
|
||||
directly connect to PORT bypassing ssh
|
||||
.TP
|
||||
\fB\-o\fR slave
|
||||
communicate over stdin and stdout bypassing network
|
||||
.TP
|
||||
\fB\-o\fR disable_hardlink
|
||||
link(2) will return with errno set to ENOSYS. Hard links don't currently work
|
||||
perfectly on sshfs, and this confuses some programs. If that happens try
|
||||
disabling hard links with this option.
|
||||
.TP
|
||||
\fB\-o\fR transform_symlinks
|
||||
transform absolute symlinks to relative
|
||||
.TP
|
||||
@@ -256,7 +265,7 @@ perform reads synchronously
|
||||
\fB\-o\fR subdir=DIR
|
||||
prepend this directory to all paths (mandatory)
|
||||
.TP
|
||||
\fB\-o\fR [no]rellinksa
|
||||
\fB\-o\fR [no]rellinks
|
||||
transform absolute symlinks to relative
|
||||
.TP
|
||||
[iconv]
|
||||
|
||||
@@ -121,6 +121,10 @@
|
||||
|
||||
#define SSHNODELAY_SO "sshnodelay.so"
|
||||
|
||||
/* Asynchronous readdir parameters */
|
||||
#define READDIR_START 2
|
||||
#define READDIR_MAX 32
|
||||
|
||||
struct buffer {
|
||||
uint8_t *p;
|
||||
size_t len;
|
||||
@@ -139,6 +143,7 @@ struct request {
|
||||
unsigned int want_reply;
|
||||
sem_t ready;
|
||||
uint8_t reply_type;
|
||||
uint32_t id;
|
||||
int replied;
|
||||
int error;
|
||||
struct buffer reply;
|
||||
@@ -203,6 +208,7 @@ struct sshfs {
|
||||
int detect_uid;
|
||||
int idmap;
|
||||
int nomap;
|
||||
int disable_hardlink;
|
||||
char *uid_file;
|
||||
char *gid_file;
|
||||
GHashTable *uid_map;
|
||||
@@ -214,6 +220,7 @@ struct sshfs {
|
||||
unsigned ssh_ver;
|
||||
int sync_write;
|
||||
int sync_read;
|
||||
int sync_readdir;
|
||||
int debug;
|
||||
int foreground;
|
||||
int reconnect;
|
||||
@@ -350,6 +357,7 @@ static struct fuse_opt sshfs_opts[] = {
|
||||
SSHFS_OPT("nomap=error", nomap, NOMAP_ERROR),
|
||||
SSHFS_OPT("sshfs_sync", sync_write, 1),
|
||||
SSHFS_OPT("no_readahead", sync_read, 1),
|
||||
SSHFS_OPT("sync_readdir", sync_readdir, 1),
|
||||
SSHFS_OPT("sshfs_debug", debug, 1),
|
||||
SSHFS_OPT("reconnect", reconnect, 1),
|
||||
SSHFS_OPT("transform_symlinks", transform_symlinks, 1),
|
||||
@@ -358,6 +366,7 @@ static struct fuse_opt sshfs_opts[] = {
|
||||
SSHFS_OPT("password_stdin", password_stdin, 1),
|
||||
SSHFS_OPT("delay_connect", delay_connect, 1),
|
||||
SSHFS_OPT("slave", slave, 1),
|
||||
SSHFS_OPT("disable_hardlink", disable_hardlink, 1),
|
||||
|
||||
FUSE_OPT_KEY("-p ", KEY_PORT),
|
||||
FUSE_OPT_KEY("-C", KEY_COMPRESS),
|
||||
@@ -1620,7 +1629,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_STAT, id, iov, 1) == -1)
|
||||
if (sftp_send_iov(SSH_FXP_LSTAT, id, iov, 1) == -1)
|
||||
goto out;
|
||||
buf_clear(&buf);
|
||||
if (sftp_read(&type, &buf) == -1)
|
||||
@@ -1790,6 +1799,13 @@ static int sftp_request_wait(struct request *req, uint8_t type,
|
||||
err = -EIO;
|
||||
break;
|
||||
|
||||
case SSH_FX_FAILURE:
|
||||
if (type == SSH_FXP_RMDIR)
|
||||
err = -ENOTEMPTY;
|
||||
else
|
||||
err = -EPERM;
|
||||
break;
|
||||
|
||||
default:
|
||||
err = -sftp_error_to_errno(serr);
|
||||
}
|
||||
@@ -1827,6 +1843,7 @@ static int sftp_request_send(uint8_t type, struct iovec *iov, size_t count,
|
||||
if (begin_func)
|
||||
begin_func(req);
|
||||
id = sftp_get_id();
|
||||
req->id = id;
|
||||
err = start_processing_thread();
|
||||
if (err) {
|
||||
pthread_mutex_unlock(&sshfs.lock);
|
||||
@@ -2014,6 +2031,113 @@ static int sshfs_readlink(const char *path, char *linkbuf, size_t size)
|
||||
return err;
|
||||
}
|
||||
|
||||
static int sftp_readdir_send(struct request **req, struct buffer *handle)
|
||||
{
|
||||
struct iovec iov;
|
||||
|
||||
buf_to_iov(handle, &iov);
|
||||
return sftp_request_send(SSH_FXP_READDIR, &iov, 1, NULL, NULL,
|
||||
SSH_FXP_NAME, NULL, req);
|
||||
}
|
||||
|
||||
static int sshfs_req_pending(struct request *req)
|
||||
{
|
||||
if (g_hash_table_lookup(sshfs.reqtab, GUINT_TO_POINTER(req->id)))
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sftp_readdir_async(struct buffer *handle, fuse_cache_dirh_t h,
|
||||
fuse_cache_dirfil_t filler)
|
||||
{
|
||||
int err = 0;
|
||||
int outstanding = 0;
|
||||
int max = READDIR_START;
|
||||
GList *list = NULL;
|
||||
|
||||
int done = 0;
|
||||
|
||||
while (!done || outstanding) {
|
||||
struct request *req;
|
||||
struct buffer name;
|
||||
int tmperr;
|
||||
|
||||
while (!done && outstanding < max) {
|
||||
tmperr = sftp_readdir_send(&req, handle);
|
||||
|
||||
if (tmperr && !done) {
|
||||
err = tmperr;
|
||||
done = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
list = g_list_append(list, req);
|
||||
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);
|
||||
outstanding--;
|
||||
|
||||
if (done) {
|
||||
pthread_mutex_lock(&sshfs.lock);
|
||||
if (sshfs_req_pending(req))
|
||||
req->want_reply = 0;
|
||||
pthread_mutex_unlock(&sshfs.lock);
|
||||
if (!req->want_reply)
|
||||
continue;
|
||||
}
|
||||
|
||||
tmperr = sftp_request_wait(req, SSH_FXP_READDIR,
|
||||
SSH_FXP_NAME, &name);
|
||||
|
||||
if (tmperr && !done) {
|
||||
err = tmperr;
|
||||
if (err == MY_EOF)
|
||||
err = 0;
|
||||
done = 1;
|
||||
}
|
||||
if (!done) {
|
||||
err = buf_get_entries(&name, h, filler);
|
||||
buf_free(&name);
|
||||
|
||||
/* increase number of outstanding requests */
|
||||
if (max < READDIR_MAX)
|
||||
max++;
|
||||
|
||||
if (err)
|
||||
done = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
assert(list == NULL);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int sftp_readdir_sync(struct buffer *handle, fuse_cache_dirh_t h,
|
||||
fuse_cache_dirfil_t filler)
|
||||
{
|
||||
int err;
|
||||
do {
|
||||
struct buffer name;
|
||||
err = sftp_request(SSH_FXP_READDIR, handle, SSH_FXP_NAME, &name);
|
||||
if (!err) {
|
||||
err = buf_get_entries(&name, h, filler);
|
||||
buf_free(&name);
|
||||
}
|
||||
} while (!err);
|
||||
if (err == MY_EOF)
|
||||
err = 0;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int sshfs_getdir(const char *path, fuse_cache_dirh_t h,
|
||||
fuse_cache_dirfil_t filler)
|
||||
{
|
||||
@@ -2026,16 +2150,11 @@ static int sshfs_getdir(const char *path, fuse_cache_dirh_t h,
|
||||
if (!err) {
|
||||
int err2;
|
||||
buf_finish(&handle);
|
||||
do {
|
||||
struct buffer name;
|
||||
err = sftp_request(SSH_FXP_READDIR, &handle, SSH_FXP_NAME, &name);
|
||||
if (!err) {
|
||||
err = buf_get_entries(&name, h, filler);
|
||||
buf_free(&name);
|
||||
}
|
||||
} while (!err);
|
||||
if (err == MY_EOF)
|
||||
err = 0;
|
||||
|
||||
if (sshfs.sync_readdir)
|
||||
err = sftp_readdir_sync(&handle, h, filler);
|
||||
else
|
||||
err = sftp_readdir_async(&handle, h, filler);
|
||||
|
||||
err2 = sftp_request(SSH_FXP_CLOSE, &handle, 0, NULL);
|
||||
if (!err)
|
||||
@@ -2192,7 +2311,7 @@ static int sshfs_link(const char *from, const char *to)
|
||||
{
|
||||
int err = -ENOSYS;
|
||||
|
||||
if (sshfs.ext_hardlink) {
|
||||
if (sshfs.ext_hardlink && !sshfs.disable_hardlink) {
|
||||
struct buffer buf;
|
||||
|
||||
buf_init(&buf, 0);
|
||||
@@ -3162,6 +3281,7 @@ static void usage(const char *progname)
|
||||
" -o delay_connect delay connection to server\n"
|
||||
" -o sshfs_sync synchronous writes\n"
|
||||
" -o no_readahead synchronous reads (no speculative readahead)\n"
|
||||
" -o sync_readdir synchronous readdir\n"
|
||||
" -o sshfs_debug print some debugging information\n"
|
||||
" -o cache=BOOL enable caching {yes,no} (default: yes)\n"
|
||||
" -o cache_timeout=N sets timeout for caches in seconds (default: 20)\n"
|
||||
@@ -3190,6 +3310,7 @@ static void usage(const char *progname)
|
||||
" -o sftp_server=SERV path to sftp server or subsystem (default: sftp)\n"
|
||||
" -o directport=PORT directly connect to PORT bypassing ssh\n"
|
||||
" -o slave communicate over stdin and stdout bypassing network\n"
|
||||
" -o disable_hardlink link(2) will return with errno set to ENOSYS\n"
|
||||
" -o transform_symlinks transform absolute symlinks to relative\n"
|
||||
" -o follow_symlinks follow symlinks on the server\n"
|
||||
" -o no_check_root don't check for existence of 'dir' on server\n"
|
||||
@@ -3863,6 +3984,10 @@ int main(int argc, char *argv[])
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* FIXME: trim $PATH so it doesn't contain anything inside the
|
||||
* mountpoint, which would deadlock.
|
||||
*/
|
||||
res = ssh_connect();
|
||||
if (res == -1) {
|
||||
fuse_unmount(mountpoint, ch);
|
||||
|
||||
Reference in New Issue
Block a user