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