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