* change usage to ssshfs user@host:path mountpath

* assorted little fixes

ssshfs now works for practical uses
This commit is contained in:
pooka 2006-11-21 23:09:23 +00:00
parent d6bc4d2b49
commit 5676e026f8
3 changed files with 139 additions and 87 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: sftp-connect.c,v 1.1 2006/11/21 00:54:06 pooka Exp $ */ /* $NetBSD: sftp-connect.c,v 1.2 2006/11/21 23:09:23 pooka Exp $ */
/* NetBSD: sftp.c,v 1.21 2006/09/28 21:22:15 christos Exp */ /* NetBSD: sftp.c,v 1.21 2006/09/28 21:22:15 christos Exp */
/* $OpenBSD: sftp.c,v 1.91 2006/08/03 03:34:42 deraadt Exp $ */ /* $OpenBSD: sftp.c,v 1.91 2006/08/03 03:34:42 deraadt Exp $ */
@ -19,7 +19,7 @@
*/ */
#include "includes.h" #include "includes.h"
__RCSID("$NetBSD: sftp-connect.c,v 1.1 2006/11/21 00:54:06 pooka Exp $"); __RCSID("$NetBSD: sftp-connect.c,v 1.2 2006/11/21 23:09:23 pooka Exp $");
#include <sys/types.h> #include <sys/types.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/wait.h> #include <sys/wait.h>
@ -147,12 +147,13 @@ sftp_main(int argc, char **argv)
extern int in, out; extern int in, out;
char *host, *userhost, *cp, *file2 = NULL; char *host, *userhost, *cp, *file2 = NULL;
int debug_level = 0, sshver = 2; int debug_level = 0, sshver = 2;
char *file1 = NULL, *sftp_server = NULL; char *sftp_server = NULL;
char *ssh_program = _PATH_SSH_PROGRAM, *sftp_direct = NULL; char *ssh_program = _PATH_SSH_PROGRAM, *sftp_direct = NULL;
LogLevel ll = SYSLOG_LEVEL_INFO; LogLevel ll = SYSLOG_LEVEL_INFO;
arglist args; arglist args;
extern int optind; extern int optind;
extern char *optarg; extern char *optarg;
extern char *argpath;
/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
sanitise_stdfd(); sanitise_stdfd();
@ -255,7 +256,7 @@ sftp_main(int argc, char **argv)
if ((cp = colon(host)) != NULL) { if ((cp = colon(host)) != NULL) {
*cp++ = '\0'; *cp++ = '\0';
file1 = cp; argpath = cp;
} }
host = cleanhostname(host); host = cleanhostname(host);

View File

