aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiklos Szeredi <miklos@szeredi.hu>2004-12-04 21:20:50 +0000
committerMiklos Szeredi <miklos@szeredi.hu>2004-12-04 21:20:50 +0000
commit7fb3a02ec51a8df16bd79d05d277310e0f5bfbee (patch)
treeb0c5a3df394eee162293b093ab3d46e9558caf44
parentb3483b6bb9d95a4c4e652d927f7a83da5305c189 (diff)
downloadsshfs-7fb3a02ec51a8df16bd79d05d277310e0f5bfbee.tar
sshfs-7fb3a02ec51a8df16bd79d05d277310e0f5bfbee.tar.gz
sshfs-7fb3a02ec51a8df16bd79d05d277310e0f5bfbee.tar.bz2
sshfs-7fb3a02ec51a8df16bd79d05d277310e0f5bfbee.zip
*** empty log message ***
-rw-r--r--AUTHORS1
-rw-r--r--ChangeLog3
-rw-r--r--NEWS4
-rw-r--r--README62
-rw-r--r--sshfs.c156
5 files changed, 180 insertions, 46 deletions
diff --git a/AUTHORS b/AUTHORS
index e69de29..221392d 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -0,0 +1 @@
+Miklos Szeredi <miklos@szeredi.hu>
diff --git a/ChangeLog b/ChangeLog
index e69de29..40354aa 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -0,0 +1,3 @@
+2004-12-04 Miklos Szeredi <miklos@szeredi.hu>
+
+ * Started ChangeLog
diff --git a/NEWS b/NEWS
index e69de29..5d9d503 100644
--- a/NEWS
+++ b/NEWS
@@ -0,0 +1,4 @@
+What is new in 1.0
+------------------
+
+* Initial release
diff --git a/README b/README
index e69de29..6905b85 100644
--- a/README
+++ b/README
@@ -0,0 +1,62 @@
+Abstract
+========
+
+This is a filesystem client based on the SSH File Transfer Protocol.
+Since most SSH servers already support this protocol it is very easy
+to set up: i.e. on the server side there's nothing to do. On the
+client side mounting the filesystem is as easy as logging into the
+server with ssh.
+
+The idea of sshfs was taken from the SSHFS filesystem distributed with
+LUFS, which I found very useful. There were some limitations of that
+codebase, so I rewrote it. Features of this implementation are:
+
+ - Based on FUSE (the best userspace filesystem framework for linux ;)
+
+ - Multithreading: more than one request can be on it's way to the
+ server
+
+ - Allowing large reads (max 64k)
+
+ - Caching directory contents
+
+
+How to mount a filesystem
+=========================
+
+Once sshfs is installed (see next section) running it is very simple:
+
+ sshfs hostname: /mountpoint
+
+Note, that it's recommended to run it as user, not as root. For this
+to work the mountpoint must be owned by the user. If the username is
+different on the host you are connecting to, then use the
+"username@host:" form. If you need to enter a password sshfs will ask
+for it (actually it just runs ssh which ask for the password if
+needed). You can also specify a directory after the ":". The default
+is the home directory.
+
+
+Installing
+==========
+
+First you need to download FUSE 2.2 or later from:
+
+ http://fuse.sourceforge.net
+
+After installing FUSE, compile sshfs the usual way:
+
+ ./configure
+ make
+ make install (as root)
+
+And you are ready to go.
+
+
+Bugs and feature requests
+=========================
+
+Send bug reports to <miklos@szeredi.hu>.
+
+Good luck!
+Miklos Szeredi
diff --git a/sshfs.c b/sshfs.c
index fce536c..a2d1671 100644
--- a/sshfs.c
+++ b/sshfs.c
@@ -1,3 +1,11 @@
+/*
+ SSH file system
+ Copyright (C) 2004 Miklos Szeredi <miklos@szeredi.hu>
+
+ This program can be distributed under the terms of the GNU GPL.
+ See the file COPYING.
+*/
+
#define FUSE_USE_VERSION 22
#include <fuse.h>
#include <stdio.h>
@@ -78,6 +86,7 @@
static int infd;
static int outfd;
static int debug = 0;
+static char *base_path;
struct buffer {
uint8_t *p;
@@ -152,7 +161,7 @@ static const char *type_name(uint8_t type)
static inline void buf_init(struct buffer *buf, size_t size)
{
if (size) {
- buf->p = malloc(size);
+ buf->p = (uint8_t *) malloc(size);
if (!buf->p)
exit(1);
} else
@@ -240,6 +249,13 @@ static inline void buf_add_string(struct buffer *buf, const char *str)
buf_add_data(buf, &data);
}
+static inline void buf_add_path(struct buffer *buf, const char *path)
+{
+ char *realpath = g_strdup_printf("%s%s", base_path, path[1] ? path+1 : ".");
+ buf_add_string(buf, realpath);
+ g_free(realpath);
+}
+
static int buf_check_get(struct buffer *buf, size_t len)
{
if (buf->len + len > buf->size) {
@@ -380,7 +396,7 @@ static void cache_clean(void)
static struct node *cache_lookup(const char *path)
{
- return g_hash_table_lookup(cache, path);
+ return (struct node *) g_hash_table_lookup(cache, path);
}
static void cache_remove(const char *path)
@@ -447,7 +463,7 @@ static int buf_get_entries(struct buffer *buf, fuse_dirh_t h,
if (buf_get_attrs(buf, &stbuf) != -1) {
char *fullpath;
filler(h, name, stbuf.st_mode >> 12, 0);
- fullpath = g_strdup_printf("%s/%s", path, name);
+ fullpath = g_strdup_printf("%s/%s", !path[1] ? "" : path, name);
cache_add_attr(fullpath, &stbuf);
g_free(fullpath);
err = 0;
@@ -460,7 +476,7 @@ static int buf_get_entries(struct buffer *buf, fuse_dirh_t h,
return 0;
}
-static int start_ssh(const char *host)
+static int start_ssh(const char *host, const char *port)
{
int inpipe[2];
int outpipe[2];
@@ -487,7 +503,7 @@ static int start_ssh(const char *host)
close(outpipe[0]);
close(outpipe[1]);
execlp("ssh", "ssh", "-2", "-x", "-a", "-oClearAllForwardings=yes",
- host, "-s", "sftp", NULL);
+ host, "-s", "sftp", port ? "-p" : NULL, port, NULL);
exit(1);
}
close(inpipe[1]);
@@ -495,18 +511,12 @@ static int start_ssh(const char *host)
return 0;
}
-static int connect_to(char *host)
+static int connect_to(char *host, char *port)
{
int err;
int sock;
struct addrinfo *ai;
struct addrinfo hint;
- char *port = strchr(host, ':');
- if (port == NULL) {
- fprintf(stderr, "destination format must be: `.host:port'\n");
- return -1;
- }
- *port++ = '\0';
memset(&hint, 0, sizeof(hint));
hint.ai_family = PF_INET;
@@ -636,7 +646,7 @@ static void *process_requests(void *_data)
break;
pthread_mutex_lock(&lock);
- req = g_hash_table_lookup(reqtab, (gpointer) id);
+ req = (struct request *) g_hash_table_lookup(reqtab, (gpointer) id);
if (req == NULL)
fprintf(stderr, "request %i not found\n", id);
else
@@ -772,7 +782,7 @@ static int sshfs_send_getattr(const char *path, struct stat *stbuf)
struct buffer buf;
struct buffer outbuf;
buf_init(&buf, 0);
- buf_add_string(&buf, path);
+ buf_add_path(&buf, path);
err = sftp_request(SSH_FXP_LSTAT, &buf, SSH_FXP_ATTRS, &outbuf);
if (!err) {
if (buf_get_attrs(&outbuf, stbuf) == -1)
@@ -809,7 +819,7 @@ static int sshfs_readlink(const char *path, char *linkbuf, size_t size)
struct buffer buf;
struct buffer name;
buf_init(&buf, 0);
- buf_add_string(&buf, path);
+ buf_add_path(&buf, path);
err = sftp_request(SSH_FXP_READLINK, &buf, SSH_FXP_NAME, &name);
if (!err) {
uint32_t count;
@@ -834,7 +844,7 @@ static int sshfs_getdir(const char *path, fuse_dirh_t h, fuse_dirfil_t filler)
struct buffer buf;
struct buffer handle;
buf_init(&buf, 0);
- buf_add_string(&buf, path);
+ buf_add_path(&buf, path);
err = sftp_request(SSH_FXP_OPENDIR, &buf, SSH_FXP_HANDLE, &handle);
if (!err) {
int err2;
@@ -865,7 +875,7 @@ static int sshfs_mkdir(const char *path, mode_t mode)
int err;
struct buffer buf;
buf_init(&buf, 0);
- buf_add_string(&buf, path);
+ buf_add_path(&buf, path);
buf_add_uint32(&buf, SSH_FILEXFER_ATTR_PERMISSIONS);
buf_add_uint32(&buf, mode);
err = sftp_request(SSH_FXP_MKDIR, &buf, SSH_FXP_STATUS, NULL);
@@ -883,7 +893,7 @@ static int sshfs_mknod(const char *path, mode_t mode, dev_t rdev)
return -EPERM;
buf_init(&buf, 0);
- buf_add_string(&buf, path);
+ buf_add_path(&buf, path);
buf_add_uint32(&buf, SSH_FXF_WRITE | SSH_FXF_CREAT | SSH_FXF_EXCL);
buf_add_uint32(&buf, SSH_FILEXFER_ATTR_PERMISSIONS);
buf_add_uint32(&buf, mode);
@@ -908,7 +918,7 @@ static int sshfs_symlink(const char *from, const char *to)
link name are mixed up, so we must also be non-standard :( */
buf_init(&buf, 0);
buf_add_string(&buf, from);
- buf_add_string(&buf, to);
+ buf_add_path(&buf, to);
err = sftp_request(SSH_FXP_SYMLINK, &buf, SSH_FXP_STATUS, NULL);
buf_free(&buf);
return err;
@@ -919,7 +929,7 @@ static int sshfs_unlink(const char *path)
int err;
struct buffer buf;
buf_init(&buf, 0);
- buf_add_string(&buf, path);
+ buf_add_path(&buf, path);
err = sftp_request(SSH_FXP_REMOVE, &buf, SSH_FXP_STATUS, NULL);
if (!err)
cache_remove(path);
@@ -932,7 +942,7 @@ static int sshfs_rmdir(const char *path)
int err;
struct buffer buf;
buf_init(&buf, 0);
- buf_add_string(&buf, path);
+ buf_add_path(&buf, path);
err = sftp_request(SSH_FXP_RMDIR, &buf, SSH_FXP_STATUS, NULL);
if (!err)
cache_remove(path);
@@ -945,8 +955,8 @@ static int sshfs_rename(const char *from, const char *to)
int err;
struct buffer buf;
buf_init(&buf, 0);
- buf_add_string(&buf, from);
- buf_add_string(&buf, to);
+ buf_add_path(&buf, from);
+ buf_add_path(&buf, to);
err = sftp_request(SSH_FXP_RENAME, &buf, SSH_FXP_STATUS, NULL);
if (!err)
cache_rename(from, to);
@@ -959,7 +969,7 @@ static int sshfs_chmod(const char *path, mode_t mode)
int err;
struct buffer buf;
buf_init(&buf, 0);
- buf_add_string(&buf, path);
+ buf_add_path(&buf, path);
buf_add_uint32(&buf, SSH_FILEXFER_ATTR_PERMISSIONS);
buf_add_uint32(&buf, mode);
err = sftp_request(SSH_FXP_SETSTAT, &buf, SSH_FXP_STATUS, NULL);
@@ -974,7 +984,7 @@ static int sshfs_chown(const char *path, uid_t uid, gid_t gid)
int err;
struct buffer buf;
buf_init(&buf, 0);
- buf_add_string(&buf, path);
+ buf_add_path(&buf, path);
buf_add_uint32(&buf, SSH_FILEXFER_ATTR_UIDGID);
buf_add_uint32(&buf, uid);
buf_add_uint32(&buf, gid);
@@ -988,7 +998,7 @@ static int sshfs_truncate(const char *path, off_t size)
int err;
struct buffer buf;
buf_init(&buf, 0);
- buf_add_string(&buf, path);
+ 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);
@@ -1004,7 +1014,7 @@ static int sshfs_utime(const char *path, struct utimbuf *ubuf)
struct buffer buf;
cache_remove(path);
buf_init(&buf, 0);
- buf_add_string(&buf, path);
+ buf_add_path(&buf, path);
buf_add_uint32(&buf, SSH_FILEXFER_ATTR_ACMODTIME);
buf_add_uint32(&buf, ubuf->actime);
buf_add_uint32(&buf, ubuf->modtime);
@@ -1032,7 +1042,7 @@ static int sshfs_open(const char *path, struct fuse_file_info *fi)
handle = g_new0(struct buffer, 1);
buf_init(&buf, 0);
- buf_add_string(&buf, path);
+ buf_add_path(&buf, path);
buf_add_uint32(&buf, pflags);
buf_add_uint32(&buf, 0);
err = sftp_request(SSH_FXP_OPEN, &buf, SSH_FXP_HANDLE, handle);
@@ -1168,27 +1178,85 @@ static struct fuse_operations sshfs_oper = {
.write = sshfs_write,
};
+static void usage(const char *progname)
+{
+ const char *fusehelp[] = { progname, "-ho", NULL };
+
+ fprintf(stderr,
+ "usage: %s [user@]host:[dir]] mountpoint [options]\n"
+ "\n"
+ "SSH Options:\n"
+ " -p port remote port\n"
+ " -c port directly connect to port bypassing ssh\n"
+ "\n", progname);
+ fuse_main(2, (char **) fusehelp, &sshfs_oper);
+ exit(1);
+}
+
int main(int argc, char *argv[])
{
- char *host;
+ char *host = NULL;
+ char *port = NULL;
int res;
int argctr;
- char **newargv;
-
- if (argc < 3) {
- fprintf(stderr, "usage: %s [+][user@]host[:port] mountpoint [mount options]\n",
- argv[0]);
+ int direct = 0;
+ int newargc = 0;
+ char **newargv = (char **) malloc((argc + 10) * sizeof(char *));
+ newargv[newargc++] = argv[0];
+
+ for (argctr = 1; argctr < argc; argctr++) {
+ char *arg = argv[argctr];
+ if (arg[0] == '-') {
+ switch (arg[1]) {
+ case 'c':
+ direct = 1;
+ /* fallthrough */
+
+ case 'p':
+ if (arg[2])
+ port = &arg[2];
+ else if (argctr + 1 < argc)
+ port = argv[++argctr];
+ else {
+ fprintf(stderr, "missing argument to %s option\n", arg);
+ fprintf(stderr, "see '%s -h' for usage\n", argv[0]);
+ exit(1);
+ }
+ break;
+
+ case 'h':
+ usage(argv[0]);
+ break;
+
+ default:
+ newargv[newargc++] = arg;
+ }
+ } else if (!host && strchr(arg, ':'))
+ host = g_strdup(arg);
+ else
+ newargv[newargc++] = arg;
+ }
+ if (!host) {
+ fprintf(stderr, "missing host\n");
+ fprintf(stderr, "see '%s -h' for usage\n", argv[0]);
exit(1);
}
- host = argv[1];
- if (host[0] == '+')
- res = connect_to(host+1);
+ base_path = strchr(host, ':');
+ *base_path++ = '\0';
+ if (base_path[0] && base_path[strlen(base_path)-1] != '/')
+ base_path = g_strdup_printf("%s/", base_path);
else
- res = start_ssh(host);
+ base_path = g_strdup(base_path);
+
+ if (!direct)
+ res = start_ssh(host, port);
+ else
+ res = connect_to(host, port);
if (res == -1)
exit(1);
-
+
+ g_free(host);
res = sftp_init();
if (res == -1)
exit(1);
@@ -1197,11 +1265,7 @@ int main(int argc, char *argv[])
if (res == -1)
exit(1);
- newargv = (char **) malloc((argc + 10) * sizeof(char *));
- newargv[0] = argv[0];
- for (argctr = 1; argctr < argc - 1; argctr++)
- newargv[argctr] = argv[argctr + 1];
- newargv[argctr++] = "-omax_read=65536";
- newargv[argctr] = NULL;
- return fuse_main(argctr, newargv, &sshfs_oper);
+ newargv[newargc++] = "-omax_read=65536";
+ newargv[newargc] = NULL;
+ return fuse_main(newargc, newargv, &sshfs_oper);
}