diff options
Diffstat (limited to 'sftp-client.c')
-rw-r--r-- | sftp-client.c | 863 |
1 files changed, 501 insertions, 362 deletions
diff --git a/sftp-client.c b/sftp-client.c index 990b58d14..80f4805cb 100644 --- a/sftp-client.c +++ b/sftp-client.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sftp-client.c,v 1.115 2014/04/21 14:36:16 logan Exp $ */ | 1 | /* $OpenBSD: sftp-client.c,v 1.117 2015/01/20 23:14:00 deraadt 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 | * |
@@ -22,8 +22,8 @@ | |||
22 | 22 | ||
23 | #include "includes.h" | 23 | #include "includes.h" |
24 | 24 | ||
25 | #include <sys/param.h> /* MIN MAX */ | ||
25 | #include <sys/types.h> | 26 | #include <sys/types.h> |
26 | #include <sys/param.h> | ||
27 | #ifdef HAVE_SYS_STATVFS_H | 27 | #ifdef HAVE_SYS_STATVFS_H |
28 | #include <sys/statvfs.h> | 28 | #include <sys/statvfs.h> |
29 | #endif | 29 | #endif |
@@ -47,7 +47,8 @@ | |||
47 | #include <unistd.h> | 47 | #include <unistd.h> |
48 | 48 | ||
49 | #include "xmalloc.h" | 49 | #include "xmalloc.h" |
50 | #include "buffer.h" | 50 | #include "ssherr.h" |
51 | #include "sshbuf.h" | ||
51 | #include "log.h" | 52 | #include "log.h" |
52 | #include "atomicio.h" | 53 | #include "atomicio.h" |
53 | #include "progressmeter.h" | 54 | #include "progressmeter.h" |
@@ -83,8 +84,8 @@ struct sftp_conn { | |||
83 | struct bwlimit bwlimit_in, bwlimit_out; | 84 | struct bwlimit bwlimit_in, bwlimit_out; |
84 | }; | 85 | }; |
85 | 86 | ||
86 | static char * | 87 | static u_char * |
87 | get_handle(struct sftp_conn *conn, u_int expected_id, u_int *len, | 88 | get_handle(struct sftp_conn *conn, u_int expected_id, size_t *len, |
88 | const char *errfmt, ...) __attribute__((format(printf, 4, 5))); | 89 | const char *errfmt, ...) __attribute__((format(printf, 4, 5))); |
89 | 90 | ||
90 | /* ARGSUSED */ | 91 | /* ARGSUSED */ |
@@ -98,36 +99,39 @@ sftpio(void *_bwlimit, size_t amount) | |||
98 | } | 99 | } |
99 | 100 | ||
100 | static void | 101 | static void |
101 | send_msg(struct sftp_conn *conn, Buffer *m) | 102 | send_msg(struct sftp_conn *conn, struct sshbuf *m) |
102 | { | 103 | { |
103 | u_char mlen[4]; | 104 | u_char mlen[4]; |
104 | struct iovec iov[2]; | 105 | struct iovec iov[2]; |
105 | 106 | ||
106 | if (buffer_len(m) > SFTP_MAX_MSG_LENGTH) | 107 | if (sshbuf_len(m) > SFTP_MAX_MSG_LENGTH) |
107 | fatal("Outbound message too long %u", buffer_len(m)); | 108 | fatal("Outbound message too long %zu", sshbuf_len(m)); |
108 | 109 | ||
109 | /* Send length first */ | 110 | /* Send length first */ |
110 | put_u32(mlen, buffer_len(m)); | 111 | put_u32(mlen, sshbuf_len(m)); |
111 | iov[0].iov_base = mlen; | 112 | iov[0].iov_base = mlen; |
112 | iov[0].iov_len = sizeof(mlen); | 113 | iov[0].iov_len = sizeof(mlen); |
113 | iov[1].iov_base = buffer_ptr(m); | 114 | iov[1].iov_base = (u_char *)sshbuf_ptr(m); |
114 | iov[1].iov_len = buffer_len(m); | 115 | iov[1].iov_len = sshbuf_len(m); |
115 | 116 | ||
116 | if (atomiciov6(writev, conn->fd_out, iov, 2, | 117 | if (atomiciov6(writev, conn->fd_out, iov, 2, |
117 | conn->limit_kbps > 0 ? sftpio : NULL, &conn->bwlimit_out) != | 118 | conn->limit_kbps > 0 ? sftpio : NULL, &conn->bwlimit_out) != |
118 | buffer_len(m) + sizeof(mlen)) | 119 | sshbuf_len(m) + sizeof(mlen)) |
119 | fatal("Couldn't send packet: %s", strerror(errno)); | 120 | fatal("Couldn't send packet: %s", strerror(errno)); |
120 | 121 | ||
121 | buffer_clear(m); | 122 | sshbuf_reset(m); |
122 | } | 123 | } |
123 | 124 | ||
124 | static void | 125 | static void |
125 | get_msg(struct sftp_conn *conn, Buffer *m) | 126 | get_msg(struct sftp_conn *conn, struct sshbuf *m) |
126 | { | 127 | { |
127 | u_int msg_len; | 128 | u_int msg_len; |
129 | u_char *p; | ||
130 | int r; | ||
128 | 131 | ||
129 | buffer_append_space(m, 4); | 132 | if ((r = sshbuf_reserve(m, 4, &p)) != 0) |
130 | if (atomicio6(read, conn->fd_in, buffer_ptr(m), 4, | 133 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
134 | if (atomicio6(read, conn->fd_in, p, 4, | ||
131 | conn->limit_kbps > 0 ? sftpio : NULL, &conn->bwlimit_in) != 4) { | 135 | conn->limit_kbps > 0 ? sftpio : NULL, &conn->bwlimit_in) != 4) { |
132 | if (errno == EPIPE) | 136 | if (errno == EPIPE) |
133 | fatal("Connection closed"); | 137 | fatal("Connection closed"); |
@@ -135,12 +139,14 @@ get_msg(struct sftp_conn *conn, Buffer *m) | |||
135 | fatal("Couldn't read packet: %s", strerror(errno)); | 139 | fatal("Couldn't read packet: %s", strerror(errno)); |
136 | } | 140 | } |
137 | 141 | ||
138 | msg_len = buffer_get_int(m); | 142 | if ((r = sshbuf_get_u32(m, &msg_len)) != 0) |
143 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
139 | if (msg_len > SFTP_MAX_MSG_LENGTH) | 144 | if (msg_len > SFTP_MAX_MSG_LENGTH) |
140 | fatal("Received message too long %u", msg_len); | 145 | fatal("Received message too long %u", msg_len); |
141 | 146 | ||
142 | buffer_append_space(m, msg_len); | 147 | if ((r = sshbuf_reserve(m, msg_len, &p)) != 0) |
143 | if (atomicio6(read, conn->fd_in, buffer_ptr(m), msg_len, | 148 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
149 | if (atomicio6(read, conn->fd_in, p, msg_len, | ||
144 | conn->limit_kbps > 0 ? sftpio : NULL, &conn->bwlimit_in) | 150 | conn->limit_kbps > 0 ? sftpio : NULL, &conn->bwlimit_in) |
145 | != msg_len) { | 151 | != msg_len) { |
146 | if (errno == EPIPE) | 152 | if (errno == EPIPE) |
@@ -151,46 +157,56 @@ get_msg(struct sftp_conn *conn, Buffer *m) | |||
151 | } | 157 | } |
152 | 158 | ||
153 | static void | 159 | static void |
154 | send_string_request(struct sftp_conn *conn, u_int id, u_int code, char *s, | 160 | send_string_request(struct sftp_conn *conn, u_int id, u_int code, const char *s, |
155 | u_int len) | 161 | u_int len) |
156 | { | 162 | { |
157 | Buffer msg; | 163 | struct sshbuf *msg; |
158 | 164 | int r; | |
159 | buffer_init(&msg); | 165 | |
160 | buffer_put_char(&msg, code); | 166 | if ((msg = sshbuf_new()) == NULL) |
161 | buffer_put_int(&msg, id); | 167 | fatal("%s: sshbuf_new failed", __func__); |
162 | buffer_put_string(&msg, s, len); | 168 | if ((r = sshbuf_put_u8(msg, code)) != 0 || |
163 | send_msg(conn, &msg); | 169 | (r = sshbuf_put_u32(msg, id)) != 0 || |
170 | (r = sshbuf_put_string(msg, s, len)) != 0) | ||
171 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
172 | send_msg(conn, msg); | ||
164 | debug3("Sent message fd %d T:%u I:%u", conn->fd_out, code, id); | 173 | debug3("Sent message fd %d T:%u I:%u", conn->fd_out, code, id); |
165 | buffer_free(&msg); | 174 | sshbuf_free(msg); |
166 | } | 175 | } |
167 | 176 | ||
168 | static void | 177 | static void |
169 | send_string_attrs_request(struct sftp_conn *conn, u_int id, u_int code, | 178 | send_string_attrs_request(struct sftp_conn *conn, u_int id, u_int code, |
170 | char *s, u_int len, Attrib *a) | 179 | const void *s, u_int len, Attrib *a) |
171 | { | 180 | { |
172 | Buffer msg; | 181 | struct sshbuf *msg; |
173 | 182 | int r; | |
174 | buffer_init(&msg); | 183 | |
175 | buffer_put_char(&msg, code); | 184 | if ((msg = sshbuf_new()) == NULL) |
176 | buffer_put_int(&msg, id); | 185 | fatal("%s: sshbuf_new failed", __func__); |
177 | buffer_put_string(&msg, s, len); | 186 | if ((r = sshbuf_put_u8(msg, code)) != 0 || |
178 | encode_attrib(&msg, a); | 187 | (r = sshbuf_put_u32(msg, id)) != 0 || |
179 | send_msg(conn, &msg); | 188 | (r = sshbuf_put_string(msg, s, len)) != 0 || |
189 | (r = encode_attrib(msg, a)) != 0) | ||
190 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
191 | send_msg(conn, msg); | ||
180 | debug3("Sent message fd %d T:%u I:%u", conn->fd_out, code, id); | 192 | debug3("Sent message fd %d T:%u I:%u", conn->fd_out, code, id); |
181 | buffer_free(&msg); | 193 | sshbuf_free(msg); |
182 | } | 194 | } |
183 | 195 | ||
184 | static u_int | 196 | static u_int |
185 | get_status(struct sftp_conn *conn, u_int expected_id) | 197 | get_status(struct sftp_conn *conn, u_int expected_id) |
186 | { | 198 | { |
187 | Buffer msg; | 199 | struct sshbuf *msg; |
188 | u_int type, id, status; | 200 | u_char type; |
201 | u_int id, status; | ||
202 | int r; | ||
189 | 203 | ||
190 | buffer_init(&msg); | 204 | if ((msg = sshbuf_new()) == NULL) |
191 | get_msg(conn, &msg); | 205 | fatal("%s: sshbuf_new failed", __func__); |
192 | type = buffer_get_char(&msg); | 206 | get_msg(conn, msg); |
193 | id = buffer_get_int(&msg); | 207 | if ((r = sshbuf_get_u8(msg, &type)) != 0 || |
208 | (r = sshbuf_get_u32(msg, &id)) != 0) | ||
209 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
194 | 210 | ||
195 | if (id != expected_id) | 211 | if (id != expected_id) |
196 | fatal("ID mismatch (%u != %u)", id, expected_id); | 212 | fatal("ID mismatch (%u != %u)", id, expected_id); |
@@ -198,112 +214,136 @@ get_status(struct sftp_conn *conn, u_int expected_id) | |||
198 | fatal("Expected SSH2_FXP_STATUS(%u) packet, got %u", | 214 | fatal("Expected SSH2_FXP_STATUS(%u) packet, got %u", |
199 | SSH2_FXP_STATUS, type); | 215 | SSH2_FXP_STATUS, type); |
200 | 216 | ||
201 | status = buffer_get_int(&msg); | 217 | if ((r = sshbuf_get_u32(msg, &status)) != 0) |
202 | buffer_free(&msg); | 218 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
219 | sshbuf_free(msg); | ||
203 | 220 | ||
204 | debug3("SSH2_FXP_STATUS %u", status); | 221 | debug3("SSH2_FXP_STATUS %u", status); |
205 | 222 | ||
206 | return status; | 223 | return status; |
207 | } | 224 | } |
208 | 225 | ||
209 | static char * | 226 | static u_char * |
210 | get_handle(struct sftp_conn *conn, u_int expected_id, u_int *len, | 227 | get_handle(struct sftp_conn *conn, u_int expected_id, size_t *len, |
211 | const char *errfmt, ...) | 228 | const char *errfmt, ...) |
212 | { | 229 | { |
213 | Buffer msg; | 230 | struct sshbuf *msg; |
214 | u_int type, id; | 231 | u_int id, status; |
215 | char *handle, errmsg[256]; | 232 | u_char type; |
233 | u_char *handle; | ||
234 | char errmsg[256]; | ||
216 | va_list args; | 235 | va_list args; |
217 | int status; | 236 | int r; |
218 | 237 | ||
219 | va_start(args, errfmt); | 238 | va_start(args, errfmt); |
220 | if (errfmt != NULL) | 239 | if (errfmt != NULL) |
221 | vsnprintf(errmsg, sizeof(errmsg), errfmt, args); | 240 | vsnprintf(errmsg, sizeof(errmsg), errfmt, args); |
222 | va_end(args); | 241 | va_end(args); |
223 | 242 | ||
224 | buffer_init(&msg); | 243 | if ((msg = sshbuf_new()) == NULL) |
225 | get_msg(conn, &msg); | 244 | fatal("%s: sshbuf_new failed", __func__); |
226 | type = buffer_get_char(&msg); | 245 | get_msg(conn, msg); |
227 | id = buffer_get_int(&msg); | 246 | if ((r = sshbuf_get_u8(msg, &type)) != 0 || |
247 | (r = sshbuf_get_u32(msg, &id)) != 0) | ||
248 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
228 | 249 | ||
229 | if (id != expected_id) | 250 | if (id != expected_id) |
230 | fatal("%s: ID mismatch (%u != %u)", | 251 | fatal("%s: ID mismatch (%u != %u)", |
231 | errfmt == NULL ? __func__ : errmsg, id, expected_id); | 252 | errfmt == NULL ? __func__ : errmsg, id, expected_id); |
232 | if (type == SSH2_FXP_STATUS) { | 253 | if (type == SSH2_FXP_STATUS) { |
233 | status = buffer_get_int(&msg); | 254 | if ((r = sshbuf_get_u32(msg, &status)) != 0) |
255 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
234 | if (errfmt != NULL) | 256 | if (errfmt != NULL) |
235 | error("%s: %s", errmsg, fx2txt(status)); | 257 | error("%s: %s", errmsg, fx2txt(status)); |
236 | buffer_free(&msg); | 258 | sshbuf_free(msg); |
237 | return(NULL); | 259 | return(NULL); |
238 | } else if (type != SSH2_FXP_HANDLE) | 260 | } else if (type != SSH2_FXP_HANDLE) |
239 | fatal("%s: Expected SSH2_FXP_HANDLE(%u) packet, got %u", | 261 | fatal("%s: Expected SSH2_FXP_HANDLE(%u) packet, got %u", |
240 | errfmt == NULL ? __func__ : errmsg, SSH2_FXP_HANDLE, type); | 262 | errfmt == NULL ? __func__ : errmsg, SSH2_FXP_HANDLE, type); |
241 | 263 | ||
242 | handle = buffer_get_string(&msg, len); | 264 | if ((r = sshbuf_get_string(msg, &handle, len)) != 0) |
243 | buffer_free(&msg); | 265 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
266 | sshbuf_free(msg); | ||
244 | 267 | ||
245 | return(handle); | 268 | return handle; |
246 | } | 269 | } |
247 | 270 | ||
248 | static Attrib * | 271 | static Attrib * |
249 | get_decode_stat(struct sftp_conn *conn, u_int expected_id, int quiet) | 272 | get_decode_stat(struct sftp_conn *conn, u_int expected_id, int quiet) |
250 | { | 273 | { |
251 | Buffer msg; | 274 | struct sshbuf *msg; |
252 | u_int type, id; | 275 | u_int id; |
253 | Attrib *a; | 276 | u_char type; |
277 | int r; | ||
278 | static Attrib a; | ||
254 | 279 | ||
255 | buffer_init(&msg); | 280 | if ((msg = sshbuf_new()) == NULL) |
256 | get_msg(conn, &msg); | 281 | fatal("%s: sshbuf_new failed", __func__); |
282 | get_msg(conn, msg); | ||
257 | 283 | ||
258 | type = buffer_get_char(&msg); | 284 | if ((r = sshbuf_get_u8(msg, &type)) != 0 || |
259 | id = buffer_get_int(&msg); | 285 | (r = sshbuf_get_u32(msg, &id)) != 0) |
286 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
260 | 287 | ||
261 | debug3("Received stat reply T:%u I:%u", type, id); | 288 | debug3("Received stat reply T:%u I:%u", type, id); |
262 | if (id != expected_id) | 289 | if (id != expected_id) |
263 | fatal("ID mismatch (%u != %u)", id, expected_id); | 290 | fatal("ID mismatch (%u != %u)", id, expected_id); |
264 | if (type == SSH2_FXP_STATUS) { | 291 | if (type == SSH2_FXP_STATUS) { |
265 | int status = buffer_get_int(&msg); | 292 | u_int status; |
266 | 293 | ||
294 | if ((r = sshbuf_get_u32(msg, &status)) != 0) | ||
295 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
267 | if (quiet) | 296 | if (quiet) |
268 | debug("Couldn't stat remote file: %s", fx2txt(status)); | 297 | debug("Couldn't stat remote file: %s", fx2txt(status)); |
269 | else | 298 | else |
270 | error("Couldn't stat remote file: %s", fx2txt(status)); | 299 | error("Couldn't stat remote file: %s", fx2txt(status)); |
271 | buffer_free(&msg); | 300 | sshbuf_free(msg); |
272 | return(NULL); | 301 | return(NULL); |
273 | } else if (type != SSH2_FXP_ATTRS) { | 302 | } else if (type != SSH2_FXP_ATTRS) { |
274 | fatal("Expected SSH2_FXP_ATTRS(%u) packet, got %u", | 303 | fatal("Expected SSH2_FXP_ATTRS(%u) packet, got %u", |
275 | SSH2_FXP_ATTRS, type); | 304 | SSH2_FXP_ATTRS, type); |
276 | } | 305 | } |
277 | a = decode_attrib(&msg); | 306 | if ((r = decode_attrib(msg, &a)) != 0) { |
278 | buffer_free(&msg); | 307 | error("%s: couldn't decode attrib: %s", __func__, ssh_err(r)); |
308 | sshbuf_free(msg); | ||
309 | return NULL; | ||
310 | } | ||
311 | sshbuf_free(msg); | ||
279 | 312 | ||
280 | return(a); | 313 | return &a; |
281 | } | 314 | } |
282 | 315 | ||
283 | static int | 316 | static int |
284 | get_decode_statvfs(struct sftp_conn *conn, struct sftp_statvfs *st, | 317 | get_decode_statvfs(struct sftp_conn *conn, struct sftp_statvfs *st, |
285 | u_int expected_id, int quiet) | 318 | u_int expected_id, int quiet) |
286 | { | 319 | { |
287 | Buffer msg; | 320 | struct sshbuf *msg; |
288 | u_int type, id, flag; | 321 | u_char type; |
322 | u_int id; | ||
323 | u_int64_t flag; | ||
324 | int r; | ||
289 | 325 | ||
290 | buffer_init(&msg); | 326 | if ((msg = sshbuf_new()) == NULL) |
291 | get_msg(conn, &msg); | 327 | fatal("%s: sshbuf_new failed", __func__); |
328 | get_msg(conn, msg); | ||
292 | 329 | ||
293 | type = buffer_get_char(&msg); | 330 | if ((r = sshbuf_get_u8(msg, &type)) != 0 || |
294 | id = buffer_get_int(&msg); | 331 | (r = sshbuf_get_u32(msg, &id)) != 0) |
332 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
295 | 333 | ||
296 | debug3("Received statvfs reply T:%u I:%u", type, id); | 334 | debug3("Received statvfs reply T:%u I:%u", type, id); |
297 | if (id != expected_id) | 335 | if (id != expected_id) |
298 | fatal("ID mismatch (%u != %u)", id, expected_id); | 336 | fatal("ID mismatch (%u != %u)", id, expected_id); |
299 | if (type == SSH2_FXP_STATUS) { | 337 | if (type == SSH2_FXP_STATUS) { |
300 | int status = buffer_get_int(&msg); | 338 | u_int status; |
301 | 339 | ||
340 | if ((r = sshbuf_get_u32(msg, &status)) != 0) | ||
341 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
302 | if (quiet) | 342 | if (quiet) |
303 | debug("Couldn't statvfs: %s", fx2txt(status)); | 343 | debug("Couldn't statvfs: %s", fx2txt(status)); |
304 | else | 344 | else |
305 | error("Couldn't statvfs: %s", fx2txt(status)); | 345 | error("Couldn't statvfs: %s", fx2txt(status)); |
306 | buffer_free(&msg); | 346 | sshbuf_free(msg); |
307 | return -1; | 347 | return -1; |
308 | } else if (type != SSH2_FXP_EXTENDED_REPLY) { | 348 | } else if (type != SSH2_FXP_EXTENDED_REPLY) { |
309 | fatal("Expected SSH2_FXP_EXTENDED_REPLY(%u) packet, got %u", | 349 | fatal("Expected SSH2_FXP_EXTENDED_REPLY(%u) packet, got %u", |
@@ -311,22 +351,23 @@ get_decode_statvfs(struct sftp_conn *conn, struct sftp_statvfs *st, | |||
311 | } | 351 | } |
312 | 352 | ||
313 | memset(st, 0, sizeof(*st)); | 353 | memset(st, 0, sizeof(*st)); |
314 | st->f_bsize = buffer_get_int64(&msg); | 354 | if ((r = sshbuf_get_u64(msg, &st->f_bsize)) != 0 || |
315 | st->f_frsize = buffer_get_int64(&msg); | 355 | (r = sshbuf_get_u64(msg, &st->f_frsize)) != 0 || |
316 | st->f_blocks = buffer_get_int64(&msg); | 356 | (r = sshbuf_get_u64(msg, &st->f_blocks)) != 0 || |
317 | st->f_bfree = buffer_get_int64(&msg); | 357 | (r = sshbuf_get_u64(msg, &st->f_bfree)) != 0 || |
318 | st->f_bavail = buffer_get_int64(&msg); | 358 | (r = sshbuf_get_u64(msg, &st->f_bavail)) != 0 || |
319 | st->f_files = buffer_get_int64(&msg); | 359 | (r = sshbuf_get_u64(msg, &st->f_files)) != 0 || |
320 | st->f_ffree = buffer_get_int64(&msg); | 360 | (r = sshbuf_get_u64(msg, &st->f_ffree)) != 0 || |
321 | st->f_favail = buffer_get_int64(&msg); | 361 | (r = sshbuf_get_u64(msg, &st->f_favail)) != 0 || |
322 | st->f_fsid = buffer_get_int64(&msg); | 362 | (r = sshbuf_get_u64(msg, &st->f_fsid)) != 0 || |
323 | flag = buffer_get_int64(&msg); | 363 | (r = sshbuf_get_u64(msg, &flag)) != 0 || |
324 | st->f_namemax = buffer_get_int64(&msg); | 364 | (r = sshbuf_get_u64(msg, &st->f_namemax)) != 0) |
365 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
325 | 366 | ||
326 | st->f_flag = (flag & SSH2_FXE_STATVFS_ST_RDONLY) ? ST_RDONLY : 0; | 367 | st->f_flag = (flag & SSH2_FXE_STATVFS_ST_RDONLY) ? ST_RDONLY : 0; |
327 | st->f_flag |= (flag & SSH2_FXE_STATVFS_ST_NOSUID) ? ST_NOSUID : 0; | 368 | st->f_flag |= (flag & SSH2_FXE_STATVFS_ST_NOSUID) ? ST_NOSUID : 0; |
328 | 369 | ||
329 | buffer_free(&msg); | 370 | sshbuf_free(msg); |
330 | 371 | ||
331 | return 0; | 372 | return 0; |
332 | } | 373 | } |
@@ -335,9 +376,10 @@ struct sftp_conn * | |||
335 | do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests, | 376 | do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests, |
336 | u_int64_t limit_kbps) | 377 | u_int64_t limit_kbps) |
337 | { | 378 | { |
338 | u_int type; | 379 | u_char type; |
339 | Buffer msg; | 380 | struct sshbuf *msg; |
340 | struct sftp_conn *ret; | 381 | struct sftp_conn *ret; |
382 | int r; | ||
341 | 383 | ||
342 | ret = xcalloc(1, sizeof(*ret)); | 384 | ret = xcalloc(1, sizeof(*ret)); |
343 | ret->msg_id = 1; | 385 | ret->msg_id = 1; |
@@ -348,52 +390,61 @@ do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests, | |||
348 | ret->exts = 0; | 390 | ret->exts = 0; |
349 | ret->limit_kbps = 0; | 391 | ret->limit_kbps = 0; |
350 | 392 | ||
351 | buffer_init(&msg); | 393 | if ((msg = sshbuf_new()) == NULL) |
352 | buffer_put_char(&msg, SSH2_FXP_INIT); | 394 | fatal("%s: sshbuf_new failed", __func__); |
353 | buffer_put_int(&msg, SSH2_FILEXFER_VERSION); | 395 | if ((r = sshbuf_put_u8(msg, SSH2_FXP_INIT)) != 0 || |
354 | send_msg(ret, &msg); | 396 | (r = sshbuf_put_u32(msg, SSH2_FILEXFER_VERSION)) != 0) |
397 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
398 | send_msg(ret, msg); | ||
355 | 399 | ||
356 | buffer_clear(&msg); | 400 | sshbuf_reset(msg); |
357 | 401 | ||
358 | get_msg(ret, &msg); | 402 | get_msg(ret, msg); |
359 | 403 | ||
360 | /* Expecting a VERSION reply */ | 404 | /* Expecting a VERSION reply */ |
361 | if ((type = buffer_get_char(&msg)) != SSH2_FXP_VERSION) { | 405 | if ((r = sshbuf_get_u8(msg, &type)) != 0) |
406 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
407 | if (type != SSH2_FXP_VERSION) { | ||
362 | error("Invalid packet back from SSH2_FXP_INIT (type %u)", | 408 | error("Invalid packet back from SSH2_FXP_INIT (type %u)", |
363 | type); | 409 | type); |
364 | buffer_free(&msg); | 410 | sshbuf_free(msg); |
365 | return(NULL); | 411 | return(NULL); |
366 | } | 412 | } |
367 | ret->version = buffer_get_int(&msg); | 413 | if ((r = sshbuf_get_u32(msg, &ret->version)) != 0) |
414 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
368 | 415 | ||
369 | debug2("Remote version: %u", ret->version); | 416 | debug2("Remote version: %u", ret->version); |
370 | 417 | ||
371 | /* Check for extensions */ | 418 | /* Check for extensions */ |
372 | while (buffer_len(&msg) > 0) { | 419 | while (sshbuf_len(msg) > 0) { |
373 | char *name = buffer_get_string(&msg, NULL); | 420 | char *name; |
374 | char *value = buffer_get_string(&msg, NULL); | 421 | u_char *value; |
422 | size_t vlen; | ||
375 | int known = 0; | 423 | int known = 0; |
376 | 424 | ||
425 | if ((r = sshbuf_get_cstring(msg, &name, NULL)) != 0 || | ||
426 | (r = sshbuf_get_string(msg, &value, &vlen)) != 0) | ||
427 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
377 | if (strcmp(name, "posix-rename@openssh.com") == 0 && | 428 | if (strcmp(name, "posix-rename@openssh.com") == 0 && |
378 | strcmp(value, "1") == 0) { | 429 | strcmp((char *)value, "1") == 0) { |
379 | ret->exts |= SFTP_EXT_POSIX_RENAME; | 430 | ret->exts |= SFTP_EXT_POSIX_RENAME; |
380 | known = 1; | 431 | known = 1; |
381 | } else if (strcmp(name, "statvfs@openssh.com") == 0 && | 432 | } else if (strcmp(name, "statvfs@openssh.com") == 0 && |
382 | strcmp(value, "2") == 0) { | 433 | strcmp((char *)value, "2") == 0) { |
383 | ret->exts |= SFTP_EXT_STATVFS; | 434 | ret->exts |= SFTP_EXT_STATVFS; |
384 | known = 1; | 435 | known = 1; |
385 | } else if (strcmp(name, "fstatvfs@openssh.com") == 0 && | 436 | } else if (strcmp(name, "fstatvfs@openssh.com") == 0 && |
386 | strcmp(value, "2") == 0) { | 437 | strcmp((char *)value, "2") == 0) { |
387 | ret->exts |= SFTP_EXT_FSTATVFS; | 438 | ret->exts |= SFTP_EXT_FSTATVFS; |
388 | known = 1; | 439 | known = 1; |
389 | } else if (strcmp(name, "hardlink@openssh.com") == 0 && | 440 | } else if (strcmp(name, "hardlink@openssh.com") == 0 && |
390 | strcmp(value, "1") == 0) { | 441 | strcmp((char *)value, "1") == 0) { |
391 | ret->exts |= SFTP_EXT_HARDLINK; | 442 | ret->exts |= SFTP_EXT_HARDLINK; |
392 | known = 1; | 443 | known = 1; |
393 | } else if (strcmp(name, "fsync@openssh.com") == 0 && | 444 | } else if (strcmp(name, "fsync@openssh.com") == 0 && |
394 | strcmp(value, "1") == 0) { | 445 | strcmp((char *)value, "1") == 0) { |
395 | ret->exts |= SFTP_EXT_FSYNC; | 446 | ret->exts |= SFTP_EXT_FSYNC; |
396 | known = 1; | 447 | known = 1; |
397 | } | 448 | } |
398 | if (known) { | 449 | if (known) { |
399 | debug2("Server supports extension \"%s\" revision %s", | 450 | debug2("Server supports extension \"%s\" revision %s", |
@@ -405,7 +456,7 @@ do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests, | |||
405 | free(value); | 456 | free(value); |
406 | } | 457 | } |
407 | 458 | ||
408 | buffer_free(&msg); | 459 | sshbuf_free(msg); |
409 | 460 | ||
410 | /* Some filexfer v.0 servers don't support large packets */ | 461 | /* Some filexfer v.0 servers don't support large packets */ |
411 | if (ret->version == 0) | 462 | if (ret->version == 0) |
@@ -429,54 +480,62 @@ sftp_proto_version(struct sftp_conn *conn) | |||
429 | } | 480 | } |
430 | 481 | ||
431 | int | 482 | int |
432 | do_close(struct sftp_conn *conn, char *handle, u_int handle_len) | 483 | do_close(struct sftp_conn *conn, const u_char *handle, u_int handle_len) |
433 | { | 484 | { |
434 | u_int id, status; | 485 | u_int id, status; |
435 | Buffer msg; | 486 | struct sshbuf *msg; |
487 | int r; | ||
436 | 488 | ||
437 | buffer_init(&msg); | 489 | if ((msg = sshbuf_new()) == NULL) |
490 | fatal("%s: sshbuf_new failed", __func__); | ||
438 | 491 | ||
439 | id = conn->msg_id++; | 492 | id = conn->msg_id++; |
440 | buffer_put_char(&msg, SSH2_FXP_CLOSE); | 493 | if ((r = sshbuf_put_u8(msg, SSH2_FXP_CLOSE)) != 0 || |
441 | buffer_put_int(&msg, id); | 494 | (r = sshbuf_put_u32(msg, id)) != 0 || |
442 | buffer_put_string(&msg, handle, handle_len); | 495 | (r = sshbuf_put_string(msg, handle, handle_len)) != 0) |
443 | send_msg(conn, &msg); | 496 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
497 | send_msg(conn, msg); | ||
444 | debug3("Sent message SSH2_FXP_CLOSE I:%u", id); | 498 | debug3("Sent message SSH2_FXP_CLOSE I:%u", id); |
445 | 499 | ||
446 | status = get_status(conn, id); | 500 | status = get_status(conn, id); |
447 | if (status != SSH2_FX_OK) | 501 | if (status != SSH2_FX_OK) |
448 | error("Couldn't close file: %s", fx2txt(status)); | 502 | error("Couldn't close file: %s", fx2txt(status)); |
449 | 503 | ||
450 | buffer_free(&msg); | 504 | sshbuf_free(msg); |
451 | 505 | ||
452 | return status; | 506 | return status == SSH2_FX_OK ? 0 : -1; |
453 | } | 507 | } |
454 | 508 | ||
455 | 509 | ||
456 | static int | 510 | static int |
457 | do_lsreaddir(struct sftp_conn *conn, char *path, int print_flag, | 511 | do_lsreaddir(struct sftp_conn *conn, const char *path, int print_flag, |
458 | SFTP_DIRENT ***dir) | 512 | SFTP_DIRENT ***dir) |
459 | { | 513 | { |
460 | Buffer msg; | 514 | struct sshbuf *msg; |
461 | u_int count, type, id, handle_len, i, expected_id, ents = 0; | 515 | u_int count, id, i, expected_id, ents = 0; |
516 | size_t handle_len; | ||
517 | u_char type; | ||
462 | char *handle; | 518 | char *handle; |
463 | int status = SSH2_FX_FAILURE; | 519 | int status = SSH2_FX_FAILURE; |
520 | int r; | ||
464 | 521 | ||
465 | if (dir) | 522 | if (dir) |
466 | *dir = NULL; | 523 | *dir = NULL; |
467 | 524 | ||
468 | id = conn->msg_id++; | 525 | id = conn->msg_id++; |
469 | 526 | ||
470 | buffer_init(&msg); | 527 | if ((msg = sshbuf_new()) == NULL) |
471 | buffer_put_char(&msg, SSH2_FXP_OPENDIR); | 528 | fatal("%s: sshbuf_new failed", __func__); |
472 | buffer_put_int(&msg, id); | 529 | if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPENDIR)) != 0 || |
473 | buffer_put_cstring(&msg, path); | 530 | (r = sshbuf_put_u32(msg, id)) != 0 || |
474 | send_msg(conn, &msg); | 531 | (r = sshbuf_put_cstring(msg, path)) != 0) |
532 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
533 | send_msg(conn, msg); | ||
475 | 534 | ||
476 | handle = get_handle(conn, id, &handle_len, | 535 | handle = get_handle(conn, id, &handle_len, |
477 | "remote readdir(\"%s\")", path); | 536 | "remote readdir(\"%s\")", path); |
478 | if (handle == NULL) { | 537 | if (handle == NULL) { |
479 | buffer_free(&msg); | 538 | sshbuf_free(msg); |
480 | return -1; | 539 | return -1; |
481 | } | 540 | } |
482 | 541 | ||
@@ -491,18 +550,20 @@ do_lsreaddir(struct sftp_conn *conn, char *path, int print_flag, | |||
491 | 550 | ||
492 | debug3("Sending SSH2_FXP_READDIR I:%u", id); | 551 | debug3("Sending SSH2_FXP_READDIR I:%u", id); |
493 | 552 | ||
494 | buffer_clear(&msg); | 553 | sshbuf_reset(msg); |
495 | buffer_put_char(&msg, SSH2_FXP_READDIR); | 554 | if ((r = sshbuf_put_u8(msg, SSH2_FXP_READDIR)) != 0 || |
496 | buffer_put_int(&msg, id); | 555 | (r = sshbuf_put_u32(msg, id)) != 0 || |
497 | buffer_put_string(&msg, handle, handle_len); | 556 | (r = sshbuf_put_string(msg, handle, handle_len)) != 0) |
498 | send_msg(conn, &msg); | 557 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
558 | send_msg(conn, msg); | ||
499 | 559 | ||
500 | buffer_clear(&msg); | 560 | sshbuf_reset(msg); |
501 | 561 | ||
502 | get_msg(conn, &msg); | 562 | get_msg(conn, msg); |
503 | 563 | ||
504 | type = buffer_get_char(&msg); | 564 | if ((r = sshbuf_get_u8(msg, &type)) != 0 || |
505 | id = buffer_get_int(&msg); | 565 | (r = sshbuf_get_u32(msg, &id)) != 0) |
566 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
506 | 567 | ||
507 | debug3("Received reply T:%u I:%u", type, id); | 568 | debug3("Received reply T:%u I:%u", type, id); |
508 | 569 | ||
@@ -510,27 +571,43 @@ do_lsreaddir(struct sftp_conn *conn, char *path, int print_flag, | |||
510 | fatal("ID mismatch (%u != %u)", id, expected_id); | 571 | fatal("ID mismatch (%u != %u)", id, expected_id); |
511 | 572 | ||
512 | if (type == SSH2_FXP_STATUS) { | 573 | if (type == SSH2_FXP_STATUS) { |
513 | status = buffer_get_int(&msg); | 574 | u_int rstatus; |
514 | debug3("Received SSH2_FXP_STATUS %d", status); | 575 | |
515 | if (status == SSH2_FX_EOF) | 576 | if ((r = sshbuf_get_u32(msg, &rstatus)) != 0) |
577 | fatal("%s: buffer error: %s", | ||
578 | __func__, ssh_err(r)); | ||
579 | debug3("Received SSH2_FXP_STATUS %d", rstatus); | ||
580 | if (rstatus == SSH2_FX_EOF) | ||
516 | break; | 581 | break; |
517 | error("Couldn't read directory: %s", fx2txt(status)); | 582 | error("Couldn't read directory: %s", fx2txt(rstatus)); |
518 | goto out; | 583 | goto out; |
519 | } else if (type != SSH2_FXP_NAME) | 584 | } else if (type != SSH2_FXP_NAME) |
520 | fatal("Expected SSH2_FXP_NAME(%u) packet, got %u", | 585 | fatal("Expected SSH2_FXP_NAME(%u) packet, got %u", |
521 | SSH2_FXP_NAME, type); | 586 | SSH2_FXP_NAME, type); |
522 | 587 | ||
523 | count = buffer_get_int(&msg); | 588 | if ((r = sshbuf_get_u32(msg, &count)) != 0) |
589 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
524 | if (count == 0) | 590 | if (count == 0) |
525 | break; | 591 | break; |
526 | debug3("Received %d SSH2_FXP_NAME responses", count); | 592 | debug3("Received %d SSH2_FXP_NAME responses", count); |
527 | for (i = 0; i < count; i++) { | 593 | for (i = 0; i < count; i++) { |
528 | char *filename, *longname; | 594 | char *filename, *longname; |
529 | Attrib *a; | 595 | Attrib a; |
530 | 596 | ||
531 | filename = buffer_get_string(&msg, NULL); | 597 | if ((r = sshbuf_get_cstring(msg, &filename, |
532 | longname = buffer_get_string(&msg, NULL); | 598 | NULL)) != 0 || |
533 | a = decode_attrib(&msg); | 599 | (r = sshbuf_get_cstring(msg, &longname, |
600 | NULL)) != 0) | ||
601 | fatal("%s: buffer error: %s", | ||
602 | __func__, ssh_err(r)); | ||
603 | if ((r = decode_attrib(msg, &a)) != 0) { | ||
604 | error("%s: couldn't decode attrib: %s", | ||
605 | __func__, ssh_err(r)); | ||
606 | free(filename); | ||
607 | free(longname); | ||
608 | sshbuf_free(msg); | ||
609 | return -1; | ||
610 | } | ||
534 | 611 | ||
535 | if (print_flag) | 612 | if (print_flag) |
536 | printf("%s\n", longname); | 613 | printf("%s\n", longname); |
@@ -548,7 +625,7 @@ do_lsreaddir(struct sftp_conn *conn, char *path, int print_flag, | |||
548 | (*dir)[ents] = xcalloc(1, sizeof(***dir)); | 625 | (*dir)[ents] = xcalloc(1, sizeof(***dir)); |
549 | (*dir)[ents]->filename = xstrdup(filename); | 626 | (*dir)[ents]->filename = xstrdup(filename); |
550 | (*dir)[ents]->longname = xstrdup(longname); | 627 | (*dir)[ents]->longname = xstrdup(longname); |
551 | memcpy(&(*dir)[ents]->a, a, sizeof(*a)); | 628 | memcpy(&(*dir)[ents]->a, &a, sizeof(a)); |
552 | (*dir)[++ents] = NULL; | 629 | (*dir)[++ents] = NULL; |
553 | } | 630 | } |
554 | free(filename); | 631 | free(filename); |
@@ -558,7 +635,7 @@ do_lsreaddir(struct sftp_conn *conn, char *path, int print_flag, | |||
558 | status = 0; | 635 | status = 0; |
559 | 636 | ||
560 | out: | 637 | out: |
561 | buffer_free(&msg); | 638 | sshbuf_free(msg); |
562 | do_close(conn, handle, handle_len); | 639 | do_close(conn, handle, handle_len); |
563 | free(handle); | 640 | free(handle); |
564 | 641 | ||
@@ -577,7 +654,7 @@ do_lsreaddir(struct sftp_conn *conn, char *path, int print_flag, | |||
577 | } | 654 | } |
578 | 655 | ||
579 | int | 656 | int |
580 | do_readdir(struct sftp_conn *conn, char *path, SFTP_DIRENT ***dir) | 657 | do_readdir(struct sftp_conn *conn, const char *path, SFTP_DIRENT ***dir) |
581 | { | 658 | { |
582 | return(do_lsreaddir(conn, path, 0, dir)); | 659 | return(do_lsreaddir(conn, path, 0, dir)); |
583 | } | 660 | } |
@@ -597,7 +674,7 @@ void free_sftp_dirents(SFTP_DIRENT **s) | |||
597 | } | 674 | } |
598 | 675 | ||
599 | int | 676 | int |
600 | do_rm(struct sftp_conn *conn, char *path) | 677 | do_rm(struct sftp_conn *conn, const char *path) |
601 | { | 678 | { |
602 | u_int status, id; | 679 | u_int status, id; |
603 | 680 | ||
@@ -608,11 +685,11 @@ do_rm(struct sftp_conn *conn, char *path) | |||
608 | status = get_status(conn, id); | 685 | status = get_status(conn, id); |
609 | if (status != SSH2_FX_OK) | 686 | if (status != SSH2_FX_OK) |
610 | error("Couldn't delete file: %s", fx2txt(status)); | 687 | error("Couldn't delete file: %s", fx2txt(status)); |
611 | return(status); | 688 | return status == SSH2_FX_OK ? 0 : -1; |
612 | } | 689 | } |
613 | 690 | ||
614 | int | 691 | int |
615 | do_mkdir(struct sftp_conn *conn, char *path, Attrib *a, int print_flag) | 692 | do_mkdir(struct sftp_conn *conn, const char *path, Attrib *a, int print_flag) |
616 | { | 693 | { |
617 | u_int status, id; | 694 | u_int status, id; |
618 | 695 | ||
@@ -624,11 +701,11 @@ do_mkdir(struct sftp_conn *conn, char *path, Attrib *a, int print_flag) | |||
624 | if (status != SSH2_FX_OK && print_flag) | 701 | if (status != SSH2_FX_OK && print_flag) |
625 | error("Couldn't create directory: %s", fx2txt(status)); | 702 | error("Couldn't create directory: %s", fx2txt(status)); |
626 | 703 | ||
627 | return(status); | 704 | return status == SSH2_FX_OK ? 0 : -1; |
628 | } | 705 | } |
629 | 706 | ||
630 | int | 707 | int |
631 | do_rmdir(struct sftp_conn *conn, char *path) | 708 | do_rmdir(struct sftp_conn *conn, const char *path) |
632 | { | 709 | { |
633 | u_int status, id; | 710 | u_int status, id; |
634 | 711 | ||
@@ -640,11 +717,11 @@ do_rmdir(struct sftp_conn *conn, char *path) | |||
640 | if (status != SSH2_FX_OK) | 717 | if (status != SSH2_FX_OK) |
641 | error("Couldn't remove directory: %s", fx2txt(status)); | 718 | error("Couldn't remove directory: %s", fx2txt(status)); |
642 | 719 | ||
643 | return(status); | 720 | return status == SSH2_FX_OK ? 0 : -1; |
644 | } | 721 | } |
645 | 722 | ||
646 | Attrib * | 723 | Attrib * |
647 | do_stat(struct sftp_conn *conn, char *path, int quiet) | 724 | do_stat(struct sftp_conn *conn, const char *path, int quiet) |
648 | { | 725 | { |
649 | u_int id; | 726 | u_int id; |
650 | 727 | ||
@@ -658,7 +735,7 @@ do_stat(struct sftp_conn *conn, char *path, int quiet) | |||
658 | } | 735 | } |
659 | 736 | ||
660 | Attrib * | 737 | Attrib * |
661 | do_lstat(struct sftp_conn *conn, char *path, int quiet) | 738 | do_lstat(struct sftp_conn *conn, const char *path, int quiet) |
662 | { | 739 | { |
663 | u_int id; | 740 | u_int id; |
664 | 741 | ||
@@ -679,7 +756,8 @@ do_lstat(struct sftp_conn *conn, char *path, int quiet) | |||
679 | 756 | ||
680 | #ifdef notyet | 757 | #ifdef notyet |
681 | Attrib * | 758 | Attrib * |
682 | do_fstat(struct sftp_conn *conn, char *handle, u_int handle_len, int quiet) | 759 | do_fstat(struct sftp_conn *conn, const u_char *handle, u_int handle_len, |
760 | int quiet) | ||
683 | { | 761 | { |
684 | u_int id; | 762 | u_int id; |
685 | 763 | ||
@@ -692,7 +770,7 @@ do_fstat(struct sftp_conn *conn, char *handle, u_int handle_len, int quiet) | |||
692 | #endif | 770 | #endif |
693 | 771 | ||
694 | int | 772 | int |
695 | do_setstat(struct sftp_conn *conn, char *path, Attrib *a) | 773 | do_setstat(struct sftp_conn *conn, const char *path, Attrib *a) |
696 | { | 774 | { |
697 | u_int status, id; | 775 | u_int status, id; |
698 | 776 | ||
@@ -705,11 +783,11 @@ do_setstat(struct sftp_conn *conn, char *path, Attrib *a) | |||
705 | error("Couldn't setstat on \"%s\": %s", path, | 783 | error("Couldn't setstat on \"%s\": %s", path, |
706 | fx2txt(status)); | 784 | fx2txt(status)); |
707 | 785 | ||
708 | return(status); | 786 | return status == SSH2_FX_OK ? 0 : -1; |
709 | } | 787 | } |
710 | 788 | ||
711 | int | 789 | int |
712 | do_fsetstat(struct sftp_conn *conn, char *handle, u_int handle_len, | 790 | do_fsetstat(struct sftp_conn *conn, const u_char *handle, u_int handle_len, |
713 | Attrib *a) | 791 | Attrib *a) |
714 | { | 792 | { |
715 | u_int status, id; | 793 | u_int status, id; |
@@ -722,181 +800,201 @@ do_fsetstat(struct sftp_conn *conn, char *handle, u_int handle_len, | |||
722 | if (status != SSH2_FX_OK) | 800 | if (status != SSH2_FX_OK) |
723 | error("Couldn't fsetstat: %s", fx2txt(status)); | 801 | error("Couldn't fsetstat: %s", fx2txt(status)); |
724 | 802 | ||
725 | return(status); | 803 | return status == SSH2_FX_OK ? 0 : -1; |
726 | } | 804 | } |
727 | 805 | ||
728 | char * | 806 | char * |
729 | do_realpath(struct sftp_conn *conn, char *path) | 807 | do_realpath(struct sftp_conn *conn, const char *path) |
730 | { | 808 | { |
731 | Buffer msg; | 809 | struct sshbuf *msg; |
732 | u_int type, expected_id, count, id; | 810 | u_int expected_id, count, id; |
733 | char *filename, *longname; | 811 | char *filename, *longname; |
734 | Attrib *a; | 812 | Attrib a; |
813 | u_char type; | ||
814 | int r; | ||
735 | 815 | ||
736 | expected_id = id = conn->msg_id++; | 816 | expected_id = id = conn->msg_id++; |
737 | send_string_request(conn, id, SSH2_FXP_REALPATH, path, | 817 | send_string_request(conn, id, SSH2_FXP_REALPATH, path, |
738 | strlen(path)); | 818 | strlen(path)); |
739 | 819 | ||
740 | buffer_init(&msg); | 820 | if ((msg = sshbuf_new()) == NULL) |
821 | fatal("%s: sshbuf_new failed", __func__); | ||
741 | 822 | ||
742 | get_msg(conn, &msg); | 823 | get_msg(conn, msg); |
743 | type = buffer_get_char(&msg); | 824 | if ((r = sshbuf_get_u8(msg, &type)) != 0 || |
744 | id = buffer_get_int(&msg); | 825 | (r = sshbuf_get_u32(msg, &id)) != 0) |
826 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
745 | 827 | ||
746 | if (id != expected_id) | 828 | if (id != expected_id) |
747 | fatal("ID mismatch (%u != %u)", id, expected_id); | 829 | fatal("ID mismatch (%u != %u)", id, expected_id); |
748 | 830 | ||
749 | if (type == SSH2_FXP_STATUS) { | 831 | if (type == SSH2_FXP_STATUS) { |
750 | u_int status = buffer_get_int(&msg); | 832 | u_int status; |
751 | 833 | ||
834 | if ((r = sshbuf_get_u32(msg, &status)) != 0) | ||
835 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
752 | error("Couldn't canonicalize: %s", fx2txt(status)); | 836 | error("Couldn't canonicalize: %s", fx2txt(status)); |
753 | buffer_free(&msg); | 837 | sshbuf_free(msg); |
754 | return NULL; | 838 | return NULL; |
755 | } else if (type != SSH2_FXP_NAME) | 839 | } else if (type != SSH2_FXP_NAME) |
756 | fatal("Expected SSH2_FXP_NAME(%u) packet, got %u", | 840 | fatal("Expected SSH2_FXP_NAME(%u) packet, got %u", |
757 | SSH2_FXP_NAME, type); | 841 | SSH2_FXP_NAME, type); |
758 | 842 | ||
759 | count = buffer_get_int(&msg); | 843 | if ((r = sshbuf_get_u32(msg, &count)) != 0) |
844 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
760 | if (count != 1) | 845 | if (count != 1) |
761 | fatal("Got multiple names (%d) from SSH_FXP_REALPATH", count); | 846 | fatal("Got multiple names (%d) from SSH_FXP_REALPATH", count); |
762 | 847 | ||
763 | filename = buffer_get_string(&msg, NULL); | 848 | if ((r = sshbuf_get_cstring(msg, &filename, NULL)) != 0 || |
764 | longname = buffer_get_string(&msg, NULL); | 849 | (r = sshbuf_get_cstring(msg, &longname, NULL)) != 0 || |
765 | a = decode_attrib(&msg); | 850 | (r = decode_attrib(msg, &a)) != 0) |
851 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
766 | 852 | ||
767 | debug3("SSH_FXP_REALPATH %s -> %s size %lu", path, filename, | 853 | debug3("SSH_FXP_REALPATH %s -> %s size %lu", path, filename, |
768 | (unsigned long)a->size); | 854 | (unsigned long)a.size); |
769 | 855 | ||
770 | free(longname); | 856 | free(longname); |
771 | 857 | ||
772 | buffer_free(&msg); | 858 | sshbuf_free(msg); |
773 | 859 | ||
774 | return(filename); | 860 | return(filename); |
775 | } | 861 | } |
776 | 862 | ||
777 | int | 863 | int |
778 | do_rename(struct sftp_conn *conn, char *oldpath, char *newpath, | 864 | do_rename(struct sftp_conn *conn, const char *oldpath, const char *newpath, |
779 | int force_legacy) | 865 | int force_legacy) |
780 | { | 866 | { |
781 | Buffer msg; | 867 | struct sshbuf *msg; |
782 | u_int status, id; | 868 | u_int status, id; |
783 | int use_ext = (conn->exts & SFTP_EXT_POSIX_RENAME) && !force_legacy; | 869 | int r, use_ext = (conn->exts & SFTP_EXT_POSIX_RENAME) && !force_legacy; |
784 | 870 | ||
785 | buffer_init(&msg); | 871 | if ((msg = sshbuf_new()) == NULL) |
872 | fatal("%s: sshbuf_new failed", __func__); | ||
786 | 873 | ||
787 | /* Send rename request */ | 874 | /* Send rename request */ |
788 | id = conn->msg_id++; | 875 | id = conn->msg_id++; |
789 | if (use_ext) { | 876 | if (use_ext) { |
790 | buffer_put_char(&msg, SSH2_FXP_EXTENDED); | 877 | if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || |
791 | buffer_put_int(&msg, id); | 878 | (r = sshbuf_put_u32(msg, id)) != 0 || |
792 | buffer_put_cstring(&msg, "posix-rename@openssh.com"); | 879 | (r = sshbuf_put_cstring(msg, |
880 | "posix-rename@openssh.com")) != 0) | ||
881 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
793 | } else { | 882 | } else { |
794 | buffer_put_char(&msg, SSH2_FXP_RENAME); | 883 | if ((r = sshbuf_put_u8(msg, SSH2_FXP_RENAME)) != 0 || |
795 | buffer_put_int(&msg, id); | 884 | (r = sshbuf_put_u32(msg, id)) != 0) |
885 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
796 | } | 886 | } |
797 | buffer_put_cstring(&msg, oldpath); | 887 | if ((r = sshbuf_put_cstring(msg, oldpath)) != 0 || |
798 | buffer_put_cstring(&msg, newpath); | 888 | (r = sshbuf_put_cstring(msg, newpath)) != 0) |
799 | send_msg(conn, &msg); | 889 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
890 | send_msg(conn, msg); | ||
800 | debug3("Sent message %s \"%s\" -> \"%s\"", | 891 | debug3("Sent message %s \"%s\" -> \"%s\"", |
801 | use_ext ? "posix-rename@openssh.com" : "SSH2_FXP_RENAME", | 892 | use_ext ? "posix-rename@openssh.com" : |
802 | oldpath, newpath); | 893 | "SSH2_FXP_RENAME", oldpath, newpath); |
803 | buffer_free(&msg); | 894 | sshbuf_free(msg); |
804 | 895 | ||
805 | status = get_status(conn, id); | 896 | status = get_status(conn, id); |
806 | if (status != SSH2_FX_OK) | 897 | if (status != SSH2_FX_OK) |
807 | error("Couldn't rename file \"%s\" to \"%s\": %s", oldpath, | 898 | error("Couldn't rename file \"%s\" to \"%s\": %s", oldpath, |
808 | newpath, fx2txt(status)); | 899 | newpath, fx2txt(status)); |
809 | 900 | ||
810 | return(status); | 901 | return status == SSH2_FX_OK ? 0 : -1; |
811 | } | 902 | } |
812 | 903 | ||
813 | int | 904 | int |
814 | do_hardlink(struct sftp_conn *conn, char *oldpath, char *newpath) | 905 | do_hardlink(struct sftp_conn *conn, const char *oldpath, const char *newpath) |
815 | { | 906 | { |
816 | Buffer msg; | 907 | struct sshbuf *msg; |
817 | u_int status, id; | 908 | u_int status, id; |
909 | int r; | ||
818 | 910 | ||
819 | if ((conn->exts & SFTP_EXT_HARDLINK) == 0) { | 911 | if ((conn->exts & SFTP_EXT_HARDLINK) == 0) { |
820 | error("Server does not support hardlink@openssh.com extension"); | 912 | error("Server does not support hardlink@openssh.com extension"); |
821 | return -1; | 913 | return -1; |
822 | } | 914 | } |
823 | 915 | ||
824 | buffer_init(&msg); | 916 | if ((msg = sshbuf_new()) == NULL) |
917 | fatal("%s: sshbuf_new failed", __func__); | ||
825 | 918 | ||
826 | /* Send link request */ | 919 | /* Send link request */ |
827 | id = conn->msg_id++; | 920 | id = conn->msg_id++; |
828 | buffer_put_char(&msg, SSH2_FXP_EXTENDED); | 921 | if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || |
829 | buffer_put_int(&msg, id); | 922 | (r = sshbuf_put_u32(msg, id)) != 0 || |
830 | buffer_put_cstring(&msg, "hardlink@openssh.com"); | 923 | (r = sshbuf_put_cstring(msg, "hardlink@openssh.com")) != 0 || |
831 | buffer_put_cstring(&msg, oldpath); | 924 | (r = sshbuf_put_cstring(msg, oldpath)) != 0 || |
832 | buffer_put_cstring(&msg, newpath); | 925 | (r = sshbuf_put_cstring(msg, newpath)) != 0) |
833 | send_msg(conn, &msg); | 926 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
927 | send_msg(conn, msg); | ||
834 | debug3("Sent message hardlink@openssh.com \"%s\" -> \"%s\"", | 928 | debug3("Sent message hardlink@openssh.com \"%s\" -> \"%s\"", |
835 | oldpath, newpath); | 929 | oldpath, newpath); |
836 | buffer_free(&msg); | 930 | sshbuf_free(msg); |
837 | 931 | ||
838 | status = get_status(conn, id); | 932 | status = get_status(conn, id); |
839 | if (status != SSH2_FX_OK) | 933 | if (status != SSH2_FX_OK) |
840 | error("Couldn't link file \"%s\" to \"%s\": %s", oldpath, | 934 | error("Couldn't link file \"%s\" to \"%s\": %s", oldpath, |
841 | newpath, fx2txt(status)); | 935 | newpath, fx2txt(status)); |
842 | 936 | ||
843 | return(status); | 937 | return status == SSH2_FX_OK ? 0 : -1; |
844 | } | 938 | } |
845 | 939 | ||
846 | int | 940 | int |
847 | do_symlink(struct sftp_conn *conn, char *oldpath, char *newpath) | 941 | do_symlink(struct sftp_conn *conn, const char *oldpath, const char *newpath) |
848 | { | 942 | { |
849 | Buffer msg; | 943 | struct sshbuf *msg; |
850 | u_int status, id; | 944 | u_int status, id; |
945 | int r; | ||
851 | 946 | ||
852 | if (conn->version < 3) { | 947 | if (conn->version < 3) { |
853 | error("This server does not support the symlink operation"); | 948 | error("This server does not support the symlink operation"); |
854 | return(SSH2_FX_OP_UNSUPPORTED); | 949 | return(SSH2_FX_OP_UNSUPPORTED); |
855 | } | 950 | } |
856 | 951 | ||
857 | buffer_init(&msg); | 952 | if ((msg = sshbuf_new()) == NULL) |
953 | fatal("%s: sshbuf_new failed", __func__); | ||
858 | 954 | ||
859 | /* Send symlink request */ | 955 | /* Send symlink request */ |
860 | id = conn->msg_id++; | 956 | id = conn->msg_id++; |
861 | buffer_put_char(&msg, SSH2_FXP_SYMLINK); | 957 | if ((r = sshbuf_put_u8(msg, SSH2_FXP_SYMLINK)) != 0 || |
862 | buffer_put_int(&msg, id); | 958 | (r = sshbuf_put_u32(msg, id)) != 0 || |
863 | buffer_put_cstring(&msg, oldpath); | 959 | (r = sshbuf_put_cstring(msg, oldpath)) != 0 || |
864 | buffer_put_cstring(&msg, newpath); | 960 | (r = sshbuf_put_cstring(msg, newpath)) != 0) |
865 | send_msg(conn, &msg); | 961 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
962 | send_msg(conn, msg); | ||
866 | debug3("Sent message SSH2_FXP_SYMLINK \"%s\" -> \"%s\"", oldpath, | 963 | debug3("Sent message SSH2_FXP_SYMLINK \"%s\" -> \"%s\"", oldpath, |
867 | newpath); | 964 | newpath); |
868 | buffer_free(&msg); | 965 | sshbuf_free(msg); |
869 | 966 | ||
870 | status = get_status(conn, id); | 967 | status = get_status(conn, id); |
871 | if (status != SSH2_FX_OK) | 968 | if (status != SSH2_FX_OK) |
872 | error("Couldn't symlink file \"%s\" to \"%s\": %s", oldpath, | 969 | error("Couldn't symlink file \"%s\" to \"%s\": %s", oldpath, |
873 | newpath, fx2txt(status)); | 970 | newpath, fx2txt(status)); |
874 | 971 | ||
875 | return(status); | 972 | return status == SSH2_FX_OK ? 0 : -1; |
876 | } | 973 | } |
877 | 974 | ||
878 | int | 975 | int |
879 | do_fsync(struct sftp_conn *conn, char *handle, u_int handle_len) | 976 | do_fsync(struct sftp_conn *conn, u_char *handle, u_int handle_len) |
880 | { | 977 | { |
881 | Buffer msg; | 978 | struct sshbuf *msg; |
882 | u_int status, id; | 979 | u_int status, id; |
980 | int r; | ||
883 | 981 | ||
884 | /* Silently return if the extension is not supported */ | 982 | /* Silently return if the extension is not supported */ |
885 | if ((conn->exts & SFTP_EXT_FSYNC) == 0) | 983 | if ((conn->exts & SFTP_EXT_FSYNC) == 0) |
886 | return -1; | 984 | return -1; |
887 | 985 | ||
888 | buffer_init(&msg); | ||
889 | |||
890 | /* Send fsync request */ | 986 | /* Send fsync request */ |
987 | if ((msg = sshbuf_new()) == NULL) | ||
988 | fatal("%s: sshbuf_new failed", __func__); | ||
891 | id = conn->msg_id++; | 989 | id = conn->msg_id++; |
892 | 990 | if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || | |
893 | buffer_put_char(&msg, SSH2_FXP_EXTENDED); | 991 | (r = sshbuf_put_u32(msg, id)) != 0 || |
894 | buffer_put_int(&msg, id); | 992 | (r = sshbuf_put_cstring(msg, "fsync@openssh.com")) != 0 || |
895 | buffer_put_cstring(&msg, "fsync@openssh.com"); | 993 | (r = sshbuf_put_string(msg, handle, handle_len)) != 0) |
896 | buffer_put_string(&msg, handle, handle_len); | 994 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
897 | send_msg(conn, &msg); | 995 | send_msg(conn, msg); |
898 | debug3("Sent message fsync@openssh.com I:%u", id); | 996 | debug3("Sent message fsync@openssh.com I:%u", id); |
899 | buffer_free(&msg); | 997 | sshbuf_free(msg); |
900 | 998 | ||
901 | status = get_status(conn, id); | 999 | status = get_status(conn, id); |
902 | if (status != SSH2_FX_OK) | 1000 | if (status != SSH2_FX_OK) |
@@ -907,50 +1005,58 @@ do_fsync(struct sftp_conn *conn, char *handle, u_int handle_len) | |||
907 | 1005 | ||
908 | #ifdef notyet | 1006 | #ifdef notyet |
909 | char * | 1007 | char * |
910 | do_readlink(struct sftp_conn *conn, char *path) | 1008 | do_readlink(struct sftp_conn *conn, const char *path) |
911 | { | 1009 | { |
912 | Buffer msg; | 1010 | struct sshbuf *msg; |
913 | u_int type, expected_id, count, id; | 1011 | u_int expected_id, count, id; |
914 | char *filename, *longname; | 1012 | char *filename, *longname; |
915 | Attrib *a; | 1013 | Attrib a; |
1014 | u_char type; | ||
1015 | int r; | ||
916 | 1016 | ||
917 | expected_id = id = conn->msg_id++; | 1017 | expected_id = id = conn->msg_id++; |
918 | send_string_request(conn, id, SSH2_FXP_READLINK, path, strlen(path)); | 1018 | send_string_request(conn, id, SSH2_FXP_READLINK, path, strlen(path)); |
919 | 1019 | ||
920 | buffer_init(&msg); | 1020 | if ((msg = sshbuf_new()) == NULL) |
1021 | fatal("%s: sshbuf_new failed", __func__); | ||
921 | 1022 | ||
922 | get_msg(conn, &msg); | 1023 | get_msg(conn, msg); |
923 | type = buffer_get_char(&msg); | 1024 | if ((r = sshbuf_get_u8(msg, &type)) != 0 || |
924 | id = buffer_get_int(&msg); | 1025 | (r = sshbuf_get_u32(msg, &id)) != 0) |
1026 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
925 | 1027 | ||
926 | if (id != expected_id) | 1028 | if (id != expected_id) |
927 | fatal("ID mismatch (%u != %u)", id, expected_id); | 1029 | fatal("ID mismatch (%u != %u)", id, expected_id); |
928 | 1030 | ||
929 | if (type == SSH2_FXP_STATUS) { | 1031 | if (type == SSH2_FXP_STATUS) { |
930 | u_int status = buffer_get_int(&msg); | 1032 | u_int status; |
931 | 1033 | ||
1034 | if ((r = sshbuf_get_u32(msg, &status)) != 0) | ||
1035 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
932 | error("Couldn't readlink: %s", fx2txt(status)); | 1036 | error("Couldn't readlink: %s", fx2txt(status)); |
933 | buffer_free(&msg); | 1037 | sshbuf_free(msg); |
934 | return(NULL); | 1038 | return(NULL); |
935 | } else if (type != SSH2_FXP_NAME) | 1039 | } else if (type != SSH2_FXP_NAME) |
936 | fatal("Expected SSH2_FXP_NAME(%u) packet, got %u", | 1040 | fatal("Expected SSH2_FXP_NAME(%u) packet, got %u", |
937 | SSH2_FXP_NAME, type); | 1041 | SSH2_FXP_NAME, type); |
938 | 1042 | ||
939 | count = buffer_get_int(&msg); | 1043 | if ((r = sshbuf_get_u32(msg, &count)) != 0) |
1044 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
940 | if (count != 1) | 1045 | if (count != 1) |
941 | fatal("Got multiple names (%d) from SSH_FXP_READLINK", count); | 1046 | fatal("Got multiple names (%d) from SSH_FXP_READLINK", count); |
942 | 1047 | ||
943 | filename = buffer_get_string(&msg, NULL); | 1048 | if ((r = sshbuf_get_cstring(msg, &filename, NULL)) != 0 || |
944 | longname = buffer_get_string(&msg, NULL); | 1049 | (r = sshbuf_get_cstring(msg, &longname, NULL)) != 0 || |
945 | a = decode_attrib(&msg); | 1050 | (r = decode_attrib(msg, &a)) != 0) |
1051 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
946 | 1052 | ||
947 | debug3("SSH_FXP_READLINK %s -> %s", path, filename); | 1053 | debug3("SSH_FXP_READLINK %s -> %s", path, filename); |
948 | 1054 | ||
949 | free(longname); | 1055 | free(longname); |
950 | 1056 | ||
951 | buffer_free(&msg); | 1057 | sshbuf_free(msg); |
952 | 1058 | ||
953 | return(filename); | 1059 | return filename; |
954 | } | 1060 | } |
955 | #endif | 1061 | #endif |
956 | 1062 | ||
@@ -958,8 +1064,9 @@ int | |||
958 | do_statvfs(struct sftp_conn *conn, const char *path, struct sftp_statvfs *st, | 1064 | do_statvfs(struct sftp_conn *conn, const char *path, struct sftp_statvfs *st, |
959 | int quiet) | 1065 | int quiet) |
960 | { | 1066 | { |
961 | Buffer msg; | 1067 | struct sshbuf *msg; |
962 | u_int id; | 1068 | u_int id; |
1069 | int r; | ||
963 | 1070 | ||
964 | if ((conn->exts & SFTP_EXT_STATVFS) == 0) { | 1071 | if ((conn->exts & SFTP_EXT_STATVFS) == 0) { |
965 | error("Server does not support statvfs@openssh.com extension"); | 1072 | error("Server does not support statvfs@openssh.com extension"); |
@@ -968,24 +1075,26 @@ do_statvfs(struct sftp_conn *conn, const char *path, struct sftp_statvfs *st, | |||
968 | 1075 | ||
969 | id = conn->msg_id++; | 1076 | id = conn->msg_id++; |
970 | 1077 | ||
971 | buffer_init(&msg); | 1078 | if ((msg = sshbuf_new()) == NULL) |
972 | buffer_clear(&msg); | 1079 | fatal("%s: sshbuf_new failed", __func__); |
973 | buffer_put_char(&msg, SSH2_FXP_EXTENDED); | 1080 | sshbuf_reset(msg); |
974 | buffer_put_int(&msg, id); | 1081 | if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || |
975 | buffer_put_cstring(&msg, "statvfs@openssh.com"); | 1082 | (r = sshbuf_put_u32(msg, id)) != 0 || |
976 | buffer_put_cstring(&msg, path); | 1083 | (r = sshbuf_put_cstring(msg, "statvfs@openssh.com")) != 0 || |
977 | send_msg(conn, &msg); | 1084 | (r = sshbuf_put_cstring(msg, path)) != 0) |
978 | buffer_free(&msg); | 1085 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
1086 | send_msg(conn, msg); | ||
1087 | sshbuf_free(msg); | ||
979 | 1088 | ||
980 | return get_decode_statvfs(conn, st, id, quiet); | 1089 | return get_decode_statvfs(conn, st, id, quiet); |
981 | } | 1090 | } |
982 | 1091 | ||
983 | #ifdef notyet | 1092 | #ifdef notyet |
984 | int | 1093 | int |
985 | do_fstatvfs(struct sftp_conn *conn, const char *handle, u_int handle_len, | 1094 | do_fstatvfs(struct sftp_conn *conn, const u_char *handle, u_int handle_len, |
986 | struct sftp_statvfs *st, int quiet) | 1095 | struct sftp_statvfs *st, int quiet) |
987 | { | 1096 | { |
988 | Buffer msg; | 1097 | struct sshbuf *msg; |
989 | u_int id; | 1098 | u_int id; |
990 | 1099 | ||
991 | if ((conn->exts & SFTP_EXT_FSTATVFS) == 0) { | 1100 | if ((conn->exts & SFTP_EXT_FSTATVFS) == 0) { |
@@ -995,14 +1104,16 @@ do_fstatvfs(struct sftp_conn *conn, const char *handle, u_int handle_len, | |||
995 | 1104 | ||
996 | id = conn->msg_id++; | 1105 | id = conn->msg_id++; |
997 | 1106 | ||
998 | buffer_init(&msg); | 1107 | if ((msg = sshbuf_new()) == NULL) |
999 | buffer_clear(&msg); | 1108 | fatal("%s: sshbuf_new failed", __func__); |
1000 | buffer_put_char(&msg, SSH2_FXP_EXTENDED); | 1109 | sshbuf_reset(msg); |
1001 | buffer_put_int(&msg, id); | 1110 | if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 || |
1002 | buffer_put_cstring(&msg, "fstatvfs@openssh.com"); | 1111 | (r = sshbuf_put_u32(msg, id)) != 0 || |
1003 | buffer_put_string(&msg, handle, handle_len); | 1112 | (r = sshbuf_put_cstring(msg, "fstatvfs@openssh.com")) != 0 || |
1004 | send_msg(conn, &msg); | 1113 | (r = sshbuf_put_string(msg, handle, handle_len)) != 0) |
1005 | buffer_free(&msg); | 1114 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
1115 | send_msg(conn, msg); | ||
1116 | sshbuf_free(msg); | ||
1006 | 1117 | ||
1007 | return get_decode_statvfs(conn, st, id, quiet); | 1118 | return get_decode_statvfs(conn, st, id, quiet); |
1008 | } | 1119 | } |
@@ -1010,42 +1121,48 @@ do_fstatvfs(struct sftp_conn *conn, const char *handle, u_int handle_len, | |||
1010 | 1121 | ||
1011 | static void | 1122 | static void |
1012 | send_read_request(struct sftp_conn *conn, u_int id, u_int64_t offset, | 1123 | send_read_request(struct sftp_conn *conn, u_int id, u_int64_t offset, |
1013 | u_int len, char *handle, u_int handle_len) | 1124 | u_int len, const u_char *handle, u_int handle_len) |
1014 | { | 1125 | { |
1015 | Buffer msg; | 1126 | struct sshbuf *msg; |
1016 | 1127 | int r; | |
1017 | buffer_init(&msg); | 1128 | |
1018 | buffer_clear(&msg); | 1129 | if ((msg = sshbuf_new()) == NULL) |
1019 | buffer_put_char(&msg, SSH2_FXP_READ); | 1130 | fatal("%s: sshbuf_new failed", __func__); |
1020 | buffer_put_int(&msg, id); | 1131 | sshbuf_reset(msg); |
1021 | buffer_put_string(&msg, handle, handle_len); | 1132 | if ((r = sshbuf_put_u8(msg, SSH2_FXP_READ)) != 0 || |
1022 | buffer_put_int64(&msg, offset); | 1133 | (r = sshbuf_put_u32(msg, id)) != 0 || |
1023 | buffer_put_int(&msg, len); | 1134 | (r = sshbuf_put_string(msg, handle, handle_len)) != 0 || |
1024 | send_msg(conn, &msg); | 1135 | (r = sshbuf_put_u64(msg, offset)) != 0 || |
1025 | buffer_free(&msg); | 1136 | (r = sshbuf_put_u32(msg, len)) != 0) |
1137 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
1138 | send_msg(conn, msg); | ||
1139 | sshbuf_free(msg); | ||
1026 | } | 1140 | } |
1027 | 1141 | ||
1028 | int | 1142 | int |
1029 | do_download(struct sftp_conn *conn, char *remote_path, char *local_path, | 1143 | do_download(struct sftp_conn *conn, const char *remote_path, |
1030 | Attrib *a, int preserve_flag, int resume_flag, int fsync_flag) | 1144 | const char *local_path, Attrib *a, int preserve_flag, int resume_flag, |
1145 | int fsync_flag) | ||
1031 | { | 1146 | { |
1032 | Attrib junk; | 1147 | Attrib junk; |
1033 | Buffer msg; | 1148 | struct sshbuf *msg; |
1034 | char *handle; | 1149 | u_char *handle; |
1035 | int local_fd = -1, status = 0, write_error; | 1150 | int local_fd = -1, write_error; |
1036 | int read_error, write_errno, reordered = 0; | 1151 | int read_error, write_errno, reordered = 0, r; |
1037 | u_int64_t offset = 0, size, highwater; | 1152 | u_int64_t offset = 0, size, highwater; |
1038 | u_int handle_len, mode, type, id, buflen, num_req, max_req; | 1153 | u_int mode, id, buflen, num_req, max_req, status = SSH2_FX_OK; |
1039 | off_t progress_counter; | 1154 | off_t progress_counter; |
1155 | size_t handle_len; | ||
1040 | struct stat st; | 1156 | struct stat st; |
1041 | struct request { | 1157 | struct request { |
1042 | u_int id; | 1158 | u_int id; |
1043 | u_int len; | 1159 | size_t len; |
1044 | u_int64_t offset; | 1160 | u_int64_t offset; |
1045 | TAILQ_ENTRY(request) tq; | 1161 | TAILQ_ENTRY(request) tq; |
1046 | }; | 1162 | }; |
1047 | TAILQ_HEAD(reqhead, request) requests; | 1163 | TAILQ_HEAD(reqhead, request) requests; |
1048 | struct request *req; | 1164 | struct request *req; |
1165 | u_char type; | ||
1049 | 1166 | ||
1050 | TAILQ_INIT(&requests); | 1167 | TAILQ_INIT(&requests); |
1051 | 1168 | ||
@@ -1070,23 +1187,26 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path, | |||
1070 | size = 0; | 1187 | size = 0; |
1071 | 1188 | ||
1072 | buflen = conn->transfer_buflen; | 1189 | buflen = conn->transfer_buflen; |
1073 | buffer_init(&msg); | 1190 | if ((msg = sshbuf_new()) == NULL) |
1191 | fatal("%s: sshbuf_new failed", __func__); | ||
1192 | |||
1193 | attrib_clear(&junk); /* Send empty attributes */ | ||
1074 | 1194 | ||
1075 | /* Send open request */ | 1195 | /* Send open request */ |
1076 | id = conn->msg_id++; | 1196 | id = conn->msg_id++; |
1077 | buffer_put_char(&msg, SSH2_FXP_OPEN); | 1197 | if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPEN)) != 0 || |
1078 | buffer_put_int(&msg, id); | 1198 | (r = sshbuf_put_u32(msg, id)) != 0 || |
1079 | buffer_put_cstring(&msg, remote_path); | 1199 | (r = sshbuf_put_cstring(msg, remote_path)) != 0 || |
1080 | buffer_put_int(&msg, SSH2_FXF_READ); | 1200 | (r = sshbuf_put_u32(msg, SSH2_FXF_READ)) != 0 || |
1081 | attrib_clear(&junk); /* Send empty attributes */ | 1201 | (r = encode_attrib(msg, &junk)) != 0) |
1082 | encode_attrib(&msg, &junk); | 1202 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
1083 | send_msg(conn, &msg); | 1203 | send_msg(conn, msg); |
1084 | debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, remote_path); | 1204 | debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, remote_path); |
1085 | 1205 | ||
1086 | handle = get_handle(conn, id, &handle_len, | 1206 | handle = get_handle(conn, id, &handle_len, |
1087 | "remote open(\"%s\")", remote_path); | 1207 | "remote open(\"%s\")", remote_path); |
1088 | if (handle == NULL) { | 1208 | if (handle == NULL) { |
1089 | buffer_free(&msg); | 1209 | sshbuf_free(msg); |
1090 | return(-1); | 1210 | return(-1); |
1091 | } | 1211 | } |
1092 | 1212 | ||
@@ -1113,7 +1233,7 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path, | |||
1113 | "local file is larger than remote", local_path); | 1233 | "local file is larger than remote", local_path); |
1114 | fail: | 1234 | fail: |
1115 | do_close(conn, handle, handle_len); | 1235 | do_close(conn, handle, handle_len); |
1116 | buffer_free(&msg); | 1236 | sshbuf_free(msg); |
1117 | free(handle); | 1237 | free(handle); |
1118 | if (local_fd != -1) | 1238 | if (local_fd != -1) |
1119 | close(local_fd); | 1239 | close(local_fd); |
@@ -1131,8 +1251,8 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path, | |||
1131 | start_progress_meter(remote_path, size, &progress_counter); | 1251 | start_progress_meter(remote_path, size, &progress_counter); |
1132 | 1252 | ||
1133 | while (num_req > 0 || max_req > 0) { | 1253 | while (num_req > 0 || max_req > 0) { |
1134 | char *data; | 1254 | u_char *data; |
1135 | u_int len; | 1255 | size_t len; |
1136 | 1256 | ||
1137 | /* | 1257 | /* |
1138 | * Simulate EOF on interrupt: stop sending new requests and | 1258 | * Simulate EOF on interrupt: stop sending new requests and |
@@ -1161,10 +1281,11 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path, | |||
1161 | req->len, handle, handle_len); | 1281 | req->len, handle, handle_len); |
1162 | } | 1282 | } |
1163 | 1283 | ||
1164 | buffer_clear(&msg); | 1284 | sshbuf_reset(msg); |
1165 | get_msg(conn, &msg); | 1285 | get_msg(conn, msg); |
1166 | type = buffer_get_char(&msg); | 1286 | if ((r = sshbuf_get_u8(msg, &type)) != 0 || |
1167 | id = buffer_get_int(&msg); | 1287 | (r = sshbuf_get_u32(msg, &id)) != 0) |
1288 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
1168 | debug3("Received reply T:%u I:%u R:%d", type, id, max_req); | 1289 | debug3("Received reply T:%u I:%u R:%d", type, id, max_req); |
1169 | 1290 | ||
1170 | /* Find the request in our queue */ | 1291 | /* Find the request in our queue */ |
@@ -1177,7 +1298,9 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path, | |||
1177 | 1298 | ||
1178 | switch (type) { | 1299 | switch (type) { |
1179 | case SSH2_FXP_STATUS: | 1300 | case SSH2_FXP_STATUS: |
1180 | status = buffer_get_int(&msg); | 1301 | if ((r = sshbuf_get_u32(msg, &status)) != 0) |
1302 | fatal("%s: buffer error: %s", | ||
1303 | __func__, ssh_err(r)); | ||
1181 | if (status != SSH2_FX_EOF) | 1304 | if (status != SSH2_FX_EOF) |
1182 | read_error = 1; | 1305 | read_error = 1; |
1183 | max_req = 0; | 1306 | max_req = 0; |
@@ -1186,13 +1309,15 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path, | |||
1186 | num_req--; | 1309 | num_req--; |
1187 | break; | 1310 | break; |
1188 | case SSH2_FXP_DATA: | 1311 | case SSH2_FXP_DATA: |
1189 | data = buffer_get_string(&msg, &len); | 1312 | if ((r = sshbuf_get_string(msg, &data, &len)) != 0) |
1313 | fatal("%s: buffer error: %s", | ||
1314 | __func__, ssh_err(r)); | ||
1190 | debug3("Received data %llu -> %llu", | 1315 | debug3("Received data %llu -> %llu", |
1191 | (unsigned long long)req->offset, | 1316 | (unsigned long long)req->offset, |
1192 | (unsigned long long)req->offset + len - 1); | 1317 | (unsigned long long)req->offset + len - 1); |
1193 | if (len > req->len) | 1318 | if (len > req->len) |
1194 | fatal("Received more data than asked for " | 1319 | fatal("Received more data than asked for " |
1195 | "%u > %u", len, req->len); | 1320 | "%zu > %zu", len, req->len); |
1196 | if ((lseek(local_fd, req->offset, SEEK_SET) == -1 || | 1321 | if ((lseek(local_fd, req->offset, SEEK_SET) == -1 || |
1197 | atomicio(vwrite, local_fd, data, len) != len) && | 1322 | atomicio(vwrite, local_fd, data, len) != len) && |
1198 | !write_error) { | 1323 | !write_error) { |
@@ -1269,12 +1394,13 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path, | |||
1269 | } else if (write_error) { | 1394 | } else if (write_error) { |
1270 | error("Couldn't write to \"%s\": %s", local_path, | 1395 | error("Couldn't write to \"%s\": %s", local_path, |
1271 | strerror(write_errno)); | 1396 | strerror(write_errno)); |
1272 | status = -1; | 1397 | status = SSH2_FX_FAILURE; |
1273 | do_close(conn, handle, handle_len); | 1398 | do_close(conn, handle, handle_len); |
1274 | } else { | 1399 | } else { |
1275 | status = do_close(conn, handle, handle_len); | 1400 | if (do_close(conn, handle, handle_len) != 0 || interrupted) |
1276 | if (interrupted || status != SSH2_FX_OK) | 1401 | status = SSH2_FX_FAILURE; |
1277 | status = -1; | 1402 | else |
1403 | status = SSH2_FX_OK; | ||
1278 | /* Override umask and utimes if asked */ | 1404 | /* Override umask and utimes if asked */ |
1279 | #ifdef HAVE_FCHMOD | 1405 | #ifdef HAVE_FCHMOD |
1280 | if (preserve_flag && fchmod(local_fd, mode) == -1) | 1406 | if (preserve_flag && fchmod(local_fd, mode) == -1) |
@@ -1301,16 +1427,16 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path, | |||
1301 | } | 1427 | } |
1302 | } | 1428 | } |
1303 | close(local_fd); | 1429 | close(local_fd); |
1304 | buffer_free(&msg); | 1430 | sshbuf_free(msg); |
1305 | free(handle); | 1431 | free(handle); |
1306 | 1432 | ||
1307 | return(status); | 1433 | return(status); |
1308 | } | 1434 | } |
1309 | 1435 | ||
1310 | static int | 1436 | static int |
1311 | download_dir_internal(struct sftp_conn *conn, char *src, char *dst, int depth, | 1437 | download_dir_internal(struct sftp_conn *conn, const char *src, const char *dst, |
1312 | Attrib *dirattrib, int preserve_flag, int print_flag, int resume_flag, | 1438 | int depth, Attrib *dirattrib, int preserve_flag, int print_flag, |
1313 | int fsync_flag) | 1439 | int resume_flag, int fsync_flag) |
1314 | { | 1440 | { |
1315 | int i, ret = 0; | 1441 | int i, ret = 0; |
1316 | SFTP_DIRENT **dir_entries; | 1442 | SFTP_DIRENT **dir_entries; |
@@ -1400,9 +1526,9 @@ download_dir_internal(struct sftp_conn *conn, char *src, char *dst, int depth, | |||
1400 | } | 1526 | } |
1401 | 1527 | ||
1402 | int | 1528 | int |
1403 | download_dir(struct sftp_conn *conn, char *src, char *dst, | 1529 | download_dir(struct sftp_conn *conn, const char *src, const char *dst, |
1404 | Attrib *dirattrib, int preserve_flag, int print_flag, | 1530 | Attrib *dirattrib, int preserve_flag, int print_flag, int resume_flag, |
1405 | int resume_flag, int fsync_flag) | 1531 | int fsync_flag) |
1406 | { | 1532 | { |
1407 | char *src_canon; | 1533 | char *src_canon; |
1408 | int ret; | 1534 | int ret; |
@@ -1419,15 +1545,16 @@ download_dir(struct sftp_conn *conn, char *src, char *dst, | |||
1419 | } | 1545 | } |
1420 | 1546 | ||
1421 | int | 1547 | int |
1422 | do_upload(struct sftp_conn *conn, char *local_path, char *remote_path, | 1548 | do_upload(struct sftp_conn *conn, const char *local_path, |
1423 | int preserve_flag, int resume, int fsync_flag) | 1549 | const char *remote_path, int preserve_flag, int resume, int fsync_flag) |
1424 | { | 1550 | { |
1425 | int local_fd; | 1551 | int r, local_fd; |
1426 | int status = SSH2_FX_OK; | 1552 | u_int status = SSH2_FX_OK; |
1427 | u_int handle_len, id, type; | 1553 | u_int id; |
1554 | u_char type; | ||
1428 | off_t offset, progress_counter; | 1555 | off_t offset, progress_counter; |
1429 | char *handle, *data; | 1556 | u_char *handle, *data; |
1430 | Buffer msg; | 1557 | struct sshbuf *msg; |
1431 | struct stat sb; | 1558 | struct stat sb; |
1432 | Attrib a, *c = NULL; | 1559 | Attrib a, *c = NULL; |
1433 | u_int32_t startid; | 1560 | u_int32_t startid; |
@@ -1440,6 +1567,7 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path, | |||
1440 | }; | 1567 | }; |
1441 | TAILQ_HEAD(ackhead, outstanding_ack) acks; | 1568 | TAILQ_HEAD(ackhead, outstanding_ack) acks; |
1442 | struct outstanding_ack *ack = NULL; | 1569 | struct outstanding_ack *ack = NULL; |
1570 | size_t handle_len; | ||
1443 | 1571 | ||
1444 | TAILQ_INIT(&acks); | 1572 | TAILQ_INIT(&acks); |
1445 | 1573 | ||
@@ -1487,26 +1615,28 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path, | |||
1487 | } | 1615 | } |
1488 | } | 1616 | } |
1489 | 1617 | ||
1490 | buffer_init(&msg); | 1618 | if ((msg = sshbuf_new()) == NULL) |
1619 | fatal("%s: sshbuf_new failed", __func__); | ||
1491 | 1620 | ||
1492 | /* Send open request */ | 1621 | /* Send open request */ |
1493 | id = conn->msg_id++; | 1622 | id = conn->msg_id++; |
1494 | buffer_put_char(&msg, SSH2_FXP_OPEN); | 1623 | if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPEN)) != 0 || |
1495 | buffer_put_int(&msg, id); | 1624 | (r = sshbuf_put_u32(msg, id)) != 0 || |
1496 | buffer_put_cstring(&msg, remote_path); | 1625 | (r = sshbuf_put_cstring(msg, remote_path)) != 0 || |
1497 | buffer_put_int(&msg, SSH2_FXF_WRITE|SSH2_FXF_CREAT| | 1626 | (r = sshbuf_put_u32(msg, SSH2_FXF_WRITE|SSH2_FXF_CREAT| |
1498 | (resume ? SSH2_FXF_APPEND : SSH2_FXF_TRUNC)); | 1627 | (resume ? SSH2_FXF_APPEND : SSH2_FXF_TRUNC))) != 0 || |
1499 | encode_attrib(&msg, &a); | 1628 | (r = encode_attrib(msg, &a)) != 0) |
1500 | send_msg(conn, &msg); | 1629 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
1630 | send_msg(conn, msg); | ||
1501 | debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, remote_path); | 1631 | debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, remote_path); |
1502 | 1632 | ||
1503 | buffer_clear(&msg); | 1633 | sshbuf_reset(msg); |
1504 | 1634 | ||
1505 | handle = get_handle(conn, id, &handle_len, | 1635 | handle = get_handle(conn, id, &handle_len, |
1506 | "remote open(\"%s\")", remote_path); | 1636 | "remote open(\"%s\")", remote_path); |
1507 | if (handle == NULL) { | 1637 | if (handle == NULL) { |
1508 | close(local_fd); | 1638 | close(local_fd); |
1509 | buffer_free(&msg); | 1639 | sshbuf_free(msg); |
1510 | return -1; | 1640 | return -1; |
1511 | } | 1641 | } |
1512 | 1642 | ||
@@ -1546,13 +1676,16 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path, | |||
1546 | ack->len = len; | 1676 | ack->len = len; |
1547 | TAILQ_INSERT_TAIL(&acks, ack, tq); | 1677 | TAILQ_INSERT_TAIL(&acks, ack, tq); |
1548 | 1678 | ||
1549 | buffer_clear(&msg); | 1679 | sshbuf_reset(msg); |
1550 | buffer_put_char(&msg, SSH2_FXP_WRITE); | 1680 | if ((r = sshbuf_put_u8(msg, SSH2_FXP_WRITE)) != 0 || |
1551 | buffer_put_int(&msg, ack->id); | 1681 | (r = sshbuf_put_u32(msg, ack->id)) != 0 || |
1552 | buffer_put_string(&msg, handle, handle_len); | 1682 | (r = sshbuf_put_string(msg, handle, |
1553 | buffer_put_int64(&msg, offset); | 1683 | handle_len)) != 0 || |
1554 | buffer_put_string(&msg, data, len); | 1684 | (r = sshbuf_put_u64(msg, offset)) != 0 || |
1555 | send_msg(conn, &msg); | 1685 | (r = sshbuf_put_string(msg, data, len)) != 0) |
1686 | fatal("%s: buffer error: %s", | ||
1687 | __func__, ssh_err(r)); | ||
1688 | send_msg(conn, msg); | ||
1556 | debug3("Sent message SSH2_FXP_WRITE I:%u O:%llu S:%u", | 1689 | debug3("Sent message SSH2_FXP_WRITE I:%u O:%llu S:%u", |
1557 | id, (unsigned long long)offset, len); | 1690 | id, (unsigned long long)offset, len); |
1558 | } else if (TAILQ_FIRST(&acks) == NULL) | 1691 | } else if (TAILQ_FIRST(&acks) == NULL) |
@@ -1563,27 +1696,31 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path, | |||
1563 | 1696 | ||
1564 | if (id == startid || len == 0 || | 1697 | if (id == startid || len == 0 || |
1565 | id - ackid >= conn->num_requests) { | 1698 | id - ackid >= conn->num_requests) { |
1566 | u_int r_id; | 1699 | u_int rid; |
1567 | 1700 | ||
1568 | buffer_clear(&msg); | 1701 | sshbuf_reset(msg); |
1569 | get_msg(conn, &msg); | 1702 | get_msg(conn, msg); |
1570 | type = buffer_get_char(&msg); | 1703 | if ((r = sshbuf_get_u8(msg, &type)) != 0 || |
1571 | r_id = buffer_get_int(&msg); | 1704 | (r = sshbuf_get_u32(msg, &rid)) != 0) |
1705 | fatal("%s: buffer error: %s", | ||
1706 | __func__, ssh_err(r)); | ||
1572 | 1707 | ||
1573 | if (type != SSH2_FXP_STATUS) | 1708 | if (type != SSH2_FXP_STATUS) |
1574 | fatal("Expected SSH2_FXP_STATUS(%d) packet, " | 1709 | fatal("Expected SSH2_FXP_STATUS(%d) packet, " |
1575 | "got %d", SSH2_FXP_STATUS, type); | 1710 | "got %d", SSH2_FXP_STATUS, type); |
1576 | 1711 | ||
1577 | status = buffer_get_int(&msg); | 1712 | if ((r = sshbuf_get_u32(msg, &status)) != 0) |
1578 | debug3("SSH2_FXP_STATUS %d", status); | 1713 | fatal("%s: buffer error: %s", |
1714 | __func__, ssh_err(r)); | ||
1715 | debug3("SSH2_FXP_STATUS %u", status); | ||
1579 | 1716 | ||
1580 | /* Find the request in our queue */ | 1717 | /* Find the request in our queue */ |
1581 | for (ack = TAILQ_FIRST(&acks); | 1718 | for (ack = TAILQ_FIRST(&acks); |
1582 | ack != NULL && ack->id != r_id; | 1719 | ack != NULL && ack->id != rid; |
1583 | ack = TAILQ_NEXT(ack, tq)) | 1720 | ack = TAILQ_NEXT(ack, tq)) |
1584 | ; | 1721 | ; |
1585 | if (ack == NULL) | 1722 | if (ack == NULL) |
1586 | fatal("Can't find request for ID %u", r_id); | 1723 | fatal("Can't find request for ID %u", rid); |
1587 | TAILQ_REMOVE(&acks, ack, tq); | 1724 | TAILQ_REMOVE(&acks, ack, tq); |
1588 | debug3("In write loop, ack for %u %u bytes at %lld", | 1725 | debug3("In write loop, ack for %u %u bytes at %lld", |
1589 | ack->id, ack->len, (long long)ack->offset); | 1726 | ack->id, ack->len, (long long)ack->offset); |
@@ -1595,7 +1732,7 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path, | |||
1595 | if (offset < 0) | 1732 | if (offset < 0) |
1596 | fatal("%s: offset < 0", __func__); | 1733 | fatal("%s: offset < 0", __func__); |
1597 | } | 1734 | } |
1598 | buffer_free(&msg); | 1735 | sshbuf_free(msg); |
1599 | 1736 | ||
1600 | if (showprogress) | 1737 | if (showprogress) |
1601 | stop_progress_meter(); | 1738 | stop_progress_meter(); |
@@ -1604,13 +1741,13 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path, | |||
1604 | if (status != SSH2_FX_OK) { | 1741 | if (status != SSH2_FX_OK) { |
1605 | error("Couldn't write to remote file \"%s\": %s", | 1742 | error("Couldn't write to remote file \"%s\": %s", |
1606 | remote_path, fx2txt(status)); | 1743 | remote_path, fx2txt(status)); |
1607 | status = -1; | 1744 | status = SSH2_FX_FAILURE; |
1608 | } | 1745 | } |
1609 | 1746 | ||
1610 | if (close(local_fd) == -1) { | 1747 | if (close(local_fd) == -1) { |
1611 | error("Couldn't close local file \"%s\": %s", local_path, | 1748 | error("Couldn't close local file \"%s\": %s", local_path, |
1612 | strerror(errno)); | 1749 | strerror(errno)); |
1613 | status = -1; | 1750 | status = SSH2_FX_FAILURE; |
1614 | } | 1751 | } |
1615 | 1752 | ||
1616 | /* Override umask and utimes if asked */ | 1753 | /* Override umask and utimes if asked */ |
@@ -1621,17 +1758,19 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path, | |||
1621 | (void)do_fsync(conn, handle, handle_len); | 1758 | (void)do_fsync(conn, handle, handle_len); |
1622 | 1759 | ||
1623 | if (do_close(conn, handle, handle_len) != SSH2_FX_OK) | 1760 | if (do_close(conn, handle, handle_len) != SSH2_FX_OK) |
1624 | status = -1; | 1761 | status = SSH2_FX_FAILURE; |
1762 | |||
1625 | free(handle); | 1763 | free(handle); |
1626 | 1764 | ||
1627 | return status; | 1765 | return status == SSH2_FX_OK ? 0 : -1; |
1628 | } | 1766 | } |
1629 | 1767 | ||
1630 | static int | 1768 | static int |
1631 | upload_dir_internal(struct sftp_conn *conn, char *src, char *dst, int depth, | 1769 | upload_dir_internal(struct sftp_conn *conn, const char *src, const char *dst, |
1632 | int preserve_flag, int print_flag, int resume, int fsync_flag) | 1770 | int depth, int preserve_flag, int print_flag, int resume, int fsync_flag) |
1633 | { | 1771 | { |
1634 | int ret = 0, status; | 1772 | int ret = 0; |
1773 | u_int status; | ||
1635 | DIR *dirp; | 1774 | DIR *dirp; |
1636 | struct dirent *dp; | 1775 | struct dirent *dp; |
1637 | char *filename, *new_src, *new_dst; | 1776 | char *filename, *new_src, *new_dst; |
@@ -1721,8 +1860,8 @@ upload_dir_internal(struct sftp_conn *conn, char *src, char *dst, int depth, | |||
1721 | } | 1860 | } |
1722 | 1861 | ||
1723 | int | 1862 | int |
1724 | upload_dir(struct sftp_conn *conn, char *src, char *dst, int preserve_flag, | 1863 | upload_dir(struct sftp_conn *conn, const char *src, const char *dst, |
1725 | int print_flag, int resume, int fsync_flag) | 1864 | int preserve_flag, int print_flag, int resume, int fsync_flag) |
1726 | { | 1865 | { |
1727 | char *dst_canon; | 1866 | char *dst_canon; |
1728 | int ret; | 1867 | int ret; |
@@ -1740,7 +1879,7 @@ upload_dir(struct sftp_conn *conn, char *src, char *dst, int preserve_flag, | |||
1740 | } | 1879 | } |
1741 | 1880 | ||
1742 | char * | 1881 | char * |
1743 | path_append(char *p1, char *p2) | 1882 | path_append(const char *p1, const char *p2) |
1744 | { | 1883 | { |
1745 | char *ret; | 1884 | char *ret; |
1746 | size_t len = strlen(p1) + strlen(p2) + 2; | 1885 | size_t len = strlen(p1) + strlen(p2) + 2; |