Home | History | Annotate | Download | only in openssh
      1 /* $OpenBSD: sftp-client.c,v 1.126 2017/01/03 05:46:51 djm Exp $ */
      2 /*
      3  * Copyright (c) 2001-2004 Damien Miller <djm (at) 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 	u_int exts;
     90 	u_int64_t limit_kbps;
     91 	struct bwlimit bwlimit_in, bwlimit_out;
     92 };
     93 
     94 static u_char *
     95 get_handle(struct sftp_conn *conn, u_int expected_id, size_t *len,
     96     const char *errfmt, ...) __attribute__((format(printf, 4, 5)));
     97 
     98 /* ARGSUSED */
     99 static int
    100 sftpio(void *_bwlimit, size_t amount)
    101 {
    102 	struct bwlimit *bwlimit = (struct bwlimit *)_bwlimit;
    103 
    104 	bandwidth_limit(bwlimit, amount);
    105 	return 0;
    106 }
    107 
    108 static void
    109 send_msg(struct sftp_conn *conn, struct sshbuf *m)
    110 {
    111 	u_char mlen[4];
    112 	struct iovec iov[2];
    113 
    114 	if (sshbuf_len(m) > SFTP_MAX_MSG_LENGTH)
    115 		fatal("Outbound message too long %zu", sshbuf_len(m));
    116 
    117 	/* Send length first */
    118 	put_u32(mlen, sshbuf_len(m));
    119 	iov[0].iov_base = mlen;
    120 	iov[0].iov_len = sizeof(mlen);
    121 	iov[1].iov_base = (u_char *)sshbuf_ptr(m);
    122 	iov[1].iov_len = sshbuf_len(m);
    123 
    124 	if (atomiciov6(writev, conn->fd_out, iov, 2,
    125 	    conn->limit_kbps > 0 ? sftpio : NULL, &conn->bwlimit_out) !=
    126 	    sshbuf_len(m) + sizeof(mlen))
    127 		fatal("Couldn't send packet: %s", strerror(errno));
    128 
    129 	sshbuf_reset(m);
    130 }
    131 
    132 static void
    133 get_msg(struct sftp_conn *conn, struct sshbuf *m)
    134 {
    135 	u_int msg_len;
    136 	u_char *p;
    137 	int r;
    138 
    139 	if ((r = sshbuf_reserve(m, 4, &p)) != 0)
    140 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
    141 	if (atomicio6(read, conn->fd_in, p, 4,
    142 	    conn->limit_kbps > 0 ? sftpio : NULL, &conn->bwlimit_in) != 4) {
    143 		if (errno == EPIPE)
    144 			fatal("Connection closed");
    145 		else
    146 			fatal("Couldn't read packet: %s", strerror(errno));
    147 	}
    148 
    149 	if ((r = sshbuf_get_u32(m, &msg_len)) != 0)
    150 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
    151 	if (msg_len > SFTP_MAX_MSG_LENGTH)
    152 		fatal("Received message too long %u", msg_len);
    153 
    154 	if ((r = sshbuf_reserve(m, msg_len, &p)) != 0)
    155 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
    156 	if (atomicio6(read, conn->fd_in, p, msg_len,
    157 	    conn->limit_kbps > 0 ? sftpio : NULL, &conn->bwlimit_in)
    158 	    != msg_len) {
    159 		if (errno == EPIPE)
    160 			fatal("Connection closed");
    161 		else
    162 			fatal("Read packet: %s", strerror(errno));
    163 	}
    164 }
    165 
    166 static void
    167 send_string_request(struct sftp_conn *conn, u_int id, u_int code, const char *s,
    168     u_int len)
    169 {
    170 	struct sshbuf *msg;
    171 	int r;
    172 
    173 	if ((msg = sshbuf_new()) == NULL)
    174 		fatal("%s: sshbuf_new failed", __func__);
    175 	if ((r = sshbuf_put_u8(msg, code)) != 0 ||
    176 	    (r = sshbuf_put_u32(msg, id)) != 0 ||
    177 	    (r = sshbuf_put_string(msg, s, len)) != 0)
    178 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
    179 	send_msg(conn, msg);
    180 	debug3("Sent message fd %d T:%u I:%u", conn->fd_out, code, id);
    181 	sshbuf_free(msg);
    182 }
    183 
    184 static void
    185 send_string_attrs_request(struct sftp_conn *conn, u_int id, u_int code,
    186     const void *s, u_int len, Attrib *a)
    187 {
    188 	struct sshbuf *msg;
    189 	int r;
    190 
    191 	if ((msg = sshbuf_new()) == NULL)
    192 		fatal("%s: sshbuf_new failed", __func__);
    193 	if ((r = sshbuf_put_u8(msg, code)) != 0 ||
    194 	    (r = sshbuf_put_u32(msg, id)) != 0 ||
    195 	    (r = sshbuf_put_string(msg, s, len)) != 0 ||
    196 	    (r = encode_attrib(msg, a)) != 0)
    197 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
    198 	send_msg(conn, msg);
    199 	debug3("Sent message fd %d T:%u I:%u", conn->fd_out, code, id);
    200 	sshbuf_free(msg);
    201 }
    202 
    203 static u_int
    204 get_status(struct sftp_conn *conn, u_int expected_id)
    205 {
    206 	struct sshbuf *msg;
    207 	u_char type;
    208 	u_int id, status;
    209 	int r;
    210 
    211 	if ((msg = sshbuf_new()) == NULL)
    212 		fatal("%s: sshbuf_new failed", __func__);
    213 	get_msg(conn, msg);
    214 	if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
    215 	    (r = sshbuf_get_u32(msg, &id)) != 0)
    216 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
    217 
    218 	if (id != expected_id)
    219 		fatal("ID mismatch (%u != %u)", id, expected_id);
    220 	if (type != SSH2_FXP_STATUS)
    221 		fatal("Expected SSH2_FXP_STATUS(%u) packet, got %u",
    222 		    SSH2_FXP_STATUS, type);
    223 
    224 	if ((r = sshbuf_get_u32(msg, &status)) != 0)
    225 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
    226 	sshbuf_free(msg);
    227 
    228 	debug3("SSH2_FXP_STATUS %u", status);
    229 
    230 	return status;
    231 }
    232 
    233 static u_char *
    234 get_handle(struct sftp_conn *conn, u_int expected_id, size_t *len,
    235     const char *errfmt, ...)
    236 {
    237 	struct sshbuf *msg;
    238 	u_int id, status;
    239 	u_char type;
    240 	u_char *handle;
    241 	char errmsg[256];
    242 	va_list args;
    243 	int r;
    244 
    245 	va_start(args, errfmt);
    246 	if (errfmt != NULL)
    247 		vsnprintf(errmsg, sizeof(errmsg), errfmt, args);
    248 	va_end(args);
    249 
    250 	if ((msg = sshbuf_new()) == NULL)
    251 		fatal("%s: sshbuf_new failed", __func__);
    252 	get_msg(conn, msg);
    253 	if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
    254 	    (r = sshbuf_get_u32(msg, &id)) != 0)
    255 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
    256 
    257 	if (id != expected_id)
    258 		fatal("%s: ID mismatch (%u != %u)",
    259 		    errfmt == NULL ? __func__ : errmsg, id, expected_id);
    260 	if (type == SSH2_FXP_STATUS) {
    261 		if ((r = sshbuf_get_u32(msg, &status)) != 0)
    262 			fatal("%s: buffer error: %s", __func__, ssh_err(r));
    263 		if (errfmt != NULL)
    264 			error("%s: %s", errmsg, fx2txt(status));
    265 		sshbuf_free(msg);
    266 		return(NULL);
    267 	} else if (type != SSH2_FXP_HANDLE)
    268 		fatal("%s: Expected SSH2_FXP_HANDLE(%u) packet, got %u",
    269 		    errfmt == NULL ? __func__ : errmsg, SSH2_FXP_HANDLE, type);
    270 
    271 	if ((r = sshbuf_get_string(msg, &handle, len)) != 0)
    272 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
    273 	sshbuf_free(msg);
    274 
    275 	return handle;
    276 }
    277 
    278 static Attrib *
    279 get_decode_stat(struct sftp_conn *conn, u_int expected_id, int quiet)
    280 {
    281 	struct sshbuf *msg;
    282 	u_int id;
    283 	u_char type;
    284 	int r;
    285 	static Attrib a;
    286 
    287 	if ((msg = sshbuf_new()) == NULL)
    288 		fatal("%s: sshbuf_new failed", __func__);
    289 	get_msg(conn, msg);
    290 
    291 	if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
    292 	    (r = sshbuf_get_u32(msg, &id)) != 0)
    293 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
    294 
    295 	debug3("Received stat reply T:%u I:%u", type, id);
    296 	if (id != expected_id)
    297 		fatal("ID mismatch (%u != %u)", id, expected_id);
    298 	if (type == SSH2_FXP_STATUS) {
    299 		u_int status;
    300 
    301 		if ((r = sshbuf_get_u32(msg, &status)) != 0)
    302 			fatal("%s: buffer error: %s", __func__, ssh_err(r));
    303 		if (quiet)
    304 			debug("Couldn't stat remote file: %s", fx2txt(status));
    305 		else
    306 			error("Couldn't stat remote file: %s", fx2txt(status));
    307 		sshbuf_free(msg);
    308 		return(NULL);
    309 	} else if (type != SSH2_FXP_ATTRS) {
    310 		fatal("Expected SSH2_FXP_ATTRS(%u) packet, got %u",
    311 		    SSH2_FXP_ATTRS, type);
    312 	}
    313 	if ((r = decode_attrib(msg, &a)) != 0) {
    314 		error("%s: couldn't decode attrib: %s", __func__, ssh_err(r));
    315 		sshbuf_free(msg);
    316 		return NULL;
    317 	}
    318 	sshbuf_free(msg);
    319 
    320 	return &a;
    321 }
    322 
    323 static int
    324 get_decode_statvfs(struct sftp_conn *conn, struct sftp_statvfs *st,
    325     u_int expected_id, int quiet)
    326 {
    327 	struct sshbuf *msg;
    328 	u_char type;
    329 	u_int id;
    330 	u_int64_t flag;
    331 	int r;
    332 
    333 	if ((msg = sshbuf_new()) == NULL)
    334 		fatal("%s: sshbuf_new failed", __func__);
    335 	get_msg(conn, msg);
    336 
    337 	if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
    338 	    (r = sshbuf_get_u32(msg, &id)) != 0)
    339 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
    340 
    341 	debug3("Received statvfs reply T:%u I:%u", type, id);
    342 	if (id != expected_id)
    343 		fatal("ID mismatch (%u != %u)", id, expected_id);
    344 	if (type == SSH2_FXP_STATUS) {
    345 		u_int status;
    346 
    347 		if ((r = sshbuf_get_u32(msg, &status)) != 0)
    348 			fatal("%s: buffer error: %s", __func__, ssh_err(r));
    349 		if (quiet)
    350 			debug("Couldn't statvfs: %s", fx2txt(status));
    351 		else
    352 			error("Couldn't statvfs: %s", fx2txt(status));
    353 		sshbuf_free(msg);
    354 		return -1;
    355 	} else if (type != SSH2_FXP_EXTENDED_REPLY) {
    356 		fatal("Expected SSH2_FXP_EXTENDED_REPLY(%u) packet, got %u",
    357 		    SSH2_FXP_EXTENDED_REPLY, type);
    358 	}
    359 
    360 	memset(st, 0, sizeof(*st));
    361 	if ((r = sshbuf_get_u64(msg, &st->f_bsize)) != 0 ||
    362 	    (r = sshbuf_get_u64(msg, &st->f_frsize)) != 0 ||
    363 	    (r = sshbuf_get_u64(msg, &st->f_blocks)) != 0 ||
    364 	    (r = sshbuf_get_u64(msg, &st->f_bfree)) != 0 ||
    365 	    (r = sshbuf_get_u64(msg, &st->f_bavail)) != 0 ||
    366 	    (r = sshbuf_get_u64(msg, &st->f_files)) != 0 ||
    367 	    (r = sshbuf_get_u64(msg, &st->f_ffree)) != 0 ||
    368 	    (r = sshbuf_get_u64(msg, &st->f_favail)) != 0 ||
    369 	    (r = sshbuf_get_u64(msg, &st->f_fsid)) != 0 ||
    370 	    (r = sshbuf_get_u64(msg, &flag)) != 0 ||
    371 	    (r = sshbuf_get_u64(msg, &st->f_namemax)) != 0)
    372 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
    373 
    374 	st->f_flag = (flag & SSH2_FXE_STATVFS_ST_RDONLY) ? ST_RDONLY : 0;
    375 	st->f_flag |= (flag & SSH2_FXE_STATVFS_ST_NOSUID) ? ST_NOSUID : 0;
    376 
    377 	sshbuf_free(msg);
    378 
    379 	return 0;
    380 }
    381 
    382 struct sftp_conn *
    383 do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests,
    384     u_int64_t limit_kbps)
    385 {
    386 	u_char type;
    387 	struct sshbuf *msg;
    388 	struct sftp_conn *ret;
    389 	int r;
    390 
    391 	ret = xcalloc(1, sizeof(*ret));
    392 	ret->msg_id = 1;
    393 	ret->fd_in = fd_in;
    394 	ret->fd_out = fd_out;
    395 	ret->transfer_buflen = transfer_buflen;
    396 	ret->num_requests = num_requests;
    397 	ret->exts = 0;
    398 	ret->limit_kbps = 0;
    399 
    400 	if ((msg = sshbuf_new()) == NULL)
    401 		fatal("%s: sshbuf_new failed", __func__);
    402 	if ((r = sshbuf_put_u8(msg, SSH2_FXP_INIT)) != 0 ||
    403 	    (r = sshbuf_put_u32(msg, SSH2_FILEXFER_VERSION)) != 0)
    404 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
    405 	send_msg(ret, msg);
    406 
    407 	sshbuf_reset(msg);
    408 
    409 	get_msg(ret, msg);
    410 
    411 	/* Expecting a VERSION reply */
    412 	if ((r = sshbuf_get_u8(msg, &type)) != 0)
    413 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
    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("%s: buffer error: %s", __func__, ssh_err(r));
    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("%s: buffer error: %s", __func__, ssh_err(r));
    436 		if (strcmp(name, "posix-rename (at) 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 (at) openssh.com") == 0 &&
    441 		    strcmp((char *)value, "2") == 0) {
    442 			ret->exts |= SFTP_EXT_STATVFS;
    443 			known = 1;
    444 		} else if (strcmp(name, "fstatvfs (at) openssh.com") == 0 &&
    445 		    strcmp((char *)value, "2") == 0) {
    446 			ret->exts |= SFTP_EXT_FSTATVFS;
    447 			known = 1;
    448 		} else if (strcmp(name, "hardlink (at) openssh.com") == 0 &&
    449 		    strcmp((char *)value, "1") == 0) {
    450 			ret->exts |= SFTP_EXT_HARDLINK;
    451 			known = 1;
    452 		} else if (strcmp(name, "fsync (at) openssh.com") == 0 &&
    453 		    strcmp((char *)value, "1") == 0) {
    454 			ret->exts |= SFTP_EXT_FSYNC;
    455 			known = 1;
    456 		}
    457 		if (known) {
    458 			debug2("Server supports extension \"%s\" revision %s",
    459 			    name, value);
    460 		} else {
    461 			debug2("Unrecognised server extension \"%s\"", name);
    462 		}
    463 		free(name);
    464 		free(value);
    465 	}
    466 
    467 	sshbuf_free(msg);
    468 
    469 	/* Some filexfer v.0 servers don't support large packets */
    470 	if (ret->version == 0)
    471 		ret->transfer_buflen = MINIMUM(ret->transfer_buflen, 20480);
    472 
    473 	ret->limit_kbps = limit_kbps;
    474 	if (ret->limit_kbps > 0) {
    475 		bandwidth_limit_init(&ret->bwlimit_in, ret->limit_kbps,
    476 		    ret->transfer_buflen);
    477 		bandwidth_limit_init(&ret->bwlimit_out, ret->limit_kbps,
    478 		    ret->transfer_buflen);
    479 	}
    480 
    481 	return ret;
    482 }
    483 
    484 u_int
    485 sftp_proto_version(struct sftp_conn *conn)
    486 {
    487 	return conn->version;
    488 }
    489 
    490 int
    491 do_close(struct sftp_conn *conn, const u_char *handle, u_int handle_len)
    492 {
    493 	u_int id, status;
    494 	struct sshbuf *msg;
    495 	int r;
    496 
    497 	if ((msg = sshbuf_new()) == NULL)
    498 		fatal("%s: sshbuf_new failed", __func__);
    499 
    500 	id = conn->msg_id++;
    501 	if ((r = sshbuf_put_u8(msg, SSH2_FXP_CLOSE)) != 0 ||
    502 	    (r = sshbuf_put_u32(msg, id)) != 0 ||
    503 	    (r = sshbuf_put_string(msg, handle, handle_len)) != 0)
    504 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
    505 	send_msg(conn, msg);
    506 	debug3("Sent message SSH2_FXP_CLOSE I:%u", id);
    507 
    508 	status = get_status(conn, id);
    509 	if (status != SSH2_FX_OK)
    510 		error("Couldn't close file: %s", fx2txt(status));
    511 
    512 	sshbuf_free(msg);
    513 
    514 	return status == SSH2_FX_OK ? 0 : -1;
    515 }
    516 
    517 
    518 static int
    519 do_lsreaddir(struct sftp_conn *conn, const char *path, int print_flag,
    520     SFTP_DIRENT ***dir)
    521 {
    522 	struct sshbuf *msg;
    523 	u_int count, id, i, expected_id, ents = 0;
    524 	size_t handle_len;
    525 	u_char type, *handle;
    526 	int status = SSH2_FX_FAILURE;
    527 	int r;
    528 
    529 	if (dir)
    530 		*dir = NULL;
    531 
    532 	id = conn->msg_id++;
    533 
    534 	if ((msg = sshbuf_new()) == NULL)
    535 		fatal("%s: sshbuf_new failed", __func__);
    536 	if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPENDIR)) != 0 ||
    537 	    (r = sshbuf_put_u32(msg, id)) != 0 ||
    538 	    (r = sshbuf_put_cstring(msg, path)) != 0)
    539 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
    540 	send_msg(conn, msg);
    541 
    542 	handle = get_handle(conn, id, &handle_len,
    543 	    "remote readdir(\"%s\")", path);
    544 	if (handle == NULL) {
    545 		sshbuf_free(msg);
    546 		return -1;
    547 	}
    548 
    549 	if (dir) {
    550 		ents = 0;
    551 		*dir = xcalloc(1, sizeof(**dir));
    552 		(*dir)[0] = NULL;
    553 	}
    554 
    555 	for (; !interrupted;) {
    556 		id = expected_id = conn->msg_id++;
    557 
    558 		debug3("Sending SSH2_FXP_READDIR I:%u", id);
    559 
    560 		sshbuf_reset(msg);
    561 		if ((r = sshbuf_put_u8(msg, SSH2_FXP_READDIR)) != 0 ||
    562 		    (r = sshbuf_put_u32(msg, id)) != 0 ||
    563 		    (r = sshbuf_put_string(msg, handle, handle_len)) != 0)
    564 			fatal("%s: buffer error: %s", __func__, ssh_err(r));
    565 		send_msg(conn, msg);
    566 
    567 		sshbuf_reset(msg);
    568 
    569 		get_msg(conn, msg);
    570 
    571 		if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
    572 		    (r = sshbuf_get_u32(msg, &id)) != 0)
    573 			fatal("%s: buffer error: %s", __func__, ssh_err(r));
    574 
    575 		debug3("Received reply T:%u I:%u", type, id);
    576 
    577 		if (id != expected_id)
    578 			fatal("ID mismatch (%u != %u)", id, expected_id);
    579 
    580 		if (type == SSH2_FXP_STATUS) {
    581 			u_int rstatus;
    582 
    583 			if ((r = sshbuf_get_u32(msg, &rstatus)) != 0)
    584 				fatal("%s: buffer error: %s",
    585 				    __func__, ssh_err(r));
    586 			debug3("Received SSH2_FXP_STATUS %d", rstatus);
    587 			if (rstatus == SSH2_FX_EOF)
    588 				break;
    589 			error("Couldn't read directory: %s", fx2txt(rstatus));
    590 			goto out;
    591 		} else if (type != SSH2_FXP_NAME)
    592 			fatal("Expected SSH2_FXP_NAME(%u) packet, got %u",
    593 			    SSH2_FXP_NAME, type);
    594 
    595 		if ((r = sshbuf_get_u32(msg, &count)) != 0)
    596 			fatal("%s: buffer error: %s", __func__, ssh_err(r));
    597 		if (count > SSHBUF_SIZE_MAX)
    598 			fatal("%s: nonsensical number of entries", __func__);
    599 		if (count == 0)
    600 			break;
    601 		debug3("Received %d SSH2_FXP_NAME responses", count);
    602 		for (i = 0; i < count; i++) {
    603 			char *filename, *longname;
    604 			Attrib a;
    605 
    606 			if ((r = sshbuf_get_cstring(msg, &filename,
    607 			    NULL)) != 0 ||
    608 			    (r = sshbuf_get_cstring(msg, &longname,
    609 			    NULL)) != 0)
    610 				fatal("%s: buffer error: %s",
    611 				    __func__, ssh_err(r));
    612 			if ((r = decode_attrib(msg, &a)) != 0) {
    613 				error("%s: couldn't decode attrib: %s",
    614 				    __func__, ssh_err(r));
    615 				free(filename);
    616 				free(longname);
    617 				sshbuf_free(msg);
    618 				return -1;
    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 (strpbrk(filename, SFTP_DIRECTORY_CHARS) != 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;
    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("%s: sshbuf_new failed", __func__);
    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("%s: buffer error: %s", __func__, ssh_err(r));
    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("%s: buffer error: %s", __func__, ssh_err(r));
    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("%s: buffer error: %s", __func__, ssh_err(r));
    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("%s: buffer error: %s", __func__, ssh_err(r));
    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("%s: sshbuf_new failed", __func__);
    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 (at) openssh.com")) != 0)
    890 			fatal("%s: buffer error: %s", __func__, ssh_err(r));
    891 	} else {
    892 		if ((r = sshbuf_put_u8(msg, SSH2_FXP_RENAME)) != 0 ||
    893 		    (r = sshbuf_put_u32(msg, id)) != 0)
    894 			fatal("%s: buffer error: %s", __func__, ssh_err(r));
    895 	}
    896 	if ((r = sshbuf_put_cstring(msg, oldpath)) != 0 ||
    897 	    (r = sshbuf_put_cstring(msg, newpath)) != 0)
    898 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
    899 	send_msg(conn, msg);
    900 	debug3("Sent message %s \"%s\" -> \"%s\"",
    901 	    use_ext ? "posix-rename (at) 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 (at) openssh.com extension");
    922 		return -1;
    923 	}
    924 
    925 	if ((msg = sshbuf_new()) == NULL)
    926 		fatal("%s: sshbuf_new failed", __func__);
    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 (at) openssh.com")) != 0 ||
    933 	    (r = sshbuf_put_cstring(msg, oldpath)) != 0 ||
    934 	    (r = sshbuf_put_cstring(msg, newpath)) != 0)
    935 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
    936 	send_msg(conn, msg);
    937 	debug3("Sent message hardlink (at) 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("%s: sshbuf_new failed", __func__);
    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("%s: buffer error: %s", __func__, ssh_err(r));
    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("%s: sshbuf_new failed", __func__);
    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 (at) openssh.com")) != 0 ||
   1002 	    (r = sshbuf_put_string(msg, handle, handle_len)) != 0)
   1003 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
   1004 	send_msg(conn, msg);
   1005 	debug3("Sent message fsync (at) 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;
   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("%s: sshbuf_new failed", __func__);
   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("%s: buffer error: %s", __func__, ssh_err(r));
   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("%s: buffer error: %s", __func__, ssh_err(r));
   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("%s: buffer error: %s", __func__, ssh_err(r));
   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("%s: buffer error: %s", __func__, ssh_err(r));
   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 (at) openssh.com extension");
   1082 		return -1;
   1083 	}
   1084 
   1085 	id = conn->msg_id++;
   1086 
   1087 	if ((msg = sshbuf_new()) == NULL)
   1088 		fatal("%s: sshbuf_new failed", __func__);
   1089 	sshbuf_reset(msg);
   1090 	if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
   1091 	    (r = sshbuf_put_u32(msg, id)) != 0 ||
   1092 	    (r = sshbuf_put_cstring(msg, "statvfs (at) openssh.com")) != 0 ||
   1093 	    (r = sshbuf_put_cstring(msg, path)) != 0)
   1094 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
   1095 	send_msg(conn, msg);
   1096 	sshbuf_free(msg);
   1097 
   1098 	return get_decode_statvfs(conn, st, id, quiet);
   1099 }
   1100 
   1101 #ifdef notyet
   1102 int
   1103 do_fstatvfs(struct sftp_conn *conn, const u_char *handle, u_int handle_len,
   1104     struct sftp_statvfs *st, int quiet)
   1105 {
   1106 	struct sshbuf *msg;
   1107 	u_int id;
   1108 
   1109 	if ((conn->exts & SFTP_EXT_FSTATVFS) == 0) {
   1110 		error("Server does not support fstatvfs (at) openssh.com extension");
   1111 		return -1;
   1112 	}
   1113 
   1114 	id = conn->msg_id++;
   1115 
   1116 	if ((msg = sshbuf_new()) == NULL)
   1117 		fatal("%s: sshbuf_new failed", __func__);
   1118 	sshbuf_reset(msg);
   1119 	if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
   1120 	    (r = sshbuf_put_u32(msg, id)) != 0 ||
   1121 	    (r = sshbuf_put_cstring(msg, "fstatvfs (at) openssh.com")) != 0 ||
   1122 	    (r = sshbuf_put_string(msg, handle, handle_len)) != 0)
   1123 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
   1124 	send_msg(conn, msg);
   1125 	sshbuf_free(msg);
   1126 
   1127 	return get_decode_statvfs(conn, st, id, quiet);
   1128 }
   1129 #endif
   1130 
   1131 static void
   1132 send_read_request(struct sftp_conn *conn, u_int id, u_int64_t offset,
   1133     u_int len, const u_char *handle, u_int handle_len)
   1134 {
   1135 	struct sshbuf *msg;
   1136 	int r;
   1137 
   1138 	if ((msg = sshbuf_new()) == NULL)
   1139 		fatal("%s: sshbuf_new failed", __func__);
   1140 	sshbuf_reset(msg);
   1141 	if ((r = sshbuf_put_u8(msg, SSH2_FXP_READ)) != 0 ||
   1142 	    (r = sshbuf_put_u32(msg, id)) != 0 ||
   1143 	    (r = sshbuf_put_string(msg, handle, handle_len)) != 0 ||
   1144 	    (r = sshbuf_put_u64(msg, offset)) != 0 ||
   1145 	    (r = sshbuf_put_u32(msg, len)) != 0)
   1146 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
   1147 	send_msg(conn, msg);
   1148 	sshbuf_free(msg);
   1149 }
   1150 
   1151 int
   1152 do_download(struct sftp_conn *conn, const char *remote_path,
   1153     const char *local_path, Attrib *a, int preserve_flag, int resume_flag,
   1154     int fsync_flag)
   1155 {
   1156 	Attrib junk;
   1157 	struct sshbuf *msg;
   1158 	u_char *handle;
   1159 	int local_fd = -1, write_error;
   1160 	int read_error, write_errno, reordered = 0, r;
   1161 	u_int64_t offset = 0, size, highwater;
   1162 	u_int mode, id, buflen, num_req, max_req, status = SSH2_FX_OK;
   1163 	off_t progress_counter;
   1164 	size_t handle_len;
   1165 	struct stat st;
   1166 	struct request {
   1167 		u_int id;
   1168 		size_t len;
   1169 		u_int64_t offset;
   1170 		TAILQ_ENTRY(request) tq;
   1171 	};
   1172 	TAILQ_HEAD(reqhead, request) requests;
   1173 	struct request *req;
   1174 	u_char type;
   1175 
   1176 	TAILQ_INIT(&requests);
   1177 
   1178 	if (a == NULL && (a = do_stat(conn, remote_path, 0)) == NULL)
   1179 		return -1;
   1180 
   1181 	/* Do not preserve set[ug]id here, as we do not preserve ownership */
   1182 	if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS)
   1183 		mode = a->perm & 0777;
   1184 	else
   1185 		mode = 0666;
   1186 
   1187 	if ((a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) &&
   1188 	    (!S_ISREG(a->perm))) {
   1189 		error("Cannot download non-regular file: %s", remote_path);
   1190 		return(-1);
   1191 	}
   1192 
   1193 	if (a->flags & SSH2_FILEXFER_ATTR_SIZE)
   1194 		size = a->size;
   1195 	else
   1196 		size = 0;
   1197 
   1198 	buflen = conn->transfer_buflen;
   1199 	if ((msg = sshbuf_new()) == NULL)
   1200 		fatal("%s: sshbuf_new failed", __func__);
   1201 
   1202 	attrib_clear(&junk); /* Send empty attributes */
   1203 
   1204 	/* Send open request */
   1205 	id = conn->msg_id++;
   1206 	if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPEN)) != 0 ||
   1207 	    (r = sshbuf_put_u32(msg, id)) != 0 ||
   1208 	    (r = sshbuf_put_cstring(msg, remote_path)) != 0 ||
   1209 	    (r = sshbuf_put_u32(msg, SSH2_FXF_READ)) != 0 ||
   1210 	    (r = encode_attrib(msg, &junk)) != 0)
   1211 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
   1212 	send_msg(conn, msg);
   1213 	debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, remote_path);
   1214 
   1215 	handle = get_handle(conn, id, &handle_len,
   1216 	    "remote open(\"%s\")", remote_path);
   1217 	if (handle == NULL) {
   1218 		sshbuf_free(msg);
   1219 		return(-1);
   1220 	}
   1221 
   1222 	local_fd = open(local_path,
   1223 	    O_WRONLY | O_CREAT | (resume_flag ? 0 : O_TRUNC), mode | S_IWUSR);
   1224 	if (local_fd == -1) {
   1225 		error("Couldn't open local file \"%s\" for writing: %s",
   1226 		    local_path, strerror(errno));
   1227 		goto fail;
   1228 	}
   1229 	offset = highwater = 0;
   1230 	if (resume_flag) {
   1231 		if (fstat(local_fd, &st) == -1) {
   1232 			error("Unable to stat local file \"%s\": %s",
   1233 			    local_path, strerror(errno));
   1234 			goto fail;
   1235 		}
   1236 		if (st.st_size < 0) {
   1237 			error("\"%s\" has negative size", local_path);
   1238 			goto fail;
   1239 		}
   1240 		if ((u_int64_t)st.st_size > size) {
   1241 			error("Unable to resume download of \"%s\": "
   1242 			    "local file is larger than remote", local_path);
   1243  fail:
   1244 			do_close(conn, handle, handle_len);
   1245 			sshbuf_free(msg);
   1246 			free(handle);
   1247 			if (local_fd != -1)
   1248 				close(local_fd);
   1249 			return -1;
   1250 		}
   1251 		offset = highwater = st.st_size;
   1252 	}
   1253 
   1254 	/* Read from remote and write to local */
   1255 	write_error = read_error = write_errno = num_req = 0;
   1256 	max_req = 1;
   1257 	progress_counter = offset;
   1258 
   1259 	if (showprogress && size != 0)
   1260 		start_progress_meter(remote_path, size, &progress_counter);
   1261 
   1262 	while (num_req > 0 || max_req > 0) {
   1263 		u_char *data;
   1264 		size_t len;
   1265 
   1266 		/*
   1267 		 * Simulate EOF on interrupt: stop sending new requests and
   1268 		 * allow outstanding requests to drain gracefully
   1269 		 */
   1270 		if (interrupted) {
   1271 			if (num_req == 0) /* If we haven't started yet... */
   1272 				break;
   1273 			max_req = 0;
   1274 		}
   1275 
   1276 		/* Send some more requests */
   1277 		while (num_req < max_req) {
   1278 			debug3("Request range %llu -> %llu (%d/%d)",
   1279 			    (unsigned long long)offset,
   1280 			    (unsigned long long)offset + buflen - 1,
   1281 			    num_req, max_req);
   1282 			req = xcalloc(1, sizeof(*req));
   1283 			req->id = conn->msg_id++;
   1284 			req->len = buflen;
   1285 			req->offset = offset;
   1286 			offset += buflen;
   1287 			num_req++;
   1288 			TAILQ_INSERT_TAIL(&requests, req, tq);
   1289 			send_read_request(conn, req->id, req->offset,
   1290 			    req->len, handle, handle_len);
   1291 		}
   1292 
   1293 		sshbuf_reset(msg);
   1294 		get_msg(conn, msg);
   1295 		if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
   1296 		    (r = sshbuf_get_u32(msg, &id)) != 0)
   1297 			fatal("%s: buffer error: %s", __func__, ssh_err(r));
   1298 		debug3("Received reply T:%u I:%u R:%d", type, id, max_req);
   1299 
   1300 		/* Find the request in our queue */
   1301 		for (req = TAILQ_FIRST(&requests);
   1302 		    req != NULL && req->id != id;
   1303 		    req = TAILQ_NEXT(req, tq))
   1304 			;
   1305 		if (req == NULL)
   1306 			fatal("Unexpected reply %u", id);
   1307 
   1308 		switch (type) {
   1309 		case SSH2_FXP_STATUS:
   1310 			if ((r = sshbuf_get_u32(msg, &status)) != 0)
   1311 				fatal("%s: buffer error: %s",
   1312 				    __func__, ssh_err(r));
   1313 			if (status != SSH2_FX_EOF)
   1314 				read_error = 1;
   1315 			max_req = 0;
   1316 			TAILQ_REMOVE(&requests, req, tq);
   1317 			free(req);
   1318 			num_req--;
   1319 			break;
   1320 		case SSH2_FXP_DATA:
   1321 			if ((r = sshbuf_get_string(msg, &data, &len)) != 0)
   1322 				fatal("%s: buffer error: %s",
   1323 				    __func__, ssh_err(r));
   1324 			debug3("Received data %llu -> %llu",
   1325 			    (unsigned long long)req->offset,
   1326 			    (unsigned long long)req->offset + len - 1);
   1327 			if (len > req->len)
   1328 				fatal("Received more data than asked for "
   1329 				    "%zu > %zu", len, req->len);
   1330 			if ((lseek(local_fd, req->offset, SEEK_SET) == -1 ||
   1331 			    atomicio(vwrite, local_fd, data, len) != len) &&
   1332 			    !write_error) {
   1333 				write_errno = errno;
   1334 				write_error = 1;
   1335 				max_req = 0;
   1336 			}
   1337 			else if (!reordered && req->offset <= highwater)
   1338 				highwater = req->offset + len;
   1339 			else if (!reordered && req->offset > highwater)
   1340 				reordered = 1;
   1341 			progress_counter += len;
   1342 			free(data);
   1343 
   1344 			if (len == req->len) {
   1345 				TAILQ_REMOVE(&requests, req, tq);
   1346 				free(req);
   1347 				num_req--;
   1348 			} else {
   1349 				/* Resend the request for the missing data */
   1350 				debug3("Short data block, re-requesting "
   1351 				    "%llu -> %llu (%2d)",
   1352 				    (unsigned long long)req->offset + len,
   1353 				    (unsigned long long)req->offset +
   1354 				    req->len - 1, num_req);
   1355 				req->id = conn->msg_id++;
   1356 				req->len -= len;
   1357 				req->offset += len;
   1358 				send_read_request(conn, req->id,
   1359 				    req->offset, req->len, handle, handle_len);
   1360 				/* Reduce the request size */
   1361 				if (len < buflen)
   1362 					buflen = MAXIMUM(MIN_READ_SIZE, len);
   1363 			}
   1364 			if (max_req > 0) { /* max_req = 0 iff EOF received */
   1365 				if (size > 0 && offset > size) {
   1366 					/* Only one request at a time
   1367 					 * after the expected EOF */
   1368 					debug3("Finish at %llu (%2d)",
   1369 					    (unsigned long long)offset,
   1370 					    num_req);
   1371 					max_req = 1;
   1372 				} else if (max_req <= conn->num_requests) {
   1373 					++max_req;
   1374 				}
   1375 			}
   1376 			break;
   1377 		default:
   1378 			fatal("Expected SSH2_FXP_DATA(%u) packet, got %u",
   1379 			    SSH2_FXP_DATA, type);
   1380 		}
   1381 	}
   1382 
   1383 	if (showprogress && size)
   1384 		stop_progress_meter();
   1385 
   1386 	/* Sanity check */
   1387 	if (TAILQ_FIRST(&requests) != NULL)
   1388 		fatal("Transfer complete, but requests still in queue");
   1389 	/* Truncate at highest contiguous point to avoid holes on interrupt */
   1390 	if (read_error || write_error || interrupted) {
   1391 		if (reordered && resume_flag) {
   1392 			error("Unable to resume download of \"%s\": "
   1393 			    "server reordered requests", local_path);
   1394 		}
   1395 		debug("truncating at %llu", (unsigned long long)highwater);
   1396 		if (ftruncate(local_fd, highwater) == -1)
   1397 			error("ftruncate \"%s\": %s", local_path,
   1398 			    strerror(errno));
   1399 	}
   1400 	if (read_error) {
   1401 		error("Couldn't read from remote file \"%s\" : %s",
   1402 		    remote_path, fx2txt(status));
   1403 		status = -1;
   1404 		do_close(conn, handle, handle_len);
   1405 	} else if (write_error) {
   1406 		error("Couldn't write to \"%s\": %s", local_path,
   1407 		    strerror(write_errno));
   1408 		status = SSH2_FX_FAILURE;
   1409 		do_close(conn, handle, handle_len);
   1410 	} else {
   1411 		if (do_close(conn, handle, handle_len) != 0 || interrupted)
   1412 			status = SSH2_FX_FAILURE;
   1413 		else
   1414 			status = SSH2_FX_OK;
   1415 		/* Override umask and utimes if asked */
   1416 #ifdef HAVE_FCHMOD
   1417 		if (preserve_flag && fchmod(local_fd, mode) == -1)
   1418 #else
   1419 		if (preserve_flag && chmod(local_path, mode) == -1)
   1420 #endif /* HAVE_FCHMOD */
   1421 			error("Couldn't set mode on \"%s\": %s", local_path,
   1422 			    strerror(errno));
   1423 		if (preserve_flag &&
   1424 		    (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME)) {
   1425 			struct timeval tv[2];
   1426 			tv[0].tv_sec = a->atime;
   1427 			tv[1].tv_sec = a->mtime;
   1428 			tv[0].tv_usec = tv[1].tv_usec = 0;
   1429 			if (utimes(local_path, tv) == -1)
   1430 				error("Can't set times on \"%s\": %s",
   1431 				    local_path, strerror(errno));
   1432 		}
   1433 		if (fsync_flag) {
   1434 			debug("syncing \"%s\"", local_path);
   1435 			if (fsync(local_fd) == -1)
   1436 				error("Couldn't sync file \"%s\": %s",
   1437 				    local_path, strerror(errno));
   1438 		}
   1439 	}
   1440 	close(local_fd);
   1441 	sshbuf_free(msg);
   1442 	free(handle);
   1443 
   1444 	return(status);
   1445 }
   1446 
   1447 static int
   1448 download_dir_internal(struct sftp_conn *conn, const char *src, const char *dst,
   1449     int depth, Attrib *dirattrib, int preserve_flag, int print_flag,
   1450     int resume_flag, int fsync_flag)
   1451 {
   1452 	int i, ret = 0;
   1453 	SFTP_DIRENT **dir_entries;
   1454 	char *filename, *new_src, *new_dst;
   1455 	mode_t mode = 0777;
   1456 
   1457 	if (depth >= MAX_DIR_DEPTH) {
   1458 		error("Maximum directory depth exceeded: %d levels", depth);
   1459 		return -1;
   1460 	}
   1461 
   1462 	if (dirattrib == NULL &&
   1463 	    (dirattrib = do_stat(conn, src, 1)) == NULL) {
   1464 		error("Unable to stat remote directory \"%s\"", src);
   1465 		return -1;
   1466 	}
   1467 	if (!S_ISDIR(dirattrib->perm)) {
   1468 		error("\"%s\" is not a directory", src);
   1469 		return -1;
   1470 	}
   1471 	if (print_flag)
   1472 		mprintf("Retrieving %s\n", src);
   1473 
   1474 	if (dirattrib->flags & SSH2_FILEXFER_ATTR_PERMISSIONS)
   1475 		mode = dirattrib->perm & 01777;
   1476 	else {
   1477 		debug("Server did not send permissions for "
   1478 		    "directory \"%s\"", dst);
   1479 	}
   1480 
   1481 	if (mkdir(dst, mode) == -1 && errno != EEXIST) {
   1482 		error("mkdir %s: %s", dst, strerror(errno));
   1483 		return -1;
   1484 	}
   1485 
   1486 	if (do_readdir(conn, src, &dir_entries) == -1) {
   1487 		error("%s: Failed to get directory contents", src);
   1488 		return -1;
   1489 	}
   1490 
   1491 	for (i = 0; dir_entries[i] != NULL && !interrupted; i++) {
   1492 		filename = dir_entries[i]->filename;
   1493 
   1494 		new_dst = path_append(dst, filename);
   1495 		new_src = path_append(src, filename);
   1496 
   1497 		if (S_ISDIR(dir_entries[i]->a.perm)) {
   1498 			if (strcmp(filename, ".") == 0 ||
   1499 			    strcmp(filename, "..") == 0)
   1500 				continue;
   1501 			if (download_dir_internal(conn, new_src, new_dst,
   1502 			    depth + 1, &(dir_entries[i]->a), preserve_flag,
   1503 			    print_flag, resume_flag, fsync_flag) == -1)
   1504 				ret = -1;
   1505 		} else if (S_ISREG(dir_entries[i]->a.perm) ) {
   1506 			if (do_download(conn, new_src, new_dst,
   1507 			    &(dir_entries[i]->a), preserve_flag,
   1508 			    resume_flag, fsync_flag) == -1) {
   1509 				error("Download of file %s to %s failed",
   1510 				    new_src, new_dst);
   1511 				ret = -1;
   1512 			}
   1513 		} else
   1514 			logit("%s: not a regular file\n", new_src);
   1515 
   1516 		free(new_dst);
   1517 		free(new_src);
   1518 	}
   1519 
   1520 	if (preserve_flag) {
   1521 		if (dirattrib->flags & SSH2_FILEXFER_ATTR_ACMODTIME) {
   1522 			struct timeval tv[2];
   1523 			tv[0].tv_sec = dirattrib->atime;
   1524 			tv[1].tv_sec = dirattrib->mtime;
   1525 			tv[0].tv_usec = tv[1].tv_usec = 0;
   1526 			if (utimes(dst, tv) == -1)
   1527 				error("Can't set times on \"%s\": %s",
   1528 				    dst, strerror(errno));
   1529 		} else
   1530 			debug("Server did not send times for directory "
   1531 			    "\"%s\"", dst);
   1532 	}
   1533 
   1534 	free_sftp_dirents(dir_entries);
   1535 
   1536 	return ret;
   1537 }
   1538 
   1539 int
   1540 download_dir(struct sftp_conn *conn, const char *src, const char *dst,
   1541     Attrib *dirattrib, int preserve_flag, int print_flag, int resume_flag,
   1542     int fsync_flag)
   1543 {
   1544 	char *src_canon;
   1545 	int ret;
   1546 
   1547 	if ((src_canon = do_realpath(conn, src)) == NULL) {
   1548 		error("Unable to canonicalize path \"%s\"", src);
   1549 		return -1;
   1550 	}
   1551 
   1552 	ret = download_dir_internal(conn, src_canon, dst, 0,
   1553 	    dirattrib, preserve_flag, print_flag, resume_flag, fsync_flag);
   1554 	free(src_canon);
   1555 	return ret;
   1556 }
   1557 
   1558 int
   1559 do_upload(struct sftp_conn *conn, const char *local_path,
   1560     const char *remote_path, int preserve_flag, int resume, int fsync_flag)
   1561 {
   1562 	int r, local_fd;
   1563 	u_int status = SSH2_FX_OK;
   1564 	u_int id;
   1565 	u_char type;
   1566 	off_t offset, progress_counter;
   1567 	u_char *handle, *data;
   1568 	struct sshbuf *msg;
   1569 	struct stat sb;
   1570 	Attrib a, *c = NULL;
   1571 	u_int32_t startid;
   1572 	u_int32_t ackid;
   1573 	struct outstanding_ack {
   1574 		u_int id;
   1575 		u_int len;
   1576 		off_t offset;
   1577 		TAILQ_ENTRY(outstanding_ack) tq;
   1578 	};
   1579 	TAILQ_HEAD(ackhead, outstanding_ack) acks;
   1580 	struct outstanding_ack *ack = NULL;
   1581 	size_t handle_len;
   1582 
   1583 	TAILQ_INIT(&acks);
   1584 
   1585 	if ((local_fd = open(local_path, O_RDONLY, 0)) == -1) {
   1586 		error("Couldn't open local file \"%s\" for reading: %s",
   1587 		    local_path, strerror(errno));
   1588 		return(-1);
   1589 	}
   1590 	if (fstat(local_fd, &sb) == -1) {
   1591 		error("Couldn't fstat local file \"%s\": %s",
   1592 		    local_path, strerror(errno));
   1593 		close(local_fd);
   1594 		return(-1);
   1595 	}
   1596 	if (!S_ISREG(sb.st_mode)) {
   1597 		error("%s is not a regular file", local_path);
   1598 		close(local_fd);
   1599 		return(-1);
   1600 	}
   1601 	stat_to_attrib(&sb, &a);
   1602 
   1603 	a.flags &= ~SSH2_FILEXFER_ATTR_SIZE;
   1604 	a.flags &= ~SSH2_FILEXFER_ATTR_UIDGID;
   1605 	a.perm &= 0777;
   1606 	if (!preserve_flag)
   1607 		a.flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME;
   1608 
   1609 	if (resume) {
   1610 		/* Get remote file size if it exists */
   1611 		if ((c = do_stat(conn, remote_path, 0)) == NULL) {
   1612 			close(local_fd);
   1613 			return -1;
   1614 		}
   1615 
   1616 		if ((off_t)c->size >= sb.st_size) {
   1617 			error("destination file bigger or same size as "
   1618 			      "source file");
   1619 			close(local_fd);
   1620 			return -1;
   1621 		}
   1622 
   1623 		if (lseek(local_fd, (off_t)c->size, SEEK_SET) == -1) {
   1624 			close(local_fd);
   1625 			return -1;
   1626 		}
   1627 	}
   1628 
   1629 	if ((msg = sshbuf_new()) == NULL)
   1630 		fatal("%s: sshbuf_new failed", __func__);
   1631 
   1632 	/* Send open request */
   1633 	id = conn->msg_id++;
   1634 	if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPEN)) != 0 ||
   1635 	    (r = sshbuf_put_u32(msg, id)) != 0 ||
   1636 	    (r = sshbuf_put_cstring(msg, remote_path)) != 0 ||
   1637 	    (r = sshbuf_put_u32(msg, SSH2_FXF_WRITE|SSH2_FXF_CREAT|
   1638 	    (resume ? SSH2_FXF_APPEND : SSH2_FXF_TRUNC))) != 0 ||
   1639 	    (r = encode_attrib(msg, &a)) != 0)
   1640 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
   1641 	send_msg(conn, msg);
   1642 	debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, remote_path);
   1643 
   1644 	sshbuf_reset(msg);
   1645 
   1646 	handle = get_handle(conn, id, &handle_len,
   1647 	    "remote open(\"%s\")", remote_path);
   1648 	if (handle == NULL) {
   1649 		close(local_fd);
   1650 		sshbuf_free(msg);
   1651 		return -1;
   1652 	}
   1653 
   1654 	startid = ackid = id + 1;
   1655 	data = xmalloc(conn->transfer_buflen);
   1656 
   1657 	/* Read from local and write to remote */
   1658 	offset = progress_counter = (resume ? c->size : 0);
   1659 	if (showprogress)
   1660 		start_progress_meter(local_path, sb.st_size,
   1661 		    &progress_counter);
   1662 
   1663 	for (;;) {
   1664 		int len;
   1665 
   1666 		/*
   1667 		 * Can't use atomicio here because it returns 0 on EOF,
   1668 		 * thus losing the last block of the file.
   1669 		 * Simulate an EOF on interrupt, allowing ACKs from the
   1670 		 * server to drain.
   1671 		 */
   1672 		if (interrupted || status != SSH2_FX_OK)
   1673 			len = 0;
   1674 		else do
   1675 			len = read(local_fd, data, conn->transfer_buflen);
   1676 		while ((len == -1) &&
   1677 		    (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
   1678 
   1679 		if (len == -1)
   1680 			fatal("Couldn't read from \"%s\": %s", local_path,
   1681 			    strerror(errno));
   1682 
   1683 		if (len != 0) {
   1684 			ack = xcalloc(1, sizeof(*ack));
   1685 			ack->id = ++id;
   1686 			ack->offset = offset;
   1687 			ack->len = len;
   1688 			TAILQ_INSERT_TAIL(&acks, ack, tq);
   1689 
   1690 			sshbuf_reset(msg);
   1691 			if ((r = sshbuf_put_u8(msg, SSH2_FXP_WRITE)) != 0 ||
   1692 			    (r = sshbuf_put_u32(msg, ack->id)) != 0 ||
   1693 			    (r = sshbuf_put_string(msg, handle,
   1694 			    handle_len)) != 0 ||
   1695 			    (r = sshbuf_put_u64(msg, offset)) != 0 ||
   1696 			    (r = sshbuf_put_string(msg, data, len)) != 0)
   1697 				fatal("%s: buffer error: %s",
   1698 				    __func__, ssh_err(r));
   1699 			send_msg(conn, msg);
   1700 			debug3("Sent message SSH2_FXP_WRITE I:%u O:%llu S:%u",
   1701 			    id, (unsigned long long)offset, len);
   1702 		} else if (TAILQ_FIRST(&acks) == NULL)
   1703 			break;
   1704 
   1705 		if (ack == NULL)
   1706 			fatal("Unexpected ACK %u", id);
   1707 
   1708 		if (id == startid || len == 0 ||
   1709 		    id - ackid >= conn->num_requests) {
   1710 			u_int rid;
   1711 
   1712 			sshbuf_reset(msg);
   1713 			get_msg(conn, msg);
   1714 			if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
   1715 			    (r = sshbuf_get_u32(msg, &rid)) != 0)
   1716 				fatal("%s: buffer error: %s",
   1717 				    __func__, ssh_err(r));
   1718 
   1719 			if (type != SSH2_FXP_STATUS)
   1720 				fatal("Expected SSH2_FXP_STATUS(%d) packet, "
   1721 				    "got %d", SSH2_FXP_STATUS, type);
   1722 
   1723 			if ((r = sshbuf_get_u32(msg, &status)) != 0)
   1724 				fatal("%s: buffer error: %s",
   1725 				    __func__, ssh_err(r));
   1726 			debug3("SSH2_FXP_STATUS %u", status);
   1727 
   1728 			/* Find the request in our queue */
   1729 			for (ack = TAILQ_FIRST(&acks);
   1730 			    ack != NULL && ack->id != rid;
   1731 			    ack = TAILQ_NEXT(ack, tq))
   1732 				;
   1733 			if (ack == NULL)
   1734 				fatal("Can't find request for ID %u", rid);
   1735 			TAILQ_REMOVE(&acks, ack, tq);
   1736 			debug3("In write loop, ack for %u %u bytes at %lld",
   1737 			    ack->id, ack->len, (long long)ack->offset);
   1738 			++ackid;
   1739 			progress_counter += ack->len;
   1740 			free(ack);
   1741 		}
   1742 		offset += len;
   1743 		if (offset < 0)
   1744 			fatal("%s: offset < 0", __func__);
   1745 	}
   1746 	sshbuf_free(msg);
   1747 
   1748 	if (showprogress)
   1749 		stop_progress_meter();
   1750 	free(data);
   1751 
   1752 	if (status != SSH2_FX_OK) {
   1753 		error("Couldn't write to remote file \"%s\": %s",
   1754 		    remote_path, fx2txt(status));
   1755 		status = SSH2_FX_FAILURE;
   1756 	}
   1757 
   1758 	if (close(local_fd) == -1) {
   1759 		error("Couldn't close local file \"%s\": %s", local_path,
   1760 		    strerror(errno));
   1761 		status = SSH2_FX_FAILURE;
   1762 	}
   1763 
   1764 	/* Override umask and utimes if asked */
   1765 	if (preserve_flag)
   1766 		do_fsetstat(conn, handle, handle_len, &a);
   1767 
   1768 	if (fsync_flag)
   1769 		(void)do_fsync(conn, handle, handle_len);
   1770 
   1771 	if (do_close(conn, handle, handle_len) != 0)
   1772 		status = SSH2_FX_FAILURE;
   1773 
   1774 	free(handle);
   1775 
   1776 	return status == SSH2_FX_OK ? 0 : -1;
   1777 }
   1778 
   1779 static int
   1780 upload_dir_internal(struct sftp_conn *conn, const char *src, const char *dst,
   1781     int depth, int preserve_flag, int print_flag, int resume, int fsync_flag)
   1782 {
   1783 	int ret = 0;
   1784 	DIR *dirp;
   1785 	struct dirent *dp;
   1786 	char *filename, *new_src, *new_dst;
   1787 	struct stat sb;
   1788 	Attrib a, *dirattrib;
   1789 
   1790 	if (depth >= MAX_DIR_DEPTH) {
   1791 		error("Maximum directory depth exceeded: %d levels", depth);
   1792 		return -1;
   1793 	}
   1794 
   1795 	if (stat(src, &sb) == -1) {
   1796 		error("Couldn't stat directory \"%s\": %s",
   1797 		    src, strerror(errno));
   1798 		return -1;
   1799 	}
   1800 	if (!S_ISDIR(sb.st_mode)) {
   1801 		error("\"%s\" is not a directory", src);
   1802 		return -1;
   1803 	}
   1804 	if (print_flag)
   1805 		mprintf("Entering %s\n", src);
   1806 
   1807 	attrib_clear(&a);
   1808 	stat_to_attrib(&sb, &a);
   1809 	a.flags &= ~SSH2_FILEXFER_ATTR_SIZE;
   1810 	a.flags &= ~SSH2_FILEXFER_ATTR_UIDGID;
   1811 	a.perm &= 01777;
   1812 	if (!preserve_flag)
   1813 		a.flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME;
   1814 
   1815 	/*
   1816 	 * sftp lacks a portable status value to match errno EEXIST,
   1817 	 * so if we get a failure back then we must check whether
   1818 	 * the path already existed and is a directory.
   1819 	 */
   1820 	if (do_mkdir(conn, dst, &a, 0) != 0) {
   1821 		if ((dirattrib = do_stat(conn, dst, 0)) == NULL)
   1822 			return -1;
   1823 		if (!S_ISDIR(dirattrib->perm)) {
   1824 			error("\"%s\" exists but is not a directory", dst);
   1825 			return -1;
   1826 		}
   1827 	}
   1828 
   1829 	if ((dirp = opendir(src)) == NULL) {
   1830 		error("Failed to open dir \"%s\": %s", src, strerror(errno));
   1831 		return -1;
   1832 	}
   1833 
   1834 	while (((dp = readdir(dirp)) != NULL) && !interrupted) {
   1835 		if (dp->d_ino == 0)
   1836 			continue;
   1837 		filename = dp->d_name;
   1838 		new_dst = path_append(dst, filename);
   1839 		new_src = path_append(src, filename);
   1840 
   1841 		if (lstat(new_src, &sb) == -1) {
   1842 			logit("%s: lstat failed: %s", filename,
   1843 			    strerror(errno));
   1844 			ret = -1;
   1845 		} else if (S_ISDIR(sb.st_mode)) {
   1846 			if (strcmp(filename, ".") == 0 ||
   1847 			    strcmp(filename, "..") == 0)
   1848 				continue;
   1849 
   1850 			if (upload_dir_internal(conn, new_src, new_dst,
   1851 			    depth + 1, preserve_flag, print_flag, resume,
   1852 			    fsync_flag) == -1)
   1853 				ret = -1;
   1854 		} else if (S_ISREG(sb.st_mode)) {
   1855 			if (do_upload(conn, new_src, new_dst,
   1856 			    preserve_flag, resume, fsync_flag) == -1) {
   1857 				error("Uploading of file %s to %s failed!",
   1858 				    new_src, new_dst);
   1859 				ret = -1;
   1860 			}
   1861 		} else
   1862 			logit("%s: not a regular file\n", filename);
   1863 		free(new_dst);
   1864 		free(new_src);
   1865 	}
   1866 
   1867 	do_setstat(conn, dst, &a);
   1868 
   1869 	(void) closedir(dirp);
   1870 	return ret;
   1871 }
   1872 
   1873 int
   1874 upload_dir(struct sftp_conn *conn, const char *src, const char *dst,
   1875     int preserve_flag, int print_flag, int resume, int fsync_flag)
   1876 {
   1877 	char *dst_canon;
   1878 	int ret;
   1879 
   1880 	if ((dst_canon = do_realpath(conn, dst)) == NULL) {
   1881 		error("Unable to canonicalize path \"%s\"", dst);
   1882 		return -1;
   1883 	}
   1884 
   1885 	ret = upload_dir_internal(conn, src, dst_canon, 0, preserve_flag,
   1886 	    print_flag, resume, fsync_flag);
   1887 
   1888 	free(dst_canon);
   1889 	return ret;
   1890 }
   1891 
   1892 char *
   1893 path_append(const char *p1, const char *p2)
   1894 {
   1895 	char *ret;
   1896 	size_t len = strlen(p1) + strlen(p2) + 2;
   1897 
   1898 	ret = xmalloc(len);
   1899 	strlcpy(ret, p1, len);
   1900 	if (p1[0] != '\0' && p1[strlen(p1) - 1] != '/')
   1901 		strlcat(ret, "/", len);
   1902 	strlcat(ret, p2, len);
   1903 
   1904 	return(ret);
   1905 }
   1906 
   1907