xref: /openbsd-src/usr.bin/ssh/sftp-client.c (revision 097a140d792de8b2bbe59ad827d39eabf9b4280a)
1 /* $OpenBSD: sftp-client.c,v 1.142 2021/04/03 06:18:41 djm Exp $ */
2 /*
3  * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 /* XXX: memleaks */
19 /* XXX: signed vs unsigned */
20 /* XXX: remove all logging, only return status codes */
21 /* XXX: copy between two remote sites */
22 
23 #include <sys/types.h>
24 #include <sys/poll.h>
25 #include <sys/queue.h>
26 #include <sys/stat.h>
27 #include <sys/time.h>
28 #include <sys/statvfs.h>
29 #include <sys/uio.h>
30 
31 #include <dirent.h>
32 #include <errno.h>
33 #include <fcntl.h>
34 #include <signal.h>
35 #include <stdarg.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <unistd.h>
40 
41 #include "xmalloc.h"
42 #include "ssherr.h"
43 #include "sshbuf.h"
44 #include "log.h"
45 #include "atomicio.h"
46 #include "progressmeter.h"
47 #include "misc.h"
48 #include "utf8.h"
49 
50 #include "sftp.h"
51 #include "sftp-common.h"
52 #include "sftp-client.h"
53 
54 extern volatile sig_atomic_t interrupted;
55 extern int showprogress;
56 
57 /* Default size of buffer for up/download */
58 #define DEFAULT_COPY_BUFLEN	32768
59 
60 /* Default number of concurrent outstanding requests */
61 #define DEFAULT_NUM_REQUESTS	64
62 
63 /* Minimum amount of data to read at a time */
64 #define MIN_READ_SIZE	512
65 
66 /* Maximum depth to descend in directory trees */
67 #define MAX_DIR_DEPTH 64
68 
69 struct sftp_conn {
70 	int fd_in;
71 	int fd_out;
72 	u_int download_buflen;
73 	u_int upload_buflen;
74 	u_int num_requests;
75 	u_int version;
76 	u_int msg_id;
77 #define SFTP_EXT_POSIX_RENAME	0x00000001
78 #define SFTP_EXT_STATVFS	0x00000002
79 #define SFTP_EXT_FSTATVFS	0x00000004
80 #define SFTP_EXT_HARDLINK	0x00000008
81 #define SFTP_EXT_FSYNC		0x00000010
82 #define SFTP_EXT_LSETSTAT	0x00000020
83 #define SFTP_EXT_LIMITS		0x00000040
84 	u_int exts;
85 	u_int64_t limit_kbps;
86 	struct bwlimit bwlimit_in, bwlimit_out;
87 };
88 
89 static u_char *
90 get_handle(struct sftp_conn *conn, u_int expected_id, size_t *len,
91     const char *errfmt, ...) __attribute__((format(printf, 4, 5)));
92 
93 /* ARGSUSED */
94 static int
95 sftpio(void *_bwlimit, size_t amount)
96 {
97 	struct bwlimit *bwlimit = (struct bwlimit *)_bwlimit;
98 
99 	refresh_progress_meter(0);
100 	if (bwlimit != NULL)
101 		bandwidth_limit(bwlimit, amount);
102 	return 0;
103 }
104 
105 static void
106 send_msg(struct sftp_conn *conn, struct sshbuf *m)
107 {
108 	u_char mlen[4];
109 	struct iovec iov[2];
110 
111 	if (sshbuf_len(m) > SFTP_MAX_MSG_LENGTH)
112 		fatal("Outbound message too long %zu", sshbuf_len(m));
113 
114 	/* Send length first */
115 	put_u32(mlen, sshbuf_len(m));
116 	iov[0].iov_base = mlen;
117 	iov[0].iov_len = sizeof(mlen);
118 	iov[1].iov_base = (u_char *)sshbuf_ptr(m);
119 	iov[1].iov_len = sshbuf_len(m);
120 
121 	if (atomiciov6(writev, conn->fd_out, iov, 2, sftpio,
122 	    conn->limit_kbps > 0 ? &conn->bwlimit_out : NULL) !=
123 	    sshbuf_len(m) + sizeof(mlen))
124 		fatal("Couldn't send packet: %s", strerror(errno));
125 
126 	sshbuf_reset(m);
127 }
128 
129 static void
130 get_msg_extended(struct sftp_conn *conn, struct sshbuf *m, int initial)
131 {
132 	u_int msg_len;
133 	u_char *p;
134 	int r;
135 
136 	if ((r = sshbuf_reserve(m, 4, &p)) != 0)
137 		fatal_fr(r, "reserve");
138 	if (atomicio6(read, conn->fd_in, p, 4, sftpio,
139 	    conn->limit_kbps > 0 ? &conn->bwlimit_in : NULL) != 4) {
140 		if (errno == EPIPE || errno == ECONNRESET)
141 			fatal("Connection closed");
142 		else
143 			fatal("Couldn't read packet: %s", strerror(errno));
144 	}
145 
146 	if ((r = sshbuf_get_u32(m, &msg_len)) != 0)
147 		fatal_fr(r, "sshbuf_get_u32");
148 	if (msg_len > SFTP_MAX_MSG_LENGTH) {
149 		do_log2(initial ? SYSLOG_LEVEL_ERROR : SYSLOG_LEVEL_FATAL,
150 		    "Received message too long %u", msg_len);
151 		fatal("Ensure the remote shell produces no output "
152 		    "for non-interactive sessions.");
153 	}
154 
155 	if ((r = sshbuf_reserve(m, msg_len, &p)) != 0)
156 		fatal_fr(r, "reserve");
157 	if (atomicio6(read, conn->fd_in, p, msg_len, sftpio,
158 	    conn->limit_kbps > 0 ? &conn->bwlimit_in : NULL)
159 	    != msg_len) {
160 		if (errno == EPIPE)
161 			fatal("Connection closed");
162 		else
163 			fatal("Read packet: %s", strerror(errno));
164 	}
165 }
166 
167 static void
168 get_msg(struct sftp_conn *conn, struct sshbuf *m)
169 {
170 	get_msg_extended(conn, m, 0);
171 }
172 
173 static void
174 send_string_request(struct sftp_conn *conn, u_int id, u_int code, const char *s,
175     u_int len)
176 {
177 	struct sshbuf *msg;
178 	int r;
179 
180 	if ((msg = sshbuf_new()) == NULL)
181 		fatal_f("sshbuf_new failed");
182 	if ((r = sshbuf_put_u8(msg, code)) != 0 ||
183 	    (r = sshbuf_put_u32(msg, id)) != 0 ||
184 	    (r = sshbuf_put_string(msg, s, len)) != 0)
185 		fatal_fr(r, "compose");
186 	send_msg(conn, msg);
187 	debug3("Sent message fd %d T:%u I:%u", conn->fd_out, code, id);
188 	sshbuf_free(msg);
189 }
190 
191 static void
192 send_string_attrs_request(struct sftp_conn *conn, u_int id, u_int code,
193     const void *s, u_int len, Attrib *a)
194 {
195 	struct sshbuf *msg;
196 	int r;
197 
198 	if ((msg = sshbuf_new()) == NULL)
199 		fatal_f("sshbuf_new failed");
200 	if ((r = sshbuf_put_u8(msg, code)) != 0 ||
201 	    (r = sshbuf_put_u32(msg, id)) != 0 ||
202 	    (r = sshbuf_put_string(msg, s, len)) != 0 ||
203 	    (r = encode_attrib(msg, a)) != 0)
204 		fatal_fr(r, "compose");
205 	send_msg(conn, msg);
206 	debug3("Sent message fd %d T:%u I:%u", conn->fd_out, code, id);
207 	sshbuf_free(msg);
208 }
209 
210 static u_int
211 get_status(struct sftp_conn *conn, u_int expected_id)
212 {
213 	struct sshbuf *msg;
214 	u_char type;
215 	u_int id, status;
216 	int r;
217 
218 	if ((msg = sshbuf_new()) == NULL)
219 		fatal_f("sshbuf_new failed");
220 	get_msg(conn, msg);
221 	if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
222 	    (r = sshbuf_get_u32(msg, &id)) != 0)
223 		fatal_fr(r, "compose");
224 
225 	if (id != expected_id)
226 		fatal("ID mismatch (%u != %u)", id, expected_id);
227 	if (type != SSH2_FXP_STATUS)
228 		fatal("Expected SSH2_FXP_STATUS(%u) packet, got %u",
229 		    SSH2_FXP_STATUS, type);
230 
231 	if ((r = sshbuf_get_u32(msg, &status)) != 0)
232 		fatal_fr(r, "parse");
233 	sshbuf_free(msg);
234 
235 	debug3("SSH2_FXP_STATUS %u", status);
236 
237 	return status;
238 }
239 
240 static u_char *
241 get_handle(struct sftp_conn *conn, u_int expected_id, size_t *len,
242     const char *errfmt, ...)
243 {
244 	struct sshbuf *msg;
245 	u_int id, status;
246 	u_char type;
247 	u_char *handle;
248 	char errmsg[256];
249 	va_list args;
250 	int r;
251 
252 	va_start(args, errfmt);
253 	if (errfmt != NULL)
254 		vsnprintf(errmsg, sizeof(errmsg), errfmt, args);
255 	va_end(args);
256 
257 	if ((msg = sshbuf_new()) == NULL)
258 		fatal_f("sshbuf_new failed");
259 	get_msg(conn, msg);
260 	if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
261 	    (r = sshbuf_get_u32(msg, &id)) != 0)
262 		fatal_fr(r, "parse");
263 
264 	if (id != expected_id)
265 		fatal("%s: ID mismatch (%u != %u)",
266 		    errfmt == NULL ? __func__ : errmsg, id, expected_id);
267 	if (type == SSH2_FXP_STATUS) {
268 		if ((r = sshbuf_get_u32(msg, &status)) != 0)
269 			fatal_fr(r, "parse status");
270 		if (errfmt != NULL)
271 			error("%s: %s", errmsg, fx2txt(status));
272 		sshbuf_free(msg);
273 		return(NULL);
274 	} else if (type != SSH2_FXP_HANDLE)
275 		fatal("%s: Expected SSH2_FXP_HANDLE(%u) packet, got %u",
276 		    errfmt == NULL ? __func__ : errmsg, SSH2_FXP_HANDLE, type);
277 
278 	if ((r = sshbuf_get_string(msg, &handle, len)) != 0)
279 		fatal_fr(r, "parse handle");
280 	sshbuf_free(msg);
281 
282 	return handle;
283 }
284 
285 static Attrib *
286 get_decode_stat(struct sftp_conn *conn, u_int expected_id, int quiet)
287 {
288 	struct sshbuf *msg;
289 	u_int id;
290 	u_char type;
291 	int r;
292 	static Attrib a;
293 
294 	if ((msg = sshbuf_new()) == NULL)
295 		fatal_f("sshbuf_new failed");
296 	get_msg(conn, msg);
297 
298 	if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
299 	    (r = sshbuf_get_u32(msg, &id)) != 0)
300 		fatal_fr(r, "parse");
301 
302 	debug3("Received stat reply T:%u I:%u", type, id);
303 	if (id != expected_id)
304 		fatal("ID mismatch (%u != %u)", id, expected_id);
305 	if (type == SSH2_FXP_STATUS) {
306 		u_int status;
307 
308 		if ((r = sshbuf_get_u32(msg, &status)) != 0)
309 			fatal_fr(r, "parse status");
310 		if (quiet)
311 			debug("Couldn't stat remote file: %s", fx2txt(status));
312 		else
313 			error("Couldn't stat remote file: %s", fx2txt(status));
314 		sshbuf_free(msg);
315 		return(NULL);
316 	} else if (type != SSH2_FXP_ATTRS) {
317 		fatal("Expected SSH2_FXP_ATTRS(%u) packet, got %u",
318 		    SSH2_FXP_ATTRS, type);
319 	}
320 	if ((r = decode_attrib(msg, &a)) != 0) {
321 		error_fr(r, "decode_attrib");
322 		sshbuf_free(msg);
323 		return NULL;
324 	}
325 	sshbuf_free(msg);
326 
327 	return &a;
328 }
329 
330 static int
331 get_decode_statvfs(struct sftp_conn *conn, struct sftp_statvfs *st,
332     u_int expected_id, int quiet)
333 {
334 	struct sshbuf *msg;
335 	u_char type;
336 	u_int id;
337 	u_int64_t flag;
338 	int r;
339 
340 	if ((msg = sshbuf_new()) == NULL)
341 		fatal_f("sshbuf_new failed");
342 	get_msg(conn, msg);
343 
344 	if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
345 	    (r = sshbuf_get_u32(msg, &id)) != 0)
346 		fatal_fr(r, "parse");
347 
348 	debug3("Received statvfs reply T:%u I:%u", type, id);
349 	if (id != expected_id)
350 		fatal("ID mismatch (%u != %u)", id, expected_id);
351 	if (type == SSH2_FXP_STATUS) {
352 		u_int status;
353 
354 		if ((r = sshbuf_get_u32(msg, &status)) != 0)
355 			fatal_fr(r, "parse status");
356 		if (quiet)
357 			debug("Couldn't statvfs: %s", fx2txt(status));
358 		else
359 			error("Couldn't statvfs: %s", fx2txt(status));
360 		sshbuf_free(msg);
361 		return -1;
362 	} else if (type != SSH2_FXP_EXTENDED_REPLY) {
363 		fatal("Expected SSH2_FXP_EXTENDED_REPLY(%u) packet, got %u",
364 		    SSH2_FXP_EXTENDED_REPLY, type);
365 	}
366 
367 	memset(st, 0, sizeof(*st));
368 	if ((r = sshbuf_get_u64(msg, &st->f_bsize)) != 0 ||
369 	    (r = sshbuf_get_u64(msg, &st->f_frsize)) != 0 ||
370 	    (r = sshbuf_get_u64(msg, &st->f_blocks)) != 0 ||
371 	    (r = sshbuf_get_u64(msg, &st->f_bfree)) != 0 ||
372 	    (r = sshbuf_get_u64(msg, &st->f_bavail)) != 0 ||
373 	    (r = sshbuf_get_u64(msg, &st->f_files)) != 0 ||
374 	    (r = sshbuf_get_u64(msg, &st->f_ffree)) != 0 ||
375 	    (r = sshbuf_get_u64(msg, &st->f_favail)) != 0 ||
376 	    (r = sshbuf_get_u64(msg, &st->f_fsid)) != 0 ||
377 	    (r = sshbuf_get_u64(msg, &flag)) != 0 ||
378 	    (r = sshbuf_get_u64(msg, &st->f_namemax)) != 0)
379 		fatal_fr(r, "parse statvfs");
380 
381 	st->f_flag = (flag & SSH2_FXE_STATVFS_ST_RDONLY) ? ST_RDONLY : 0;
382 	st->f_flag |= (flag & SSH2_FXE_STATVFS_ST_NOSUID) ? ST_NOSUID : 0;
383 
384 	sshbuf_free(msg);
385 
386 	return 0;
387 }
388 
389 struct sftp_conn *
390 do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests,
391     u_int64_t limit_kbps)
392 {
393 	u_char type;
394 	struct sshbuf *msg;
395 	struct sftp_conn *ret;
396 	int r;
397 
398 	ret = xcalloc(1, sizeof(*ret));
399 	ret->msg_id = 1;
400 	ret->fd_in = fd_in;
401 	ret->fd_out = fd_out;
402 	ret->download_buflen = ret->upload_buflen =
403 	    transfer_buflen ? transfer_buflen : DEFAULT_COPY_BUFLEN;
404 	ret->num_requests =
405 	    num_requests ? num_requests : DEFAULT_NUM_REQUESTS;
406 	ret->exts = 0;
407 	ret->limit_kbps = 0;
408 
409 	if ((msg = sshbuf_new()) == NULL)
410 		fatal_f("sshbuf_new failed");
411 	if ((r = sshbuf_put_u8(msg, SSH2_FXP_INIT)) != 0 ||
412 	    (r = sshbuf_put_u32(msg, SSH2_FILEXFER_VERSION)) != 0)
413 		fatal_fr(r, "parse");
414 
415 	send_msg(ret, msg);
416 
417 	get_msg_extended(ret, msg, 1);
418 
419 	/* Expecting a VERSION reply */
420 	if ((r = sshbuf_get_u8(msg, &type)) != 0)
421 		fatal_fr(r, "parse type");
422 	if (type != SSH2_FXP_VERSION) {
423 		error("Invalid packet back from SSH2_FXP_INIT (type %u)",
424 		    type);
425 		sshbuf_free(msg);
426 		free(ret);
427 		return(NULL);
428 	}
429 	if ((r = sshbuf_get_u32(msg, &ret->version)) != 0)
430 		fatal_fr(r, "parse version");
431 
432 	debug2("Remote version: %u", ret->version);
433 
434 	/* Check for extensions */
435 	while (sshbuf_len(msg) > 0) {
436 		char *name;
437 		u_char *value;
438 		size_t vlen;
439 		int known = 0;
440 
441 		if ((r = sshbuf_get_cstring(msg, &name, NULL)) != 0 ||
442 		    (r = sshbuf_get_string(msg, &value, &vlen)) != 0)
443 			fatal_fr(r, "parse extension");
444 		if (strcmp(name, "posix-rename@openssh.com") == 0 &&
445 		    strcmp((char *)value, "1") == 0) {
446 			ret->exts |= SFTP_EXT_POSIX_RENAME;
447 			known = 1;
448 		} else if (strcmp(name, "statvfs@openssh.com") == 0 &&
449 		    strcmp((char *)value, "2") == 0) {
450 			ret->exts |= SFTP_EXT_STATVFS;
451 			known = 1;
452 		} else if (strcmp(name, "fstatvfs@openssh.com") == 0 &&
453 		    strcmp((char *)value, "2") == 0) {
454 			ret->exts |= SFTP_EXT_FSTATVFS;
455 			known = 1;
456 		} else if (strcmp(name, "hardlink@openssh.com") == 0 &&
457 		    strcmp((char *)value, "1") == 0) {
458 			ret->exts |= SFTP_EXT_HARDLINK;
459 			known = 1;
460 		} else if (strcmp(name, "fsync@openssh.com") == 0 &&
461 		    strcmp((char *)value, "1") == 0) {
462 			ret->exts |= SFTP_EXT_FSYNC;
463 			known = 1;
464 		} else if (strcmp(name, "lsetstat@openssh.com") == 0 &&
465 		    strcmp((char *)value, "1") == 0) {
466 			ret->exts |= SFTP_EXT_LSETSTAT;
467 			known = 1;
468 		} else if (strcmp(name, "limits@openssh.com") == 0 &&
469 		    strcmp((char *)value, "1") == 0) {
470 			ret->exts |= SFTP_EXT_LIMITS;
471 			known = 1;
472 		}
473 		if (known) {
474 			debug2("Server supports extension \"%s\" revision %s",
475 			    name, value);
476 		} else {
477 			debug2("Unrecognised server extension \"%s\"", name);
478 		}
479 		free(name);
480 		free(value);
481 	}
482 
483 	sshbuf_free(msg);
484 
485 	/* Query the server for its limits */
486 	if (ret->exts & SFTP_EXT_LIMITS) {
487 		struct sftp_limits limits;
488 		if (do_limits(ret, &limits) != 0)
489 			fatal_f("limits failed");
490 
491 		/* If the caller did not specify, find a good value */
492 		if (transfer_buflen == 0) {
493 			ret->download_buflen = limits.read_length;
494 			ret->upload_buflen = limits.write_length;
495 			debug("Using server download size %u", ret->download_buflen);
496 			debug("Using server upload size %u", ret->upload_buflen);
497 		}
498 
499 		/* Use the server limit to scale down our value only */
500 		if (num_requests == 0 && limits.open_handles) {
501 			ret->num_requests =
502 			    MINIMUM(DEFAULT_NUM_REQUESTS, limits.open_handles);
503 			debug("Server handle limit %llu; using %u",
504 			    (unsigned long long)limits.open_handles,
505 			    ret->num_requests);
506 		}
507 	}
508 
509 	/* Some filexfer v.0 servers don't support large packets */
510 	if (ret->version == 0) {
511 		ret->download_buflen = MINIMUM(ret->download_buflen, 20480);
512 		ret->upload_buflen = MINIMUM(ret->upload_buflen, 20480);
513 	}
514 
515 	ret->limit_kbps = limit_kbps;
516 	if (ret->limit_kbps > 0) {
517 		bandwidth_limit_init(&ret->bwlimit_in, ret->limit_kbps,
518 		    ret->download_buflen);
519 		bandwidth_limit_init(&ret->bwlimit_out, ret->limit_kbps,
520 		    ret->upload_buflen);
521 	}
522 
523 	return ret;
524 }
525 
526 u_int
527 sftp_proto_version(struct sftp_conn *conn)
528 {
529 	return conn->version;
530 }
531 
532 int
533 do_limits(struct sftp_conn *conn, struct sftp_limits *limits)
534 {
535 	u_int id, msg_id;
536 	u_char type;
537 	struct sshbuf *msg;
538 	int r;
539 
540 	if ((conn->exts & SFTP_EXT_LIMITS) == 0) {
541 		error("Server does not support limits@openssh.com extension");
542 		return -1;
543 	}
544 
545 	if ((msg = sshbuf_new()) == NULL)
546 		fatal_f("sshbuf_new failed");
547 
548 	id = conn->msg_id++;
549 	if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
550 	    (r = sshbuf_put_u32(msg, id)) != 0 ||
551 	    (r = sshbuf_put_cstring(msg, "limits@openssh.com")) != 0)
552 		fatal_fr(r, "compose");
553 	send_msg(conn, msg);
554 	debug3("Sent message limits@openssh.com I:%u", id);
555 
556 	get_msg(conn, msg);
557 
558 	if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
559 	    (r = sshbuf_get_u32(msg, &msg_id)) != 0)
560 		fatal_fr(r, "parse");
561 
562 	debug3("Received limits reply T:%u I:%u", type, msg_id);
563 	if (id != msg_id)
564 		fatal("ID mismatch (%u != %u)", msg_id, id);
565 	if (type != SSH2_FXP_EXTENDED_REPLY) {
566 		fatal("Expected SSH2_FXP_EXTENDED_REPLY(%u) packet, got %u",
567 		    SSH2_FXP_EXTENDED_REPLY, type);
568 	}
569 
570 	memset(limits, 0, sizeof(*limits));
571 	if ((r = sshbuf_get_u64(msg, &limits->packet_length)) != 0 ||
572 	    (r = sshbuf_get_u64(msg, &limits->read_length)) != 0 ||
573 	    (r = sshbuf_get_u64(msg, &limits->write_length)) != 0 ||
574 	    (r = sshbuf_get_u64(msg, &limits->open_handles)) != 0)
575 		fatal_fr(r, "parse limits");
576 
577 	sshbuf_free(msg);
578 
579 	return 0;
580 }
581 
582 int
583 do_close(struct sftp_conn *conn, const u_char *handle, u_int handle_len)
584 {
585 	u_int id, status;
586 	struct sshbuf *msg;
587 	int r;
588 
589 	if ((msg = sshbuf_new()) == NULL)
590 		fatal_f("sshbuf_new failed");
591 
592 	id = conn->msg_id++;
593 	if ((r = sshbuf_put_u8(msg, SSH2_FXP_CLOSE)) != 0 ||
594 	    (r = sshbuf_put_u32(msg, id)) != 0 ||
595 	    (r = sshbuf_put_string(msg, handle, handle_len)) != 0)
596 		fatal_fr(r, "parse");
597 	send_msg(conn, msg);
598 	debug3("Sent message SSH2_FXP_CLOSE I:%u", id);
599 
600 	status = get_status(conn, id);
601 	if (status != SSH2_FX_OK)
602 		error("Couldn't close file: %s", fx2txt(status));
603 
604 	sshbuf_free(msg);
605 
606 	return status == SSH2_FX_OK ? 0 : -1;
607 }
608 
609 
610 static int
611 do_lsreaddir(struct sftp_conn *conn, const char *path, int print_flag,
612     SFTP_DIRENT ***dir)
613 {
614 	struct sshbuf *msg;
615 	u_int count, id, i, expected_id, ents = 0;
616 	size_t handle_len;
617 	u_char type, *handle;
618 	int status = SSH2_FX_FAILURE;
619 	int r;
620 
621 	if (dir)
622 		*dir = NULL;
623 
624 	id = conn->msg_id++;
625 
626 	if ((msg = sshbuf_new()) == NULL)
627 		fatal_f("sshbuf_new failed");
628 	if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPENDIR)) != 0 ||
629 	    (r = sshbuf_put_u32(msg, id)) != 0 ||
630 	    (r = sshbuf_put_cstring(msg, path)) != 0)
631 		fatal_fr(r, "compose OPENDIR");
632 	send_msg(conn, msg);
633 
634 	handle = get_handle(conn, id, &handle_len,
635 	    "remote readdir(\"%s\")", path);
636 	if (handle == NULL) {
637 		sshbuf_free(msg);
638 		return -1;
639 	}
640 
641 	if (dir) {
642 		ents = 0;
643 		*dir = xcalloc(1, sizeof(**dir));
644 		(*dir)[0] = NULL;
645 	}
646 
647 	for (; !interrupted;) {
648 		id = expected_id = conn->msg_id++;
649 
650 		debug3("Sending SSH2_FXP_READDIR I:%u", id);
651 
652 		sshbuf_reset(msg);
653 		if ((r = sshbuf_put_u8(msg, SSH2_FXP_READDIR)) != 0 ||
654 		    (r = sshbuf_put_u32(msg, id)) != 0 ||
655 		    (r = sshbuf_put_string(msg, handle, handle_len)) != 0)
656 			fatal_fr(r, "compose READDIR");
657 		send_msg(conn, msg);
658 
659 		sshbuf_reset(msg);
660 
661 		get_msg(conn, msg);
662 
663 		if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
664 		    (r = sshbuf_get_u32(msg, &id)) != 0)
665 			fatal_fr(r, "parse");
666 
667 		debug3("Received reply T:%u I:%u", type, id);
668 
669 		if (id != expected_id)
670 			fatal("ID mismatch (%u != %u)", id, expected_id);
671 
672 		if (type == SSH2_FXP_STATUS) {
673 			u_int rstatus;
674 
675 			if ((r = sshbuf_get_u32(msg, &rstatus)) != 0)
676 				fatal_fr(r, "parse status");
677 			debug3("Received SSH2_FXP_STATUS %d", rstatus);
678 			if (rstatus == SSH2_FX_EOF)
679 				break;
680 			error("Couldn't read directory: %s", fx2txt(rstatus));
681 			goto out;
682 		} else if (type != SSH2_FXP_NAME)
683 			fatal("Expected SSH2_FXP_NAME(%u) packet, got %u",
684 			    SSH2_FXP_NAME, type);
685 
686 		if ((r = sshbuf_get_u32(msg, &count)) != 0)
687 			fatal_fr(r, "parse count");
688 		if (count > SSHBUF_SIZE_MAX)
689 			fatal_f("nonsensical number of entries");
690 		if (count == 0)
691 			break;
692 		debug3("Received %d SSH2_FXP_NAME responses", count);
693 		for (i = 0; i < count; i++) {
694 			char *filename, *longname;
695 			Attrib a;
696 
697 			if ((r = sshbuf_get_cstring(msg, &filename,
698 			    NULL)) != 0 ||
699 			    (r = sshbuf_get_cstring(msg, &longname,
700 			    NULL)) != 0)
701 				fatal_fr(r, "parse filenames");
702 			if ((r = decode_attrib(msg, &a)) != 0) {
703 				error_fr(r, "couldn't decode attrib");
704 				free(filename);
705 				free(longname);
706 				goto out;
707 			}
708 
709 			if (print_flag)
710 				mprintf("%s\n", longname);
711 
712 			/*
713 			 * Directory entries should never contain '/'
714 			 * These can be used to attack recursive ops
715 			 * (e.g. send '../../../../etc/passwd')
716 			 */
717 			if (strchr(filename, '/') != NULL) {
718 				error("Server sent suspect path \"%s\" "
719 				    "during readdir of \"%s\"", filename, path);
720 			} else if (dir) {
721 				*dir = xreallocarray(*dir, ents + 2, sizeof(**dir));
722 				(*dir)[ents] = xcalloc(1, sizeof(***dir));
723 				(*dir)[ents]->filename = xstrdup(filename);
724 				(*dir)[ents]->longname = xstrdup(longname);
725 				memcpy(&(*dir)[ents]->a, &a, sizeof(a));
726 				(*dir)[++ents] = NULL;
727 			}
728 			free(filename);
729 			free(longname);
730 		}
731 	}
732 	status = 0;
733 
734  out:
735 	sshbuf_free(msg);
736 	do_close(conn, handle, handle_len);
737 	free(handle);
738 
739 	if (status != 0 && dir != NULL) {
740 		/* Don't return results on error */
741 		free_sftp_dirents(*dir);
742 		*dir = NULL;
743 	} else if (interrupted && dir != NULL && *dir != NULL) {
744 		/* Don't return partial matches on interrupt */
745 		free_sftp_dirents(*dir);
746 		*dir = xcalloc(1, sizeof(**dir));
747 		**dir = NULL;
748 	}
749 
750 	return status == SSH2_FX_OK ? 0 : -1;
751 }
752 
753 int
754 do_readdir(struct sftp_conn *conn, const char *path, SFTP_DIRENT ***dir)
755 {
756 	return(do_lsreaddir(conn, path, 0, dir));
757 }
758 
759 void free_sftp_dirents(SFTP_DIRENT **s)
760 {
761 	int i;
762 
763 	if (s == NULL)
764 		return;
765 	for (i = 0; s[i]; i++) {
766 		free(s[i]->filename);
767 		free(s[i]->longname);
768 		free(s[i]);
769 	}
770 	free(s);
771 }
772 
773 int
774 do_rm(struct sftp_conn *conn, const char *path)
775 {
776 	u_int status, id;
777 
778 	debug2("Sending SSH2_FXP_REMOVE \"%s\"", path);
779 
780 	id = conn->msg_id++;
781 	send_string_request(conn, id, SSH2_FXP_REMOVE, path, strlen(path));
782 	status = get_status(conn, id);
783 	if (status != SSH2_FX_OK)
784 		error("Couldn't delete file: %s", fx2txt(status));
785 	return status == SSH2_FX_OK ? 0 : -1;
786 }
787 
788 int
789 do_mkdir(struct sftp_conn *conn, const char *path, Attrib *a, int print_flag)
790 {
791 	u_int status, id;
792 
793 	id = conn->msg_id++;
794 	send_string_attrs_request(conn, id, SSH2_FXP_MKDIR, path,
795 	    strlen(path), a);
796 
797 	status = get_status(conn, id);
798 	if (status != SSH2_FX_OK && print_flag)
799 		error("Couldn't create directory: %s", fx2txt(status));
800 
801 	return status == SSH2_FX_OK ? 0 : -1;
802 }
803 
804 int
805 do_rmdir(struct sftp_conn *conn, const char *path)
806 {
807 	u_int status, id;
808 
809 	id = conn->msg_id++;
810 	send_string_request(conn, id, SSH2_FXP_RMDIR, path,
811 	    strlen(path));
812 
813 	status = get_status(conn, id);
814 	if (status != SSH2_FX_OK)
815 		error("Couldn't remove directory: %s", fx2txt(status));
816 
817 	return status == SSH2_FX_OK ? 0 : -1;
818 }
819 
820 Attrib *
821 do_stat(struct sftp_conn *conn, const char *path, int quiet)
822 {
823 	u_int id;
824 
825 	id = conn->msg_id++;
826 
827 	send_string_request(conn, id,
828 	    conn->version == 0 ? SSH2_FXP_STAT_VERSION_0 : SSH2_FXP_STAT,
829 	    path, strlen(path));
830 
831 	return(get_decode_stat(conn, id, quiet));
832 }
833 
834 Attrib *
835 do_lstat(struct sftp_conn *conn, const char *path, int quiet)
836 {
837 	u_int id;
838 
839 	if (conn->version == 0) {
840 		if (quiet)
841 			debug("Server version does not support lstat operation");
842 		else
843 			logit("Server version does not support lstat operation");
844 		return(do_stat(conn, path, quiet));
845 	}
846 
847 	id = conn->msg_id++;
848 	send_string_request(conn, id, SSH2_FXP_LSTAT, path,
849 	    strlen(path));
850 
851 	return(get_decode_stat(conn, id, quiet));
852 }
853 
854 #ifdef notyet
855 Attrib *
856 do_fstat(struct sftp_conn *conn, const u_char *handle, u_int handle_len,
857     int quiet)
858 {
859 	u_int id;
860 
861 	id = conn->msg_id++;
862 	send_string_request(conn, id, SSH2_FXP_FSTAT, handle,
863 	    handle_len);
864 
865 	return(get_decode_stat(conn, id, quiet));
866 }
867 #endif
868 
869 int
870 do_setstat(struct sftp_conn *conn, const char *path, Attrib *a)
871 {
872 	u_int status, id;
873 
874 	id = conn->msg_id++;
875 	send_string_attrs_request(conn, id, SSH2_FXP_SETSTAT, path,
876 	    strlen(path), a);
877 
878 	status = get_status(conn, id);
879 	if (status != SSH2_FX_OK)
880 		error("Couldn't setstat on \"%s\": %s", path,
881 		    fx2txt(status));
882 
883 	return status == SSH2_FX_OK ? 0 : -1;
884 }
885 
886 int
887 do_fsetstat(struct sftp_conn *conn, const u_char *handle, u_int handle_len,
888     Attrib *a)
889 {
890 	u_int status, id;
891 
892 	id = conn->msg_id++;
893 	send_string_attrs_request(conn, id, SSH2_FXP_FSETSTAT, handle,
894 	    handle_len, a);
895 
896 	status = get_status(conn, id);
897 	if (status != SSH2_FX_OK)
898 		error("Couldn't fsetstat: %s", fx2txt(status));
899 
900 	return status == SSH2_FX_OK ? 0 : -1;
901 }
902 
903 char *
904 do_realpath(struct sftp_conn *conn, const char *path)
905 {
906 	struct sshbuf *msg;
907 	u_int expected_id, count, id;
908 	char *filename, *longname;
909 	Attrib a;
910 	u_char type;
911 	int r;
912 
913 	expected_id = id = conn->msg_id++;
914 	send_string_request(conn, id, SSH2_FXP_REALPATH, path,
915 	    strlen(path));
916 
917 	if ((msg = sshbuf_new()) == NULL)
918 		fatal_f("sshbuf_new failed");
919 
920 	get_msg(conn, msg);
921 	if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
922 	    (r = sshbuf_get_u32(msg, &id)) != 0)
923 		fatal_fr(r, "parse");
924 
925 	if (id != expected_id)
926 		fatal("ID mismatch (%u != %u)", id, expected_id);
927 
928 	if (type == SSH2_FXP_STATUS) {
929 		u_int status;
930 
931 		if ((r = sshbuf_get_u32(msg, &status)) != 0)
932 			fatal_fr(r, "parse status");
933 		error("Couldn't canonicalize: %s", fx2txt(status));
934 		sshbuf_free(msg);
935 		return NULL;
936 	} else if (type != SSH2_FXP_NAME)
937 		fatal("Expected SSH2_FXP_NAME(%u) packet, got %u",
938 		    SSH2_FXP_NAME, type);
939 
940 	if ((r = sshbuf_get_u32(msg, &count)) != 0)
941 		fatal_fr(r, "parse count");
942 	if (count != 1)
943 		fatal("Got multiple names (%d) from SSH_FXP_REALPATH", count);
944 
945 	if ((r = sshbuf_get_cstring(msg, &filename, NULL)) != 0 ||
946 	    (r = sshbuf_get_cstring(msg, &longname, NULL)) != 0 ||
947 	    (r = decode_attrib(msg, &a)) != 0)
948 		fatal_fr(r, "parse filename/attrib");
949 
950 	debug3("SSH_FXP_REALPATH %s -> %s size %lu", path, filename,
951 	    (unsigned long)a.size);
952 
953 	free(longname);
954 
955 	sshbuf_free(msg);
956 
957 	return(filename);
958 }
959 
960 int
961 do_rename(struct sftp_conn *conn, const char *oldpath, const char *newpath,
962     int force_legacy)
963 {
964 	struct sshbuf *msg;
965 	u_int status, id;
966 	int r, use_ext = (conn->exts & SFTP_EXT_POSIX_RENAME) && !force_legacy;
967 
968 	if ((msg = sshbuf_new()) == NULL)
969 		fatal_f("sshbuf_new failed");
970 
971 	/* Send rename request */
972 	id = conn->msg_id++;
973 	if (use_ext) {
974 		if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
975 		    (r = sshbuf_put_u32(msg, id)) != 0 ||
976 		    (r = sshbuf_put_cstring(msg,
977 		    "posix-rename@openssh.com")) != 0)
978 			fatal_fr(r, "compose posix-rename");
979 	} else {
980 		if ((r = sshbuf_put_u8(msg, SSH2_FXP_RENAME)) != 0 ||
981 		    (r = sshbuf_put_u32(msg, id)) != 0)
982 			fatal_fr(r, "compose rename");
983 	}
984 	if ((r = sshbuf_put_cstring(msg, oldpath)) != 0 ||
985 	    (r = sshbuf_put_cstring(msg, newpath)) != 0)
986 		fatal_fr(r, "compose paths");
987 	send_msg(conn, msg);
988 	debug3("Sent message %s \"%s\" -> \"%s\"",
989 	    use_ext ? "posix-rename@openssh.com" :
990 	    "SSH2_FXP_RENAME", oldpath, newpath);
991 	sshbuf_free(msg);
992 
993 	status = get_status(conn, id);
994 	if (status != SSH2_FX_OK)
995 		error("Couldn't rename file \"%s\" to \"%s\": %s", oldpath,
996 		    newpath, fx2txt(status));
997 
998 	return status == SSH2_FX_OK ? 0 : -1;
999 }
1000 
1001 int
1002 do_hardlink(struct sftp_conn *conn, const char *oldpath, const char *newpath)
1003 {
1004 	struct sshbuf *msg;
1005 	u_int status, id;
1006 	int r;
1007 
1008 	if ((conn->exts & SFTP_EXT_HARDLINK) == 0) {
1009 		error("Server does not support hardlink@openssh.com extension");
1010 		return -1;
1011 	}
1012 
1013 	if ((msg = sshbuf_new()) == NULL)
1014 		fatal_f("sshbuf_new failed");
1015 
1016 	/* Send link request */
1017 	id = conn->msg_id++;
1018 	if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
1019 	    (r = sshbuf_put_u32(msg, id)) != 0 ||
1020 	    (r = sshbuf_put_cstring(msg, "hardlink@openssh.com")) != 0 ||
1021 	    (r = sshbuf_put_cstring(msg, oldpath)) != 0 ||
1022 	    (r = sshbuf_put_cstring(msg, newpath)) != 0)
1023 		fatal_fr(r, "compose");
1024 	send_msg(conn, msg);
1025 	debug3("Sent message hardlink@openssh.com \"%s\" -> \"%s\"",
1026 	    oldpath, newpath);
1027 	sshbuf_free(msg);
1028 
1029 	status = get_status(conn, id);
1030 	if (status != SSH2_FX_OK)
1031 		error("Couldn't link file \"%s\" to \"%s\": %s", oldpath,
1032 		    newpath, fx2txt(status));
1033 
1034 	return status == SSH2_FX_OK ? 0 : -1;
1035 }
1036 
1037 int
1038 do_symlink(struct sftp_conn *conn, const char *oldpath, const char *newpath)
1039 {
1040 	struct sshbuf *msg;
1041 	u_int status, id;
1042 	int r;
1043 
1044 	if (conn->version < 3) {
1045 		error("This server does not support the symlink operation");
1046 		return(SSH2_FX_OP_UNSUPPORTED);
1047 	}
1048 
1049 	if ((msg = sshbuf_new()) == NULL)
1050 		fatal_f("sshbuf_new failed");
1051 
1052 	/* Send symlink request */
1053 	id = conn->msg_id++;
1054 	if ((r = sshbuf_put_u8(msg, SSH2_FXP_SYMLINK)) != 0 ||
1055 	    (r = sshbuf_put_u32(msg, id)) != 0 ||
1056 	    (r = sshbuf_put_cstring(msg, oldpath)) != 0 ||
1057 	    (r = sshbuf_put_cstring(msg, newpath)) != 0)
1058 		fatal_fr(r, "compose");
1059 	send_msg(conn, msg);
1060 	debug3("Sent message SSH2_FXP_SYMLINK \"%s\" -> \"%s\"", oldpath,
1061 	    newpath);
1062 	sshbuf_free(msg);
1063 
1064 	status = get_status(conn, id);
1065 	if (status != SSH2_FX_OK)
1066 		error("Couldn't symlink file \"%s\" to \"%s\": %s", oldpath,
1067 		    newpath, fx2txt(status));
1068 
1069 	return status == SSH2_FX_OK ? 0 : -1;
1070 }
1071 
1072 int
1073 do_fsync(struct sftp_conn *conn, u_char *handle, u_int handle_len)
1074 {
1075 	struct sshbuf *msg;
1076 	u_int status, id;
1077 	int r;
1078 
1079 	/* Silently return if the extension is not supported */
1080 	if ((conn->exts & SFTP_EXT_FSYNC) == 0)
1081 		return -1;
1082 
1083 	/* Send fsync request */
1084 	if ((msg = sshbuf_new()) == NULL)
1085 		fatal_f("sshbuf_new failed");
1086 	id = conn->msg_id++;
1087 	if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
1088 	    (r = sshbuf_put_u32(msg, id)) != 0 ||
1089 	    (r = sshbuf_put_cstring(msg, "fsync@openssh.com")) != 0 ||
1090 	    (r = sshbuf_put_string(msg, handle, handle_len)) != 0)
1091 		fatal_fr(r, "compose");
1092 	send_msg(conn, msg);
1093 	debug3("Sent message fsync@openssh.com I:%u", id);
1094 	sshbuf_free(msg);
1095 
1096 	status = get_status(conn, id);
1097 	if (status != SSH2_FX_OK)
1098 		error("Couldn't sync file: %s", fx2txt(status));
1099 
1100 	return status == SSH2_FX_OK ? 0 : -1;
1101 }
1102 
1103 #ifdef notyet
1104 char *
1105 do_readlink(struct sftp_conn *conn, const char *path)
1106 {
1107 	struct sshbuf *msg;
1108 	u_int expected_id, count, id;
1109 	char *filename, *longname;
1110 	Attrib a;
1111 	u_char type;
1112 	int r;
1113 
1114 	expected_id = id = conn->msg_id++;
1115 	send_string_request(conn, id, SSH2_FXP_READLINK, path, strlen(path));
1116 
1117 	if ((msg = sshbuf_new()) == NULL)
1118 		fatal_f("sshbuf_new failed");
1119 
1120 	get_msg(conn, msg);
1121 	if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
1122 	    (r = sshbuf_get_u32(msg, &id)) != 0)
1123 		fatal_fr(r, "parse");
1124 
1125 	if (id != expected_id)
1126 		fatal("ID mismatch (%u != %u)", id, expected_id);
1127 
1128 	if (type == SSH2_FXP_STATUS) {
1129 		u_int status;
1130 
1131 		if ((r = sshbuf_get_u32(msg, &status)) != 0)
1132 			fatal_fr(r, "parse status");
1133 		error("Couldn't readlink: %s", fx2txt(status));
1134 		sshbuf_free(msg);
1135 		return(NULL);
1136 	} else if (type != SSH2_FXP_NAME)
1137 		fatal("Expected SSH2_FXP_NAME(%u) packet, got %u",
1138 		    SSH2_FXP_NAME, type);
1139 
1140 	if ((r = sshbuf_get_u32(msg, &count)) != 0)
1141 		fatal_fr(r, "parse count");
1142 	if (count != 1)
1143 		fatal("Got multiple names (%d) from SSH_FXP_READLINK", count);
1144 
1145 	if ((r = sshbuf_get_cstring(msg, &filename, NULL)) != 0 ||
1146 	    (r = sshbuf_get_cstring(msg, &longname, NULL)) != 0 ||
1147 	    (r = decode_attrib(msg, &a)) != 0)
1148 		fatal_fr(r, "parse filenames/attrib");
1149 
1150 	debug3("SSH_FXP_READLINK %s -> %s", path, filename);
1151 
1152 	free(longname);
1153 
1154 	sshbuf_free(msg);
1155 
1156 	return filename;
1157 }
1158 #endif
1159 
1160 int
1161 do_statvfs(struct sftp_conn *conn, const char *path, struct sftp_statvfs *st,
1162     int quiet)
1163 {
1164 	struct sshbuf *msg;
1165 	u_int id;
1166 	int r;
1167 
1168 	if ((conn->exts & SFTP_EXT_STATVFS) == 0) {
1169 		error("Server does not support statvfs@openssh.com extension");
1170 		return -1;
1171 	}
1172 
1173 	id = conn->msg_id++;
1174 
1175 	if ((msg = sshbuf_new()) == NULL)
1176 		fatal_f("sshbuf_new failed");
1177 	if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
1178 	    (r = sshbuf_put_u32(msg, id)) != 0 ||
1179 	    (r = sshbuf_put_cstring(msg, "statvfs@openssh.com")) != 0 ||
1180 	    (r = sshbuf_put_cstring(msg, path)) != 0)
1181 		fatal_fr(r, "compose");
1182 	send_msg(conn, msg);
1183 	sshbuf_free(msg);
1184 
1185 	return get_decode_statvfs(conn, st, id, quiet);
1186 }
1187 
1188 #ifdef notyet
1189 int
1190 do_fstatvfs(struct sftp_conn *conn, const u_char *handle, u_int handle_len,
1191     struct sftp_statvfs *st, int quiet)
1192 {
1193 	struct sshbuf *msg;
1194 	u_int id;
1195 
1196 	if ((conn->exts & SFTP_EXT_FSTATVFS) == 0) {
1197 		error("Server does not support fstatvfs@openssh.com extension");
1198 		return -1;
1199 	}
1200 
1201 	id = conn->msg_id++;
1202 
1203 	if ((msg = sshbuf_new()) == NULL)
1204 		fatal_f("sshbuf_new failed");
1205 	if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
1206 	    (r = sshbuf_put_u32(msg, id)) != 0 ||
1207 	    (r = sshbuf_put_cstring(msg, "fstatvfs@openssh.com")) != 0 ||
1208 	    (r = sshbuf_put_string(msg, handle, handle_len)) != 0)
1209 		fatal_fr(r, "compose");
1210 	send_msg(conn, msg);
1211 	sshbuf_free(msg);
1212 
1213 	return get_decode_statvfs(conn, st, id, quiet);
1214 }
1215 #endif
1216 
1217 int
1218 do_lsetstat(struct sftp_conn *conn, const char *path, Attrib *a)
1219 {
1220 	struct sshbuf *msg;
1221 	u_int status, id;
1222 	int r;
1223 
1224 	if ((conn->exts & SFTP_EXT_LSETSTAT) == 0) {
1225 		error("Server does not support lsetstat@openssh.com extension");
1226 		return -1;
1227 	}
1228 
1229 	id = conn->msg_id++;
1230 	if ((msg = sshbuf_new()) == NULL)
1231 		fatal_f("sshbuf_new failed");
1232 	if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
1233 	    (r = sshbuf_put_u32(msg, id)) != 0 ||
1234 	    (r = sshbuf_put_cstring(msg, "lsetstat@openssh.com")) != 0 ||
1235 	    (r = sshbuf_put_cstring(msg, path)) != 0 ||
1236 	    (r = encode_attrib(msg, a)) != 0)
1237 		fatal_fr(r, "compose");
1238 	send_msg(conn, msg);
1239 	sshbuf_free(msg);
1240 
1241 	status = get_status(conn, id);
1242 	if (status != SSH2_FX_OK)
1243 		error("Couldn't setstat on \"%s\": %s", path,
1244 		    fx2txt(status));
1245 
1246 	return status == SSH2_FX_OK ? 0 : -1;
1247 }
1248 
1249 static void
1250 send_read_request(struct sftp_conn *conn, u_int id, u_int64_t offset,
1251     u_int len, const u_char *handle, u_int handle_len)
1252 {
1253 	struct sshbuf *msg;
1254 	int r;
1255 
1256 	if ((msg = sshbuf_new()) == NULL)
1257 		fatal_f("sshbuf_new failed");
1258 	if ((r = sshbuf_put_u8(msg, SSH2_FXP_READ)) != 0 ||
1259 	    (r = sshbuf_put_u32(msg, id)) != 0 ||
1260 	    (r = sshbuf_put_string(msg, handle, handle_len)) != 0 ||
1261 	    (r = sshbuf_put_u64(msg, offset)) != 0 ||
1262 	    (r = sshbuf_put_u32(msg, len)) != 0)
1263 		fatal_fr(r, "compose");
1264 	send_msg(conn, msg);
1265 	sshbuf_free(msg);
1266 }
1267 
1268 int
1269 do_download(struct sftp_conn *conn, const char *remote_path,
1270     const char *local_path, Attrib *a, int preserve_flag, int resume_flag,
1271     int fsync_flag)
1272 {
1273 	Attrib junk;
1274 	struct sshbuf *msg;
1275 	u_char *handle;
1276 	int local_fd = -1, write_error;
1277 	int read_error, write_errno, lmodified = 0, reordered = 0, r;
1278 	u_int64_t offset = 0, size, highwater;
1279 	u_int mode, id, buflen, num_req, max_req, status = SSH2_FX_OK;
1280 	off_t progress_counter;
1281 	size_t handle_len;
1282 	struct stat st;
1283 	struct request {
1284 		u_int id;
1285 		size_t len;
1286 		u_int64_t offset;
1287 		TAILQ_ENTRY(request) tq;
1288 	};
1289 	TAILQ_HEAD(reqhead, request) requests;
1290 	struct request *req;
1291 	u_char type;
1292 
1293 	TAILQ_INIT(&requests);
1294 
1295 	if (a == NULL && (a = do_stat(conn, remote_path, 0)) == NULL)
1296 		return -1;
1297 
1298 	/* Do not preserve set[ug]id here, as we do not preserve ownership */
1299 	if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS)
1300 		mode = a->perm & 0777;
1301 	else
1302 		mode = 0666;
1303 
1304 	if ((a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) &&
1305 	    (!S_ISREG(a->perm))) {
1306 		error("Cannot download non-regular file: %s", remote_path);
1307 		return(-1);
1308 	}
1309 
1310 	if (a->flags & SSH2_FILEXFER_ATTR_SIZE)
1311 		size = a->size;
1312 	else
1313 		size = 0;
1314 
1315 	buflen = conn->download_buflen;
1316 	if ((msg = sshbuf_new()) == NULL)
1317 		fatal_f("sshbuf_new failed");
1318 
1319 	attrib_clear(&junk); /* Send empty attributes */
1320 
1321 	/* Send open request */
1322 	id = conn->msg_id++;
1323 	if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPEN)) != 0 ||
1324 	    (r = sshbuf_put_u32(msg, id)) != 0 ||
1325 	    (r = sshbuf_put_cstring(msg, remote_path)) != 0 ||
1326 	    (r = sshbuf_put_u32(msg, SSH2_FXF_READ)) != 0 ||
1327 	    (r = encode_attrib(msg, &junk)) != 0)
1328 		fatal_fr(r, "compose");
1329 	send_msg(conn, msg);
1330 	debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, remote_path);
1331 
1332 	handle = get_handle(conn, id, &handle_len,
1333 	    "remote open(\"%s\")", remote_path);
1334 	if (handle == NULL) {
1335 		sshbuf_free(msg);
1336 		return(-1);
1337 	}
1338 
1339 	local_fd = open(local_path,
1340 	    O_WRONLY | O_CREAT | (resume_flag ? 0 : O_TRUNC), mode | S_IWUSR);
1341 	if (local_fd == -1) {
1342 		error("Couldn't open local file \"%s\" for writing: %s",
1343 		    local_path, strerror(errno));
1344 		goto fail;
1345 	}
1346 	offset = highwater = 0;
1347 	if (resume_flag) {
1348 		if (fstat(local_fd, &st) == -1) {
1349 			error("Unable to stat local file \"%s\": %s",
1350 			    local_path, strerror(errno));
1351 			goto fail;
1352 		}
1353 		if (st.st_size < 0) {
1354 			error("\"%s\" has negative size", local_path);
1355 			goto fail;
1356 		}
1357 		if ((u_int64_t)st.st_size > size) {
1358 			error("Unable to resume download of \"%s\": "
1359 			    "local file is larger than remote", local_path);
1360  fail:
1361 			do_close(conn, handle, handle_len);
1362 			sshbuf_free(msg);
1363 			free(handle);
1364 			if (local_fd != -1)
1365 				close(local_fd);
1366 			return -1;
1367 		}
1368 		offset = highwater = st.st_size;
1369 	}
1370 
1371 	/* Read from remote and write to local */
1372 	write_error = read_error = write_errno = num_req = 0;
1373 	max_req = 1;
1374 	progress_counter = offset;
1375 
1376 	if (showprogress && size != 0)
1377 		start_progress_meter(remote_path, size, &progress_counter);
1378 
1379 	while (num_req > 0 || max_req > 0) {
1380 		u_char *data;
1381 		size_t len;
1382 
1383 		/*
1384 		 * Simulate EOF on interrupt: stop sending new requests and
1385 		 * allow outstanding requests to drain gracefully
1386 		 */
1387 		if (interrupted) {
1388 			if (num_req == 0) /* If we haven't started yet... */
1389 				break;
1390 			max_req = 0;
1391 		}
1392 
1393 		/* Send some more requests */
1394 		while (num_req < max_req) {
1395 			debug3("Request range %llu -> %llu (%d/%d)",
1396 			    (unsigned long long)offset,
1397 			    (unsigned long long)offset + buflen - 1,
1398 			    num_req, max_req);
1399 			req = xcalloc(1, sizeof(*req));
1400 			req->id = conn->msg_id++;
1401 			req->len = buflen;
1402 			req->offset = offset;
1403 			offset += buflen;
1404 			num_req++;
1405 			TAILQ_INSERT_TAIL(&requests, req, tq);
1406 			send_read_request(conn, req->id, req->offset,
1407 			    req->len, handle, handle_len);
1408 		}
1409 
1410 		sshbuf_reset(msg);
1411 		get_msg(conn, msg);
1412 		if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
1413 		    (r = sshbuf_get_u32(msg, &id)) != 0)
1414 			fatal_fr(r, "parse");
1415 		debug3("Received reply T:%u I:%u R:%d", type, id, max_req);
1416 
1417 		/* Find the request in our queue */
1418 		for (req = TAILQ_FIRST(&requests);
1419 		    req != NULL && req->id != id;
1420 		    req = TAILQ_NEXT(req, tq))
1421 			;
1422 		if (req == NULL)
1423 			fatal("Unexpected reply %u", id);
1424 
1425 		switch (type) {
1426 		case SSH2_FXP_STATUS:
1427 			if ((r = sshbuf_get_u32(msg, &status)) != 0)
1428 				fatal_fr(r, "parse status");
1429 			if (status != SSH2_FX_EOF)
1430 				read_error = 1;
1431 			max_req = 0;
1432 			TAILQ_REMOVE(&requests, req, tq);
1433 			free(req);
1434 			num_req--;
1435 			break;
1436 		case SSH2_FXP_DATA:
1437 			if ((r = sshbuf_get_string(msg, &data, &len)) != 0)
1438 				fatal_fr(r, "parse data");
1439 			debug3("Received data %llu -> %llu",
1440 			    (unsigned long long)req->offset,
1441 			    (unsigned long long)req->offset + len - 1);
1442 			if (len > req->len)
1443 				fatal("Received more data than asked for "
1444 				    "%zu > %zu", len, req->len);
1445 			lmodified = 1;
1446 			if ((lseek(local_fd, req->offset, SEEK_SET) == -1 ||
1447 			    atomicio(vwrite, local_fd, data, len) != len) &&
1448 			    !write_error) {
1449 				write_errno = errno;
1450 				write_error = 1;
1451 				max_req = 0;
1452 			}
1453 			else if (!reordered && req->offset <= highwater)
1454 				highwater = req->offset + len;
1455 			else if (!reordered && req->offset > highwater)
1456 				reordered = 1;
1457 			progress_counter += len;
1458 			free(data);
1459 
1460 			if (len == req->len) {
1461 				TAILQ_REMOVE(&requests, req, tq);
1462 				free(req);
1463 				num_req--;
1464 			} else {
1465 				/* Resend the request for the missing data */
1466 				debug3("Short data block, re-requesting "
1467 				    "%llu -> %llu (%2d)",
1468 				    (unsigned long long)req->offset + len,
1469 				    (unsigned long long)req->offset +
1470 				    req->len - 1, num_req);
1471 				req->id = conn->msg_id++;
1472 				req->len -= len;
1473 				req->offset += len;
1474 				send_read_request(conn, req->id,
1475 				    req->offset, req->len, handle, handle_len);
1476 				/* Reduce the request size */
1477 				if (len < buflen)
1478 					buflen = MAXIMUM(MIN_READ_SIZE, len);
1479 			}
1480 			if (max_req > 0) { /* max_req = 0 iff EOF received */
1481 				if (size > 0 && offset > size) {
1482 					/* Only one request at a time
1483 					 * after the expected EOF */
1484 					debug3("Finish at %llu (%2d)",
1485 					    (unsigned long long)offset,
1486 					    num_req);
1487 					max_req = 1;
1488 				} else if (max_req < conn->num_requests) {
1489 					++max_req;
1490 				}
1491 			}
1492 			break;
1493 		default:
1494 			fatal("Expected SSH2_FXP_DATA(%u) packet, got %u",
1495 			    SSH2_FXP_DATA, type);
1496 		}
1497 	}
1498 
1499 	if (showprogress && size)
1500 		stop_progress_meter();
1501 
1502 	/* Sanity check */
1503 	if (TAILQ_FIRST(&requests) != NULL)
1504 		fatal("Transfer complete, but requests still in queue");
1505 	/* Truncate at highest contiguous point to avoid holes on interrupt */
1506 	if (read_error || write_error || interrupted) {
1507 		if (reordered && resume_flag) {
1508 			error("Unable to resume download of \"%s\": "
1509 			    "server reordered requests", local_path);
1510 		}
1511 		debug("truncating at %llu", (unsigned long long)highwater);
1512 		if (ftruncate(local_fd, highwater) == -1)
1513 			error("ftruncate \"%s\": %s", local_path,
1514 			    strerror(errno));
1515 	}
1516 	if (read_error) {
1517 		error("Couldn't read from remote file \"%s\" : %s",
1518 		    remote_path, fx2txt(status));
1519 		status = -1;
1520 		do_close(conn, handle, handle_len);
1521 	} else if (write_error) {
1522 		error("Couldn't write to \"%s\": %s", local_path,
1523 		    strerror(write_errno));
1524 		status = SSH2_FX_FAILURE;
1525 		do_close(conn, handle, handle_len);
1526 	} else {
1527 		if (do_close(conn, handle, handle_len) != 0 || interrupted)
1528 			status = SSH2_FX_FAILURE;
1529 		else
1530 			status = SSH2_FX_OK;
1531 		/* Override umask and utimes if asked */
1532 		if (preserve_flag && fchmod(local_fd, mode) == -1)
1533 			error("Couldn't set mode on \"%s\": %s", local_path,
1534 			    strerror(errno));
1535 		if (preserve_flag &&
1536 		    (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME)) {
1537 			struct timeval tv[2];
1538 			tv[0].tv_sec = a->atime;
1539 			tv[1].tv_sec = a->mtime;
1540 			tv[0].tv_usec = tv[1].tv_usec = 0;
1541 			if (utimes(local_path, tv) == -1)
1542 				error("Can't set times on \"%s\": %s",
1543 				    local_path, strerror(errno));
1544 		}
1545 		if (resume_flag && !lmodified)
1546 			logit("File \"%s\" was not modified", local_path);
1547 		else if (fsync_flag) {
1548 			debug("syncing \"%s\"", local_path);
1549 			if (fsync(local_fd) == -1)
1550 				error("Couldn't sync file \"%s\": %s",
1551 				    local_path, strerror(errno));
1552 		}
1553 	}
1554 	close(local_fd);
1555 	sshbuf_free(msg);
1556 	free(handle);
1557 
1558 	return status == SSH2_FX_OK ? 0 : -1;
1559 }
1560 
1561 static int
1562 download_dir_internal(struct sftp_conn *conn, const char *src, const char *dst,
1563     int depth, Attrib *dirattrib, int preserve_flag, int print_flag,
1564     int resume_flag, int fsync_flag)
1565 {
1566 	int i, ret = 0;
1567 	SFTP_DIRENT **dir_entries;
1568 	char *filename, *new_src = NULL, *new_dst = NULL;
1569 	mode_t mode = 0777, tmpmode = mode;
1570 
1571 	if (depth >= MAX_DIR_DEPTH) {
1572 		error("Maximum directory depth exceeded: %d levels", depth);
1573 		return -1;
1574 	}
1575 
1576 	if (dirattrib == NULL &&
1577 	    (dirattrib = do_stat(conn, src, 1)) == NULL) {
1578 		error("Unable to stat remote directory \"%s\"", src);
1579 		return -1;
1580 	}
1581 	if (!S_ISDIR(dirattrib->perm)) {
1582 		error("\"%s\" is not a directory", src);
1583 		return -1;
1584 	}
1585 	if (print_flag)
1586 		mprintf("Retrieving %s\n", src);
1587 
1588 	if (dirattrib->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) {
1589 		mode = dirattrib->perm & 01777;
1590 		tmpmode = mode | (S_IWUSR|S_IXUSR);
1591 	} else {
1592 		debug("Server did not send permissions for "
1593 		    "directory \"%s\"", dst);
1594 	}
1595 
1596 	if (mkdir(dst, tmpmode) == -1 && errno != EEXIST) {
1597 		error("mkdir %s: %s", dst, strerror(errno));
1598 		return -1;
1599 	}
1600 
1601 	if (do_readdir(conn, src, &dir_entries) == -1) {
1602 		error("%s: Failed to get directory contents", src);
1603 		return -1;
1604 	}
1605 
1606 	for (i = 0; dir_entries[i] != NULL && !interrupted; i++) {
1607 		free(new_dst);
1608 		free(new_src);
1609 
1610 		filename = dir_entries[i]->filename;
1611 		new_dst = path_append(dst, filename);
1612 		new_src = path_append(src, filename);
1613 
1614 		if (S_ISDIR(dir_entries[i]->a.perm)) {
1615 			if (strcmp(filename, ".") == 0 ||
1616 			    strcmp(filename, "..") == 0)
1617 				continue;
1618 			if (download_dir_internal(conn, new_src, new_dst,
1619 			    depth + 1, &(dir_entries[i]->a), preserve_flag,
1620 			    print_flag, resume_flag, fsync_flag) == -1)
1621 				ret = -1;
1622 		} else if (S_ISREG(dir_entries[i]->a.perm) ) {
1623 			if (do_download(conn, new_src, new_dst,
1624 			    &(dir_entries[i]->a), preserve_flag,
1625 			    resume_flag, fsync_flag) == -1) {
1626 				error("Download of file %s to %s failed",
1627 				    new_src, new_dst);
1628 				ret = -1;
1629 			}
1630 		} else
1631 			logit("%s: not a regular file\n", new_src);
1632 
1633 	}
1634 	free(new_dst);
1635 	free(new_src);
1636 
1637 	if (preserve_flag) {
1638 		if (dirattrib->flags & SSH2_FILEXFER_ATTR_ACMODTIME) {
1639 			struct timeval tv[2];
1640 			tv[0].tv_sec = dirattrib->atime;
1641 			tv[1].tv_sec = dirattrib->mtime;
1642 			tv[0].tv_usec = tv[1].tv_usec = 0;
1643 			if (utimes(dst, tv) == -1)
1644 				error("Can't set times on \"%s\": %s",
1645 				    dst, strerror(errno));
1646 		} else
1647 			debug("Server did not send times for directory "
1648 			    "\"%s\"", dst);
1649 	}
1650 
1651 	if (mode != tmpmode && chmod(dst, mode) == -1)
1652 		error("Can't set final mode on \"%s\": %s", dst,
1653 		    strerror(errno));
1654 
1655 	free_sftp_dirents(dir_entries);
1656 
1657 	return ret;
1658 }
1659 
1660 int
1661 download_dir(struct sftp_conn *conn, const char *src, const char *dst,
1662     Attrib *dirattrib, int preserve_flag, int print_flag, int resume_flag,
1663     int fsync_flag)
1664 {
1665 	char *src_canon;
1666 	int ret;
1667 
1668 	if ((src_canon = do_realpath(conn, src)) == NULL) {
1669 		error("Unable to canonicalize path \"%s\"", src);
1670 		return -1;
1671 	}
1672 
1673 	ret = download_dir_internal(conn, src_canon, dst, 0,
1674 	    dirattrib, preserve_flag, print_flag, resume_flag, fsync_flag);
1675 	free(src_canon);
1676 	return ret;
1677 }
1678 
1679 int
1680 do_upload(struct sftp_conn *conn, const char *local_path,
1681     const char *remote_path, int preserve_flag, int resume, int fsync_flag)
1682 {
1683 	int r, local_fd;
1684 	u_int status = SSH2_FX_OK;
1685 	u_int id;
1686 	u_char type;
1687 	off_t offset, progress_counter;
1688 	u_char *handle, *data;
1689 	struct sshbuf *msg;
1690 	struct stat sb;
1691 	Attrib a, *c = NULL;
1692 	u_int32_t startid;
1693 	u_int32_t ackid;
1694 	struct outstanding_ack {
1695 		u_int id;
1696 		u_int len;
1697 		off_t offset;
1698 		TAILQ_ENTRY(outstanding_ack) tq;
1699 	};
1700 	TAILQ_HEAD(ackhead, outstanding_ack) acks;
1701 	struct outstanding_ack *ack = NULL;
1702 	size_t handle_len;
1703 
1704 	TAILQ_INIT(&acks);
1705 
1706 	if ((local_fd = open(local_path, O_RDONLY, 0)) == -1) {
1707 		error("Couldn't open local file \"%s\" for reading: %s",
1708 		    local_path, strerror(errno));
1709 		return(-1);
1710 	}
1711 	if (fstat(local_fd, &sb) == -1) {
1712 		error("Couldn't fstat local file \"%s\": %s",
1713 		    local_path, strerror(errno));
1714 		close(local_fd);
1715 		return(-1);
1716 	}
1717 	if (!S_ISREG(sb.st_mode)) {
1718 		error("%s is not a regular file", local_path);
1719 		close(local_fd);
1720 		return(-1);
1721 	}
1722 	stat_to_attrib(&sb, &a);
1723 
1724 	a.flags &= ~SSH2_FILEXFER_ATTR_SIZE;
1725 	a.flags &= ~SSH2_FILEXFER_ATTR_UIDGID;
1726 	a.perm &= 0777;
1727 	if (!preserve_flag)
1728 		a.flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME;
1729 
1730 	if (resume) {
1731 		/* Get remote file size if it exists */
1732 		if ((c = do_stat(conn, remote_path, 0)) == NULL) {
1733 			close(local_fd);
1734 			return -1;
1735 		}
1736 
1737 		if ((off_t)c->size >= sb.st_size) {
1738 			error("destination file bigger or same size as "
1739 			    "source file");
1740 			close(local_fd);
1741 			return -1;
1742 		}
1743 
1744 		if (lseek(local_fd, (off_t)c->size, SEEK_SET) == -1) {
1745 			close(local_fd);
1746 			return -1;
1747 		}
1748 	}
1749 
1750 	if ((msg = sshbuf_new()) == NULL)
1751 		fatal_f("sshbuf_new failed");
1752 
1753 	/* Send open request */
1754 	id = conn->msg_id++;
1755 	if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPEN)) != 0 ||
1756 	    (r = sshbuf_put_u32(msg, id)) != 0 ||
1757 	    (r = sshbuf_put_cstring(msg, remote_path)) != 0 ||
1758 	    (r = sshbuf_put_u32(msg, SSH2_FXF_WRITE|SSH2_FXF_CREAT|
1759 	    (resume ? SSH2_FXF_APPEND : SSH2_FXF_TRUNC))) != 0 ||
1760 	    (r = encode_attrib(msg, &a)) != 0)
1761 		fatal_fr(r, "compose");
1762 	send_msg(conn, msg);
1763 	debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, remote_path);
1764 
1765 	sshbuf_reset(msg);
1766 
1767 	handle = get_handle(conn, id, &handle_len,
1768 	    "remote open(\"%s\")", remote_path);
1769 	if (handle == NULL) {
1770 		close(local_fd);
1771 		sshbuf_free(msg);
1772 		return -1;
1773 	}
1774 
1775 	startid = ackid = id + 1;
1776 	data = xmalloc(conn->upload_buflen);
1777 
1778 	/* Read from local and write to remote */
1779 	offset = progress_counter = (resume ? c->size : 0);
1780 	if (showprogress)
1781 		start_progress_meter(local_path, sb.st_size,
1782 		    &progress_counter);
1783 
1784 	for (;;) {
1785 		int len;
1786 
1787 		/*
1788 		 * Can't use atomicio here because it returns 0 on EOF,
1789 		 * thus losing the last block of the file.
1790 		 * Simulate an EOF on interrupt, allowing ACKs from the
1791 		 * server to drain.
1792 		 */
1793 		if (interrupted || status != SSH2_FX_OK)
1794 			len = 0;
1795 		else do
1796 			len = read(local_fd, data, conn->upload_buflen);
1797 		while ((len == -1) && (errno == EINTR || errno == EAGAIN));
1798 
1799 		if (len == -1)
1800 			fatal("Couldn't read from \"%s\": %s", local_path,
1801 			    strerror(errno));
1802 
1803 		if (len != 0) {
1804 			ack = xcalloc(1, sizeof(*ack));
1805 			ack->id = ++id;
1806 			ack->offset = offset;
1807 			ack->len = len;
1808 			TAILQ_INSERT_TAIL(&acks, ack, tq);
1809 
1810 			sshbuf_reset(msg);
1811 			if ((r = sshbuf_put_u8(msg, SSH2_FXP_WRITE)) != 0 ||
1812 			    (r = sshbuf_put_u32(msg, ack->id)) != 0 ||
1813 			    (r = sshbuf_put_string(msg, handle,
1814 			    handle_len)) != 0 ||
1815 			    (r = sshbuf_put_u64(msg, offset)) != 0 ||
1816 			    (r = sshbuf_put_string(msg, data, len)) != 0)
1817 				fatal_fr(r, "compose");
1818 			send_msg(conn, msg);
1819 			debug3("Sent message SSH2_FXP_WRITE I:%u O:%llu S:%u",
1820 			    id, (unsigned long long)offset, len);
1821 		} else if (TAILQ_FIRST(&acks) == NULL)
1822 			break;
1823 
1824 		if (ack == NULL)
1825 			fatal("Unexpected ACK %u", id);
1826 
1827 		if (id == startid || len == 0 ||
1828 		    id - ackid >= conn->num_requests) {
1829 			u_int rid;
1830 
1831 			sshbuf_reset(msg);
1832 			get_msg(conn, msg);
1833 			if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
1834 			    (r = sshbuf_get_u32(msg, &rid)) != 0)
1835 				fatal_fr(r, "parse");
1836 
1837 			if (type != SSH2_FXP_STATUS)
1838 				fatal("Expected SSH2_FXP_STATUS(%d) packet, "
1839 				    "got %d", SSH2_FXP_STATUS, type);
1840 
1841 			if ((r = sshbuf_get_u32(msg, &status)) != 0)
1842 				fatal_fr(r, "parse status");
1843 			debug3("SSH2_FXP_STATUS %u", status);
1844 
1845 			/* Find the request in our queue */
1846 			for (ack = TAILQ_FIRST(&acks);
1847 			    ack != NULL && ack->id != rid;
1848 			    ack = TAILQ_NEXT(ack, tq))
1849 				;
1850 			if (ack == NULL)
1851 				fatal("Can't find request for ID %u", rid);
1852 			TAILQ_REMOVE(&acks, ack, tq);
1853 			debug3("In write loop, ack for %u %u bytes at %lld",
1854 			    ack->id, ack->len, (long long)ack->offset);
1855 			++ackid;
1856 			progress_counter += ack->len;
1857 			free(ack);
1858 		}
1859 		offset += len;
1860 		if (offset < 0)
1861 			fatal_f("offset < 0");
1862 	}
1863 	sshbuf_free(msg);
1864 
1865 	if (showprogress)
1866 		stop_progress_meter();
1867 	free(data);
1868 
1869 	if (status != SSH2_FX_OK) {
1870 		error("Couldn't write to remote file \"%s\": %s",
1871 		    remote_path, fx2txt(status));
1872 		status = SSH2_FX_FAILURE;
1873 	}
1874 
1875 	if (close(local_fd) == -1) {
1876 		error("Couldn't close local file \"%s\": %s", local_path,
1877 		    strerror(errno));
1878 		status = SSH2_FX_FAILURE;
1879 	}
1880 
1881 	/* Override umask and utimes if asked */
1882 	if (preserve_flag)
1883 		do_fsetstat(conn, handle, handle_len, &a);
1884 
1885 	if (fsync_flag)
1886 		(void)do_fsync(conn, handle, handle_len);
1887 
1888 	if (do_close(conn, handle, handle_len) != 0)
1889 		status = SSH2_FX_FAILURE;
1890 
1891 	free(handle);
1892 
1893 	return status == SSH2_FX_OK ? 0 : -1;
1894 }
1895 
1896 static int
1897 upload_dir_internal(struct sftp_conn *conn, const char *src, const char *dst,
1898     int depth, int preserve_flag, int print_flag, int resume, int fsync_flag)
1899 {
1900 	int ret = 0;
1901 	DIR *dirp;
1902 	struct dirent *dp;
1903 	char *filename, *new_src = NULL, *new_dst = NULL;
1904 	struct stat sb;
1905 	Attrib a, *dirattrib;
1906 	u_int32_t saved_perm;
1907 
1908 	if (depth >= MAX_DIR_DEPTH) {
1909 		error("Maximum directory depth exceeded: %d levels", depth);
1910 		return -1;
1911 	}
1912 
1913 	if (stat(src, &sb) == -1) {
1914 		error("Couldn't stat directory \"%s\": %s",
1915 		    src, strerror(errno));
1916 		return -1;
1917 	}
1918 	if (!S_ISDIR(sb.st_mode)) {
1919 		error("\"%s\" is not a directory", src);
1920 		return -1;
1921 	}
1922 	if (print_flag)
1923 		mprintf("Entering %s\n", src);
1924 
1925 	attrib_clear(&a);
1926 	stat_to_attrib(&sb, &a);
1927 	a.flags &= ~SSH2_FILEXFER_ATTR_SIZE;
1928 	a.flags &= ~SSH2_FILEXFER_ATTR_UIDGID;
1929 	a.perm &= 01777;
1930 	if (!preserve_flag)
1931 		a.flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME;
1932 
1933 	/*
1934 	 * sftp lacks a portable status value to match errno EEXIST,
1935 	 * so if we get a failure back then we must check whether
1936 	 * the path already existed and is a directory.  Ensure we can
1937 	 * write to the directory we create for the duration of the transfer.
1938 	 */
1939 	saved_perm = a.perm;
1940 	a.perm |= (S_IWUSR|S_IXUSR);
1941 	if (do_mkdir(conn, dst, &a, 0) != 0) {
1942 		if ((dirattrib = do_stat(conn, dst, 0)) == NULL)
1943 			return -1;
1944 		if (!S_ISDIR(dirattrib->perm)) {
1945 			error("\"%s\" exists but is not a directory", dst);
1946 			return -1;
1947 		}
1948 	}
1949 	a.perm = saved_perm;
1950 
1951 	if ((dirp = opendir(src)) == NULL) {
1952 		error("Failed to open dir \"%s\": %s", src, strerror(errno));
1953 		return -1;
1954 	}
1955 
1956 	while (((dp = readdir(dirp)) != NULL) && !interrupted) {
1957 		if (dp->d_ino == 0)
1958 			continue;
1959 		free(new_dst);
1960 		free(new_src);
1961 		filename = dp->d_name;
1962 		new_dst = path_append(dst, filename);
1963 		new_src = path_append(src, filename);
1964 
1965 		if (lstat(new_src, &sb) == -1) {
1966 			logit("%s: lstat failed: %s", filename,
1967 			    strerror(errno));
1968 			ret = -1;
1969 		} else if (S_ISDIR(sb.st_mode)) {
1970 			if (strcmp(filename, ".") == 0 ||
1971 			    strcmp(filename, "..") == 0)
1972 				continue;
1973 
1974 			if (upload_dir_internal(conn, new_src, new_dst,
1975 			    depth + 1, preserve_flag, print_flag, resume,
1976 			    fsync_flag) == -1)
1977 				ret = -1;
1978 		} else if (S_ISREG(sb.st_mode)) {
1979 			if (do_upload(conn, new_src, new_dst,
1980 			    preserve_flag, resume, fsync_flag) == -1) {
1981 				error("Uploading of file %s to %s failed!",
1982 				    new_src, new_dst);
1983 				ret = -1;
1984 			}
1985 		} else
1986 			logit("%s: not a regular file\n", filename);
1987 	}
1988 	free(new_dst);
1989 	free(new_src);
1990 
1991 	do_setstat(conn, dst, &a);
1992 
1993 	(void) closedir(dirp);
1994 	return ret;
1995 }
1996 
1997 int
1998 upload_dir(struct sftp_conn *conn, const char *src, const char *dst,
1999     int preserve_flag, int print_flag, int resume, int fsync_flag)
2000 {
2001 	char *dst_canon;
2002 	int ret;
2003 
2004 	if ((dst_canon = do_realpath(conn, dst)) == NULL) {
2005 		error("Unable to canonicalize path \"%s\"", dst);
2006 		return -1;
2007 	}
2008 
2009 	ret = upload_dir_internal(conn, src, dst_canon, 0, preserve_flag,
2010 	    print_flag, resume, fsync_flag);
2011 
2012 	free(dst_canon);
2013 	return ret;
2014 }
2015 
2016 char *
2017 path_append(const char *p1, const char *p2)
2018 {
2019 	char *ret;
2020 	size_t len = strlen(p1) + strlen(p2) + 2;
2021 
2022 	ret = xmalloc(len);
2023 	strlcpy(ret, p1, len);
2024 	if (p1[0] != '\0' && p1[strlen(p1) - 1] != '/')
2025 		strlcat(ret, "/", len);
2026 	strlcat(ret, p2, len);
2027 
2028 	return(ret);
2029 }
2030 
2031 char *
2032 make_absolute(char *p, const char *pwd)
2033 {
2034 	char *abs_str;
2035 
2036 	/* Derelativise */
2037 	if (p && !path_absolute(p)) {
2038 		abs_str = path_append(pwd, p);
2039 		free(p);
2040 		return(abs_str);
2041 	} else
2042 		return(p);
2043 }
2044 
2045 int
2046 remote_is_dir(struct sftp_conn *conn, const char *path)
2047 {
2048 	Attrib *a;
2049 
2050 	/* XXX: report errors? */
2051 	if ((a = do_stat(conn, path, 1)) == NULL)
2052 		return(0);
2053 	if (!(a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS))
2054 		return(0);
2055 	return(S_ISDIR(a->perm));
2056 }
2057 
2058 
2059 int
2060 local_is_dir(const char *path)
2061 {
2062 	struct stat sb;
2063 
2064 	/* XXX: report errors? */
2065 	if (stat(path, &sb) == -1)
2066 		return(0);
2067 
2068 	return(S_ISDIR(sb.st_mode));
2069 }
2070 
2071 /* Check whether path returned from glob(..., GLOB_MARK, ...) is a directory */
2072 int
2073 globpath_is_dir(const char *pathname)
2074 {
2075 	size_t l = strlen(pathname);
2076 
2077 	return l > 0 && pathname[l - 1] == '/';
2078 }
2079 
2080