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