From 5521539314d87d3432e3c5c0e74954a673a884bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dag-Erling=20Sm=C3=B8rgrav?= Date: Wed, 23 Jul 2008 09:33:08 +0000 Subject: Vendor import of OpenSSH 5.1p1 --- sftp-client.c | 140 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 134 insertions(+), 6 deletions(-) (limited to 'sftp-client.c') 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 * @@ -24,6 +24,9 @@ #include #include +#ifdef HAVE_SYS_STATVFS_H +#include +#endif #include "openbsd-compat/sys-queue.h" #ifdef HAVE_SYS_STAT_H # include @@ -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, -- cgit v1.2.3