aboutsummaryrefslogtreecommitdiff
path: root/sftp-client.c
diff options
context:
space:
mode:
authorDag-Erling Smørgrav <des@FreeBSD.org>2008-07-23 09:33:08 +0000
committerDag-Erling Smørgrav <des@FreeBSD.org>2008-07-23 09:33:08 +0000
commit5521539314d87d3432e3c5c0e74954a673a884bd (patch)
tree8f06d9ad2f958f06e579924065ecbaf74dd734f7 /sftp-client.c
parentd4033b6b6f7aa0e69be09f9613e062e0fb7a9f11 (diff)
downloadsrc-5521539314d87d3432e3c5c0e74954a673a884bd.tar.gz
src-5521539314d87d3432e3c5c0e74954a673a884bd.zip
Vendor import of OpenSSH 5.1p1
Notes
Notes: svn path=/vendor-crypto/openssh/dist/; revision=180750
Diffstat (limited to 'sftp-client.c')
-rw-r--r--sftp-client.c140
1 files changed, 134 insertions, 6 deletions
diff --git a/sftp-client.c b/sftp-client.c
index 69c637785907..5e39aa7d21bd 100644
--- a/sftp-client.c
+++ b/sftp-client.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sftp-client.c,v 1.81 2008/03/23 12:54:01 djm Exp $ */
+/* $OpenBSD: sftp-client.c,v 1.86 2008/06/26 06:10:09 djm Exp $ */
/*
* Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
*
@@ -24,6 +24,9 @@
#include <sys/types.h>
#include <sys/param.h>
+#ifdef HAVE_SYS_STATVFS_H
+#include <sys/statvfs.h>
+#endif
#include "openbsd-compat/sys-queue.h"
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
@@ -65,7 +68,9 @@ struct sftp_conn {
u_int num_requests;
u_int version;
u_int msg_id;
-#define SFTP_EXT_POSIX_RENAME 1
+#define SFTP_EXT_POSIX_RENAME 0x00000001
+#define SFTP_EXT_STATVFS 0x00000002
+#define SFTP_EXT_FSTATVFS 0x00000004
u_int exts;
};
@@ -238,6 +243,57 @@ get_decode_stat(int fd, u_int expected_id, int quiet)
return(a);
}
+static int
+get_decode_statvfs(int fd, struct sftp_statvfs *st, u_int expected_id,
+ int quiet)
+{
+ Buffer msg;
+ u_int type, id, flag;
+
+ buffer_init(&msg);
+ get_msg(fd, &msg);
+
+ type = buffer_get_char(&msg);
+ id = buffer_get_int(&msg);
+
+ debug3("Received statvfs reply T:%u I:%u", type, id);
+ if (id != expected_id)
+ fatal("ID mismatch (%u != %u)", id, expected_id);
+ if (type == SSH2_FXP_STATUS) {
+ int status = buffer_get_int(&msg);
+
+ if (quiet)
+ debug("Couldn't statvfs: %s", fx2txt(status));
+ else
+ error("Couldn't statvfs: %s", fx2txt(status));
+ buffer_free(&msg);
+ return -1;
+ } else if (type != SSH2_FXP_EXTENDED_REPLY) {
+ fatal("Expected SSH2_FXP_EXTENDED_REPLY(%u) packet, got %u",
+ SSH2_FXP_EXTENDED_REPLY, type);
+ }
+
+ bzero(st, sizeof(*st));
+ st->f_bsize = buffer_get_int64(&msg);
+ st->f_frsize = buffer_get_int64(&msg);
+ st->f_blocks = buffer_get_int64(&msg);
+ st->f_bfree = buffer_get_int64(&msg);
+ st->f_bavail = buffer_get_int64(&msg);
+ st->f_files = buffer_get_int64(&msg);
+ st->f_ffree = buffer_get_int64(&msg);
+ st->f_favail = buffer_get_int64(&msg);
+ st->f_fsid = buffer_get_int64(&msg);
+ flag = buffer_get_int64(&msg);
+ st->f_namemax = buffer_get_int64(&msg);
+
+ st->f_flag = (flag & SSH2_FXE_STATVFS_ST_RDONLY) ? ST_RDONLY : 0;
+ st->f_flag |= (flag & SSH2_FXE_STATVFS_ST_NOSUID) ? ST_NOSUID : 0;
+
+ buffer_free(&msg);
+
+ return 0;
+}
+
struct sftp_conn *
do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests)
{
@@ -270,10 +326,27 @@ do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests)
while (buffer_len(&msg) > 0) {
char *name = buffer_get_string(&msg, NULL);
char *value = buffer_get_string(&msg, NULL);
+ int known = 0;
- debug2("Init extension: \"%s\"", name);
- if (strcmp(name, "posix-rename@openssh.com") == 0)
+ if (strcmp(name, "posix-rename@openssh.com") == 0 &&
+ strcmp(value, "1") == 0) {
exts |= SFTP_EXT_POSIX_RENAME;
+ known = 1;
+ } else if (strcmp(name, "statvfs@openssh.com") == 0 &&
+ strcmp(value, "2") == 0) {
+ exts |= SFTP_EXT_STATVFS;
+ known = 1;
+ } if (strcmp(name, "fstatvfs@openssh.com") == 0 &&
+ strcmp(value, "2") == 0) {
+ exts |= SFTP_EXT_FSTATVFS;
+ known = 1;
+ }
+ if (known) {
+ debug2("Server supports extension \"%s\" revision %s",
+ name, value);
+ } else {
+ debug2("Unrecognised server extension \"%s\"", name);
+ }
xfree(name);
xfree(value);
}
@@ -749,6 +822,60 @@ do_readlink(struct sftp_conn *conn, char *path)
}
#endif
+int
+do_statvfs(struct sftp_conn *conn, const char *path, struct sftp_statvfs *st,
+ int quiet)
+{
+ Buffer msg;
+ u_int id;
+
+ if ((conn->exts & SFTP_EXT_STATVFS) == 0) {
+ error("Server does not support statvfs@openssh.com extension");
+ return -1;
+ }
+
+ id = conn->msg_id++;
+
+ buffer_init(&msg);
+ buffer_clear(&msg);
+ buffer_put_char(&msg, SSH2_FXP_EXTENDED);
+ buffer_put_int(&msg, id);
+ buffer_put_cstring(&msg, "statvfs@openssh.com");
+ buffer_put_cstring(&msg, path);
+ send_msg(conn->fd_out, &msg);
+ buffer_free(&msg);
+
+ return get_decode_statvfs(conn->fd_in, st, id, quiet);
+}
+
+#ifdef notyet
+int
+do_fstatvfs(struct sftp_conn *conn, const char *handle, u_int handle_len,
+ struct sftp_statvfs *st, int quiet)
+{
+ Buffer msg;
+ u_int id;
+
+ if ((conn->exts & SFTP_EXT_FSTATVFS) == 0) {
+ error("Server does not support fstatvfs@openssh.com extension");
+ return -1;
+ }
+
+ id = conn->msg_id++;
+
+ buffer_init(&msg);
+ buffer_clear(&msg);
+ buffer_put_char(&msg, SSH2_FXP_EXTENDED);
+ buffer_put_int(&msg, id);
+ buffer_put_cstring(&msg, "fstatvfs@openssh.com");
+ buffer_put_string(&msg, handle, handle_len);
+ send_msg(conn->fd_out, &msg);
+ buffer_free(&msg);
+
+ return get_decode_statvfs(conn->fd_in, st, id, quiet);
+}
+#endif
+
static void
send_read_request(int fd_out, u_int id, u_int64_t offset, u_int len,
char *handle, u_int handle_len)
@@ -793,7 +920,7 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
if (a == NULL)
return(-1);
- /* XXX: should we preserve set[ug]id? */
+ /* Do not preserve set[ug]id here, as we do not preserve ownership */
if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS)
mode = a->perm & 0777;
else
@@ -1096,7 +1223,8 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path,
len = 0;
else do
len = read(local_fd, data, conn->transfer_buflen);
- while ((len == -1) && (errno == EINTR || errno == EAGAIN));
+ while ((len == -1) &&
+ (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
if (len == -1)
fatal("Couldn't read from \"%s\": %s", local_path,