summaryrefslogtreecommitdiff
path: root/sftp-client.c
diff options
context:
space:
mode:
Diffstat (limited to 'sftp-client.c')
-rw-r--r--sftp-client.c58
1 files changed, 47 insertions, 11 deletions
diff --git a/sftp-client.c b/sftp-client.c
index 4986d6d8d..73e3c2f53 100644
--- a/sftp-client.c
+++ b/sftp-client.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sftp-client.c,v 1.130 2018/07/31 03:07:24 djm Exp $ */ 1/* $OpenBSD: sftp-client.c,v 1.133 2019/01/24 16:52:17 dtucker Exp $ */
2/* 2/*
3 * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org> 3 * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
4 * 4 *
@@ -86,6 +86,7 @@ struct sftp_conn {
86#define SFTP_EXT_FSTATVFS 0x00000004 86#define SFTP_EXT_FSTATVFS 0x00000004
87#define SFTP_EXT_HARDLINK 0x00000008 87#define SFTP_EXT_HARDLINK 0x00000008
88#define SFTP_EXT_FSYNC 0x00000010 88#define SFTP_EXT_FSYNC 0x00000010
89#define SFTP_EXT_LSETSTAT 0x00000020
89 u_int exts; 90 u_int exts;
90 u_int64_t limit_kbps; 91 u_int64_t limit_kbps;
91 struct bwlimit bwlimit_in, bwlimit_out; 92 struct bwlimit bwlimit_in, bwlimit_out;
@@ -101,7 +102,9 @@ sftpio(void *_bwlimit, size_t amount)
101{ 102{
102 struct bwlimit *bwlimit = (struct bwlimit *)_bwlimit; 103 struct bwlimit *bwlimit = (struct bwlimit *)_bwlimit;
103 104
104 bandwidth_limit(bwlimit, amount); 105 refresh_progress_meter(0);
106 if (bwlimit != NULL)
107 bandwidth_limit(bwlimit, amount);
105 return 0; 108 return 0;
106} 109}
107 110
@@ -121,8 +124,8 @@ send_msg(struct sftp_conn *conn, struct sshbuf *m)
121 iov[1].iov_base = (u_char *)sshbuf_ptr(m); 124 iov[1].iov_base = (u_char *)sshbuf_ptr(m);
122 iov[1].iov_len = sshbuf_len(m); 125 iov[1].iov_len = sshbuf_len(m);
123 126
124 if (atomiciov6(writev, conn->fd_out, iov, 2, 127 if (atomiciov6(writev, conn->fd_out, iov, 2, sftpio,
125 conn->limit_kbps > 0 ? sftpio : NULL, &conn->bwlimit_out) != 128 conn->limit_kbps > 0 ? &conn->bwlimit_out : NULL) !=
126 sshbuf_len(m) + sizeof(mlen)) 129 sshbuf_len(m) + sizeof(mlen))
127 fatal("Couldn't send packet: %s", strerror(errno)); 130 fatal("Couldn't send packet: %s", strerror(errno));
128 131
@@ -138,8 +141,8 @@ get_msg_extended(struct sftp_conn *conn, struct sshbuf *m, int initial)
138 141
139 if ((r = sshbuf_reserve(m, 4, &p)) != 0) 142 if ((r = sshbuf_reserve(m, 4, &p)) != 0)
140 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 143 fatal("%s: buffer error: %s", __func__, ssh_err(r));
141 if (atomicio6(read, conn->fd_in, p, 4, 144 if (atomicio6(read, conn->fd_in, p, 4, sftpio,
142 conn->limit_kbps > 0 ? sftpio : NULL, &conn->bwlimit_in) != 4) { 145 conn->limit_kbps > 0 ? &conn->bwlimit_in : NULL) != 4) {
143 if (errno == EPIPE || errno == ECONNRESET) 146 if (errno == EPIPE || errno == ECONNRESET)
144 fatal("Connection closed"); 147 fatal("Connection closed");
145 else 148 else
@@ -157,8 +160,8 @@ get_msg_extended(struct sftp_conn *conn, struct sshbuf *m, int initial)
157 160
158 if ((r = sshbuf_reserve(m, msg_len, &p)) != 0) 161 if ((r = sshbuf_reserve(m, msg_len, &p)) != 0)
159 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 162 fatal("%s: buffer error: %s", __func__, ssh_err(r));
160 if (atomicio6(read, conn->fd_in, p, msg_len, 163 if (atomicio6(read, conn->fd_in, p, msg_len, sftpio,
161 conn->limit_kbps > 0 ? sftpio : NULL, &conn->bwlimit_in) 164 conn->limit_kbps > 0 ? &conn->bwlimit_in : NULL)
162 != msg_len) { 165 != msg_len) {
163 if (errno == EPIPE) 166 if (errno == EPIPE)
164 fatal("Connection closed"); 167 fatal("Connection closed");
@@ -463,6 +466,10 @@ do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests,
463 strcmp((char *)value, "1") == 0) { 466 strcmp((char *)value, "1") == 0) {
464 ret->exts |= SFTP_EXT_FSYNC; 467 ret->exts |= SFTP_EXT_FSYNC;
465 known = 1; 468 known = 1;
469 } else if (strcmp(name, "lsetstat@openssh.com") == 0 &&
470 strcmp((char *)value, "1") == 0) {
471 ret->exts |= SFTP_EXT_LSETSTAT;
472 known = 1;
466 } 473 }
467 if (known) { 474 if (known) {
468 debug2("Server supports extension \"%s\" revision %s", 475 debug2("Server supports extension \"%s\" revision %s",
@@ -1096,7 +1103,6 @@ do_statvfs(struct sftp_conn *conn, const char *path, struct sftp_statvfs *st,
1096 1103
1097 if ((msg = sshbuf_new()) == NULL) 1104 if ((msg = sshbuf_new()) == NULL)
1098 fatal("%s: sshbuf_new failed", __func__); 1105 fatal("%s: sshbuf_new failed", __func__);
1099 sshbuf_reset(msg);
1100 if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || 1106 if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
1101 (r = sshbuf_put_u32(msg, id)) != 0 || 1107 (r = sshbuf_put_u32(msg, id)) != 0 ||
1102 (r = sshbuf_put_cstring(msg, "statvfs@openssh.com")) != 0 || 1108 (r = sshbuf_put_cstring(msg, "statvfs@openssh.com")) != 0 ||
@@ -1125,7 +1131,6 @@ do_fstatvfs(struct sftp_conn *conn, const u_char *handle, u_int handle_len,
1125 1131
1126 if ((msg = sshbuf_new()) == NULL) 1132 if ((msg = sshbuf_new()) == NULL)
1127 fatal("%s: sshbuf_new failed", __func__); 1133 fatal("%s: sshbuf_new failed", __func__);
1128 sshbuf_reset(msg);
1129 if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || 1134 if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
1130 (r = sshbuf_put_u32(msg, id)) != 0 || 1135 (r = sshbuf_put_u32(msg, id)) != 0 ||
1131 (r = sshbuf_put_cstring(msg, "fstatvfs@openssh.com")) != 0 || 1136 (r = sshbuf_put_cstring(msg, "fstatvfs@openssh.com")) != 0 ||
@@ -1138,6 +1143,38 @@ do_fstatvfs(struct sftp_conn *conn, const u_char *handle, u_int handle_len,
1138} 1143}
1139#endif 1144#endif
1140 1145
1146int
1147do_lsetstat(struct sftp_conn *conn, const char *path, Attrib *a)
1148{
1149 struct sshbuf *msg;
1150 u_int status, id;
1151 int r;
1152
1153 if ((conn->exts & SFTP_EXT_LSETSTAT) == 0) {
1154 error("Server does not support lsetstat@openssh.com extension");
1155 return -1;
1156 }
1157
1158 id = conn->msg_id++;
1159 if ((msg = sshbuf_new()) == NULL)
1160 fatal("%s: sshbuf_new failed", __func__);
1161 if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
1162 (r = sshbuf_put_u32(msg, id)) != 0 ||
1163 (r = sshbuf_put_cstring(msg, "lsetstat@openssh.com")) != 0 ||
1164 (r = sshbuf_put_cstring(msg, path)) != 0 ||
1165 (r = encode_attrib(msg, a)) != 0)
1166 fatal("%s: buffer error: %s", __func__, ssh_err(r));
1167 send_msg(conn, msg);
1168 sshbuf_free(msg);
1169
1170 status = get_status(conn, id);
1171 if (status != SSH2_FX_OK)
1172 error("Couldn't setstat on \"%s\": %s", path,
1173 fx2txt(status));
1174
1175 return status == SSH2_FX_OK ? 0 : -1;
1176}
1177
1141static void 1178static void
1142send_read_request(struct sftp_conn *conn, u_int id, u_int64_t offset, 1179send_read_request(struct sftp_conn *conn, u_int id, u_int64_t offset,
1143 u_int len, const u_char *handle, u_int handle_len) 1180 u_int len, const u_char *handle, u_int handle_len)
@@ -1147,7 +1184,6 @@ send_read_request(struct sftp_conn *conn, u_int id, u_int64_t offset,
1147 1184
1148 if ((msg = sshbuf_new()) == NULL) 1185 if ((msg = sshbuf_new()) == NULL)
1149 fatal("%s: sshbuf_new failed", __func__); 1186 fatal("%s: sshbuf_new failed", __func__);
1150 sshbuf_reset(msg);
1151 if ((r = sshbuf_put_u8(msg, SSH2_FXP_READ)) != 0 || 1187 if ((r = sshbuf_put_u8(msg, SSH2_FXP_READ)) != 0 ||
1152 (r = sshbuf_put_u32(msg, id)) != 0 || 1188 (r = sshbuf_put_u32(msg, id)) != 0 ||
1153 (r = sshbuf_put_string(msg, handle, handle_len)) != 0 || 1189 (r = sshbuf_put_string(msg, handle, handle_len)) != 0 ||