Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| adf379b056 | |||
| 82d15b68d4 | |||
| 2d959740ea | |||
| 28495b3bb2 | |||
| 61a154807b | |||
| c67cf9b98b | |||
| effd586502 | |||
| b1ddd5f430 |
@@ -1,3 +1,34 @@
|
||||
2005-08-15 Miklos Szeredi <miklos@szeredi.hu>
|
||||
|
||||
* Released 1.2
|
||||
|
||||
2005-08-13 Miklos Szeredi <miklos@szeredi.hu>
|
||||
|
||||
* Add 'reconnect' option, which tries to reconnect to the server
|
||||
when the connection is broken. If a password is required for
|
||||
connection, it is recommended that you install ssh-askpass, and
|
||||
set the SSH_ASKPASS environment variable (see 'man ssh' for more
|
||||
details).
|
||||
|
||||
2005-05-05 Miklos Szeredi <miklos@szeredi.hu>
|
||||
|
||||
* Work around missing truncate() support in some older sftp
|
||||
servers (only works for zero size truncate). Thanks to Eduard
|
||||
Czimbalmos for the bug report and help with testing
|
||||
|
||||
2005-04-13 Miklos Szeredi <miklos@szeredi.hu>
|
||||
|
||||
* Fix compilation with gcc-2.95. Reported by David A. Gershman
|
||||
|
||||
2005-03-08 Miklos Szeredi <miklos@szeredi.hu>
|
||||
|
||||
* Make it work on server version 2 (e.g. Sun_SSH_1.0.1). Report
|
||||
and testing by Pieter J. Kersten
|
||||
|
||||
2005-03-04 Miklos Szeredi <miklos@szeredi.hu>
|
||||
|
||||
* Released 1.1
|
||||
|
||||
2005-03-03 Miklos Szeredi <miklos@szeredi.hu>
|
||||
|
||||
* Slightly optimize readahead. Still not clever enough to always
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
What is new in 1.2
|
||||
------------------
|
||||
|
||||
* Better compatibility with different sftp servers
|
||||
|
||||
* Automatic reconnect (optional)
|
||||
|
||||
What is new in 1.1
|
||||
------------------
|
||||
|
||||
|
||||
@@ -20,6 +20,8 @@ codebase, so I rewrote it. Features of this implementation are:
|
||||
|
||||
- Caching directory contents
|
||||
|
||||
- Reconnect on failure
|
||||
|
||||
|
||||
How to mount a filesystem
|
||||
=========================
|
||||
|
||||
@@ -244,9 +244,9 @@ static int cache_dirfill(fuse_cache_dirh_t ch, const char *name,
|
||||
{
|
||||
int err = ch->filler(ch->h, name, 0, 0);
|
||||
if (!err) {
|
||||
char *fullpath;
|
||||
g_ptr_array_add(ch->dir, g_strdup(name));
|
||||
char *fullpath = g_strdup_printf("%s/%s",
|
||||
!ch->path[1] ? "" : ch->path, name);
|
||||
fullpath = g_strdup_printf("%s/%s", !ch->path[1] ? "" : ch->path, name);
|
||||
cache_add_attr(fullpath, stbuf);
|
||||
g_free(fullpath);
|
||||
}
|
||||
@@ -406,6 +406,9 @@ static int cache_write(const char *path, const char *buf, size_t size,
|
||||
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->readlink = oper->oper.readlink;
|
||||
cache_oper->getdir = cache_unity_getdir;
|
||||
|
||||
@@ -8,6 +8,10 @@
|
||||
|
||||
#include <fuse.h>
|
||||
|
||||
#ifndef FUSE_VERSION
|
||||
#define FUSE_VERSION (FUSE_MAJOR_VERSION * 10 + FUSE_MINOR_VERSION)
|
||||
#endif
|
||||
|
||||
typedef struct fuse_cache_dirhandle *fuse_cache_dirh_t;
|
||||
typedef int (*fuse_cache_dirfil_t) (fuse_cache_dirh_t h, const char *name,
|
||||
const struct stat *stbuf);
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
AC_INIT(sshfs-fuse, 1.1)
|
||||
AC_INIT(sshfs-fuse, 1.2)
|
||||
AM_INIT_AUTOMAKE
|
||||
AM_CONFIG_HEADER(config.h)
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <netdb.h>
|
||||
#include <signal.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/wait.h>
|
||||
#include <netinet/in.h>
|
||||
#include <glib.h>
|
||||
|
||||
@@ -86,10 +87,14 @@
|
||||
|
||||
static int infd;
|
||||
static int outfd;
|
||||
static int connver;
|
||||
static int server_version;
|
||||
static int debug = 0;
|
||||
static int reconnect = 0;
|
||||
static int sync_write = 0;
|
||||
static int sync_read = 0;
|
||||
static char *base_path;
|
||||
static char *host;
|
||||
|
||||
struct buffer {
|
||||
uint8_t *p;
|
||||
@@ -110,6 +115,7 @@ struct request {
|
||||
sem_t ready;
|
||||
uint8_t reply_type;
|
||||
int replied;
|
||||
int error;
|
||||
struct buffer reply;
|
||||
struct timeval start;
|
||||
void *data;
|
||||
@@ -134,6 +140,7 @@ struct sshfs_file {
|
||||
struct read_chunk *readahead;
|
||||
off_t next_pos;
|
||||
int is_seq;
|
||||
int connver;
|
||||
};
|
||||
|
||||
static GHashTable *reqtab;
|
||||
@@ -191,6 +198,7 @@ enum {
|
||||
SOPT_SYNC_READ,
|
||||
SOPT_MAX_READ,
|
||||
SOPT_DEBUG,
|
||||
SOPT_RECONNECT,
|
||||
SOPT_LAST /* Last entry in this list! */
|
||||
};
|
||||
|
||||
@@ -201,6 +209,7 @@ static struct opt sshfs_opts[] = {
|
||||
[SOPT_SYNC_READ] = { .optname = "no_readahead" },
|
||||
[SOPT_MAX_READ] = { .optname = "max_read" },
|
||||
[SOPT_DEBUG] = { .optname = "sshfs_debug" },
|
||||
[SOPT_RECONNECT] = { .optname = "reconnect" },
|
||||
[SOPT_LAST] = { .optname = NULL }
|
||||
};
|
||||
|
||||
@@ -544,9 +553,13 @@ static int start_ssh(char *host)
|
||||
perror("failed to fork");
|
||||
return -1;
|
||||
} else if (pid == 0) {
|
||||
int devnull;
|
||||
int argctr = 0;
|
||||
char *ssh_args[sizeof(ssh_opts)/sizeof(struct opt) + 32];
|
||||
char *ssh_cmd;
|
||||
|
||||
devnull = open("/dev/null", O_WRONLY);
|
||||
|
||||
if (sshfs_opts[SOPT_SSHCMD].present)
|
||||
ssh_cmd = sshfs_opts[SOPT_SSHCMD].value;
|
||||
else
|
||||
@@ -554,13 +567,28 @@ static int start_ssh(char *host)
|
||||
|
||||
if (dup2(outpipe[0], 0) == -1 || dup2(inpipe[1], 1) == -1) {
|
||||
perror("failed to redirect input/output");
|
||||
exit(1);
|
||||
_exit(1);
|
||||
}
|
||||
if (!debug && devnull != -1)
|
||||
dup2(devnull, 2);
|
||||
|
||||
close(devnull);
|
||||
close(inpipe[0]);
|
||||
close(inpipe[1]);
|
||||
close(outpipe[0]);
|
||||
close(outpipe[1]);
|
||||
|
||||
switch (fork()) {
|
||||
case -1:
|
||||
perror("failed to fork");
|
||||
_exit(1);
|
||||
case 0:
|
||||
break;
|
||||
default:
|
||||
_exit(0);
|
||||
}
|
||||
chdir("/");
|
||||
|
||||
ssh_args[argctr++] = ssh_cmd;
|
||||
ssh_args[argctr++] = "-2";
|
||||
ssh_args[argctr++] = "-x";
|
||||
@@ -580,8 +608,9 @@ static int start_ssh(char *host)
|
||||
ssh_args[argctr++] = NULL;
|
||||
|
||||
execvp(ssh_cmd, ssh_args);
|
||||
exit(1);
|
||||
_exit(1);
|
||||
}
|
||||
waitpid(pid, NULL, 0);
|
||||
close(inpipe[1]);
|
||||
close(outpipe[0]);
|
||||
return 0;
|
||||
@@ -653,11 +682,9 @@ static int sftp_send(uint8_t type, struct buffer *buf)
|
||||
buf_init(&buf2, 5);
|
||||
buf_add_uint32(&buf2, buf->len + 1);
|
||||
buf_add_uint8(&buf2, type);
|
||||
pthread_mutex_lock(&lock);
|
||||
res = do_write(&buf2);
|
||||
if (res != -1)
|
||||
res = do_write(buf);
|
||||
pthread_mutex_unlock(&lock);
|
||||
buf_free(&buf2);
|
||||
return res;
|
||||
}
|
||||
@@ -673,7 +700,7 @@ static int do_read(struct buffer *buf)
|
||||
perror("read");
|
||||
return -1;
|
||||
} else if (res == 0) {
|
||||
fprintf(stderr, "end of file read\n");
|
||||
fprintf(stderr, "remote host has disconnected\n");
|
||||
return -1;
|
||||
}
|
||||
size -= res;
|
||||
@@ -690,12 +717,14 @@ static int sftp_read(uint8_t *type, struct buffer *buf)
|
||||
buf_init(&buf2, 5);
|
||||
res = do_read(&buf2);
|
||||
if (res != -1) {
|
||||
buf_get_uint32(&buf2, &len);
|
||||
if (buf_get_uint32(&buf2, &len) == -1)
|
||||
return -1;
|
||||
if (len > MAX_REPLY_LEN) {
|
||||
fprintf(stderr, "reply len too large: %u\n", len);
|
||||
return -1;
|
||||
}
|
||||
buf_get_uint8(&buf2, type);
|
||||
if (buf_get_uint8(&buf2, type) == -1)
|
||||
return -1;
|
||||
buf_init(buf, len - 1);
|
||||
res = do_read(buf);
|
||||
}
|
||||
@@ -733,12 +762,27 @@ static void chunk_put_locked(struct read_chunk *chunk)
|
||||
pthread_mutex_unlock(&lock);
|
||||
}
|
||||
|
||||
static void *process_requests(void *_data)
|
||||
static int clean_req(void *key_, struct request *req)
|
||||
{
|
||||
(void) _data;
|
||||
(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 void *process_requests(void *data_)
|
||||
{
|
||||
int res;
|
||||
(void) data_;
|
||||
|
||||
while (1) {
|
||||
int res;
|
||||
struct buffer buf;
|
||||
uint8_t type;
|
||||
struct request *req;
|
||||
@@ -772,17 +816,80 @@ static void *process_requests(void *_data)
|
||||
if (req->want_reply)
|
||||
sem_post(&req->ready);
|
||||
else {
|
||||
if (req->end_func)
|
||||
if (req->end_func) {
|
||||
pthread_mutex_lock(&lock);
|
||||
req->end_func(req);
|
||||
pthread_mutex_unlock(&lock);
|
||||
}
|
||||
request_free(req);
|
||||
}
|
||||
} else
|
||||
buf_free(&buf);
|
||||
}
|
||||
kill(getpid(), SIGTERM);
|
||||
if (!reconnect) {
|
||||
/* harakiri */
|
||||
kill(getpid(), SIGTERM);
|
||||
} else {
|
||||
pthread_mutex_lock(&lock);
|
||||
processing_thread_started = 0;
|
||||
close(infd);
|
||||
infd = -1;
|
||||
close(outfd);
|
||||
outfd = -1;
|
||||
g_hash_table_foreach_remove(reqtab, (GHRFunc) clean_req, NULL);
|
||||
connver ++;
|
||||
pthread_mutex_unlock(&lock);
|
||||
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int sftp_init()
|
||||
{
|
||||
int res = -1;
|
||||
uint8_t type;
|
||||
uint32_t version;
|
||||
struct buffer buf;
|
||||
buf_init(&buf, 4);
|
||||
buf_add_uint32(&buf, PROTO_VERSION);
|
||||
if (sftp_send(SSH_FXP_INIT, &buf) == -1)
|
||||
goto out;
|
||||
buf_clear(&buf);
|
||||
if (sftp_read(&type, &buf) == -1)
|
||||
goto out;
|
||||
if (type != SSH_FXP_VERSION) {
|
||||
fprintf(stderr, "protocol error\n");
|
||||
goto out;
|
||||
}
|
||||
if (buf_get_uint32(&buf, &version) == -1)
|
||||
goto out;
|
||||
|
||||
server_version = version;
|
||||
DEBUG("Server version: %i\n", server_version);
|
||||
if (version > PROTO_VERSION)
|
||||
fprintf(stderr, "Warning: server uses version: %i, we support: %i\n",
|
||||
version, PROTO_VERSION);
|
||||
res = 0;
|
||||
|
||||
out:
|
||||
buf_free(&buf);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int connect_remote(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (sshfs_opts[SOPT_DIRECTPORT].present)
|
||||
err = connect_to(host, sshfs_opts[SOPT_DIRECTPORT].value);
|
||||
else
|
||||
err = start_ssh(host);
|
||||
if (!err)
|
||||
err = sftp_init();
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int start_processing_thread(void)
|
||||
{
|
||||
int err;
|
||||
@@ -790,16 +897,30 @@ static int start_processing_thread(void)
|
||||
if (processing_thread_started)
|
||||
return 0;
|
||||
|
||||
if (outfd == -1) {
|
||||
err = connect_remote();
|
||||
if (err)
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
err = pthread_create(&thread_id, NULL, process_requests, NULL);
|
||||
if (err) {
|
||||
fprintf(stderr, "failed to create thread: %s\n", strerror(err));
|
||||
return -EPERM;
|
||||
return -EIO;
|
||||
}
|
||||
pthread_detach(thread_id);
|
||||
processing_thread_started = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if FUSE_VERSION >= 23
|
||||
static void *sshfs_init(void)
|
||||
{
|
||||
start_processing_thread();
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int sftp_request_common(uint8_t type, const struct buffer *buf,
|
||||
uint8_t expect_type, struct buffer *outbuf,
|
||||
request_func begin_func, request_func end_func,
|
||||
@@ -823,26 +944,32 @@ static int sftp_request_common(uint8_t type, const struct buffer *buf,
|
||||
begin_func(req);
|
||||
pthread_mutex_lock(&lock);
|
||||
err = start_processing_thread();
|
||||
if (err) {
|
||||
pthread_mutex_unlock(&lock);
|
||||
goto out;
|
||||
}
|
||||
g_hash_table_insert(reqtab, (gpointer) id, req);
|
||||
gettimeofday(&req->start, NULL);
|
||||
DEBUG("[%05i] %s\n", id, type_name(type));
|
||||
pthread_mutex_unlock(&lock);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
err = -EIO;
|
||||
if (sftp_send(type, &buf2) == -1) {
|
||||
pthread_mutex_lock(&lock);
|
||||
g_hash_table_remove(reqtab, (gpointer) id);
|
||||
pthread_mutex_unlock(&lock);
|
||||
goto out;
|
||||
}
|
||||
pthread_mutex_unlock(&lock);
|
||||
|
||||
if (expect_type == 0) {
|
||||
buf_free(&buf2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
sem_wait(&req->ready);
|
||||
if (req->error) {
|
||||
err = req->error;
|
||||
goto out;
|
||||
}
|
||||
err = -EPROTO;
|
||||
if (req->reply_type != expect_type && req->reply_type != SSH_FXP_STATUS) {
|
||||
fprintf(stderr, "protocol error\n");
|
||||
@@ -924,6 +1051,10 @@ static int sshfs_readlink(const char *path, char *linkbuf, size_t size)
|
||||
int err;
|
||||
struct buffer buf;
|
||||
struct buffer name;
|
||||
|
||||
if (server_version < 3)
|
||||
return -EPERM;
|
||||
|
||||
buf_init(&buf, 0);
|
||||
buf_add_path(&buf, path);
|
||||
err = sftp_request(SSH_FXP_READLINK, &buf, SSH_FXP_NAME, &name);
|
||||
@@ -1022,6 +1153,10 @@ static int sshfs_symlink(const char *from, const char *to)
|
||||
{
|
||||
int err;
|
||||
struct buffer buf;
|
||||
|
||||
if (server_version < 3)
|
||||
return -EPERM;
|
||||
|
||||
/* openssh sftp server doesn't follow standard: link target and
|
||||
link name are mixed up, so we must also be non-standard :( */
|
||||
buf_init(&buf, 0);
|
||||
@@ -1099,9 +1234,26 @@ static int sshfs_truncate(const char *path, off_t size)
|
||||
struct buffer buf;
|
||||
buf_init(&buf, 0);
|
||||
buf_add_path(&buf, path);
|
||||
buf_add_uint32(&buf, SSH_FILEXFER_ATTR_SIZE);
|
||||
buf_add_uint64(&buf, size);
|
||||
err = sftp_request(SSH_FXP_SETSTAT, &buf, SSH_FXP_STATUS, NULL);
|
||||
if (size == 0) {
|
||||
/* If size is zero, use open(..., O_TRUNC), to work around
|
||||
broken sftp servers */
|
||||
struct buffer handle;
|
||||
buf_add_uint32(&buf, SSH_FXF_WRITE | SSH_FXF_TRUNC);
|
||||
buf_add_uint32(&buf, 0);
|
||||
err = sftp_request(SSH_FXP_OPEN, &buf, SSH_FXP_HANDLE, &handle);
|
||||
if (!err) {
|
||||
int err2;
|
||||
buf_finish(&handle);
|
||||
err2 = sftp_request(SSH_FXP_CLOSE, &handle, 0, NULL);
|
||||
if (!err)
|
||||
err = err2;
|
||||
buf_free(&handle);
|
||||
}
|
||||
} else {
|
||||
buf_add_uint32(&buf, SSH_FILEXFER_ATTR_SIZE);
|
||||
buf_add_uint64(&buf, size);
|
||||
err = sftp_request(SSH_FXP_SETSTAT, &buf, SSH_FXP_STATUS, NULL);
|
||||
}
|
||||
buf_free(&buf);
|
||||
return err;
|
||||
}
|
||||
@@ -1120,6 +1272,11 @@ static int sshfs_utime(const char *path, struct utimbuf *ubuf)
|
||||
return err;
|
||||
}
|
||||
|
||||
static inline int sshfs_file_is_conn(struct sshfs_file *sf)
|
||||
{
|
||||
return sf->connver == connver;
|
||||
}
|
||||
|
||||
static int sshfs_open(const char *path, struct fuse_file_info *fi)
|
||||
{
|
||||
int err;
|
||||
@@ -1141,6 +1298,7 @@ static int sshfs_open(const char *path, struct fuse_file_info *fi)
|
||||
/* Assume random read after open */
|
||||
sf->is_seq = 0;
|
||||
sf->next_pos = 0;
|
||||
sf->connver = connver;
|
||||
buf_init(&buf, 0);
|
||||
buf_add_path(&buf, path);
|
||||
buf_add_uint32(&buf, pflags);
|
||||
@@ -1162,6 +1320,9 @@ static int sshfs_flush(const char *path, struct fuse_file_info *fi)
|
||||
struct list_head write_reqs;
|
||||
struct list_head *curr_list;
|
||||
|
||||
if (!sshfs_file_is_conn(sf))
|
||||
return -EIO;
|
||||
|
||||
if (sync_write)
|
||||
return 0;
|
||||
|
||||
@@ -1192,8 +1353,10 @@ static int sshfs_release(const char *path, struct fuse_file_info *fi)
|
||||
{
|
||||
struct sshfs_file *sf = (struct sshfs_file *) fi->fh;
|
||||
struct buffer *handle = &sf->handle;
|
||||
sshfs_flush(path, fi);
|
||||
sftp_request(SSH_FXP_CLOSE, handle, 0, NULL);
|
||||
if (sshfs_file_is_conn(sf)) {
|
||||
sshfs_flush(path, fi);
|
||||
sftp_request(SSH_FXP_CLOSE, handle, 0, NULL);
|
||||
}
|
||||
buf_free(handle);
|
||||
chunk_put_locked(sf->readahead);
|
||||
g_free(sf);
|
||||
@@ -1233,7 +1396,9 @@ static int sshfs_sync_read(struct sshfs_file *sf, char *rbuf, size_t size,
|
||||
static void sshfs_read_end(struct request *req)
|
||||
{
|
||||
struct read_chunk *chunk = (struct read_chunk *) req->data;
|
||||
if (req->replied) {
|
||||
if (req->error)
|
||||
chunk->res = req->error;
|
||||
else if (req->replied) {
|
||||
chunk->res = -EPROTO;
|
||||
|
||||
if (req->reply_type == SSH_FXP_STATUS) {
|
||||
@@ -1259,8 +1424,9 @@ static void sshfs_read_end(struct request *req)
|
||||
chunk->res = -EIO;
|
||||
|
||||
sem_post(&chunk->ready);
|
||||
chunk_put_locked(chunk);
|
||||
chunk_put(chunk);
|
||||
}
|
||||
|
||||
static void sshfs_read_begin(struct request *req)
|
||||
{
|
||||
struct read_chunk *chunk = (struct read_chunk *) req->data;
|
||||
@@ -1390,6 +1556,10 @@ static int sshfs_read(const char *path, char *rbuf, size_t size, off_t offset,
|
||||
{
|
||||
struct sshfs_file *sf = (struct sshfs_file *) fi->fh;
|
||||
(void) path;
|
||||
|
||||
if (!sshfs_file_is_conn(sf))
|
||||
return -EIO;
|
||||
|
||||
if (sync_read)
|
||||
return sshfs_sync_read(sf, rbuf, size, offset);
|
||||
else
|
||||
@@ -1409,8 +1579,9 @@ static void sshfs_write_end(struct request *req)
|
||||
uint32_t serr;
|
||||
struct sshfs_file *sf = (struct sshfs_file *) req->data;
|
||||
|
||||
pthread_mutex_lock(&lock);
|
||||
if (req->replied) {
|
||||
if (req->error)
|
||||
sf->write_error = req->error;
|
||||
else if (req->replied) {
|
||||
if (req->reply_type != SSH_FXP_STATUS)
|
||||
fprintf(stderr, "protocol error\n");
|
||||
else if (buf_get_uint32(&req->reply, &serr) != -1 && serr != SSH_FX_OK)
|
||||
@@ -1418,7 +1589,6 @@ static void sshfs_write_end(struct request *req)
|
||||
}
|
||||
list_del(&req->list);
|
||||
pthread_cond_broadcast(&sf->write_finished);
|
||||
pthread_mutex_unlock(&lock);
|
||||
}
|
||||
|
||||
static int sshfs_write(const char *path, const char *wbuf, size_t size,
|
||||
@@ -1431,6 +1601,10 @@ static int sshfs_write(const char *path, const char *wbuf, size_t size,
|
||||
struct buffer *handle = &sf->handle;
|
||||
|
||||
(void) path;
|
||||
|
||||
if (!sshfs_file_is_conn(sf))
|
||||
return -EIO;
|
||||
|
||||
data.p = (uint8_t *) wbuf;
|
||||
data.len = size;
|
||||
buf_init(&buf, 0);
|
||||
@@ -1446,36 +1620,6 @@ static int sshfs_write(const char *path, const char *wbuf, size_t size,
|
||||
return err ? err : (int) size;
|
||||
}
|
||||
|
||||
static int sftp_init()
|
||||
{
|
||||
int res = -1;
|
||||
uint8_t type;
|
||||
uint32_t version;
|
||||
struct buffer buf;
|
||||
buf_init(&buf, 4);
|
||||
buf_add_uint32(&buf, PROTO_VERSION);
|
||||
if (sftp_send(SSH_FXP_INIT, &buf) == -1)
|
||||
goto out;
|
||||
buf_clear(&buf);
|
||||
if (sftp_read(&type, &buf) == -1)
|
||||
goto out;
|
||||
if (type != SSH_FXP_VERSION) {
|
||||
fprintf(stderr, "protocol error\n");
|
||||
goto out;
|
||||
}
|
||||
if (buf_get_uint32(&buf, &version) == -1)
|
||||
goto out;
|
||||
if (version != PROTO_VERSION) {
|
||||
fprintf(stderr, "server version: %i, we need: %i\n",
|
||||
version, PROTO_VERSION);
|
||||
goto out;
|
||||
}
|
||||
res = 0;
|
||||
out:
|
||||
buf_free(&buf);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int processing_init(void)
|
||||
{
|
||||
pthread_mutex_init(&lock, NULL);
|
||||
@@ -1489,6 +1633,9 @@ static int processing_init(void)
|
||||
|
||||
static struct fuse_cache_operations sshfs_oper = {
|
||||
.oper = {
|
||||
#if FUSE_VERSION >= 23
|
||||
.init = sshfs_init,
|
||||
#endif
|
||||
.getattr = sshfs_getattr,
|
||||
.readlink = sshfs_readlink,
|
||||
.mknod = sshfs_mknod,
|
||||
@@ -1522,6 +1669,7 @@ static void usage(const char *progname)
|
||||
" -V show version information\n"
|
||||
" -p PORT equivalent to '-o port=PORT'\n"
|
||||
" -C equivalent to '-o compression=yes'\n"
|
||||
" -o reconnect reconnect to server\n"
|
||||
" -o sshfs_sync synchronous writes\n"
|
||||
" -o no_readahead synchronous reads (no speculative readahead)\n"
|
||||
" -o sshfs_debug print some debugging information\n"
|
||||
@@ -1538,7 +1686,6 @@ static void usage(const char *progname)
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char *host = NULL;
|
||||
char *fsname;
|
||||
int res;
|
||||
int argctr;
|
||||
@@ -1614,6 +1761,8 @@ int main(int argc, char *argv[])
|
||||
sync_read = 1;
|
||||
if (sshfs_opts[SOPT_DEBUG].present)
|
||||
debug = 1;
|
||||
if (sshfs_opts[SOPT_RECONNECT].present)
|
||||
reconnect = 1;
|
||||
if (sshfs_opts[SOPT_MAX_READ].present) {
|
||||
unsigned val;
|
||||
if (opt_get_unsigned(&sshfs_opts[SOPT_MAX_READ], &val) == -1)
|
||||
@@ -1631,7 +1780,6 @@ int main(int argc, char *argv[])
|
||||
if (res == -1)
|
||||
exit(1);
|
||||
|
||||
g_free(host);
|
||||
res = sftp_init();
|
||||
if (res == -1)
|
||||
exit(1);
|
||||
|
||||
Reference in New Issue
Block a user