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