@ -1,4 +1,4 @@
/* $NetBSD: sftp-getput.c,v 1.1 2006/11/21 00:54:06 pooka Exp $ */ /* $NetBSD: sftp-getput.c,v 1.2 2006/11/21 23:09:23 pooka Exp $ */
/* NetBSD: sftp-client.c,v 1.26 2006/09/28 21:22:15 christos Exp */ /* NetBSD: sftp-client.c,v 1.26 2006/09/28 21:22:15 christos Exp */
/* $OpenBSD: sftp-client.c,v 1.74 2006/08/03 03:34:42 deraadt Exp $ */ /* $OpenBSD: sftp-client.c,v 1.74 2006/08/03 03:34:42 deraadt Exp $ */
@ -26,7 +26,7 @@
/* XXX: copy between two remote sites */ /* XXX: copy between two remote sites */
#include "includes.h" #include "includes.h"
__RCSID("$NetBSD: sftp-getput.c,v 1.1 2006/11/21 00:54:06 pooka Exp $"); __RCSID("$NetBSD: sftp-getput.c,v 1.2 2006/11/21 23:09:23 pooka Exp $");
#include <sys/types.h> #include <sys/types.h>
#include <sys/queue.h> #include <sys/queue.h>
@ -429,7 +429,7 @@ do_readfile(struct sftp_conn *conn, char *path, uint8_t *localbuf,
} }
int int
do_writefile(struct sftp_conn *conn, const char *path, uint8_t *localbuf, do_writefile(struct sftp_conn *conn, char *path, uint8_t *localbuf,
off_t putoff, size_t *putlen, int append) off_t putoff, size_t *putlen, int append)
{ {
int status; int status;
@ -437,7 +437,8 @@ do_writefile(struct sftp_conn *conn, const char *path, uint8_t *localbuf,
u_int64_t offset; u_int64_t offset;
char *handle, *data; char *handle, *data;
Buffer msg; Buffer msg;
Attrib a; Attrib a, savea;
Attrib *ap;
u_int32_t startid; u_int32_t startid;
u_int32_t ackid; u_int32_t ackid;
struct outstanding_ack { struct outstanding_ack {
@ -451,11 +452,20 @@ do_writefile(struct sftp_conn *conn, const char *path, uint8_t *localbuf,
TAILQ_INIT(&acks); TAILQ_INIT(&acks);
/* XXX: temporarily set file permission to allow writing */
ap = do_stat(conn, path, 1);
if (!ap)
return -1;
memcpy(&savea, ap, sizeof(Attrib));
savea.flags &= ~SSH2_FILEXFER_ATTR_SIZE;
memset(&a, 0, sizeof(a)); memset(&a, 0, sizeof(a));
a.flags &= ~SSH2_FILEXFER_ATTR_SIZE; a.flags = SSH2_FILEXFER_ATTR_PERMISSIONS;
a.flags &= ~SSH2_FILEXFER_ATTR_UIDGID; a.perm = 0777;
a.flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME; if (do_setstat(conn, path, &a)) {
a.perm &= 0777; printf("lossage\n");
return -1;
}
buffer_init(&msg); buffer_init(&msg);
@ -473,6 +483,7 @@ do_writefile(struct sftp_conn *conn, const char *path, uint8_t *localbuf,
handle = get_handle(conn->fd_in, id, &handle_len); handle = get_handle(conn->fd_in, id, &handle_len);
if (handle == NULL) { if (handle == NULL) {
do_setstat(conn, path, &savea);
buffer_free(&msg); buffer_free(&msg);
return(-1); return(-1);
} }
@ -559,6 +570,7 @@ do_writefile(struct sftp_conn *conn, const char *path, uint8_t *localbuf,
*putlen -= (offset - putoff); *putlen -= (offset - putoff);
done: done:
do_setstat(conn, path, &savea);
xfree(handle); xfree(handle);
buffer_free(&msg); buffer_free(&msg);
return(status); return(status);

View File

@ -1,4 +1,4 @@
/* $NetBSD: ssshfs.c,v 1.5 2006/11/21 15:35:58 pooka Exp $ */ /* $NetBSD: ssshfs.c,v 1.6 2006/11/21 23:09:23 pooka Exp $ */
/* /*
* Copyright (c) 2006 Antti Kantee. All Rights Reserved. * Copyright (c) 2006 Antti Kantee. All Rights Reserved.
@ -55,7 +55,7 @@ PUFFSVN_PROTOS(ssshfs)
struct ssshnode { struct ssshnode {
struct ssshnode *dotdot; struct ssshnode *dotdot;
int refcount; int childcount;
ino_t myid; ino_t myid;
char name[MAXPATHLEN+1]; char name[MAXPATHLEN+1];
@ -66,17 +66,19 @@ struct ssshnode {
struct vattr va; struct vattr va;
}; };
#define DCACHE_EXISTS 0x1
#define DCACHE_CHANGED 0x2
static struct sftp_conn *sftpc; static struct sftp_conn *sftpc;
int in, out; int in, out;
static char *basepath;
static struct ssshnode rn; static struct ssshnode rn;
static ino_t nextid = 3; static ino_t nextid = 3;
extern int sftp_main(int argc, char *argv[]); extern int sftp_main(int argc, char *argv[]);
char *argpath; /* XXX: arg passing nightmare */
/* /*
* uberquickhack one-person uidgid-mangler in case the target * uberquickhack one-person uidgid-mangler in case the target
* system doesn't have the same uids and gids * system doesn't have the same uids and gids
@ -95,8 +97,8 @@ main(int argc, char *argv[])
setprogname(argv[0]); setprogname(argv[0]);
if (argc < 4) if (argc < 3)
errx(1, "usage: %s mountpath hostpath user@host",getprogname()); errx(1, "usage: %s user@host:path mountpath", getprogname());
memset(&pvfs, 0, sizeof(struct puffs_vfsops)); memset(&pvfs, 0, sizeof(struct puffs_vfsops));
memset(&pvn, 0, sizeof(struct puffs_vnops)); memset(&pvn, 0, sizeof(struct puffs_vnops));
@ -121,14 +123,12 @@ main(int argc, char *argv[])
pvn.puffs_rename = ssshfs_rename; pvn.puffs_rename = ssshfs_rename;
pvn.puffs_reclaim = ssshfs_reclaim; pvn.puffs_reclaim = ssshfs_reclaim;
mountpath = argv[1]; mountpath = argv[--argc]; /* urgh */
basepath = estrdup(argv[2]);
argv += 2;
argc -= 2;
sftp_main(argc, argv); sftp_main(argc, argv);
if ((pu = puffs_mount(&pvfs, &pvn, mountpath, 0, "ssshfs", 0, 0))==NULL) if ((pu = puffs_mount(&pvfs, &pvn, mountpath, 0, "ssshfs",
PUFFSFLAG_NOCACHE, 0))==NULL)
err(1, "mount"); err(1, "mount");
if (puffs_mainloop(pu) == -1) if (puffs_mainloop(pu) == -1)
@ -186,24 +186,37 @@ vattrtoAttrib(const struct vattr *va)
{ {
static Attrib a; /* XXX, but sftp isn't threadsafe either */ static Attrib a; /* XXX, but sftp isn't threadsafe either */
a.size = va->va_size; memset(&a, 0, sizeof(a));
if (va->va_uid == uidmangle_from && mangle) if (va->va_size != PUFFS_VNOVAL) {
a.uid = uidmangle_to; a.size = va->va_size;
else a.flags |= SSH2_FILEXFER_ATTR_SIZE;
a.uid = va->va_uid; }
if (va->va_gid == gidmangle_from && mangle) if (va->va_uid != PUFFS_VNOVAL) {
a.gid = gidmangle_to; if (va->va_uid == uidmangle_from && mangle)
else a.uid = uidmangle_to;
a.gid = va->va_gid; else
a.uid = va->va_uid;
a.perm = va->va_mode; if (va->va_gid == gidmangle_from && mangle)
a.atime = va->va_atime.tv_sec; a.gid = gidmangle_to;
a.mtime = va->va_mtime.tv_sec; else
a.gid = va->va_gid;
a.flags = SSH2_FILEXFER_ATTR_SIZE | SSH2_FILEXFER_ATTR_UIDGID a.flags |= SSH2_FILEXFER_ATTR_UIDGID;
| SSH2_FILEXFER_ATTR_PERMISSIONS | SSH2_FILEXFER_ATTR_ACMODTIME; }
if (va->va_mode != PUFFS_VNOVAL) {
a.perm = va->va_mode & 0777;
a.flags |= SSH2_FILEXFER_ATTR_PERMISSIONS;
}
if (va->va_atime.tv_sec != PUFFS_VNOVAL) {
a.atime = va->va_atime.tv_sec;
a.mtime = va->va_mtime.tv_sec;
a.flags |= SSH2_FILEXFER_ATTR_ACMODTIME;
}
return &a; return &a;
} }
@ -214,13 +227,19 @@ dircache(struct ssshnode *ssn)
assert(ssn->va.va_type == VDIR); assert(ssn->va.va_type == VDIR);
if (ssn->dcache) if ((ssn->dcache & DCACHE_EXISTS)
&& ((ssn->dcache & DCACHE_CHANGED) == 0))
return 0;
if (ssn->dcache & DCACHE_EXISTS)
free_sftp_dirents(ssn->ents); free_sftp_dirents(ssn->ents);
ssn->dcache = 0; ssn->dcache &= ~DCACHE_EXISTS;
if (do_readdir(sftpc, ssn->name, &ssn->ents) != 0) if (do_readdir(sftpc, ssn->name, &ssn->ents) != 0)
return 1; return 1;
ssn->dcache = 1;
ssn->dcache |= DCACHE_EXISTS;
ssn->dcache &= ~DCACHE_CHANGED;
return 0; return 0;
} }
@ -239,10 +258,12 @@ makenewnode(struct ssshnode *ossn, const char *pcomp, const char *longname)
buildpath(newssn, ossn, pcomp); buildpath(newssn, ossn, pcomp);
ossn->refcount++; ossn->childcount++;
newssn->refcount = 1; newssn->childcount = 0;
newssn->va.va_fileid = newssn->myid; newssn->va.va_fileid = newssn->myid;
newssn->va.va_blocksize = 512; newssn->va.va_blocksize = 512;
newssn->va.va_size = 0;
newssn->va.va_bytes = 0;
/* XXX: only way I know how (didn't look into the protocol, though) */ /* XXX: only way I know how (didn't look into the protocol, though) */
if (longname && (sscanf(longname, "%*s%d", &links) == 1)) if (longname && (sscanf(longname, "%*s%d", &links) == 1))
@ -257,22 +278,32 @@ int
ssshfs_mount(struct puffs_usermount *pu, void **rootcookie) ssshfs_mount(struct puffs_usermount *pu, void **rootcookie)
{ {
rn.refcount = 1;
rn.myid = 2;
memset(rn.name, 0, sizeof(rn.name));
strcpy(rn.name, basepath);
rn.namelen = strlen(rn.name);
rn.va.va_type = VDIR;
rn.va.va_mode = 0777;
sftpc = do_init(in, out, 1<<15, 1); sftpc = do_init(in, out, 1<<15, 1);
if (sftpc == NULL) { if (sftpc == NULL) {
printf("can't init sftpc\n"); printf("can't init sftpc\n");
return EBUSY; return EBUSY;
} }
rn.childcount = 1;
rn.myid = 2;
memset(rn.name, 0, sizeof(rn.name));
if (argpath)
strcpy(rn.name, argpath);
else {
char *dotpath;
dotpath = do_realpath(sftpc, ".");
if (!dotpath)
return ENOENT;
strcpy(rn.name, dotpath);
}
rn.namelen = strlen(rn.name);
rn.va.va_type = VDIR;
rn.va.va_mode = 0777;
rn.va.va_nlink = 1024; /* XXXX */
*rootcookie = &rn; *rootcookie = &rn;
return 0; return 0;
@ -303,8 +334,7 @@ ssshfs_lookup(struct puffs_usermount *pu, void *opc, void **newnode,
return 0; return 0;
} }
if (!ssn->dcache) dircache(ssn);
dircache(ssn);
for (i = 0, de = ssn->ents[0]; de; de = ssn->ents[i++]) for (i = 0, de = ssn->ents[0]; de; de = ssn->ents[i++])
if (strcmp(de->filename, pcn->pcn_name) == 0) if (strcmp(de->filename, pcn->pcn_name) == 0)
@ -330,7 +360,6 @@ ssshfs_getattr(struct puffs_usermount *pu, void *opc, struct vattr *va,
struct ssshnode *ssn = opc; struct ssshnode *ssn = opc;
memcpy(va, &ssn->va, sizeof(struct vattr)); memcpy(va, &ssn->va, sizeof(struct vattr));
va->va_type = VREG;
return 0; return 0;
} }
@ -344,10 +373,12 @@ ssshfs_setattr(struct puffs_usermount *pu, void *opc, const struct vattr *va,
int rv; int rv;
puffs_setvattr(&ssn->va, va); puffs_setvattr(&ssn->va, va);
a = vattrtoAttrib(&ssn->va); a = vattrtoAttrib(va);
/* XXXXX */ /* XXX: compensate for lack of granulatity of SSH2_FILEXFER */
return 0; if ((a->flags & SSH2_FILEXFER_ATTR_ACMODTIME)
&& (va->va_mtime.tv_sec == PUFFS_VNOVAL))
a->mtime = ssn->va.va_mtime.tv_sec;
rv = do_setstat(sftpc, ssn->name, a); rv = do_setstat(sftpc, ssn->name, a);
if (rv) if (rv)
@ -366,14 +397,14 @@ ssshfs_create(struct puffs_usermount *pu, void *opc, void **newnode,
int rv; int rv;
newssn = makenewnode(ssd, pcn->pcn_name, NULL); newssn = makenewnode(ssd, pcn->pcn_name, NULL);
memcpy(&newssn->va, va, sizeof(struct vattr)); puffs_setvattr(&newssn->va, va);
a = vattrtoAttrib(va); a = vattrtoAttrib(va);
if ((rv = do_creatfile(sftpc, newssn->name, a)) != 0) { if ((rv = do_creatfile(sftpc, newssn->name, a)) != 0) {
/* XXX: free newssn */ /* XXX: free newssn */
return EIO; return EIO;
} }
dircache(ssd); ssd->dcache |= DCACHE_CHANGED;
ssd->va.va_nlink++; ssd->va.va_nlink++;
*newnode = newssn; *newnode = newssn;
@ -387,8 +418,7 @@ ssshfs_readdir(struct puffs_usermount *pu, void *opc, struct dirent *dent,
struct ssshnode *ssn = opc; struct ssshnode *ssn = opc;
struct SFTP_DIRENT *de; struct SFTP_DIRENT *de;
if (!ssn->dcache) dircache(ssn);
dircache(ssn);
for (de = ssn->ents[*readoff]; de; de = ssn->ents[++(*readoff)]) { for (de = ssn->ents[*readoff]; de; de = ssn->ents[++(*readoff)]) {
if (!puffs_nextdent(&dent, de->filename, nextid++, if (!puffs_nextdent(&dent, de->filename, nextid++,
@ -404,18 +434,27 @@ ssshfs_read(struct puffs_usermount *pu, void *opc, uint8_t *buf,
off_t offset, size_t *resid, const struct puffs_cred *pcr, off_t offset, size_t *resid, const struct puffs_cred *pcr,
int ioflag) int ioflag)
{ {
size_t x1, x2;
struct ssshnode *ssn = opc; struct ssshnode *ssn = opc;
int rv; int rv;
if (offset + *resid > ssn->va.va_size) if (offset > ssn->va.va_size)
*resid = ssn->va.va_size - offset;
if (*resid == 0)
return 0; return 0;
rv = do_readfile(sftpc, ssn->name, buf, offset, resid); x1 = *resid;
if (offset + *resid > ssn->va.va_size)
x1 = ssn->va.va_size - offset;
if (x1 == 0)
return 0;
x2 = x1;
rv = do_readfile(sftpc, ssn->name, buf, offset, &x1);
if (rv) if (rv)
return EIO; return EIO;
*resid -= (x2 - x1);
return 0; return 0;
} }
@ -442,8 +481,6 @@ ssshfs_write(struct puffs_usermount *pu, void *opc, uint8_t *buf,
if (rv) if (rv)
return EIO; return EIO;
dircache(ssn->dotdot);
return 0; return 0;
} }
@ -476,7 +513,7 @@ ssshfs_remove(struct puffs_usermount *pu, void *opc, void *targ,
if ((rv = do_rm(sftpc, ssn->name)) != 0) if ((rv = do_rm(sftpc, ssn->name)) != 0)
return EIO; return EIO;
dircache(ssd); ssd->dcache |= DCACHE_CHANGED;
ssd->va.va_nlink--; ssd->va.va_nlink--;
return 0; return 0;
@ -491,16 +528,16 @@ ssshfs_mkdir(struct puffs_usermount *pu, void *opc, void **newnode,
int rv; int rv;
newssn = makenewnode(ssd, pcn->pcn_name, NULL); newssn = makenewnode(ssd, pcn->pcn_name, NULL);
memcpy(&newssn->va, va, sizeof(struct vattr)); newssn->va.va_nlink++;
puffs_setvattr(&newssn->va, va);
a = vattrtoAttrib(va); a = vattrtoAttrib(va);
if ((rv = do_mkdir(sftpc, newssn->name, a)) != 0) { if ((rv = do_mkdir(sftpc, newssn->name, a)) != 0) {
/* XXX: free newssn */ /* XXX: free newssn */
return EIO; return EIO;
} }
dircache(ssd); ssd->dcache |= DCACHE_CHANGED;
ssd->va.va_nlink++; ssd->va.va_nlink++;
newssn->va.va_nlink++;
*newnode = newssn; *newnode = newssn;
return 0; return 0;
@ -519,7 +556,7 @@ ssshfs_rmdir(struct puffs_usermount *pu, void *opc, void *targ,
if ((rv = do_rmdir(sftpc, ssn->name)) != 0) if ((rv = do_rmdir(sftpc, ssn->name)) != 0)
return EIO; return EIO;
dircache(ssd); ssd->dcache |= DCACHE_CHANGED;
ssd->va.va_nlink--; ssd->va.va_nlink--;
return 0; return 0;
@ -544,12 +581,12 @@ ssshfs_symlink(struct puffs_usermount *pu, void *opc, void **newnode,
} }
newssn = makenewnode(ssd, pcn->pcn_name, NULL); newssn = makenewnode(ssd, pcn->pcn_name, NULL);
memcpy(&newssn->va, va, sizeof(struct vattr)); puffs_setvattr(&newssn->va, va);
a = vattrtoAttrib(va); a = vattrtoAttrib(va);
if ((rv = do_symlink(sftpc, newssn->name, buf)) != 0) if ((rv = do_symlink(sftpc, newssn->name, buf)) != 0)
return EIO; return EIO;
dircache(ssd); ssd->dcache |= DCACHE_CHANGED;
ssd->va.va_nlink++; ssd->va.va_nlink++;
*newnode = newssn; *newnode = newssn;
@ -578,13 +615,13 @@ ssshfs_rename(struct puffs_usermount *pu, void *opc, void *src,
/* ok, commit */ /* ok, commit */
ssn_file->namelen = strlen(newname); ssn_file->namelen = strlen(newname);
ssd_src->refcount--; ssd_src->childcount--;
ssd_src->va.va_nlink--; ssd_src->va.va_nlink--;
ssd_dest->refcount++; ssd_dest->childcount++;
ssd_dest->va.va_nlink++; ssd_dest->va.va_nlink++;
dircache(ssd_src); ssd_src->dcache |= DCACHE_CHANGED;
dircache(ssd_dest); ssd_dest->dcache |= DCACHE_CHANGED;
return 0; return 0;
} }
@ -592,16 +629,18 @@ ssshfs_rename(struct puffs_usermount *pu, void *opc, void *src,
int int
ssshfs_reclaim(struct puffs_usermount *pu, void *opc, pid_t pid) ssshfs_reclaim(struct puffs_usermount *pu, void *opc, pid_t pid)
{ {
struct ssshnode *ssn = opc; struct ssshnode *ssn, *ssn_next;
/* XXX */ for (ssn = opc; ssn != &rn; ssn = ssn_next) {
if (ssn->childcount == 0) {
#if 0 if (ssn->dcache & DCACHE_EXISTS)
if (--ssn->refcount == 0) { free_sftp_dirents(ssn->ents);
free_sftp_dirents(ssn->ents); ssn_next = ssn->dotdot;
free(ssn); ssn_next->childcount--;
free(ssn);
} else
break;
} }
#endif
return 0; return 0;
} }