mirror of
https://github.com/PowerShell/openssh-portable.git
synced 2025-04-08 18:35:05 +02:00
- djm@cvs.openbsd.org 2002/02/13 00:59:23
[sftp-client.c sftp-client.h sftp-glob.c sftp-glob.h sftp.h] [sftp-int.c sftp-int.h] API cleanup and backwards compat for filexfer v.0 servers; ok markus@
This commit is contained in:
parent
3606ee2938
commit
3db5f530d0
@ -30,6 +30,10 @@
|
||||
- markus@cvs.openbsd.org 2002/02/13 00:39:15
|
||||
[readpass.c]
|
||||
readpass.c is not longer from UCB, since we now use readpassphrase(3)
|
||||
- djm@cvs.openbsd.org 2002/02/13 00:59:23
|
||||
[sftp-client.c sftp-client.h sftp-glob.c sftp-glob.h sftp.h]
|
||||
[sftp-int.c sftp-int.h]
|
||||
API cleanup and backwards compat for filexfer v.0 servers; ok markus@
|
||||
|
||||
20020210
|
||||
- (djm) OpenBSD CVS Sync
|
||||
@ -7577,4 +7581,4 @@
|
||||
- Wrote replacements for strlcpy and mkdtemp
|
||||
- Released 1.0pre1
|
||||
|
||||
$Id: ChangeLog,v 1.1847 2002/02/13 03:05:23 djm Exp $
|
||||
$Id: ChangeLog,v 1.1848 2002/02/13 03:10:32 djm Exp $
|
||||
|
302
sftp-client.c
302
sftp-client.c
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001-2002 Damien Miller. All rights reserved.
|
||||
* Copyright (c) 2001,2002 Damien Miller. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@ -24,11 +24,11 @@
|
||||
|
||||
/* XXX: memleaks */
|
||||
/* XXX: signed vs unsigned */
|
||||
/* XXX: we use fatal too much, error may be more appropriate in places */
|
||||
/* XXX: remove all logging, only return status codes */
|
||||
/* XXX: copy between two remote sites */
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: sftp-client.c,v 1.22 2002/02/12 12:44:46 djm Exp $");
|
||||
RCSID("$OpenBSD: sftp-client.c,v 1.23 2002/02/13 00:59:23 djm Exp $");
|
||||
|
||||
#if defined(HAVE_SYS_QUEUE_H) && !defined(HAVE_BOGUS_SYS_QUEUE_H)
|
||||
#include <sys/queue.h>
|
||||
@ -50,8 +50,14 @@ RCSID("$OpenBSD: sftp-client.c,v 1.22 2002/02/12 12:44:46 djm Exp $");
|
||||
/* Minimum amount of data to read at at time */
|
||||
#define MIN_READ_SIZE 512
|
||||
|
||||
/* Message ID */
|
||||
static u_int msg_id = 1;
|
||||
struct sftp_conn {
|
||||
int fd_in;
|
||||
int fd_out;
|
||||
u_int transfer_buflen;
|
||||
u_int num_requests;
|
||||
u_int version;
|
||||
u_int msg_id;
|
||||
};
|
||||
|
||||
static void
|
||||
send_msg(int fd, Buffer *m)
|
||||
@ -219,11 +225,12 @@ get_decode_stat(int fd, u_int expected_id, int quiet)
|
||||
return(a);
|
||||
}
|
||||
|
||||
int
|
||||
do_init(int fd_in, int fd_out)
|
||||
struct sftp_conn *
|
||||
do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests)
|
||||
{
|
||||
int type, version;
|
||||
Buffer msg;
|
||||
struct sftp_conn *ret;
|
||||
|
||||
buffer_init(&msg);
|
||||
buffer_put_char(&msg, SSH2_FXP_INIT);
|
||||
@ -239,7 +246,7 @@ do_init(int fd_in, int fd_out)
|
||||
error("Invalid packet back from SSH2_FXP_INIT (type %d)",
|
||||
type);
|
||||
buffer_free(&msg);
|
||||
return(-1);
|
||||
return(NULL);
|
||||
}
|
||||
version = buffer_get_int(&msg);
|
||||
|
||||
@ -257,25 +264,43 @@ do_init(int fd_in, int fd_out)
|
||||
|
||||
buffer_free(&msg);
|
||||
|
||||
return(version);
|
||||
ret = xmalloc(sizeof(*ret));
|
||||
ret->fd_in = fd_in;
|
||||
ret->fd_out = fd_out;
|
||||
ret->transfer_buflen = transfer_buflen;
|
||||
ret->num_requests = num_requests;
|
||||
ret->version = version;
|
||||
ret->msg_id = 1;
|
||||
|
||||
/* Some filexfer v.0 servers don't support large packets */
|
||||
if (version == 0)
|
||||
ret->transfer_buflen = MAX(ret->transfer_buflen, 20480);
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
u_int
|
||||
sftp_proto_version(struct sftp_conn *conn)
|
||||
{
|
||||
return(conn->version);
|
||||
}
|
||||
|
||||
int
|
||||
do_close(int fd_in, int fd_out, char *handle, u_int handle_len)
|
||||
do_close(struct sftp_conn *conn, char *handle, u_int handle_len)
|
||||
{
|
||||
u_int id, status;
|
||||
Buffer msg;
|
||||
|
||||
buffer_init(&msg);
|
||||
|
||||
id = msg_id++;
|
||||
id = conn->msg_id++;
|
||||
buffer_put_char(&msg, SSH2_FXP_CLOSE);
|
||||
buffer_put_int(&msg, id);
|
||||
buffer_put_string(&msg, handle, handle_len);
|
||||
send_msg(fd_out, &msg);
|
||||
send_msg(conn->fd_out, &msg);
|
||||
debug3("Sent message SSH2_FXP_CLOSE I:%d", id);
|
||||
|
||||
status = get_status(fd_in, id);
|
||||
status = get_status(conn->fd_in, id);
|
||||
if (status != SSH2_FX_OK)
|
||||
error("Couldn't close file: %s", fx2txt(status));
|
||||
|
||||
@ -286,24 +311,24 @@ do_close(int fd_in, int fd_out, char *handle, u_int handle_len)
|
||||
|
||||
|
||||
static int
|
||||
do_lsreaddir(int fd_in, int fd_out, char *path, int printflag,
|
||||
do_lsreaddir(struct sftp_conn *conn, char *path, int printflag,
|
||||
SFTP_DIRENT ***dir)
|
||||
{
|
||||
Buffer msg;
|
||||
u_int type, id, handle_len, i, expected_id, ents = 0;
|
||||
char *handle;
|
||||
|
||||
id = msg_id++;
|
||||
id = conn->msg_id++;
|
||||
|
||||
buffer_init(&msg);
|
||||
buffer_put_char(&msg, SSH2_FXP_OPENDIR);
|
||||
buffer_put_int(&msg, id);
|
||||
buffer_put_cstring(&msg, path);
|
||||
send_msg(fd_out, &msg);
|
||||
send_msg(conn->fd_out, &msg);
|
||||
|
||||
buffer_clear(&msg);
|
||||
|
||||
handle = get_handle(fd_in, id, &handle_len);
|
||||
handle = get_handle(conn->fd_in, id, &handle_len);
|
||||
if (handle == NULL)
|
||||
return(-1);
|
||||
|
||||
@ -316,7 +341,7 @@ do_lsreaddir(int fd_in, int fd_out, char *path, int printflag,
|
||||
for (;;) {
|
||||
int count;
|
||||
|
||||
id = expected_id = msg_id++;
|
||||
id = expected_id = conn->msg_id++;
|
||||
|
||||
debug3("Sending SSH2_FXP_READDIR I:%d", id);
|
||||
|
||||
@ -324,11 +349,11 @@ do_lsreaddir(int fd_in, int fd_out, char *path, int printflag,
|
||||
buffer_put_char(&msg, SSH2_FXP_READDIR);
|
||||
buffer_put_int(&msg, id);
|
||||
buffer_put_string(&msg, handle, handle_len);
|
||||
send_msg(fd_out, &msg);
|
||||
send_msg(conn->fd_out, &msg);
|
||||
|
||||
buffer_clear(&msg);
|
||||
|
||||
get_msg(fd_in, &msg);
|
||||
get_msg(conn->fd_in, &msg);
|
||||
|
||||
type = buffer_get_char(&msg);
|
||||
id = buffer_get_int(&msg);
|
||||
@ -348,7 +373,7 @@ do_lsreaddir(int fd_in, int fd_out, char *path, int printflag,
|
||||
} else {
|
||||
error("Couldn't read directory: %s",
|
||||
fx2txt(status));
|
||||
do_close(fd_in, fd_out, handle, handle_len);
|
||||
do_close(conn, handle, handle_len);
|
||||
return(status);
|
||||
}
|
||||
} else if (type != SSH2_FXP_NAME)
|
||||
@ -386,22 +411,22 @@ do_lsreaddir(int fd_in, int fd_out, char *path, int printflag,
|
||||
}
|
||||
|
||||
buffer_free(&msg);
|
||||
do_close(fd_in, fd_out, handle, handle_len);
|
||||
do_close(conn, handle, handle_len);
|
||||
xfree(handle);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
int
|
||||
do_ls(int fd_in, int fd_out, char *path)
|
||||
do_ls(struct sftp_conn *conn, char *path)
|
||||
{
|
||||
return(do_lsreaddir(fd_in, fd_out, path, 1, NULL));
|
||||
return(do_lsreaddir(conn, path, 1, NULL));
|
||||
}
|
||||
|
||||
int
|
||||
do_readdir(int fd_in, int fd_out, char *path, SFTP_DIRENT ***dir)
|
||||
do_readdir(struct sftp_conn *conn, char *path, SFTP_DIRENT ***dir)
|
||||
{
|
||||
return(do_lsreaddir(fd_in, fd_out, path, 0, dir));
|
||||
return(do_lsreaddir(conn, path, 0, dir));
|
||||
}
|
||||
|
||||
void free_sftp_dirents(SFTP_DIRENT **s)
|
||||
@ -417,30 +442,31 @@ void free_sftp_dirents(SFTP_DIRENT **s)
|
||||
}
|
||||
|
||||
int
|
||||
do_rm(int fd_in, int fd_out, char *path)
|
||||
do_rm(struct sftp_conn *conn, char *path)
|
||||
{
|
||||
u_int status, id;
|
||||
|
||||
debug2("Sending SSH2_FXP_REMOVE \"%s\"", path);
|
||||
|
||||
id = msg_id++;
|
||||
send_string_request(fd_out, id, SSH2_FXP_REMOVE, path, strlen(path));
|
||||
status = get_status(fd_in, id);
|
||||
id = conn->msg_id++;
|
||||
send_string_request(conn->fd_out, id, SSH2_FXP_REMOVE, path,
|
||||
strlen(path));
|
||||
status = get_status(conn->fd_in, id);
|
||||
if (status != SSH2_FX_OK)
|
||||
error("Couldn't delete file: %s", fx2txt(status));
|
||||
return(status);
|
||||
}
|
||||
|
||||
int
|
||||
do_mkdir(int fd_in, int fd_out, char *path, Attrib *a)
|
||||
do_mkdir(struct sftp_conn *conn, char *path, Attrib *a)
|
||||
{
|
||||
u_int status, id;
|
||||
|
||||
id = msg_id++;
|
||||
send_string_attrs_request(fd_out, id, SSH2_FXP_MKDIR, path,
|
||||
id = conn->msg_id++;
|
||||
send_string_attrs_request(conn->fd_out, id, SSH2_FXP_MKDIR, path,
|
||||
strlen(path), a);
|
||||
|
||||
status = get_status(fd_in, id);
|
||||
status = get_status(conn->fd_in, id);
|
||||
if (status != SSH2_FX_OK)
|
||||
error("Couldn't create directory: %s", fx2txt(status));
|
||||
|
||||
@ -448,14 +474,15 @@ do_mkdir(int fd_in, int fd_out, char *path, Attrib *a)
|
||||
}
|
||||
|
||||
int
|
||||
do_rmdir(int fd_in, int fd_out, char *path)
|
||||
do_rmdir(struct sftp_conn *conn, char *path)
|
||||
{
|
||||
u_int status, id;
|
||||
|
||||
id = msg_id++;
|
||||
send_string_request(fd_out, id, SSH2_FXP_RMDIR, path, strlen(path));
|
||||
id = conn->msg_id++;
|
||||
send_string_request(conn->fd_out, id, SSH2_FXP_RMDIR, path,
|
||||
strlen(path));
|
||||
|
||||
status = get_status(fd_in, id);
|
||||
status = get_status(conn->fd_in, id);
|
||||
if (status != SSH2_FX_OK)
|
||||
error("Couldn't remove directory: %s", fx2txt(status));
|
||||
|
||||
@ -463,45 +490,61 @@ do_rmdir(int fd_in, int fd_out, char *path)
|
||||
}
|
||||
|
||||
Attrib *
|
||||
do_stat(int fd_in, int fd_out, char *path, int quiet)
|
||||
do_stat(struct sftp_conn *conn, char *path, int quiet)
|
||||
{
|
||||
u_int id;
|
||||
|
||||
id = msg_id++;
|
||||
send_string_request(fd_out, id, SSH2_FXP_STAT, path, strlen(path));
|
||||
return(get_decode_stat(fd_in, id, quiet));
|
||||
id = conn->msg_id++;
|
||||
|
||||
send_string_request(conn->fd_out, id,
|
||||
conn->version == 0 ? SSH2_FXP_STAT_VERSION_0 : SSH2_FXP_STAT,
|
||||
path, strlen(path));
|
||||
|
||||
return(get_decode_stat(conn->fd_in, id, quiet));
|
||||
}
|
||||
|
||||
Attrib *
|
||||
do_lstat(int fd_in, int fd_out, char *path, int quiet)
|
||||
do_lstat(struct sftp_conn *conn, char *path, int quiet)
|
||||
{
|
||||
u_int id;
|
||||
|
||||
id = msg_id++;
|
||||
send_string_request(fd_out, id, SSH2_FXP_LSTAT, path, strlen(path));
|
||||
return(get_decode_stat(fd_in, id, quiet));
|
||||
if (conn->version == 0) {
|
||||
if (quiet)
|
||||
debug("Server version does not support lstat operation");
|
||||
else
|
||||
error("Server version does not support lstat operation");
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
id = conn->msg_id++;
|
||||
send_string_request(conn->fd_out, id, SSH2_FXP_LSTAT, path,
|
||||
strlen(path));
|
||||
|
||||
return(get_decode_stat(conn->fd_in, id, quiet));
|
||||
}
|
||||
|
||||
Attrib *
|
||||
do_fstat(int fd_in, int fd_out, char *handle, u_int handle_len, int quiet)
|
||||
do_fstat(struct sftp_conn *conn, char *handle, u_int handle_len, int quiet)
|
||||
{
|
||||
u_int id;
|
||||
|
||||
id = msg_id++;
|
||||
send_string_request(fd_out, id, SSH2_FXP_FSTAT, handle, handle_len);
|
||||
return(get_decode_stat(fd_in, id, quiet));
|
||||
id = conn->msg_id++;
|
||||
send_string_request(conn->fd_out, id, SSH2_FXP_FSTAT, handle,
|
||||
handle_len);
|
||||
|
||||
return(get_decode_stat(conn->fd_in, id, quiet));
|
||||
}
|
||||
|
||||
int
|
||||
do_setstat(int fd_in, int fd_out, char *path, Attrib *a)
|
||||
do_setstat(struct sftp_conn *conn, char *path, Attrib *a)
|
||||
{
|
||||
u_int status, id;
|
||||
|
||||
id = msg_id++;
|
||||
send_string_attrs_request(fd_out, id, SSH2_FXP_SETSTAT, path,
|
||||
id = conn->msg_id++;
|
||||
send_string_attrs_request(conn->fd_out, id, SSH2_FXP_SETSTAT, path,
|
||||
strlen(path), a);
|
||||
|
||||
status = get_status(fd_in, id);
|
||||
status = get_status(conn->fd_in, id);
|
||||
if (status != SSH2_FX_OK)
|
||||
error("Couldn't setstat on \"%s\": %s", path,
|
||||
fx2txt(status));
|
||||
@ -510,16 +553,16 @@ do_setstat(int fd_in, int fd_out, char *path, Attrib *a)
|
||||
}
|
||||
|
||||
int
|
||||
do_fsetstat(int fd_in, int fd_out, char *handle, u_int handle_len,
|
||||
do_fsetstat(struct sftp_conn *conn, char *handle, u_int handle_len,
|
||||
Attrib *a)
|
||||
{
|
||||
u_int status, id;
|
||||
|
||||
id = msg_id++;
|
||||
send_string_attrs_request(fd_out, id, SSH2_FXP_FSETSTAT, handle,
|
||||
id = conn->msg_id++;
|
||||
send_string_attrs_request(conn->fd_out, id, SSH2_FXP_FSETSTAT, handle,
|
||||
handle_len, a);
|
||||
|
||||
status = get_status(fd_in, id);
|
||||
status = get_status(conn->fd_in, id);
|
||||
if (status != SSH2_FX_OK)
|
||||
error("Couldn't fsetstat: %s", fx2txt(status));
|
||||
|
||||
@ -527,19 +570,20 @@ do_fsetstat(int fd_in, int fd_out, char *handle, u_int handle_len,
|
||||
}
|
||||
|
||||
char *
|
||||
do_realpath(int fd_in, int fd_out, char *path)
|
||||
do_realpath(struct sftp_conn *conn, char *path)
|
||||
{
|
||||
Buffer msg;
|
||||
u_int type, expected_id, count, id;
|
||||
char *filename, *longname;
|
||||
Attrib *a;
|
||||
|
||||
expected_id = id = msg_id++;
|
||||
send_string_request(fd_out, id, SSH2_FXP_REALPATH, path, strlen(path));
|
||||
expected_id = id = conn->msg_id++;
|
||||
send_string_request(conn->fd_out, id, SSH2_FXP_REALPATH, path,
|
||||
strlen(path));
|
||||
|
||||
buffer_init(&msg);
|
||||
|
||||
get_msg(fd_in, &msg);
|
||||
get_msg(conn->fd_in, &msg);
|
||||
type = buffer_get_char(&msg);
|
||||
id = buffer_get_int(&msg);
|
||||
|
||||
@ -573,7 +617,7 @@ do_realpath(int fd_in, int fd_out, char *path)
|
||||
}
|
||||
|
||||
int
|
||||
do_rename(int fd_in, int fd_out, char *oldpath, char *newpath)
|
||||
do_rename(struct sftp_conn *conn, char *oldpath, char *newpath)
|
||||
{
|
||||
Buffer msg;
|
||||
u_int status, id;
|
||||
@ -581,65 +625,71 @@ do_rename(int fd_in, int fd_out, char *oldpath, char *newpath)
|
||||
buffer_init(&msg);
|
||||
|
||||
/* Send rename request */
|
||||
id = msg_id++;
|
||||
id = conn->msg_id++;
|
||||
buffer_put_char(&msg, SSH2_FXP_RENAME);
|
||||
buffer_put_int(&msg, id);
|
||||
buffer_put_cstring(&msg, oldpath);
|
||||
buffer_put_cstring(&msg, newpath);
|
||||
send_msg(fd_out, &msg);
|
||||
send_msg(conn->fd_out, &msg);
|
||||
debug3("Sent message SSH2_FXP_RENAME \"%s\" -> \"%s\"", oldpath,
|
||||
newpath);
|
||||
buffer_free(&msg);
|
||||
|
||||
status = get_status(fd_in, id);
|
||||
status = get_status(conn->fd_in, id);
|
||||
if (status != SSH2_FX_OK)
|
||||
error("Couldn't rename file \"%s\" to \"%s\": %s", oldpath, newpath,
|
||||
fx2txt(status));
|
||||
error("Couldn't rename file \"%s\" to \"%s\": %s", oldpath,
|
||||
newpath, fx2txt(status));
|
||||
|
||||
return(status);
|
||||
}
|
||||
|
||||
int
|
||||
do_symlink(int fd_in, int fd_out, char *oldpath, char *newpath)
|
||||
do_symlink(struct sftp_conn *conn, char *oldpath, char *newpath)
|
||||
{
|
||||
Buffer msg;
|
||||
u_int status, id;
|
||||
|
||||
if (conn->version < 3) {
|
||||
error("This server does not support the symlink operation");
|
||||
return(SSH2_FX_OP_UNSUPPORTED);
|
||||
}
|
||||
|
||||
buffer_init(&msg);
|
||||
|
||||
/* Send rename request */
|
||||
id = msg_id++;
|
||||
id = conn->msg_id++;
|
||||
buffer_put_char(&msg, SSH2_FXP_SYMLINK);
|
||||
buffer_put_int(&msg, id);
|
||||
buffer_put_cstring(&msg, oldpath);
|
||||
buffer_put_cstring(&msg, newpath);
|
||||
send_msg(fd_out, &msg);
|
||||
send_msg(conn->fd_out, &msg);
|
||||
debug3("Sent message SSH2_FXP_SYMLINK \"%s\" -> \"%s\"", oldpath,
|
||||
newpath);
|
||||
buffer_free(&msg);
|
||||
|
||||
status = get_status(fd_in, id);
|
||||
status = get_status(conn->fd_in, id);
|
||||
if (status != SSH2_FX_OK)
|
||||
error("Couldn't rename file \"%s\" to \"%s\": %s", oldpath, newpath,
|
||||
fx2txt(status));
|
||||
error("Couldn't rename file \"%s\" to \"%s\": %s", oldpath,
|
||||
newpath, fx2txt(status));
|
||||
|
||||
return(status);
|
||||
}
|
||||
|
||||
char *
|
||||
do_readlink(int fd_in, int fd_out, char *path)
|
||||
do_readlink(struct sftp_conn *conn, char *path)
|
||||
{
|
||||
Buffer msg;
|
||||
u_int type, expected_id, count, id;
|
||||
char *filename, *longname;
|
||||
Attrib *a;
|
||||
|
||||
expected_id = id = msg_id++;
|
||||
send_string_request(fd_out, id, SSH2_FXP_READLINK, path, strlen(path));
|
||||
expected_id = id = conn->msg_id++;
|
||||
send_string_request(conn->fd_out, id, SSH2_FXP_READLINK, path,
|
||||
strlen(path));
|
||||
|
||||
buffer_init(&msg);
|
||||
|
||||
get_msg(fd_in, &msg);
|
||||
get_msg(conn->fd_in, &msg);
|
||||
type = buffer_get_char(&msg);
|
||||
id = buffer_get_int(&msg);
|
||||
|
||||
@ -690,8 +740,8 @@ send_read_request(int fd_out, u_int id, u_int64_t offset, u_int len,
|
||||
}
|
||||
|
||||
int
|
||||
do_download(int fd_in, int fd_out, char *remote_path, char *local_path,
|
||||
int pflag, size_t buflen, int num_requests)
|
||||
do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
|
||||
int pflag)
|
||||
{
|
||||
Attrib junk, *a;
|
||||
Buffer msg;
|
||||
@ -699,7 +749,7 @@ do_download(int fd_in, int fd_out, char *remote_path, char *local_path,
|
||||
int local_fd, status, num_req, max_req, write_error;
|
||||
int read_error, write_errno;
|
||||
u_int64_t offset, size;
|
||||
u_int handle_len, mode, type, id;
|
||||
u_int handle_len, mode, type, id, buflen;
|
||||
struct request {
|
||||
u_int id;
|
||||
u_int len;
|
||||
@ -711,7 +761,7 @@ do_download(int fd_in, int fd_out, char *remote_path, char *local_path,
|
||||
|
||||
TAILQ_INIT(&requests);
|
||||
|
||||
a = do_stat(fd_in, fd_out, remote_path, 0);
|
||||
a = do_stat(conn, remote_path, 0);
|
||||
if (a == NULL)
|
||||
return(-1);
|
||||
|
||||
@ -732,33 +782,34 @@ do_download(int fd_in, int fd_out, char *remote_path, char *local_path,
|
||||
else
|
||||
size = 0;
|
||||
|
||||
local_fd = open(local_path, O_WRONLY | O_CREAT | O_TRUNC, mode);
|
||||
if (local_fd == -1) {
|
||||
error("Couldn't open local file \"%s\" for writing: %s",
|
||||
local_path, strerror(errno));
|
||||
return(-1);
|
||||
}
|
||||
|
||||
buflen = conn->transfer_buflen;
|
||||
buffer_init(&msg);
|
||||
|
||||
/* Send open request */
|
||||
id = msg_id++;
|
||||
id = conn->msg_id++;
|
||||
buffer_put_char(&msg, SSH2_FXP_OPEN);
|
||||
buffer_put_int(&msg, id);
|
||||
buffer_put_cstring(&msg, remote_path);
|
||||
buffer_put_int(&msg, SSH2_FXF_READ);
|
||||
attrib_clear(&junk); /* Send empty attributes */
|
||||
encode_attrib(&msg, &junk);
|
||||
send_msg(fd_out, &msg);
|
||||
send_msg(conn->fd_out, &msg);
|
||||
debug3("Sent message SSH2_FXP_OPEN I:%d P:%s", id, remote_path);
|
||||
|
||||
handle = get_handle(fd_in, id, &handle_len);
|
||||
handle = get_handle(conn->fd_in, id, &handle_len);
|
||||
if (handle == NULL) {
|
||||
buffer_free(&msg);
|
||||
close(local_fd);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
local_fd = open(local_path, O_WRONLY | O_CREAT | O_TRUNC, mode);
|
||||
if (local_fd == -1) {
|
||||
error("Couldn't open local file \"%s\" for writing: %s",
|
||||
local_path, strerror(errno));
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/* Read from remote and write to local */
|
||||
write_error = read_error = write_errno = num_req = offset = 0;
|
||||
max_req = 1;
|
||||
@ -771,18 +822,18 @@ do_download(int fd_in, int fd_out, char *remote_path, char *local_path,
|
||||
debug3("Request range %llu -> %llu (%d/%d)",
|
||||
offset, offset + buflen - 1, num_req, max_req);
|
||||
req = xmalloc(sizeof(*req));
|
||||
req->id = msg_id++;
|
||||
req->id = conn->msg_id++;
|
||||
req->len = buflen;
|
||||
req->offset = offset;
|
||||
offset += buflen;
|
||||
num_req++;
|
||||
TAILQ_INSERT_TAIL(&requests, req, tq);
|
||||
send_read_request(fd_out, req->id, req->offset,
|
||||
send_read_request(conn->fd_out, req->id, req->offset,
|
||||
req->len, handle, handle_len);
|
||||
}
|
||||
|
||||
buffer_clear(&msg);
|
||||
get_msg(fd_in, &msg);
|
||||
get_msg(conn->fd_in, &msg);
|
||||
type = buffer_get_char(&msg);
|
||||
id = buffer_get_int(&msg);
|
||||
debug3("Received reply T:%d I:%d R:%d", type, id, max_req);
|
||||
@ -830,12 +881,11 @@ do_download(int fd_in, int fd_out, char *remote_path, char *local_path,
|
||||
debug3("Short data block, re-requesting "
|
||||
"%llu -> %llu (%2d)", req->offset + len,
|
||||
req->offset + req->len - 1, num_req);
|
||||
req->id = msg_id++;
|
||||
req->id = conn->msg_id++;
|
||||
req->len -= len;
|
||||
req->offset += len;
|
||||
send_read_request(fd_out, req->id,
|
||||
req->offset, req->len, handle,
|
||||
handle_len);
|
||||
send_read_request(conn->fd_out, req->id,
|
||||
req->offset, req->len, handle, handle_len);
|
||||
/* Reduce the request size */
|
||||
if (len < buflen)
|
||||
buflen = MAX(MIN_READ_SIZE, len);
|
||||
@ -848,7 +898,7 @@ do_download(int fd_in, int fd_out, char *remote_path, char *local_path,
|
||||
offset, num_req);
|
||||
max_req = 1;
|
||||
}
|
||||
else if (max_req < num_requests + 1) {
|
||||
else if (max_req < conn->num_requests + 1) {
|
||||
++max_req;
|
||||
}
|
||||
}
|
||||
@ -864,17 +914,16 @@ do_download(int fd_in, int fd_out, char *remote_path, char *local_path,
|
||||
fatal("Transfer complete, but requests still in queue");
|
||||
|
||||
if (read_error) {
|
||||
error("Couldn't read from remote "
|
||||
"file \"%s\" : %s", remote_path,
|
||||
fx2txt(status));
|
||||
do_close(fd_in, fd_out, handle, handle_len);
|
||||
error("Couldn't read from remote file \"%s\" : %s",
|
||||
remote_path, fx2txt(status));
|
||||
do_close(conn, handle, handle_len);
|
||||
} else if (write_error) {
|
||||
error("Couldn't write to \"%s\": %s", local_path,
|
||||
strerror(write_errno));
|
||||
status = -1;
|
||||
do_close(fd_in, fd_out, handle, handle_len);
|
||||
error("Couldn't write to \"%s\": %s", local_path,
|
||||
strerror(write_errno));
|
||||
status = -1;
|
||||
do_close(conn, handle, handle_len);
|
||||
} else {
|
||||
status = do_close(fd_in, fd_out, handle, handle_len);
|
||||
status = do_close(conn, handle, handle_len);
|
||||
|
||||
/* Override umask and utimes if asked */
|
||||
#ifdef HAVE_FCHMOD
|
||||
@ -897,12 +946,13 @@ do_download(int fd_in, int fd_out, char *remote_path, char *local_path,
|
||||
close(local_fd);
|
||||
buffer_free(&msg);
|
||||
xfree(handle);
|
||||
return status;
|
||||
|
||||
return(status);
|
||||
}
|
||||
|
||||
int
|
||||
do_upload(int fd_in, int fd_out, char *local_path, char *remote_path,
|
||||
int pflag, size_t buflen, int num_requests)
|
||||
do_upload(struct sftp_conn *conn, char *local_path, char *remote_path,
|
||||
int pflag)
|
||||
{
|
||||
int local_fd, status;
|
||||
u_int handle_len, id, type;
|
||||
@ -946,18 +996,18 @@ do_upload(int fd_in, int fd_out, char *local_path, char *remote_path,
|
||||
buffer_init(&msg);
|
||||
|
||||
/* Send open request */
|
||||
id = msg_id++;
|
||||
id = conn->msg_id++;
|
||||
buffer_put_char(&msg, SSH2_FXP_OPEN);
|
||||
buffer_put_int(&msg, id);
|
||||
buffer_put_cstring(&msg, remote_path);
|
||||
buffer_put_int(&msg, SSH2_FXF_WRITE|SSH2_FXF_CREAT|SSH2_FXF_TRUNC);
|
||||
encode_attrib(&msg, &a);
|
||||
send_msg(fd_out, &msg);
|
||||
send_msg(conn->fd_out, &msg);
|
||||
debug3("Sent message SSH2_FXP_OPEN I:%d P:%s", id, remote_path);
|
||||
|
||||
buffer_clear(&msg);
|
||||
|
||||
handle = get_handle(fd_in, id, &handle_len);
|
||||
handle = get_handle(conn->fd_in, id, &handle_len);
|
||||
if (handle == NULL) {
|
||||
close(local_fd);
|
||||
buffer_free(&msg);
|
||||
@ -965,7 +1015,7 @@ do_upload(int fd_in, int fd_out, char *local_path, char *remote_path,
|
||||
}
|
||||
|
||||
startid = ackid = id + 1;
|
||||
data = xmalloc(buflen);
|
||||
data = xmalloc(conn->transfer_buflen);
|
||||
|
||||
/* Read from local and write to remote */
|
||||
offset = 0;
|
||||
@ -977,7 +1027,7 @@ do_upload(int fd_in, int fd_out, char *local_path, char *remote_path,
|
||||
* the last block of the file
|
||||
*/
|
||||
do
|
||||
len = read(local_fd, data, buflen);
|
||||
len = read(local_fd, data, conn->transfer_buflen);
|
||||
while ((len == -1) && (errno == EINTR || errno == EAGAIN));
|
||||
|
||||
if (len == -1)
|
||||
@ -997,7 +1047,7 @@ do_upload(int fd_in, int fd_out, char *local_path, char *remote_path,
|
||||
buffer_put_string(&msg, handle, handle_len);
|
||||
buffer_put_int64(&msg, offset);
|
||||
buffer_put_string(&msg, data, len);
|
||||
send_msg(fd_out, &msg);
|
||||
send_msg(conn->fd_out, &msg);
|
||||
debug3("Sent message SSH2_FXP_WRITE I:%d O:%llu S:%u",
|
||||
id, (u_int64_t)offset, len);
|
||||
} else if (TAILQ_FIRST(&acks) == NULL)
|
||||
@ -1006,9 +1056,10 @@ do_upload(int fd_in, int fd_out, char *local_path, char *remote_path,
|
||||
if (ack == NULL)
|
||||
fatal("Unexpected ACK %u", id);
|
||||
|
||||
if (id == startid || len == 0 || id - ackid >= num_requests) {
|
||||
if (id == startid || len == 0 ||
|
||||
id - ackid >= conn->num_requests) {
|
||||
buffer_clear(&msg);
|
||||
get_msg(fd_in, &msg);
|
||||
get_msg(conn->fd_in, &msg);
|
||||
type = buffer_get_char(&msg);
|
||||
id = buffer_get_int(&msg);
|
||||
|
||||
@ -1031,7 +1082,7 @@ do_upload(int fd_in, int fd_out, char *local_path, char *remote_path,
|
||||
if (status != SSH2_FX_OK) {
|
||||
error("Couldn't write to remote file \"%s\": %s",
|
||||
remote_path, fx2txt(status));
|
||||
do_close(fd_in, fd_out, handle, handle_len);
|
||||
do_close(conn, handle, handle_len);
|
||||
close(local_fd);
|
||||
goto done;
|
||||
}
|
||||
@ -1040,7 +1091,6 @@ do_upload(int fd_in, int fd_out, char *local_path, char *remote_path,
|
||||
++ackid;
|
||||
free(ack);
|
||||
}
|
||||
|
||||
offset += len;
|
||||
}
|
||||
xfree(data);
|
||||
@ -1048,19 +1098,19 @@ do_upload(int fd_in, int fd_out, char *local_path, char *remote_path,
|
||||
if (close(local_fd) == -1) {
|
||||
error("Couldn't close local file \"%s\": %s", local_path,
|
||||
strerror(errno));
|
||||
do_close(fd_in, fd_out, handle, handle_len);
|
||||
do_close(conn, handle, handle_len);
|
||||
status = -1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Override umask and utimes if asked */
|
||||
if (pflag)
|
||||
do_fsetstat(fd_in, fd_out, handle, handle_len, &a);
|
||||
do_fsetstat(conn, handle, handle_len, &a);
|
||||
|
||||
status = do_close(fd_in, fd_out, handle, handle_len);
|
||||
status = do_close(conn, handle, handle_len);
|
||||
|
||||
done:
|
||||
xfree(handle);
|
||||
buffer_free(&msg);
|
||||
return status;
|
||||
return(status);
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* $OpenBSD: sftp-client.h,v 1.8 2002/02/12 12:32:27 djm Exp $ */
|
||||
/* $OpenBSD: sftp-client.h,v 1.9 2002/02/13 00:59:23 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2002 Damien Miller. All rights reserved.
|
||||
* Copyright (c) 2001,2002 Damien Miller. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@ -26,6 +26,9 @@
|
||||
|
||||
/* Client side of SSH2 filexfer protocol */
|
||||
|
||||
#ifndef _SFTP_CLIENT_H
|
||||
#define _SFTP_CLIENT_H
|
||||
|
||||
typedef struct SFTP_DIRENT SFTP_DIRENT;
|
||||
|
||||
struct SFTP_DIRENT {
|
||||
@ -38,55 +41,59 @@ struct SFTP_DIRENT {
|
||||
* Initialiase a SSH filexfer connection. Returns -1 on error or
|
||||
* protocol version on success.
|
||||
*/
|
||||
int do_init(int, int);
|
||||
struct sftp_conn *
|
||||
do_init(int, int, u_int, u_int);
|
||||
|
||||
u_int
|
||||
sftp_proto_version(struct sftp_conn *);
|
||||
|
||||
/* Close file referred to by 'handle' */
|
||||
int do_close(int, int, char *, u_int);
|
||||
int do_close(struct sftp_conn *, char *, u_int);
|
||||
|
||||
/* List contents of directory 'path' to stdout */
|
||||
int do_ls(int, int, char *);
|
||||
int do_ls(struct sftp_conn *, char *);
|
||||
|
||||
/* Read contents of 'path' to NULL-terminated array 'dir' */
|
||||
int do_readdir(int, int, char *, SFTP_DIRENT ***);
|
||||
int do_readdir(struct sftp_conn *, char *, SFTP_DIRENT ***);
|
||||
|
||||
/* Frees a NULL-terminated array of SFTP_DIRENTs (eg. from do_readdir) */
|
||||
void free_sftp_dirents(SFTP_DIRENT **);
|
||||
|
||||
/* Delete file 'path' */
|
||||
int do_rm(int, int, char *);
|
||||
int do_rm(struct sftp_conn *, char *);
|
||||
|
||||
/* Create directory 'path' */
|
||||
int do_mkdir(int, int, char *, Attrib *);
|
||||
int do_mkdir(struct sftp_conn *, char *, Attrib *);
|
||||
|
||||
/* Remove directory 'path' */
|
||||
int do_rmdir(int, int, char *);
|
||||
int do_rmdir(struct sftp_conn *, char *);
|
||||
|
||||
/* Get file attributes of 'path' (follows symlinks) */
|
||||
Attrib *do_stat(int, int, char *, int);
|
||||
Attrib *do_stat(struct sftp_conn *, char *, int);
|
||||
|
||||
/* Get file attributes of 'path' (does not follow symlinks) */
|
||||
Attrib *do_lstat(int, int, char *, int);
|
||||
Attrib *do_lstat(struct sftp_conn *, char *, int);
|
||||
|
||||
/* Get file attributes of open file 'handle' */
|
||||
Attrib *do_fstat(int, int, char *, u_int, int);
|
||||
Attrib *do_fstat(struct sftp_conn *, char *, u_int, int);
|
||||
|
||||
/* Set file attributes of 'path' */
|
||||
int do_setstat(int, int, char *, Attrib *);
|
||||
int do_setstat(struct sftp_conn *, char *, Attrib *);
|
||||
|
||||
/* Set file attributes of open file 'handle' */
|
||||
int do_fsetstat(int, int, char *, u_int, Attrib *);
|
||||
int do_fsetstat(struct sftp_conn *, char *, u_int, Attrib *);
|
||||
|
||||
/* Canonicalise 'path' - caller must free result */
|
||||
char *do_realpath(int, int, char *);
|
||||
char *do_realpath(struct sftp_conn *, char *);
|
||||
|
||||
/* Rename 'oldpath' to 'newpath' */
|
||||
int do_rename(int, int, char *, char *);
|
||||
int do_rename(struct sftp_conn *, char *, char *);
|
||||
|
||||
/* Rename 'oldpath' to 'newpath' */
|
||||
int do_symlink(int, int, char *, char *);
|
||||
int do_symlink(struct sftp_conn *, char *, char *);
|
||||
|
||||
/* Return target of symlink 'path' - caller must free result */
|
||||
char *do_readlink(int, int, char *);
|
||||
char *do_readlink(struct sftp_conn *, char *);
|
||||
|
||||
/* XXX: add callbacks to do_download/do_upload so we can do progress meter */
|
||||
|
||||
@ -94,10 +101,12 @@ char *do_readlink(int, int, char *);
|
||||
* Download 'remote_path' to 'local_path'. Preserve permissions and times
|
||||
* if 'pflag' is set
|
||||
*/
|
||||
int do_download(int, int, char *, char *, int, size_t, int);
|
||||
int do_download(struct sftp_conn *, char *, char *, int);
|
||||
|
||||
/*
|
||||
* Upload 'local_path' to 'remote_path'. Preserve permissions and times
|
||||
* if 'pflag' is set
|
||||
*/
|
||||
int do_upload(int, int, char *, char *, int , size_t, int);
|
||||
int do_upload(struct sftp_conn *, char *, char *, int);
|
||||
|
||||
#endif
|
||||
|
21
sftp-glob.c
21
sftp-glob.c
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001 Damien Miller. All rights reserved.
|
||||
* Copyright (c) 2001,2002 Damien Miller. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@ -23,7 +23,7 @@
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: sftp-glob.c,v 1.9 2001/12/19 07:18:56 deraadt Exp $");
|
||||
RCSID("$OpenBSD: sftp-glob.c,v 1.10 2002/02/13 00:59:23 djm Exp $");
|
||||
|
||||
#include "buffer.h"
|
||||
#include "bufaux.h"
|
||||
@ -41,8 +41,7 @@ struct SFTP_OPENDIR {
|
||||
};
|
||||
|
||||
static struct {
|
||||
int fd_in;
|
||||
int fd_out;
|
||||
struct sftp_conn *conn;
|
||||
} cur;
|
||||
|
||||
static void *
|
||||
@ -52,7 +51,7 @@ fudge_opendir(const char *path)
|
||||
|
||||
r = xmalloc(sizeof(*r));
|
||||
|
||||
if (do_readdir(cur.fd_in, cur.fd_out, (char*)path, &r->dir))
|
||||
if (do_readdir(cur.conn, (char*)path, &r->dir))
|
||||
return(NULL);
|
||||
|
||||
r->offset = 0;
|
||||
@ -130,7 +129,7 @@ fudge_lstat(const char *path, struct stat *st)
|
||||
{
|
||||
Attrib *a;
|
||||
|
||||
if (!(a = do_lstat(cur.fd_in, cur.fd_out, (char*)path, 0)))
|
||||
if (!(a = do_lstat(cur.conn, (char*)path, 0)))
|
||||
return(-1);
|
||||
|
||||
attrib_to_stat(a, st);
|
||||
@ -143,7 +142,7 @@ fudge_stat(const char *path, struct stat *st)
|
||||
{
|
||||
Attrib *a;
|
||||
|
||||
if (!(a = do_stat(cur.fd_in, cur.fd_out, (char*)path, 0)))
|
||||
if (!(a = do_stat(cur.conn, (char*)path, 0)))
|
||||
return(-1);
|
||||
|
||||
attrib_to_stat(a, st);
|
||||
@ -152,7 +151,7 @@ fudge_stat(const char *path, struct stat *st)
|
||||
}
|
||||
|
||||
int
|
||||
remote_glob(int fd_in, int fd_out, const char *pattern, int flags,
|
||||
remote_glob(struct sftp_conn *conn, const char *pattern, int flags,
|
||||
int (*errfunc)(const char *, int), glob_t *pglob)
|
||||
{
|
||||
pglob->gl_opendir = fudge_opendir;
|
||||
@ -162,9 +161,7 @@ remote_glob(int fd_in, int fd_out, const char *pattern, int flags,
|
||||
pglob->gl_stat = fudge_stat;
|
||||
|
||||
memset(&cur, 0, sizeof(cur));
|
||||
cur.fd_in = fd_in;
|
||||
cur.fd_out = fd_out;
|
||||
cur.conn = conn;
|
||||
|
||||
return(glob(pattern, flags | GLOB_ALTDIRFUNC, errfunc,
|
||||
pglob));
|
||||
return(glob(pattern, flags | GLOB_ALTDIRFUNC, errfunc, pglob));
|
||||
}
|
||||
|
14
sftp-glob.h
14
sftp-glob.h
@ -1,7 +1,7 @@
|
||||
/* $OpenBSD: sftp-glob.h,v 1.5 2001/06/26 17:27:24 markus Exp $ */
|
||||
/* $OpenBSD: sftp-glob.h,v 1.6 2002/02/13 00:59:23 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001 Damien Miller. All rights reserved.
|
||||
* Copyright (c) 2001,2002 Damien Miller. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@ -26,5 +26,13 @@
|
||||
|
||||
/* Remote sftp filename globbing */
|
||||
|
||||
#ifndef _SFTP_GLOB_H
|
||||
#define _SFTP_GLOB_H
|
||||
|
||||
#include "sftp-client.h"
|
||||
|
||||
int
|
||||
remote_glob(int, int, const char *, int, int (*)(const char *, int), glob_t *);
|
||||
remote_glob(struct sftp_conn *, const char *, int,
|
||||
int (*)(const char *, int), glob_t *);
|
||||
|
||||
#endif
|
||||
|
104
sftp-int.c
104
sftp-int.c
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001 Damien Miller. All rights reserved.
|
||||
* Copyright (c) 2001,2002 Damien Miller. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@ -26,7 +26,7 @@
|
||||
/* XXX: recursive operations */
|
||||
|
||||
#include "includes.h"
|
||||
RCSID("$OpenBSD: sftp-int.c,v 1.43 2002/02/12 12:32:27 djm Exp $");
|
||||
RCSID("$OpenBSD: sftp-int.c,v 1.44 2002/02/13 00:59:23 djm Exp $");
|
||||
|
||||
#include "buffer.h"
|
||||
#include "xmalloc.h"
|
||||
@ -48,9 +48,6 @@ extern size_t copy_buffer_len;
|
||||
/* Number of concurrent outstanding requests */
|
||||
extern int num_requests;
|
||||
|
||||
/* Version of server we are speaking to */
|
||||
int version;
|
||||
|
||||
/* Seperators for interactive commands */
|
||||
#define WHITESPACE " \t\r\n"
|
||||
|
||||
@ -336,12 +333,12 @@ is_dir(char *path)
|
||||
}
|
||||
|
||||
static int
|
||||
remote_is_dir(int in, int out, char *path)
|
||||
remote_is_dir(struct sftp_conn *conn, char *path)
|
||||
{
|
||||
Attrib *a;
|
||||
|
||||
/* XXX: report errors? */
|
||||
if ((a = do_stat(in, out, path, 1)) == NULL)
|
||||
if ((a = do_stat(conn, path, 1)) == NULL)
|
||||
return(0);
|
||||
if (!(a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS))
|
||||
return(0);
|
||||
@ -349,7 +346,7 @@ remote_is_dir(int in, int out, char *path)
|
||||
}
|
||||
|
||||
static int
|
||||
process_get(int in, int out, char *src, char *dst, char *pwd, int pflag)
|
||||
process_get(struct sftp_conn *conn, char *src, char *dst, char *pwd, int pflag)
|
||||
{
|
||||
char *abs_src = NULL;
|
||||
char *abs_dst = NULL;
|
||||
@ -363,7 +360,7 @@ process_get(int in, int out, char *src, char *dst, char *pwd, int pflag)
|
||||
|
||||
memset(&g, 0, sizeof(g));
|
||||
debug3("Looking up %s", abs_src);
|
||||
if (remote_glob(in, out, abs_src, 0, NULL, &g)) {
|
||||
if (remote_glob(conn, abs_src, 0, NULL, &g)) {
|
||||
error("File \"%s\" not found.", abs_src);
|
||||
err = -1;
|
||||
goto out;
|
||||
@ -387,8 +384,7 @@ process_get(int in, int out, char *src, char *dst, char *pwd, int pflag)
|
||||
goto out;
|
||||
}
|
||||
printf("Fetching %s to %s\n", g.gl_pathv[0], abs_dst);
|
||||
err = do_download(in, out, g.gl_pathv[0], abs_dst, pflag,
|
||||
copy_buffer_len, num_requests);
|
||||
err = do_download(conn, g.gl_pathv[0], abs_dst, pflag);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -412,8 +408,7 @@ process_get(int in, int out, char *src, char *dst, char *pwd, int pflag)
|
||||
abs_dst = tmp;
|
||||
|
||||
printf("Fetching %s to %s\n", g.gl_pathv[i], abs_dst);
|
||||
if (do_download(in, out, g.gl_pathv[i], abs_dst, pflag,
|
||||
copy_buffer_len, num_requests) == -1)
|
||||
if (do_download(conn, g.gl_pathv[i], abs_dst, pflag) == -1)
|
||||
err = -1;
|
||||
xfree(abs_dst);
|
||||
abs_dst = NULL;
|
||||
@ -428,7 +423,7 @@ out:
|
||||
}
|
||||
|
||||
static int
|
||||
process_put(int in, int out, char *src, char *dst, char *pwd, int pflag)
|
||||
process_put(struct sftp_conn *conn, char *src, char *dst, char *pwd, int pflag)
|
||||
{
|
||||
char *tmp_dst = NULL;
|
||||
char *abs_dst = NULL;
|
||||
@ -454,7 +449,7 @@ process_put(int in, int out, char *src, char *dst, char *pwd, int pflag)
|
||||
if (g.gl_pathv[0] && g.gl_matchc == 1) {
|
||||
if (tmp_dst) {
|
||||
/* If directory specified, append filename */
|
||||
if (remote_is_dir(in, out, tmp_dst)) {
|
||||
if (remote_is_dir(conn, tmp_dst)) {
|
||||
if (infer_path(g.gl_pathv[0], &tmp)) {
|
||||
err = 1;
|
||||
goto out;
|
||||
@ -471,13 +466,12 @@ process_put(int in, int out, char *src, char *dst, char *pwd, int pflag)
|
||||
abs_dst = make_absolute(abs_dst, pwd);
|
||||
}
|
||||
printf("Uploading %s to %s\n", g.gl_pathv[0], abs_dst);
|
||||
err = do_upload(in, out, g.gl_pathv[0], abs_dst, pflag,
|
||||
copy_buffer_len, num_requests);
|
||||
err = do_upload(conn, g.gl_pathv[0], abs_dst, pflag);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Multiple matches, dst may be directory or unspecified */
|
||||
if (tmp_dst && !remote_is_dir(in, out, tmp_dst)) {
|
||||
if (tmp_dst && !remote_is_dir(conn, tmp_dst)) {
|
||||
error("Multiple files match, but \"%s\" is not a directory",
|
||||
tmp_dst);
|
||||
err = -1;
|
||||
@ -496,8 +490,7 @@ process_put(int in, int out, char *src, char *dst, char *pwd, int pflag)
|
||||
abs_dst = make_absolute(tmp, pwd);
|
||||
|
||||
printf("Uploading %s to %s\n", g.gl_pathv[i], abs_dst);
|
||||
if (do_upload(in, out, g.gl_pathv[i], abs_dst, pflag,
|
||||
copy_buffer_len, num_requests) == -1)
|
||||
if (do_upload(conn, g.gl_pathv[i], abs_dst, pflag) == -1)
|
||||
err = -1;
|
||||
}
|
||||
|
||||
@ -655,7 +648,7 @@ parse_args(const char **cpp, int *pflag, unsigned long *n_arg,
|
||||
}
|
||||
|
||||
static int
|
||||
parse_dispatch_command(int in, int out, const char *cmd, char **pwd)
|
||||
parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd)
|
||||
{
|
||||
char *path1, *path2, *tmp;
|
||||
int pflag, cmdnum, i;
|
||||
@ -675,32 +668,26 @@ parse_dispatch_command(int in, int out, const char *cmd, char **pwd)
|
||||
case -1:
|
||||
break;
|
||||
case I_GET:
|
||||
err = process_get(in, out, path1, path2, *pwd, pflag);
|
||||
err = process_get(conn, path1, path2, *pwd, pflag);
|
||||
break;
|
||||
case I_PUT:
|
||||
err = process_put(in, out, path1, path2, *pwd, pflag);
|
||||
err = process_put(conn, path1, path2, *pwd, pflag);
|
||||
break;
|
||||
case I_RENAME:
|
||||
path1 = make_absolute(path1, *pwd);
|
||||
path2 = make_absolute(path2, *pwd);
|
||||
err = do_rename(in, out, path1, path2);
|
||||
err = do_rename(conn, path1, path2);
|
||||
break;
|
||||
case I_SYMLINK:
|
||||
if (version < 3) {
|
||||
error("The server (version %d) does not support "
|
||||
"this operation", version);
|
||||
err = -1;
|
||||
} else {
|
||||
path2 = make_absolute(path2, *pwd);
|
||||
err = do_symlink(in, out, path1, path2);
|
||||
}
|
||||
path2 = make_absolute(path2, *pwd);
|
||||
err = do_symlink(conn, path1, path2);
|
||||
break;
|
||||
case I_RM:
|
||||
path1 = make_absolute(path1, *pwd);
|
||||
remote_glob(in, out, path1, GLOB_NOCHECK, NULL, &g);
|
||||
remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g);
|
||||
for (i = 0; g.gl_pathv[i]; i++) {
|
||||
printf("Removing %s\n", g.gl_pathv[i]);
|
||||
if (do_rm(in, out, g.gl_pathv[i]) == -1)
|
||||
if (do_rm(conn, g.gl_pathv[i]) == -1)
|
||||
err = -1;
|
||||
}
|
||||
break;
|
||||
@ -709,19 +696,19 @@ parse_dispatch_command(int in, int out, const char *cmd, char **pwd)
|
||||
attrib_clear(&a);
|
||||
a.flags |= SSH2_FILEXFER_ATTR_PERMISSIONS;
|
||||
a.perm = 0777;
|
||||
err = do_mkdir(in, out, path1, &a);
|
||||
err = do_mkdir(conn, path1, &a);
|
||||
break;
|
||||
case I_RMDIR:
|
||||
path1 = make_absolute(path1, *pwd);
|
||||
err = do_rmdir(in, out, path1);
|
||||
err = do_rmdir(conn, path1);
|
||||
break;
|
||||
case I_CHDIR:
|
||||
path1 = make_absolute(path1, *pwd);
|
||||
if ((tmp = do_realpath(in, out, path1)) == NULL) {
|
||||
if ((tmp = do_realpath(conn, path1)) == NULL) {
|
||||
err = 1;
|
||||
break;
|
||||
}
|
||||
if ((aa = do_stat(in, out, tmp, 0)) == NULL) {
|
||||
if ((aa = do_stat(conn, tmp, 0)) == NULL) {
|
||||
xfree(tmp);
|
||||
err = 1;
|
||||
break;
|
||||
@ -744,22 +731,22 @@ parse_dispatch_command(int in, int out, const char *cmd, char **pwd)
|
||||
break;
|
||||
case I_LS:
|
||||
if (!path1) {
|
||||
do_ls(in, out, *pwd);
|
||||
do_ls(conn, *pwd);
|
||||
break;
|
||||
}
|
||||
path1 = make_absolute(path1, *pwd);
|
||||
if ((tmp = do_realpath(in, out, path1)) == NULL)
|
||||
if ((tmp = do_realpath(conn, path1)) == NULL)
|
||||
break;
|
||||
xfree(path1);
|
||||
path1 = tmp;
|
||||
if ((aa = do_stat(in, out, path1, 0)) == NULL)
|
||||
if ((aa = do_stat(conn, path1, 0)) == NULL)
|
||||
break;
|
||||
if ((aa->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) &&
|
||||
!S_ISDIR(aa->perm)) {
|
||||
error("Can't ls: \"%s\" is not a directory", path1);
|
||||
break;
|
||||
}
|
||||
do_ls(in, out, path1);
|
||||
do_ls(conn, path1);
|
||||
break;
|
||||
case I_LCHDIR:
|
||||
if (chdir(path1) == -1) {
|
||||
@ -790,17 +777,17 @@ parse_dispatch_command(int in, int out, const char *cmd, char **pwd)
|
||||
attrib_clear(&a);
|
||||
a.flags |= SSH2_FILEXFER_ATTR_PERMISSIONS;
|
||||
a.perm = n_arg;
|
||||
remote_glob(in, out, path1, GLOB_NOCHECK, NULL, &g);
|
||||
remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g);
|
||||
for (i = 0; g.gl_pathv[i]; i++) {
|
||||
printf("Changing mode on %s\n", g.gl_pathv[i]);
|
||||
do_setstat(in, out, g.gl_pathv[i], &a);
|
||||
do_setstat(conn, g.gl_pathv[i], &a);
|
||||
}
|
||||
break;
|
||||
case I_CHOWN:
|
||||
path1 = make_absolute(path1, *pwd);
|
||||
remote_glob(in, out, path1, GLOB_NOCHECK, NULL, &g);
|
||||
remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g);
|
||||
for (i = 0; g.gl_pathv[i]; i++) {
|
||||
if (!(aa = do_stat(in, out, g.gl_pathv[i], 0)))
|
||||
if (!(aa = do_stat(conn, g.gl_pathv[i], 0)))
|
||||
continue;
|
||||
if (!(aa->flags & SSH2_FILEXFER_ATTR_UIDGID)) {
|
||||
error("Can't get current ownership of "
|
||||
@ -810,14 +797,14 @@ parse_dispatch_command(int in, int out, const char *cmd, char **pwd)
|
||||
printf("Changing owner on %s\n", g.gl_pathv[i]);
|
||||
aa->flags &= SSH2_FILEXFER_ATTR_UIDGID;
|
||||
aa->uid = n_arg;
|
||||
do_setstat(in, out, g.gl_pathv[i], aa);
|
||||
do_setstat(conn, g.gl_pathv[i], aa);
|
||||
}
|
||||
break;
|
||||
case I_CHGRP:
|
||||
path1 = make_absolute(path1, *pwd);
|
||||
remote_glob(in, out, path1, GLOB_NOCHECK, NULL, &g);
|
||||
remote_glob(conn, path1, GLOB_NOCHECK, NULL, &g);
|
||||
for (i = 0; g.gl_pathv[i]; i++) {
|
||||
if (!(aa = do_stat(in, out, g.gl_pathv[i], 0)))
|
||||
if (!(aa = do_stat(conn, g.gl_pathv[i], 0)))
|
||||
continue;
|
||||
if (!(aa->flags & SSH2_FILEXFER_ATTR_UIDGID)) {
|
||||
error("Can't get current ownership of "
|
||||
@ -827,7 +814,7 @@ parse_dispatch_command(int in, int out, const char *cmd, char **pwd)
|
||||
printf("Changing group on %s\n", g.gl_pathv[i]);
|
||||
aa->flags &= SSH2_FILEXFER_ATTR_UIDGID;
|
||||
aa->gid = n_arg;
|
||||
do_setstat(in, out, g.gl_pathv[i], aa);
|
||||
do_setstat(conn, g.gl_pathv[i], aa);
|
||||
}
|
||||
break;
|
||||
case I_PWD:
|
||||
@ -847,7 +834,7 @@ parse_dispatch_command(int in, int out, const char *cmd, char **pwd)
|
||||
help();
|
||||
break;
|
||||
case I_VERSION:
|
||||
printf("SFTP protocol version %d\n", version);
|
||||
printf("SFTP protocol version %d\n", sftp_proto_version(conn));
|
||||
break;
|
||||
default:
|
||||
fatal("%d is not implemented", cmdnum);
|
||||
@ -873,12 +860,13 @@ interactive_loop(int fd_in, int fd_out, char *file1, char *file2)
|
||||
char *pwd;
|
||||
char *dir = NULL;
|
||||
char cmd[2048];
|
||||
struct sftp_conn *conn;
|
||||
|
||||
version = do_init(fd_in, fd_out);
|
||||
if (version == -1)
|
||||
conn = do_init(fd_in, fd_out, copy_buffer_len, num_requests);
|
||||
if (conn == NULL)
|
||||
fatal("Couldn't initialise connection to server");
|
||||
|
||||
pwd = do_realpath(fd_in, fd_out, ".");
|
||||
pwd = do_realpath(conn, ".");
|
||||
if (pwd == NULL)
|
||||
fatal("Need cwd");
|
||||
|
||||
@ -886,10 +874,10 @@ interactive_loop(int fd_in, int fd_out, char *file1, char *file2)
|
||||
dir = xstrdup(file1);
|
||||
dir = make_absolute(dir, pwd);
|
||||
|
||||
if (remote_is_dir(fd_in, fd_out, dir) && file2 == NULL) {
|
||||
if (remote_is_dir(conn, dir) && file2 == NULL) {
|
||||
printf("Changing to: %s\n", dir);
|
||||
snprintf(cmd, sizeof cmd, "cd \"%s\"", dir);
|
||||
parse_dispatch_command(fd_in, fd_out, cmd, &pwd);
|
||||
parse_dispatch_command(conn, cmd, &pwd);
|
||||
} else {
|
||||
if (file2 == NULL)
|
||||
snprintf(cmd, sizeof cmd, "get %s", dir);
|
||||
@ -897,7 +885,7 @@ interactive_loop(int fd_in, int fd_out, char *file1, char *file2)
|
||||
snprintf(cmd, sizeof cmd, "get %s %s", dir,
|
||||
file2);
|
||||
|
||||
parse_dispatch_command(fd_in, fd_out, cmd, &pwd);
|
||||
parse_dispatch_command(conn, cmd, &pwd);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -925,7 +913,7 @@ interactive_loop(int fd_in, int fd_out, char *file1, char *file2)
|
||||
if (cp)
|
||||
*cp = '\0';
|
||||
|
||||
if (parse_dispatch_command(fd_in, fd_out, cmd, &pwd))
|
||||
if (parse_dispatch_command(conn, cmd, &pwd))
|
||||
break;
|
||||
}
|
||||
xfree(pwd);
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* $OpenBSD: sftp-int.h,v 1.4 2001/06/26 17:27:25 markus Exp $ */
|
||||
/* $OpenBSD: sftp-int.h,v 1.5 2002/02/13 00:59:23 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001 Damien Miller. All rights reserved.
|
||||
* Copyright (c) 2001,2002 Damien Miller. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
|
3
sftp.h
3
sftp.h
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: sftp.h,v 1.3 2001/03/07 10:11:23 djm Exp $ */
|
||||
/* $OpenBSD: sftp.h,v 1.4 2002/02/13 00:59:23 djm Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001 Markus Friedl. All rights reserved.
|
||||
@ -38,6 +38,7 @@
|
||||
#define SSH2_FXP_READ 5
|
||||
#define SSH2_FXP_WRITE 6
|
||||
#define SSH2_FXP_LSTAT 7
|
||||
#define SSH2_FXP_STAT_VERSION_0 7
|
||||
#define SSH2_FXP_FSTAT 8
|
||||
#define SSH2_FXP_SETSTAT 9
|
||||
#define SSH2_FXP_FSETSTAT 10
|
||||
|
Loading…
x
Reference in New Issue
Block a user