Home | History | Annotate | Line # | Download | only in dist
      1 /*	$NetBSD: sftp-client.c,v 1.40 2026/09/21 21:31:00 christos Exp $	*/
      2 /* $OpenBSD: sftp-client.c,v 1.186 2026/06/29 01:53:21 djm Exp $ */
      3 
      4 /*
      5  * Copyright (c) 2001-2004 Damien Miller <djm (at) openbsd.org>
      6  *
      7  * Permission to use, copy, modify, and distribute this software for any
      8  * purpose with or without fee is hereby granted, provided that the above
      9  * copyright notice and this permission notice appear in all copies.
     10  *
     11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
     12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     18  */
     19 
     20 /* XXX: memleaks */
     21 /* XXX: signed vs unsigned */
     22 /* XXX: remove all logging, only return status codes */
     23 /* XXX: copy between two remote sites */
     24 
     25 #include "includes.h"
     26 __RCSID("$NetBSD: sftp-client.c,v 1.40 2026/09/21 21:31:00 christos Exp $");
     27 
     28 #include <sys/param.h>	/* MIN MAX */
     29 #include <sys/types.h>
     30 #include <sys/queue.h>
     31 #include <sys/stat.h>
     32 #include <sys/time.h>
     33 #include <sys/statvfs.h>
     34 #include <sys/uio.h>
     35 
     36 #include <dirent.h>
     37 #include <errno.h>
     38 #include <fcntl.h>
     39 #include <poll.h>
     40 #include <signal.h>
     41 #include <stdarg.h>
     42 #include <stdio.h>
     43 #include <stdlib.h>
     44 #include <string.h>
     45 #include <unistd.h>
     46 
     47 #include "xmalloc.h"
     48 #include "ssherr.h"
     49 #include "sshbuf.h"
     50 #include "log.h"
     51 #include "atomicio.h"
     52 #include "progressmeter.h"
     53 #include "misc.h"
     54 #include "utf8.h"
     55 
     56 #include "sftp.h"
     57 #include "sftp-common.h"
     58 #include "sftp-client.h"
     59 
     60 extern volatile sig_atomic_t interrupted;
     61 extern int showprogress;
     62 
     63 /* Default size of buffer for up/download (fix sftp.1 scp.1 if changed) */
     64 #define DEFAULT_COPY_BUFLEN	32768
     65 
     66 /* Default number of concurrent xfer requests (fix sftp.1 scp.1 if changed) */
     67 #define DEFAULT_NUM_REQUESTS	64
     68 
     69 /* Minimum amount of data to read at a time */
     70 #define MIN_READ_SIZE	512
     71 
     72 /* Maximum depth to descend in directory trees */
     73 #define MAX_DIR_DEPTH 64
     74 
     75 struct sftp_conn {
     76 	int fd_in;
     77 	int fd_out;
     78 	u_int download_buflen;
     79 	u_int upload_buflen;
     80 	u_int num_requests;
     81 	u_int version;
     82 	u_int msg_id;
     83 #define SFTP_EXT_POSIX_RENAME		0x00000001
     84 #define SFTP_EXT_STATVFS		0x00000002
     85 #define SFTP_EXT_FSTATVFS		0x00000004
     86 #define SFTP_EXT_HARDLINK		0x00000008
     87 #define SFTP_EXT_FSYNC			0x00000010
     88 #define SFTP_EXT_LSETSTAT		0x00000020
     89 #define SFTP_EXT_LIMITS			0x00000040
     90 #define SFTP_EXT_PATH_EXPAND		0x00000080
     91 #define SFTP_EXT_COPY_DATA		0x00000100
     92 #define SFTP_EXT_GETUSERSGROUPS_BY_ID	0x00000200
     93 	u_int exts;
     94 	uint64_t limit_kbps;
     95 	struct bwlimit bwlimit_in, bwlimit_out;
     96 };
     97 
     98 /* Tracks in-progress requests during file transfers */
     99 struct request {
    100 	u_int id;
    101 	size_t len;
    102 	uint64_t offset;
    103 	TAILQ_ENTRY(request) tq;
    104 };
    105 TAILQ_HEAD(requests, request);
    106 
    107 static u_char *
    108 get_handle(struct sftp_conn *conn, u_int expected_id, size_t *len,
    109     const char *errfmt, ...) __attribute__((format(printf, 4, 5)));
    110 
    111 static struct request *
    112 request_enqueue(struct requests *requests, u_int id, size_t len,
    113     uint64_t offset)
    114 {
    115 	struct request *req;
    116 
    117 	req = xcalloc(1, sizeof(*req));
    118 	req->id = id;
    119 	req->len = len;
    120 	req->offset = offset;
    121 	TAILQ_INSERT_TAIL(requests, req, tq);
    122 	return req;
    123 }
    124 
    125 static struct request *
    126 request_find(struct requests *requests, u_int id)
    127 {
    128 	struct request *req;
    129 
    130 	for (req = TAILQ_FIRST(requests);
    131 	    req != NULL && req->id != id;
    132 	    req = TAILQ_NEXT(req, tq))
    133 		;
    134 	return req;
    135 }
    136 
    137 static int
    138 sftpio(void *_bwlimit, size_t amount)
    139 {
    140 	struct bwlimit *bwlimit = (struct bwlimit *)_bwlimit;
    141 
    142 	refresh_progress_meter(0);
    143 	if (bwlimit != NULL)
    144 		bandwidth_limit(bwlimit, amount);
    145 	return 0;
    146 }
    147 
    148 static void
    149 send_msg(struct sftp_conn *conn, struct sshbuf *m)
    150 {
    151 	u_char mlen[4];
    152 	struct iovec iov[2];
    153 
    154 	if (sshbuf_len(m) > SFTP_MAX_MSG_LENGTH)
    155 		fatal("Outbound message too long %zu", sshbuf_len(m));
    156 
    157 	/* Send length first */
    158 	put_u32(mlen, sshbuf_len(m));
    159 	iov[0].iov_base = mlen;
    160 	iov[0].iov_len = sizeof(mlen);
    161 	iov[1].iov_base = __UNCONST(sshbuf_ptr(m));
    162 	iov[1].iov_len = sshbuf_len(m);
    163 
    164 	if (atomiciov6(writev, conn->fd_out, iov, 2, sftpio,
    165 	    conn->limit_kbps > 0 ? &conn->bwlimit_out : NULL) !=
    166 	    sshbuf_len(m) + sizeof(mlen))
    167 		fatal("Couldn't send packet: %s", strerror(errno));
    168 
    169 	sshbuf_reset(m);
    170 }
    171 
    172 static void
    173 get_msg_extended(struct sftp_conn *conn, struct sshbuf *m, int initial)
    174 {
    175 	u_int msg_len;
    176 	u_char *p;
    177 	int r;
    178 
    179 	sshbuf_reset(m);
    180 	if ((r = sshbuf_reserve(m, 4, &p)) != 0)
    181 		fatal_fr(r, "reserve");
    182 	if (atomicio6(read, conn->fd_in, p, 4, sftpio,
    183 	    conn->limit_kbps > 0 ? &conn->bwlimit_in : NULL) != 4) {
    184 		if (errno == EPIPE || errno == ECONNRESET)
    185 			fatal("Connection closed");
    186 		else
    187 			fatal("Couldn't read packet: %s", strerror(errno));
    188 	}
    189 
    190 	if ((r = sshbuf_get_u32(m, &msg_len)) != 0)
    191 		fatal_fr(r, "sshbuf_get_u32");
    192 	if (msg_len > SFTP_MAX_MSG_LENGTH) {
    193 		do_log2(initial ? SYSLOG_LEVEL_ERROR : SYSLOG_LEVEL_FATAL,
    194 		    "Received message too long %u", msg_len);
    195 		fatal("Ensure the remote shell produces no output "
    196 		    "for non-interactive sessions.");
    197 	}
    198 
    199 	if ((r = sshbuf_reserve(m, msg_len, &p)) != 0)
    200 		fatal_fr(r, "reserve");
    201 	if (atomicio6(read, conn->fd_in, p, msg_len, sftpio,
    202 	    conn->limit_kbps > 0 ? &conn->bwlimit_in : NULL)
    203 	    != msg_len) {
    204 		if (errno == EPIPE)
    205 			fatal("Connection closed");
    206 		else
    207 			fatal("Read packet: %s", strerror(errno));
    208 	}
    209 }
    210 
    211 static void
    212 get_msg(struct sftp_conn *conn, struct sshbuf *m)
    213 {
    214 	get_msg_extended(conn, m, 0);
    215 }
    216 
    217 static void
    218 send_string_request(struct sftp_conn *conn, u_int id, u_int code, const char *s,
    219     u_int len)
    220 {
    221 	struct sshbuf *msg;
    222 	int r;
    223 
    224 	if ((msg = sshbuf_new()) == NULL)
    225 		fatal_f("sshbuf_new failed");
    226 	if ((r = sshbuf_put_u8(msg, code)) != 0 ||
    227 	    (r = sshbuf_put_u32(msg, id)) != 0 ||
    228 	    (r = sshbuf_put_string(msg, s, len)) != 0)
    229 		fatal_fr(r, "compose");
    230 	send_msg(conn, msg);
    231 	debug3("Sent message fd %d T:%u I:%u", conn->fd_out, code, id);
    232 	sshbuf_free(msg);
    233 }
    234 
    235 static void
    236 send_string_attrs_request(struct sftp_conn *conn, u_int id, u_int code,
    237     const void *s, u_int len, Attrib *a)
    238 {
    239 	struct sshbuf *msg;
    240 	int r;
    241 
    242 	if ((msg = sshbuf_new()) == NULL)
    243 		fatal_f("sshbuf_new failed");
    244 	if ((r = sshbuf_put_u8(msg, code)) != 0 ||
    245 	    (r = sshbuf_put_u32(msg, id)) != 0 ||
    246 	    (r = sshbuf_put_string(msg, s, len)) != 0 ||
    247 	    (r = encode_attrib(msg, a)) != 0)
    248 		fatal_fr(r, "compose");
    249 	send_msg(conn, msg);
    250 	debug3("Sent message fd %d T:%u I:%u F:0x%04x M:%05o",
    251 	    conn->fd_out, code, id, a->flags, a->perm);
    252 	sshbuf_free(msg);
    253 }
    254 
    255 static u_int
    256 get_status(struct sftp_conn *conn, u_int expected_id)
    257 {
    258 	struct sshbuf *msg;
    259 	u_char type;
    260 	u_int id, status;
    261 	int r;
    262 
    263 	if ((msg = sshbuf_new()) == NULL)
    264 		fatal_f("sshbuf_new failed");
    265 	get_msg(conn, msg);
    266 	if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
    267 	    (r = sshbuf_get_u32(msg, &id)) != 0)
    268 		fatal_fr(r, "compose");
    269 
    270 	if (id != expected_id)
    271 		fatal("ID mismatch (%u != %u)", id, expected_id);
    272 	if (type != SSH2_FXP_STATUS)
    273 		fatal("Expected SSH2_FXP_STATUS(%u) packet, got %u",
    274 		    SSH2_FXP_STATUS, type);
    275 
    276 	if ((r = sshbuf_get_u32(msg, &status)) != 0)
    277 		fatal_fr(r, "parse");
    278 	sshbuf_free(msg);
    279 
    280 	debug3("SSH2_FXP_STATUS %u", status);
    281 
    282 	return status;
    283 }
    284 
    285 static u_char *
    286 get_handle(struct sftp_conn *conn, u_int expected_id, size_t *len,
    287     const char *errfmt, ...)
    288 {
    289 	struct sshbuf *msg;
    290 	u_int id, status;
    291 	u_char type;
    292 	u_char *handle;
    293 	char errmsg[256];
    294 	va_list args;
    295 	int r;
    296 
    297 	va_start(args, errfmt);
    298 	if (errfmt != NULL)
    299 		vsnprintf(errmsg, sizeof(errmsg), errfmt, args);
    300 	va_end(args);
    301 
    302 	if ((msg = sshbuf_new()) == NULL)
    303 		fatal_f("sshbuf_new failed");
    304 	get_msg(conn, msg);
    305 	if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
    306 	    (r = sshbuf_get_u32(msg, &id)) != 0)
    307 		fatal_fr(r, "parse");
    308 
    309 	if (id != expected_id)
    310 		fatal("%s: ID mismatch (%u != %u)",
    311 		    errfmt == NULL ? __func__ : errmsg, id, expected_id);
    312 	if (type == SSH2_FXP_STATUS) {
    313 		if ((r = sshbuf_get_u32(msg, &status)) != 0)
    314 			fatal_fr(r, "parse status");
    315 		if (errfmt != NULL)
    316 			error("%s: %s", errmsg, fx2txt(status));
    317 		sshbuf_free(msg);
    318 		return(NULL);
    319 	} else if (type != SSH2_FXP_HANDLE)
    320 		fatal("%s: Expected SSH2_FXP_HANDLE(%u) packet, got %u",
    321 		    errfmt == NULL ? __func__ : errmsg, SSH2_FXP_HANDLE, type);
    322 
    323 	if ((r = sshbuf_get_string(msg, &handle, len)) != 0)
    324 		fatal_fr(r, "parse handle");
    325 	sshbuf_free(msg);
    326 
    327 	return handle;
    328 }
    329 
    330 static int
    331 get_decode_stat(struct sftp_conn *conn, u_int expected_id, int quiet, Attrib *a)
    332 {
    333 	struct sshbuf *msg;
    334 	u_int id;
    335 	u_char type;
    336 	int r;
    337 	Attrib attr;
    338 
    339 	if (a != NULL)
    340 		memset(a, '\0', sizeof(*a));
    341 	if ((msg = sshbuf_new()) == NULL)
    342 		fatal_f("sshbuf_new failed");
    343 	get_msg(conn, msg);
    344 
    345 	if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
    346 	    (r = sshbuf_get_u32(msg, &id)) != 0)
    347 		fatal_fr(r, "parse");
    348 
    349 	if (id != expected_id)
    350 		fatal("ID mismatch (%u != %u)", id, expected_id);
    351 	if (type == SSH2_FXP_STATUS) {
    352 		u_int status;
    353 
    354 		if ((r = sshbuf_get_u32(msg, &status)) != 0)
    355 			fatal_fr(r, "parse status");
    356 		if (quiet)
    357 			debug("stat remote: %s", fx2txt(status));
    358 		else
    359 			error("stat remote: %s", fx2txt(status));
    360 		sshbuf_free(msg);
    361 		return -1;
    362 	} else if (type != SSH2_FXP_ATTRS) {
    363 		fatal("Expected SSH2_FXP_ATTRS(%u) packet, got %u",
    364 		    SSH2_FXP_ATTRS, type);
    365 	}
    366 	if ((r = decode_attrib(msg, &attr)) != 0) {
    367 		error_fr(r, "decode_attrib");
    368 		sshbuf_free(msg);
    369 		return -1;
    370 	}
    371 	/* success */
    372 	if (a != NULL)
    373 		*a = attr;
    374 	debug3("Received stat reply T:%u I:%u F:0x%04x M:%05o",
    375 	    type, id, attr.flags, attr.perm);
    376 	sshbuf_free(msg);
    377 
    378 	return 0;
    379 }
    380 
    381 static int
    382 get_decode_statvfs(struct sftp_conn *conn, struct sftp_statvfs *st,
    383     u_int expected_id, int quiet)
    384 {
    385 	struct sshbuf *msg;
    386 	u_char type;
    387 	u_int id;
    388 	uint64_t flag;
    389 	int r;
    390 
    391 	if ((msg = sshbuf_new()) == NULL)
    392 		fatal_f("sshbuf_new failed");
    393 	get_msg(conn, msg);
    394 
    395 	if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
    396 	    (r = sshbuf_get_u32(msg, &id)) != 0)
    397 		fatal_fr(r, "parse");
    398 
    399 	debug3("Received statvfs reply T:%u I:%u", type, id);
    400 	if (id != expected_id)
    401 		fatal("ID mismatch (%u != %u)", id, expected_id);
    402 	if (type == SSH2_FXP_STATUS) {
    403 		u_int status;
    404 
    405 		if ((r = sshbuf_get_u32(msg, &status)) != 0)
    406 			fatal_fr(r, "parse status");
    407 		if (quiet)
    408 			debug("remote statvfs: %s", fx2txt(status));
    409 		else
    410 			error("remote statvfs: %s", fx2txt(status));
    411 		sshbuf_free(msg);
    412 		return -1;
    413 	} else if (type != SSH2_FXP_EXTENDED_REPLY) {
    414 		fatal("Expected SSH2_FXP_EXTENDED_REPLY(%u) packet, got %u",
    415 		    SSH2_FXP_EXTENDED_REPLY, type);
    416 	}
    417 
    418 	memset(st, 0, sizeof(*st));
    419 	if ((r = sshbuf_get_u64(msg, &st->f_bsize)) != 0 ||
    420 	    (r = sshbuf_get_u64(msg, &st->f_frsize)) != 0 ||
    421 	    (r = sshbuf_get_u64(msg, &st->f_blocks)) != 0 ||
    422 	    (r = sshbuf_get_u64(msg, &st->f_bfree)) != 0 ||
    423 	    (r = sshbuf_get_u64(msg, &st->f_bavail)) != 0 ||
    424 	    (r = sshbuf_get_u64(msg, &st->f_files)) != 0 ||
    425 	    (r = sshbuf_get_u64(msg, &st->f_ffree)) != 0 ||
    426 	    (r = sshbuf_get_u64(msg, &st->f_favail)) != 0 ||
    427 	    (r = sshbuf_get_u64(msg, &st->f_fsid)) != 0 ||
    428 	    (r = sshbuf_get_u64(msg, &flag)) != 0 ||
    429 	    (r = sshbuf_get_u64(msg, &st->f_namemax)) != 0)
    430 		fatal_fr(r, "parse statvfs");
    431 
    432 	st->f_flag = (flag & SSH2_FXE_STATVFS_ST_RDONLY) ? ST_RDONLY : 0;
    433 	st->f_flag |= (flag & SSH2_FXE_STATVFS_ST_NOSUID) ? ST_NOSUID : 0;
    434 
    435 	sshbuf_free(msg);
    436 
    437 	return 0;
    438 }
    439 
    440 struct sftp_conn *
    441 sftp_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests,
    442     uint64_t limit_kbps)
    443 {
    444 	u_char type;
    445 	struct sshbuf *msg;
    446 	struct sftp_conn *ret;
    447 	int r;
    448 
    449 	ret = xcalloc(1, sizeof(*ret));
    450 	ret->msg_id = 1;
    451 	ret->fd_in = fd_in;
    452 	ret->fd_out = fd_out;
    453 	ret->download_buflen = ret->upload_buflen =
    454 	    transfer_buflen ? transfer_buflen : DEFAULT_COPY_BUFLEN;
    455 	ret->num_requests =
    456 	    num_requests ? num_requests : DEFAULT_NUM_REQUESTS;
    457 	ret->exts = 0;
    458 	ret->limit_kbps = 0;
    459 
    460 	if ((msg = sshbuf_new()) == NULL)
    461 		fatal_f("sshbuf_new failed");
    462 	if ((r = sshbuf_put_u8(msg, SSH2_FXP_INIT)) != 0 ||
    463 	    (r = sshbuf_put_u32(msg, SSH2_FILEXFER_VERSION)) != 0)
    464 		fatal_fr(r, "parse");
    465 
    466 	send_msg(ret, msg);
    467 
    468 	get_msg_extended(ret, msg, 1);
    469 
    470 	/* Expecting a VERSION reply */
    471 	if ((r = sshbuf_get_u8(msg, &type)) != 0)
    472 		fatal_fr(r, "parse type");
    473 	if (type != SSH2_FXP_VERSION) {
    474 		error("Invalid packet back from SSH2_FXP_INIT (type %u)",
    475 		    type);
    476 		sshbuf_free(msg);
    477 		free(ret);
    478 		return(NULL);
    479 	}
    480 	if ((r = sshbuf_get_u32(msg, &ret->version)) != 0)
    481 		fatal_fr(r, "parse version");
    482 
    483 	debug2("Remote version: %u", ret->version);
    484 
    485 	/* Check for extensions */
    486 	while (sshbuf_len(msg) > 0) {
    487 		char *name;
    488 		u_char *value;
    489 		size_t vlen;
    490 		int known = 0;
    491 
    492 		if ((r = sshbuf_get_cstring(msg, &name, NULL)) != 0 ||
    493 		    (r = sshbuf_get_string(msg, &value, &vlen)) != 0)
    494 			fatal_fr(r, "parse extension");
    495 		if (strcmp(name, "posix-rename (at) openssh.com") == 0 &&
    496 		    strcmp((char *)value, "1") == 0) {
    497 			ret->exts |= SFTP_EXT_POSIX_RENAME;
    498 			known = 1;
    499 		} else if (strcmp(name, "statvfs (at) openssh.com") == 0 &&
    500 		    strcmp((char *)value, "2") == 0) {
    501 			ret->exts |= SFTP_EXT_STATVFS;
    502 			known = 1;
    503 		} else if (strcmp(name, "fstatvfs (at) openssh.com") == 0 &&
    504 		    strcmp((char *)value, "2") == 0) {
    505 			ret->exts |= SFTP_EXT_FSTATVFS;
    506 			known = 1;
    507 		} else if (strcmp(name, "hardlink (at) openssh.com") == 0 &&
    508 		    strcmp((char *)value, "1") == 0) {
    509 			ret->exts |= SFTP_EXT_HARDLINK;
    510 			known = 1;
    511 		} else if (strcmp(name, "fsync (at) openssh.com") == 0 &&
    512 		    strcmp((char *)value, "1") == 0) {
    513 			ret->exts |= SFTP_EXT_FSYNC;
    514 			known = 1;
    515 		} else if (strcmp(name, "lsetstat (at) openssh.com") == 0 &&
    516 		    strcmp((char *)value, "1") == 0) {
    517 			ret->exts |= SFTP_EXT_LSETSTAT;
    518 			known = 1;
    519 		} else if (strcmp(name, "limits (at) openssh.com") == 0 &&
    520 		    strcmp((char *)value, "1") == 0) {
    521 			ret->exts |= SFTP_EXT_LIMITS;
    522 			known = 1;
    523 		} else if (strcmp(name, "expand-path (at) openssh.com") == 0 &&
    524 		    strcmp((char *)value, "1") == 0) {
    525 			ret->exts |= SFTP_EXT_PATH_EXPAND;
    526 			known = 1;
    527 		} else if (strcmp(name, "copy-data") == 0 &&
    528 		    strcmp((char *)value, "1") == 0) {
    529 			ret->exts |= SFTP_EXT_COPY_DATA;
    530 			known = 1;
    531 		} else if (strcmp(name,
    532 		    "users-groups-by-id (at) openssh.com") == 0 &&
    533 		    strcmp((char *)value, "1") == 0) {
    534 			ret->exts |= SFTP_EXT_GETUSERSGROUPS_BY_ID;
    535 			known = 1;
    536 		}
    537 		if (known) {
    538 			debug2("Server supports extension \"%s\" revision %s",
    539 			    name, value);
    540 		} else {
    541 			debug2("Unrecognised server extension \"%s\"", name);
    542 		}
    543 		free(name);
    544 		free(value);
    545 	}
    546 
    547 	sshbuf_free(msg);
    548 
    549 	/* Query the server for its limits */
    550 	if (ret->exts & SFTP_EXT_LIMITS) {
    551 		struct sftp_limits limits;
    552 		if (sftp_get_limits(ret, &limits) != 0)
    553 			fatal_f("limits failed");
    554 
    555 		/* If the caller did not specify, find a good value */
    556 		if (transfer_buflen == 0) {
    557 			ret->download_buflen = MINIMUM(limits.read_length,
    558 			    SFTP_MAX_MSG_LENGTH - 1024);
    559 			ret->upload_buflen = MINIMUM(limits.write_length,
    560 			    SFTP_MAX_MSG_LENGTH - 1024);
    561 			ret->download_buflen = MAXIMUM(ret->download_buflen, 64);
    562 			ret->upload_buflen = MAXIMUM(ret->upload_buflen, 64);
    563 			debug3("server upload/download buffer sizes "
    564 			    "%llu / %llu; using %u / %u",
    565 			    (unsigned long long)limits.write_length,
    566 			    (unsigned long long)limits.read_length,
    567 			    ret->upload_buflen, ret->download_buflen);
    568 		}
    569 	}
    570 
    571 	/* Some filexfer v.0 servers don't support large packets */
    572 	if (ret->version == 0) {
    573 		ret->download_buflen = MINIMUM(ret->download_buflen, 20480);
    574 		ret->upload_buflen = MINIMUM(ret->upload_buflen, 20480);
    575 	}
    576 
    577 	ret->limit_kbps = limit_kbps;
    578 	if (ret->limit_kbps > 0) {
    579 		bandwidth_limit_init(&ret->bwlimit_in, ret->limit_kbps,
    580 		    ret->download_buflen);
    581 		bandwidth_limit_init(&ret->bwlimit_out, ret->limit_kbps,
    582 		    ret->upload_buflen);
    583 	}
    584 
    585 	return ret;
    586 }
    587 
    588 void
    589 sftp_free(struct sftp_conn *conn)
    590 {
    591 	if (conn == NULL)
    592 		return;
    593 	freezero(conn, sizeof(*conn));
    594 }
    595 
    596 u_int
    597 sftp_proto_version(struct sftp_conn *conn)
    598 {
    599 	return conn->version;
    600 }
    601 
    602 int
    603 sftp_get_limits(struct sftp_conn *conn, struct sftp_limits *limits)
    604 {
    605 	u_int id, msg_id;
    606 	u_char type;
    607 	struct sshbuf *msg;
    608 	int r;
    609 
    610 	if ((conn->exts & SFTP_EXT_LIMITS) == 0) {
    611 		error("Server does not support limits (at) openssh.com extension");
    612 		return -1;
    613 	}
    614 
    615 	if ((msg = sshbuf_new()) == NULL)
    616 		fatal_f("sshbuf_new failed");
    617 
    618 	id = conn->msg_id++;
    619 	if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
    620 	    (r = sshbuf_put_u32(msg, id)) != 0 ||
    621 	    (r = sshbuf_put_cstring(msg, "limits (at) openssh.com")) != 0)
    622 		fatal_fr(r, "compose");
    623 	send_msg(conn, msg);
    624 	debug3("Sent message limits (at) openssh.com I:%u", id);
    625 
    626 	get_msg(conn, msg);
    627 
    628 	if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
    629 	    (r = sshbuf_get_u32(msg, &msg_id)) != 0)
    630 		fatal_fr(r, "parse");
    631 
    632 	debug3("Received limits reply T:%u I:%u", type, msg_id);
    633 	if (id != msg_id)
    634 		fatal("ID mismatch (%u != %u)", msg_id, id);
    635 	if (type != SSH2_FXP_EXTENDED_REPLY) {
    636 		debug_f("expected SSH2_FXP_EXTENDED_REPLY(%u) packet, got %u",
    637 		    SSH2_FXP_EXTENDED_REPLY, type);
    638 		/* Disable the limits extension */
    639 		conn->exts &= ~SFTP_EXT_LIMITS;
    640 		sshbuf_free(msg);
    641 		return -1;
    642 	}
    643 
    644 	memset(limits, 0, sizeof(*limits));
    645 	if ((r = sshbuf_get_u64(msg, &limits->packet_length)) != 0 ||
    646 	    (r = sshbuf_get_u64(msg, &limits->read_length)) != 0 ||
    647 	    (r = sshbuf_get_u64(msg, &limits->write_length)) != 0 ||
    648 	    (r = sshbuf_get_u64(msg, &limits->open_handles)) != 0)
    649 		fatal_fr(r, "parse limits");
    650 
    651 	sshbuf_free(msg);
    652 
    653 	return 0;
    654 }
    655 
    656 int
    657 sftp_close(struct sftp_conn *conn, const u_char *handle, u_int handle_len)
    658 {
    659 	u_int id, status;
    660 	struct sshbuf *msg;
    661 	int r;
    662 
    663 	if ((msg = sshbuf_new()) == NULL)
    664 		fatal_f("sshbuf_new failed");
    665 
    666 	id = conn->msg_id++;
    667 	if ((r = sshbuf_put_u8(msg, SSH2_FXP_CLOSE)) != 0 ||
    668 	    (r = sshbuf_put_u32(msg, id)) != 0 ||
    669 	    (r = sshbuf_put_string(msg, handle, handle_len)) != 0)
    670 		fatal_fr(r, "parse");
    671 	send_msg(conn, msg);
    672 	debug3("Sent message SSH2_FXP_CLOSE I:%u", id);
    673 
    674 	status = get_status(conn, id);
    675 	if (status != SSH2_FX_OK)
    676 		error("close remote: %s", fx2txt(status));
    677 
    678 	sshbuf_free(msg);
    679 
    680 	return status == SSH2_FX_OK ? 0 : -1;
    681 }
    682 
    683 
    684 static int
    685 sftp_lsreaddir(struct sftp_conn *conn, const char *path, int print_flag,
    686     SFTP_DIRENT ***dir)
    687 {
    688 	struct sshbuf *msg;
    689 	u_int count, id, i, expected_id, ents = 0;
    690 	size_t handle_len;
    691 	u_char type, *handle;
    692 	int status = SSH2_FX_FAILURE;
    693 	int r;
    694 
    695 	if (dir)
    696 		*dir = NULL;
    697 
    698 	id = conn->msg_id++;
    699 
    700 	if ((msg = sshbuf_new()) == NULL)
    701 		fatal_f("sshbuf_new failed");
    702 	if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPENDIR)) != 0 ||
    703 	    (r = sshbuf_put_u32(msg, id)) != 0 ||
    704 	    (r = sshbuf_put_cstring(msg, path)) != 0)
    705 		fatal_fr(r, "compose OPENDIR");
    706 	send_msg(conn, msg);
    707 
    708 	handle = get_handle(conn, id, &handle_len,
    709 	    "remote readdir(\"%s\")", path);
    710 	if (handle == NULL) {
    711 		sshbuf_free(msg);
    712 		return -1;
    713 	}
    714 
    715 	if (dir) {
    716 		ents = 0;
    717 		*dir = xcalloc(1, sizeof(**dir));
    718 		(*dir)[0] = NULL;
    719 	}
    720 
    721 	for (; !interrupted;) {
    722 		id = expected_id = conn->msg_id++;
    723 
    724 		debug3("Sending SSH2_FXP_READDIR I:%u", id);
    725 
    726 		sshbuf_reset(msg);
    727 		if ((r = sshbuf_put_u8(msg, SSH2_FXP_READDIR)) != 0 ||
    728 		    (r = sshbuf_put_u32(msg, id)) != 0 ||
    729 		    (r = sshbuf_put_string(msg, handle, handle_len)) != 0)
    730 			fatal_fr(r, "compose READDIR");
    731 		send_msg(conn, msg);
    732 
    733 		sshbuf_reset(msg);
    734 
    735 		get_msg(conn, msg);
    736 
    737 		if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
    738 		    (r = sshbuf_get_u32(msg, &id)) != 0)
    739 			fatal_fr(r, "parse");
    740 
    741 		debug3("Received reply T:%u I:%u", type, id);
    742 
    743 		if (id != expected_id)
    744 			fatal("ID mismatch (%u != %u)", id, expected_id);
    745 
    746 		if (type == SSH2_FXP_STATUS) {
    747 			u_int rstatus;
    748 
    749 			if ((r = sshbuf_get_u32(msg, &rstatus)) != 0)
    750 				fatal_fr(r, "parse status");
    751 			debug3("Received SSH2_FXP_STATUS %d", rstatus);
    752 			if (rstatus == SSH2_FX_EOF)
    753 				break;
    754 			error("Couldn't read directory: %s", fx2txt(rstatus));
    755 			goto out;
    756 		} else if (type != SSH2_FXP_NAME)
    757 			fatal("Expected SSH2_FXP_NAME(%u) packet, got %u",
    758 			    SSH2_FXP_NAME, type);
    759 
    760 		if ((r = sshbuf_get_u32(msg, &count)) != 0)
    761 			fatal_fr(r, "parse count");
    762 		if (count > SSHBUF_SIZE_MAX)
    763 			fatal_f("nonsensical number of entries");
    764 		if (count == 0)
    765 			break;
    766 		debug3("Received %d SSH2_FXP_NAME responses", count);
    767 		for (i = 0; i < count; i++) {
    768 			char *filename, *longname;
    769 			Attrib a;
    770 
    771 			if ((r = sshbuf_get_cstring(msg, &filename,
    772 			    NULL)) != 0 ||
    773 			    (r = sshbuf_get_cstring(msg, &longname,
    774 			    NULL)) != 0)
    775 				fatal_fr(r, "parse filenames");
    776 			if ((r = decode_attrib(msg, &a)) != 0) {
    777 				error_fr(r, "couldn't decode attrib");
    778 				free(filename);
    779 				free(longname);
    780 				goto out;
    781 			}
    782 
    783 			if (print_flag)
    784 				mprintf("%s\n", longname);
    785 
    786 			/*
    787 			 * Directory entries should never contain '/'
    788 			 * These can be used to attack recursive ops
    789 			 * (e.g. send '../../../../etc/passwd')
    790 			 */
    791 			if (strchr(filename, '/') != NULL) {
    792 				error("Server sent suspect path \"%s\" "
    793 				    "during readdir of \"%s\"", filename, path);
    794 			} else if (dir) {
    795 				*dir = xreallocarray(*dir, ents + 2, sizeof(**dir));
    796 				(*dir)[ents] = xcalloc(1, sizeof(***dir));
    797 				(*dir)[ents]->filename = xstrdup(filename);
    798 				(*dir)[ents]->longname = xstrdup(longname);
    799 				memcpy(&(*dir)[ents]->a, &a, sizeof(a));
    800 				(*dir)[++ents] = NULL;
    801 			}
    802 			free(filename);
    803 			free(longname);
    804 		}
    805 	}
    806 	status = 0;
    807 
    808  out:
    809 	sshbuf_free(msg);
    810 	sftp_close(conn, handle, handle_len);
    811 	free(handle);
    812 
    813 	if (status != 0 && dir != NULL) {
    814 		/* Don't return results on error */
    815 		sftp_free_dirents(*dir);
    816 		*dir = NULL;
    817 	} else if (interrupted && dir != NULL && *dir != NULL) {
    818 		/* Don't return partial matches on interrupt */
    819 		sftp_free_dirents(*dir);
    820 		*dir = xcalloc(1, sizeof(**dir));
    821 		**dir = NULL;
    822 	}
    823 
    824 	return status == SSH2_FX_OK ? 0 : -1;
    825 }
    826 
    827 int
    828 sftp_readdir(struct sftp_conn *conn, const char *path, SFTP_DIRENT ***dir)
    829 {
    830 	return sftp_lsreaddir(conn, path, 0, dir);
    831 }
    832 
    833 void sftp_free_dirents(SFTP_DIRENT **s)
    834 {
    835 	int i;
    836 
    837 	if (s == NULL)
    838 		return;
    839 	for (i = 0; s[i]; i++) {
    840 		free(s[i]->filename);
    841 		free(s[i]->longname);
    842 		free(s[i]);
    843 	}
    844 	free(s);
    845 }
    846 
    847 int
    848 sftp_rm(struct sftp_conn *conn, const char *path)
    849 {
    850 	u_int status, id;
    851 
    852 	debug2("Sending SSH2_FXP_REMOVE \"%s\"", path);
    853 
    854 	id = conn->msg_id++;
    855 	send_string_request(conn, id, SSH2_FXP_REMOVE, path, strlen(path));
    856 	status = get_status(conn, id);
    857 	if (status != SSH2_FX_OK)
    858 		error("remote delete %s: %s", path, fx2txt(status));
    859 	return status == SSH2_FX_OK ? 0 : -1;
    860 }
    861 
    862 int
    863 sftp_mkdir(struct sftp_conn *conn, const char *path, Attrib *a, int print_flag)
    864 {
    865 	u_int status, id;
    866 
    867 	debug2("Sending SSH2_FXP_MKDIR \"%s\"", path);
    868 
    869 	id = conn->msg_id++;
    870 	send_string_attrs_request(conn, id, SSH2_FXP_MKDIR, path,
    871 	    strlen(path), a);
    872 
    873 	status = get_status(conn, id);
    874 	if (status != SSH2_FX_OK && print_flag)
    875 		error("remote mkdir \"%s\": %s", path, fx2txt(status));
    876 
    877 	return status == SSH2_FX_OK ? 0 : -1;
    878 }
    879 
    880 int
    881 sftp_rmdir(struct sftp_conn *conn, const char *path)
    882 {
    883 	u_int status, id;
    884 
    885 	debug2("Sending SSH2_FXP_RMDIR \"%s\"", path);
    886 
    887 	id = conn->msg_id++;
    888 	send_string_request(conn, id, SSH2_FXP_RMDIR, path,
    889 	    strlen(path));
    890 
    891 	status = get_status(conn, id);
    892 	if (status != SSH2_FX_OK)
    893 		error("remote rmdir \"%s\": %s", path, fx2txt(status));
    894 
    895 	return status == SSH2_FX_OK ? 0 : -1;
    896 }
    897 
    898 int
    899 sftp_stat(struct sftp_conn *conn, const char *path, int quiet, Attrib *a)
    900 {
    901 	u_int id;
    902 
    903 	debug2("Sending SSH2_FXP_STAT \"%s\"", path);
    904 
    905 	id = conn->msg_id++;
    906 
    907 	send_string_request(conn, id,
    908 	    conn->version == 0 ? SSH2_FXP_STAT_VERSION_0 : SSH2_FXP_STAT,
    909 	    path, strlen(path));
    910 
    911 	return get_decode_stat(conn, id, quiet, a);
    912 }
    913 
    914 int
    915 sftp_lstat(struct sftp_conn *conn, const char *path, int quiet, Attrib *a)
    916 {
    917 	u_int id;
    918 
    919 	if (conn->version == 0) {
    920 		do_log2(quiet ? SYSLOG_LEVEL_DEBUG1 : SYSLOG_LEVEL_INFO,
    921 		    "Server version does not support lstat operation");
    922 		return sftp_stat(conn, path, quiet, a);
    923 	}
    924 
    925 	id = conn->msg_id++;
    926 	send_string_request(conn, id, SSH2_FXP_LSTAT, path,
    927 	    strlen(path));
    928 
    929 	return get_decode_stat(conn, id, quiet, a);
    930 }
    931 
    932 #ifdef notyet
    933 int
    934 sftp_fstat(struct sftp_conn *conn, const u_char *handle, u_int handle_len,
    935     int quiet, Attrib *a)
    936 {
    937 	u_int id;
    938 
    939 	debug2("Sending SSH2_FXP_FSTAT \"%s\"");
    940 
    941 	id = conn->msg_id++;
    942 	send_string_request(conn, id, SSH2_FXP_FSTAT, handle,
    943 	    handle_len);
    944 
    945 	return get_decode_stat(conn, id, quiet, a);
    946 }
    947 #endif
    948 
    949 int
    950 sftp_setstat(struct sftp_conn *conn, const char *path, Attrib *a)
    951 {
    952 	u_int status, id;
    953 
    954 	debug2("Sending SSH2_FXP_SETSTAT \"%s\"", path);
    955 
    956 	id = conn->msg_id++;
    957 	send_string_attrs_request(conn, id, SSH2_FXP_SETSTAT, path,
    958 	    strlen(path), a);
    959 
    960 	status = get_status(conn, id);
    961 	if (status != SSH2_FX_OK)
    962 		error("remote setstat \"%s\": %s", path, fx2txt(status));
    963 
    964 	return status == SSH2_FX_OK ? 0 : -1;
    965 }
    966 
    967 int
    968 sftp_fsetstat(struct sftp_conn *conn, const u_char *handle, u_int handle_len,
    969     Attrib *a)
    970 {
    971 	u_int status, id;
    972 
    973 	debug2("Sending SSH2_FXP_FSETSTAT");
    974 
    975 	id = conn->msg_id++;
    976 	send_string_attrs_request(conn, id, SSH2_FXP_FSETSTAT, handle,
    977 	    handle_len, a);
    978 
    979 	status = get_status(conn, id);
    980 	if (status != SSH2_FX_OK)
    981 		error("remote fsetstat: %s", fx2txt(status));
    982 
    983 	return status == SSH2_FX_OK ? 0 : -1;
    984 }
    985 
    986 /* Implements both the realpath and expand-path operations */
    987 static char *
    988 sftp_realpath_expand(struct sftp_conn *conn, const char *path, int expand)
    989 {
    990 	struct sshbuf *msg;
    991 	u_int expected_id, count, id;
    992 	char *filename, *longname;
    993 	Attrib a;
    994 	u_char type;
    995 	int r;
    996 	const char *what = "SSH2_FXP_REALPATH";
    997 
    998 	if (expand)
    999 		what = "expand-path (at) openssh.com";
   1000 	if ((msg = sshbuf_new()) == NULL)
   1001 		fatal_f("sshbuf_new failed");
   1002 
   1003 	expected_id = id = conn->msg_id++;
   1004 	if (expand) {
   1005 		debug2("Sending SSH2_FXP_EXTENDED(expand-path (at) openssh.com) "
   1006 		    "\"%s\"", path);
   1007 		if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
   1008 		    (r = sshbuf_put_u32(msg, id)) != 0 ||
   1009 		    (r = sshbuf_put_cstring(msg,
   1010 		    "expand-path (at) openssh.com")) != 0 ||
   1011 		    (r = sshbuf_put_cstring(msg, path)) != 0)
   1012 			fatal_fr(r, "compose %s", what);
   1013 		send_msg(conn, msg);
   1014 	} else {
   1015 		debug2("Sending SSH2_FXP_REALPATH \"%s\"", path);
   1016 		send_string_request(conn, id, SSH2_FXP_REALPATH,
   1017 		    path, strlen(path));
   1018 	}
   1019 	get_msg(conn, msg);
   1020 	if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
   1021 	    (r = sshbuf_get_u32(msg, &id)) != 0)
   1022 		fatal_fr(r, "parse");
   1023 
   1024 	if (id != expected_id)
   1025 		fatal("ID mismatch (%u != %u)", id, expected_id);
   1026 
   1027 	if (type == SSH2_FXP_STATUS) {
   1028 		u_int status;
   1029 		char *errmsg;
   1030 
   1031 		if ((r = sshbuf_get_u32(msg, &status)) != 0 ||
   1032 		    (r = sshbuf_get_cstring(msg, &errmsg, NULL)) != 0)
   1033 			fatal_fr(r, "parse status");
   1034 		error("%s %s: %s", expand ? "expand" : "realpath",
   1035 		    path, *errmsg == '\0' ? fx2txt(status) : errmsg);
   1036 		free(errmsg);
   1037 		sshbuf_free(msg);
   1038 		return NULL;
   1039 	} else if (type != SSH2_FXP_NAME)
   1040 		fatal("Expected SSH2_FXP_NAME(%u) packet, got %u",
   1041 		    SSH2_FXP_NAME, type);
   1042 
   1043 	if ((r = sshbuf_get_u32(msg, &count)) != 0)
   1044 		fatal_fr(r, "parse count");
   1045 	if (count != 1)
   1046 		fatal("Got multiple names (%d) from %s", count, what);
   1047 
   1048 	if ((r = sshbuf_get_cstring(msg, &filename, NULL)) != 0 ||
   1049 	    (r = sshbuf_get_cstring(msg, &longname, NULL)) != 0 ||
   1050 	    (r = decode_attrib(msg, &a)) != 0)
   1051 		fatal_fr(r, "parse filename/attrib");
   1052 
   1053 	debug3("%s %s -> %s", what, path, filename);
   1054 
   1055 	free(longname);
   1056 
   1057 	sshbuf_free(msg);
   1058 
   1059 	return(filename);
   1060 }
   1061 
   1062 char *
   1063 sftp_realpath(struct sftp_conn *conn, const char *path)
   1064 {
   1065 	return sftp_realpath_expand(conn, path, 0);
   1066 }
   1067 
   1068 int
   1069 sftp_can_expand_path(struct sftp_conn *conn)
   1070 {
   1071 	return (conn->exts & SFTP_EXT_PATH_EXPAND) != 0;
   1072 }
   1073 
   1074 char *
   1075 sftp_expand_path(struct sftp_conn *conn, const char *path)
   1076 {
   1077 	if (!sftp_can_expand_path(conn)) {
   1078 		debug3_f("no server support, fallback to realpath");
   1079 		return sftp_realpath_expand(conn, path, 0);
   1080 	}
   1081 	return sftp_realpath_expand(conn, path, 1);
   1082 }
   1083 
   1084 int
   1085 sftp_copy(struct sftp_conn *conn, const char *oldpath, const char *newpath)
   1086 {
   1087 	Attrib junk, attr;
   1088 	struct sshbuf *msg;
   1089 	u_char *old_handle, *new_handle;
   1090 	u_int mode, status, id;
   1091 	size_t old_handle_len, new_handle_len;
   1092 	int r;
   1093 
   1094 	/* Return if the extension is not supported */
   1095 	if ((conn->exts & SFTP_EXT_COPY_DATA) == 0) {
   1096 		error("Server does not support copy-data extension");
   1097 		return -1;
   1098 	}
   1099 
   1100 	/* Make sure the file exists, and we can copy its perms */
   1101 	if (sftp_stat(conn, oldpath, 0, &attr) != 0)
   1102 		return -1;
   1103 
   1104 	/* Do not preserve set[ug]id here, as we do not preserve ownership */
   1105 	if (attr.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) {
   1106 		mode = attr.perm & 0777;
   1107 
   1108 		if (!S_ISREG(attr.perm)) {
   1109 			error("Cannot copy non-regular file: %s", oldpath);
   1110 			return -1;
   1111 		}
   1112 	} else {
   1113 		/* NB: The user's umask will apply to this */
   1114 		mode = 0666;
   1115 	}
   1116 
   1117 	/* Set up the new perms for the new file */
   1118 	attrib_clear(&attr);
   1119 	attr.perm = mode;
   1120 	attr.flags |= SSH2_FILEXFER_ATTR_PERMISSIONS;
   1121 
   1122 	if ((msg = sshbuf_new()) == NULL)
   1123 		fatal_f("sshbuf_new failed");
   1124 
   1125 	attrib_clear(&junk); /* Send empty attributes */
   1126 
   1127 	/* Open the old file for reading */
   1128 	id = conn->msg_id++;
   1129 	if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPEN)) != 0 ||
   1130 	    (r = sshbuf_put_u32(msg, id)) != 0 ||
   1131 	    (r = sshbuf_put_cstring(msg, oldpath)) != 0 ||
   1132 	    (r = sshbuf_put_u32(msg, SSH2_FXF_READ)) != 0 ||
   1133 	    (r = encode_attrib(msg, &junk)) != 0)
   1134 		fatal_fr(r, "buffer error");
   1135 	send_msg(conn, msg);
   1136 	debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, oldpath);
   1137 
   1138 	sshbuf_reset(msg);
   1139 
   1140 	old_handle = get_handle(conn, id, &old_handle_len,
   1141 	    "remote open(\"%s\")", oldpath);
   1142 	if (old_handle == NULL) {
   1143 		sshbuf_free(msg);
   1144 		return -1;
   1145 	}
   1146 
   1147 	/* Open the new file for writing */
   1148 	id = conn->msg_id++;
   1149 	if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPEN)) != 0 ||
   1150 	    (r = sshbuf_put_u32(msg, id)) != 0 ||
   1151 	    (r = sshbuf_put_cstring(msg, newpath)) != 0 ||
   1152 	    (r = sshbuf_put_u32(msg, SSH2_FXF_WRITE|SSH2_FXF_CREAT|
   1153 	    SSH2_FXF_TRUNC)) != 0 ||
   1154 	    (r = encode_attrib(msg, &attr)) != 0)
   1155 		fatal_fr(r, "buffer error");
   1156 	send_msg(conn, msg);
   1157 	debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, newpath);
   1158 
   1159 	sshbuf_reset(msg);
   1160 
   1161 	new_handle = get_handle(conn, id, &new_handle_len,
   1162 	    "remote open(\"%s\")", newpath);
   1163 	if (new_handle == NULL) {
   1164 		sshbuf_free(msg);
   1165 		free(old_handle);
   1166 		return -1;
   1167 	}
   1168 
   1169 	/* Copy the file data */
   1170 	id = conn->msg_id++;
   1171 	if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
   1172 	    (r = sshbuf_put_u32(msg, id)) != 0 ||
   1173 	    (r = sshbuf_put_cstring(msg, "copy-data")) != 0 ||
   1174 	    (r = sshbuf_put_string(msg, old_handle, old_handle_len)) != 0 ||
   1175 	    (r = sshbuf_put_u64(msg, 0)) != 0 ||
   1176 	    (r = sshbuf_put_u64(msg, 0)) != 0 ||
   1177 	    (r = sshbuf_put_string(msg, new_handle, new_handle_len)) != 0 ||
   1178 	    (r = sshbuf_put_u64(msg, 0)) != 0)
   1179 		fatal_fr(r, "buffer error");
   1180 	send_msg(conn, msg);
   1181 	debug3("Sent message copy-data \"%s\" 0 0 -> \"%s\" 0",
   1182 	       oldpath, newpath);
   1183 
   1184 	status = get_status(conn, id);
   1185 	if (status != SSH2_FX_OK)
   1186 		error("Couldn't copy file \"%s\" to \"%s\": %s", oldpath,
   1187 		    newpath, fx2txt(status));
   1188 
   1189 	/* Clean up everything */
   1190 	sshbuf_free(msg);
   1191 	sftp_close(conn, old_handle, old_handle_len);
   1192 	sftp_close(conn, new_handle, new_handle_len);
   1193 	free(old_handle);
   1194 	free(new_handle);
   1195 
   1196 	return status == SSH2_FX_OK ? 0 : -1;
   1197 }
   1198 
   1199 int
   1200 sftp_rename(struct sftp_conn *conn, const char *oldpath, const char *newpath,
   1201     int force_legacy)
   1202 {
   1203 	struct sshbuf *msg;
   1204 	u_int status, id;
   1205 	int r, use_ext = (conn->exts & SFTP_EXT_POSIX_RENAME) && !force_legacy;
   1206 
   1207 	if ((msg = sshbuf_new()) == NULL)
   1208 		fatal_f("sshbuf_new failed");
   1209 
   1210 	/* Send rename request */
   1211 	id = conn->msg_id++;
   1212 	if (use_ext) {
   1213 		debug2("Sending SSH2_FXP_EXTENDED(posix-rename (at) openssh.com) "
   1214 		    "\"%s\" to \"%s\"", oldpath, newpath);
   1215 		if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
   1216 		    (r = sshbuf_put_u32(msg, id)) != 0 ||
   1217 		    (r = sshbuf_put_cstring(msg,
   1218 		    "posix-rename (at) openssh.com")) != 0)
   1219 			fatal_fr(r, "compose posix-rename");
   1220 	} else {
   1221 		debug2("Sending SSH2_FXP_RENAME \"%s\" to \"%s\"",
   1222 		    oldpath, newpath);
   1223 		if ((r = sshbuf_put_u8(msg, SSH2_FXP_RENAME)) != 0 ||
   1224 		    (r = sshbuf_put_u32(msg, id)) != 0)
   1225 			fatal_fr(r, "compose rename");
   1226 	}
   1227 	if ((r = sshbuf_put_cstring(msg, oldpath)) != 0 ||
   1228 	    (r = sshbuf_put_cstring(msg, newpath)) != 0)
   1229 		fatal_fr(r, "compose paths");
   1230 	send_msg(conn, msg);
   1231 	debug3("Sent message %s \"%s\" -> \"%s\"",
   1232 	    use_ext ? "posix-rename (at) openssh.com" :
   1233 	    "SSH2_FXP_RENAME", oldpath, newpath);
   1234 	sshbuf_free(msg);
   1235 
   1236 	status = get_status(conn, id);
   1237 	if (status != SSH2_FX_OK)
   1238 		error("remote rename \"%s\" to \"%s\": %s", oldpath,
   1239 		    newpath, fx2txt(status));
   1240 
   1241 	return status == SSH2_FX_OK ? 0 : -1;
   1242 }
   1243 
   1244 int
   1245 sftp_hardlink(struct sftp_conn *conn, const char *oldpath, const char *newpath)
   1246 {
   1247 	struct sshbuf *msg;
   1248 	u_int status, id;
   1249 	int r;
   1250 
   1251 	if ((conn->exts & SFTP_EXT_HARDLINK) == 0) {
   1252 		error("Server does not support hardlink (at) openssh.com extension");
   1253 		return -1;
   1254 	}
   1255 	debug2("Sending SSH2_FXP_EXTENDED(hardlink (at) openssh.com) "
   1256 	    "\"%s\" to \"%s\"", oldpath, newpath);
   1257 
   1258 	if ((msg = sshbuf_new()) == NULL)
   1259 		fatal_f("sshbuf_new failed");
   1260 
   1261 	/* Send link request */
   1262 	id = conn->msg_id++;
   1263 	if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
   1264 	    (r = sshbuf_put_u32(msg, id)) != 0 ||
   1265 	    (r = sshbuf_put_cstring(msg, "hardlink (at) openssh.com")) != 0 ||
   1266 	    (r = sshbuf_put_cstring(msg, oldpath)) != 0 ||
   1267 	    (r = sshbuf_put_cstring(msg, newpath)) != 0)
   1268 		fatal_fr(r, "compose");
   1269 	send_msg(conn, msg);
   1270 	debug3("Sent message hardlink (at) openssh.com \"%s\" -> \"%s\"",
   1271 	    oldpath, newpath);
   1272 	sshbuf_free(msg);
   1273 
   1274 	status = get_status(conn, id);
   1275 	if (status != SSH2_FX_OK)
   1276 		error("remote link \"%s\" to \"%s\": %s", oldpath,
   1277 		    newpath, fx2txt(status));
   1278 
   1279 	return status == SSH2_FX_OK ? 0 : -1;
   1280 }
   1281 
   1282 int
   1283 sftp_symlink(struct sftp_conn *conn, const char *oldpath, const char *newpath)
   1284 {
   1285 	struct sshbuf *msg;
   1286 	u_int status, id;
   1287 	int r;
   1288 
   1289 	if (conn->version < 3) {
   1290 		error("This server does not support the symlink operation");
   1291 		return(SSH2_FX_OP_UNSUPPORTED);
   1292 	}
   1293 	debug2("Sending SSH2_FXP_SYMLINK \"%s\" to \"%s\"", oldpath, newpath);
   1294 
   1295 	if ((msg = sshbuf_new()) == NULL)
   1296 		fatal_f("sshbuf_new failed");
   1297 
   1298 	/* Send symlink request */
   1299 	id = conn->msg_id++;
   1300 	if ((r = sshbuf_put_u8(msg, SSH2_FXP_SYMLINK)) != 0 ||
   1301 	    (r = sshbuf_put_u32(msg, id)) != 0 ||
   1302 	    (r = sshbuf_put_cstring(msg, oldpath)) != 0 ||
   1303 	    (r = sshbuf_put_cstring(msg, newpath)) != 0)
   1304 		fatal_fr(r, "compose");
   1305 	send_msg(conn, msg);
   1306 	debug3("Sent message SSH2_FXP_SYMLINK \"%s\" -> \"%s\"", oldpath,
   1307 	    newpath);
   1308 	sshbuf_free(msg);
   1309 
   1310 	status = get_status(conn, id);
   1311 	if (status != SSH2_FX_OK)
   1312 		error("remote symlink file \"%s\" to \"%s\": %s", oldpath,
   1313 		    newpath, fx2txt(status));
   1314 
   1315 	return status == SSH2_FX_OK ? 0 : -1;
   1316 }
   1317 
   1318 int
   1319 sftp_fsync(struct sftp_conn *conn, u_char *handle, u_int handle_len)
   1320 {
   1321 	struct sshbuf *msg;
   1322 	u_int status, id;
   1323 	int r;
   1324 
   1325 	/* Silently return if the extension is not supported */
   1326 	if ((conn->exts & SFTP_EXT_FSYNC) == 0)
   1327 		return -1;
   1328 	debug2("Sending SSH2_FXP_EXTENDED(fsync (at) openssh.com)");
   1329 
   1330 	/* Send fsync request */
   1331 	if ((msg = sshbuf_new()) == NULL)
   1332 		fatal_f("sshbuf_new failed");
   1333 	id = conn->msg_id++;
   1334 	if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
   1335 	    (r = sshbuf_put_u32(msg, id)) != 0 ||
   1336 	    (r = sshbuf_put_cstring(msg, "fsync (at) openssh.com")) != 0 ||
   1337 	    (r = sshbuf_put_string(msg, handle, handle_len)) != 0)
   1338 		fatal_fr(r, "compose");
   1339 	send_msg(conn, msg);
   1340 	debug3("Sent message fsync (at) openssh.com I:%u", id);
   1341 	sshbuf_free(msg);
   1342 
   1343 	status = get_status(conn, id);
   1344 	if (status != SSH2_FX_OK)
   1345 		error("remote fsync: %s", fx2txt(status));
   1346 
   1347 	return status == SSH2_FX_OK ? 0 : -1;
   1348 }
   1349 
   1350 #ifdef notyet
   1351 char *
   1352 sftp_readlink(struct sftp_conn *conn, const char *path)
   1353 {
   1354 	struct sshbuf *msg;
   1355 	u_int expected_id, count, id;
   1356 	char *filename, *longname;
   1357 	Attrib a;
   1358 	u_char type;
   1359 	int r;
   1360 
   1361 	debug2("Sending SSH2_FXP_READLINK \"%s\"", path);
   1362 
   1363 	expected_id = id = conn->msg_id++;
   1364 	send_string_request(conn, id, SSH2_FXP_READLINK, path, strlen(path));
   1365 
   1366 	if ((msg = sshbuf_new()) == NULL)
   1367 		fatal_f("sshbuf_new failed");
   1368 
   1369 	get_msg(conn, msg);
   1370 	if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
   1371 	    (r = sshbuf_get_u32(msg, &id)) != 0)
   1372 		fatal_fr(r, "parse");
   1373 
   1374 	if (id != expected_id)
   1375 		fatal("ID mismatch (%u != %u)", id, expected_id);
   1376 
   1377 	if (type == SSH2_FXP_STATUS) {
   1378 		u_int status;
   1379 
   1380 		if ((r = sshbuf_get_u32(msg, &status)) != 0)
   1381 			fatal_fr(r, "parse status");
   1382 		error("Couldn't readlink: %s", fx2txt(status));
   1383 		sshbuf_free(msg);
   1384 		return(NULL);
   1385 	} else if (type != SSH2_FXP_NAME)
   1386 		fatal("Expected SSH2_FXP_NAME(%u) packet, got %u",
   1387 		    SSH2_FXP_NAME, type);
   1388 
   1389 	if ((r = sshbuf_get_u32(msg, &count)) != 0)
   1390 		fatal_fr(r, "parse count");
   1391 	if (count != 1)
   1392 		fatal("Got multiple names (%d) from SSH_FXP_READLINK", count);
   1393 
   1394 	if ((r = sshbuf_get_cstring(msg, &filename, NULL)) != 0 ||
   1395 	    (r = sshbuf_get_cstring(msg, &longname, NULL)) != 0 ||
   1396 	    (r = decode_attrib(msg, &a)) != 0)
   1397 		fatal_fr(r, "parse filenames/attrib");
   1398 
   1399 	debug3("SSH_FXP_READLINK %s -> %s", path, filename);
   1400 
   1401 	free(longname);
   1402 
   1403 	sshbuf_free(msg);
   1404 
   1405 	return filename;
   1406 }
   1407 #endif
   1408 
   1409 int
   1410 sftp_statvfs(struct sftp_conn *conn, const char *path, struct sftp_statvfs *st,
   1411     int quiet)
   1412 {
   1413 	struct sshbuf *msg;
   1414 	u_int id;
   1415 	int r;
   1416 
   1417 	if ((conn->exts & SFTP_EXT_STATVFS) == 0) {
   1418 		error("Server does not support statvfs (at) openssh.com extension");
   1419 		return -1;
   1420 	}
   1421 
   1422 	debug2("Sending SSH2_FXP_EXTENDED(statvfs (at) openssh.com) \"%s\"", path);
   1423 
   1424 	id = conn->msg_id++;
   1425 
   1426 	if ((msg = sshbuf_new()) == NULL)
   1427 		fatal_f("sshbuf_new failed");
   1428 	if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
   1429 	    (r = sshbuf_put_u32(msg, id)) != 0 ||
   1430 	    (r = sshbuf_put_cstring(msg, "statvfs (at) openssh.com")) != 0 ||
   1431 	    (r = sshbuf_put_cstring(msg, path)) != 0)
   1432 		fatal_fr(r, "compose");
   1433 	send_msg(conn, msg);
   1434 	sshbuf_free(msg);
   1435 
   1436 	return get_decode_statvfs(conn, st, id, quiet);
   1437 }
   1438 
   1439 #ifdef notyet
   1440 int
   1441 sftp_fstatvfs(struct sftp_conn *conn, const u_char *handle, u_int handle_len,
   1442     struct sftp_statvfs *st, int quiet)
   1443 {
   1444 	struct sshbuf *msg;
   1445 	u_int id;
   1446 
   1447 	if ((conn->exts & SFTP_EXT_FSTATVFS) == 0) {
   1448 		error("Server does not support fstatvfs (at) openssh.com extension");
   1449 		return -1;
   1450 	}
   1451 
   1452 	debug2("Sending SSH2_FXP_EXTENDED(fstatvfs (at) openssh.com)");
   1453 
   1454 	id = conn->msg_id++;
   1455 
   1456 	if ((msg = sshbuf_new()) == NULL)
   1457 		fatal_f("sshbuf_new failed");
   1458 	if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
   1459 	    (r = sshbuf_put_u32(msg, id)) != 0 ||
   1460 	    (r = sshbuf_put_cstring(msg, "fstatvfs (at) openssh.com")) != 0 ||
   1461 	    (r = sshbuf_put_string(msg, handle, handle_len)) != 0)
   1462 		fatal_fr(r, "compose");
   1463 	send_msg(conn, msg);
   1464 	sshbuf_free(msg);
   1465 
   1466 	return get_decode_statvfs(conn, st, id, quiet);
   1467 }
   1468 #endif
   1469 
   1470 int
   1471 sftp_lsetstat(struct sftp_conn *conn, const char *path, Attrib *a)
   1472 {
   1473 	struct sshbuf *msg;
   1474 	u_int status, id;
   1475 	int r;
   1476 
   1477 	if ((conn->exts & SFTP_EXT_LSETSTAT) == 0) {
   1478 		error("Server does not support lsetstat (at) openssh.com extension");
   1479 		return -1;
   1480 	}
   1481 
   1482 	debug2("Sending SSH2_FXP_EXTENDED(lsetstat (at) openssh.com) \"%s\"", path);
   1483 
   1484 	id = conn->msg_id++;
   1485 	if ((msg = sshbuf_new()) == NULL)
   1486 		fatal_f("sshbuf_new failed");
   1487 	if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
   1488 	    (r = sshbuf_put_u32(msg, id)) != 0 ||
   1489 	    (r = sshbuf_put_cstring(msg, "lsetstat (at) openssh.com")) != 0 ||
   1490 	    (r = sshbuf_put_cstring(msg, path)) != 0 ||
   1491 	    (r = encode_attrib(msg, a)) != 0)
   1492 		fatal_fr(r, "compose");
   1493 	send_msg(conn, msg);
   1494 	sshbuf_free(msg);
   1495 
   1496 	status = get_status(conn, id);
   1497 	if (status != SSH2_FX_OK)
   1498 		error("remote lsetstat \"%s\": %s", path, fx2txt(status));
   1499 
   1500 	return status == SSH2_FX_OK ? 0 : -1;
   1501 }
   1502 
   1503 static void
   1504 send_read_request(struct sftp_conn *conn, u_int id, uint64_t offset,
   1505     u_int len, const u_char *handle, u_int handle_len)
   1506 {
   1507 	struct sshbuf *msg;
   1508 	int r;
   1509 
   1510 	if ((msg = sshbuf_new()) == NULL)
   1511 		fatal_f("sshbuf_new failed");
   1512 	if ((r = sshbuf_put_u8(msg, SSH2_FXP_READ)) != 0 ||
   1513 	    (r = sshbuf_put_u32(msg, id)) != 0 ||
   1514 	    (r = sshbuf_put_string(msg, handle, handle_len)) != 0 ||
   1515 	    (r = sshbuf_put_u64(msg, offset)) != 0 ||
   1516 	    (r = sshbuf_put_u32(msg, len)) != 0)
   1517 		fatal_fr(r, "compose");
   1518 	send_msg(conn, msg);
   1519 	sshbuf_free(msg);
   1520 }
   1521 
   1522 static int
   1523 send_open(struct sftp_conn *conn, const char *path, const char *tag,
   1524     u_int openmode, Attrib *a, u_char **handlep, size_t *handle_lenp)
   1525 {
   1526 	Attrib junk;
   1527 	u_char *handle;
   1528 	size_t handle_len;
   1529 	struct sshbuf *msg;
   1530 	int r;
   1531 	u_int id;
   1532 
   1533 	debug2("Sending SSH2_FXP_OPEN \"%s\"", path);
   1534 
   1535 	*handlep = NULL;
   1536 	*handle_lenp = 0;
   1537 
   1538 	if (a == NULL) {
   1539 		attrib_clear(&junk); /* Send empty attributes */
   1540 		a = &junk;
   1541 	}
   1542 	/* Send open request */
   1543 	if ((msg = sshbuf_new()) == NULL)
   1544 		fatal_f("sshbuf_new failed");
   1545 	id = conn->msg_id++;
   1546 	if ((r = sshbuf_put_u8(msg, SSH2_FXP_OPEN)) != 0 ||
   1547 	    (r = sshbuf_put_u32(msg, id)) != 0 ||
   1548 	    (r = sshbuf_put_cstring(msg, path)) != 0 ||
   1549 	    (r = sshbuf_put_u32(msg, openmode)) != 0 ||
   1550 	    (r = encode_attrib(msg, a)) != 0)
   1551 		fatal_fr(r, "compose %s open", tag);
   1552 	send_msg(conn, msg);
   1553 	sshbuf_free(msg);
   1554 	debug3("Sent %s message SSH2_FXP_OPEN I:%u P:%s M:0x%04x",
   1555 	    tag, id, path, openmode);
   1556 	if ((handle = get_handle(conn, id, &handle_len,
   1557 	    "%s open \"%s\"", tag, path)) == NULL)
   1558 		return -1;
   1559 	/* success */
   1560 	*handlep = handle;
   1561 	*handle_lenp = handle_len;
   1562 	return 0;
   1563 }
   1564 
   1565 static const char *
   1566 progress_meter_path(const char *path)
   1567 {
   1568 	const char *progresspath;
   1569 
   1570 	if ((progresspath = strrchr(path, '/')) == NULL)
   1571 		return path;
   1572 	progresspath++;
   1573 	if (*progresspath == '\0')
   1574 		return path;
   1575 	return progresspath;
   1576 }
   1577 
   1578 int
   1579 sftp_download(struct sftp_conn *conn, const char *remote_path,
   1580     const char *local_path, Attrib *a, int preserve_flag, int resume_flag,
   1581     int fsync_flag, int inplace_flag)
   1582 {
   1583 	struct sshbuf *msg;
   1584 	u_char *handle;
   1585 	int local_fd = -1, write_error, seen_zerolen = 0;
   1586 	int read_error, write_errno, lmodified = 0, reordered = 0, r;
   1587 	uint64_t offset = 0, size, highwater = 0, maxack = 0;
   1588 	u_int mode, id, buflen, num_req, max_req, status = SSH2_FX_OK;
   1589 	off_t progress_counter;
   1590 	size_t handle_len;
   1591 	struct stat st;
   1592 	struct requests requests;
   1593 	struct request *req;
   1594 	u_char type;
   1595 	Attrib attr;
   1596 
   1597 	debug2_f("download remote \"%s\" to local \"%s\"",
   1598 	    remote_path, local_path);
   1599 
   1600 	TAILQ_INIT(&requests);
   1601 
   1602 	if (a == NULL) {
   1603 		if (sftp_stat(conn, remote_path, 0, &attr) != 0)
   1604 			return -1;
   1605 		a = &attr;
   1606 	}
   1607 
   1608 	/* Do not preserve set[ug]id here, as we do not preserve ownership */
   1609 	if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS)
   1610 		mode = a->perm & 0777;
   1611 	else
   1612 		mode = 0666;
   1613 
   1614 	if ((a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) &&
   1615 	    (!S_ISREG(a->perm))) {
   1616 		error("download %s: not a regular file", remote_path);
   1617 		return(-1);
   1618 	}
   1619 
   1620 	if (a->flags & SSH2_FILEXFER_ATTR_SIZE)
   1621 		size = a->size;
   1622 	else
   1623 		size = 0;
   1624 
   1625 	buflen = conn->download_buflen;
   1626 
   1627 	/* Send open request */
   1628 	if (send_open(conn, remote_path, "remote", SSH2_FXF_READ, NULL,
   1629 	    &handle, &handle_len) != 0)
   1630 		return -1;
   1631 
   1632 	local_fd = open(local_path, O_WRONLY | O_CREAT |
   1633 	((resume_flag || inplace_flag) ? 0 : O_TRUNC), mode | S_IWUSR);
   1634 	if (local_fd == -1) {
   1635 		error("open local \"%s\": %s", local_path, strerror(errno));
   1636 		goto fail;
   1637 	}
   1638 	if (resume_flag) {
   1639 		if (fstat(local_fd, &st) == -1) {
   1640 			error("stat local \"%s\": %s",
   1641 			    local_path, strerror(errno));
   1642 			goto fail;
   1643 		}
   1644 		if (st.st_size < 0) {
   1645 			error("\"%s\" has negative size", local_path);
   1646 			goto fail;
   1647 		}
   1648 		if ((uint64_t)st.st_size > size) {
   1649 			error("Unable to resume download of \"%s\": "
   1650 			    "local file is larger than remote", local_path);
   1651  fail:
   1652 			sftp_close(conn, handle, handle_len);
   1653 			free(handle);
   1654 			if (local_fd != -1)
   1655 				close(local_fd);
   1656 			return -1;
   1657 		}
   1658 		offset = highwater = maxack = st.st_size;
   1659 	}
   1660 
   1661 	/* Read from remote and write to local */
   1662 	write_error = read_error = write_errno = num_req = 0;
   1663 	max_req = 1;
   1664 	progress_counter = offset;
   1665 
   1666 	if (showprogress && size != 0) {
   1667 		start_progress_meter(progress_meter_path(remote_path),
   1668 		    size, &progress_counter);
   1669 	}
   1670 
   1671 	if ((msg = sshbuf_new()) == NULL)
   1672 		fatal_f("sshbuf_new failed");
   1673 
   1674 	while (num_req > 0 || max_req > 0) {
   1675 		u_char *data;
   1676 		size_t len;
   1677 
   1678 		/*
   1679 		 * Simulate EOF on interrupt: stop sending new requests and
   1680 		 * allow outstanding requests to drain gracefully
   1681 		 */
   1682 		if (interrupted) {
   1683 			if (num_req == 0) /* If we haven't started yet... */
   1684 				break;
   1685 			max_req = 0;
   1686 		}
   1687 
   1688 		/* Send some more requests */
   1689 		while (num_req < max_req) {
   1690 			debug3("Request range %llu -> %llu (%d/%d)",
   1691 			    (unsigned long long)offset,
   1692 			    (unsigned long long)offset + buflen - 1,
   1693 			    num_req, max_req);
   1694 			req = request_enqueue(&requests, conn->msg_id++,
   1695 			    buflen, offset);
   1696 			offset += buflen;
   1697 			num_req++;
   1698 			send_read_request(conn, req->id, req->offset,
   1699 			    req->len, handle, handle_len);
   1700 		}
   1701 
   1702 		sshbuf_reset(msg);
   1703 		get_msg(conn, msg);
   1704 		if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
   1705 		    (r = sshbuf_get_u32(msg, &id)) != 0)
   1706 			fatal_fr(r, "parse");
   1707 		debug3("Received reply T:%u I:%u R:%d", type, id, max_req);
   1708 
   1709 		/* Find the request in our queue */
   1710 		if ((req = request_find(&requests, id)) == NULL)
   1711 			fatal("Unexpected reply %u", id);
   1712 
   1713 		switch (type) {
   1714 		case SSH2_FXP_STATUS:
   1715 			if ((r = sshbuf_get_u32(msg, &status)) != 0)
   1716 				fatal_fr(r, "parse status");
   1717 			if (status != SSH2_FX_EOF)
   1718 				read_error = 1;
   1719 			max_req = 0;
   1720 			TAILQ_REMOVE(&requests, req, tq);
   1721 			free(req);
   1722 			num_req--;
   1723 			break;
   1724 		case SSH2_FXP_DATA:
   1725 			if ((r = sshbuf_get_string(msg, &data, &len)) != 0)
   1726 				fatal_fr(r, "parse data");
   1727 			debug3("Received data %llu -> %llu",
   1728 			    (unsigned long long)req->offset,
   1729 			    (unsigned long long)req->offset + len - 1);
   1730 			if (len > req->len)
   1731 				fatal("Received more data than asked for "
   1732 				    "%zu > %zu", len, req->len);
   1733 			if (len == 0) {
   1734 				if (seen_zerolen)
   1735 					fatal_f("server sent zero data length");
   1736 				seen_zerolen = 1;
   1737 			}
   1738 			lmodified = 1;
   1739 			if ((lseek(local_fd, req->offset, SEEK_SET) == -1 ||
   1740 			    atomicio(vwrite, local_fd, data, len) != len) &&
   1741 			    !write_error) {
   1742 				write_errno = errno;
   1743 				write_error = 1;
   1744 				max_req = 0;
   1745 			} else {
   1746 				/*
   1747 				 * Track both the highest offset acknowledged
   1748 				 * and the highest *contiguous* offset
   1749 				 * acknowledged.
   1750 				 * We'll need the latter for ftruncate()ing
   1751 				 * interrupted transfers.
   1752 				 */
   1753 				if (maxack < req->offset + len)
   1754 					maxack = req->offset + len;
   1755 				if (!reordered && req->offset <= highwater)
   1756 					highwater = maxack;
   1757 				else if (!reordered && req->offset > highwater)
   1758 					reordered = 1;
   1759 			}
   1760 			progress_counter += len;
   1761 			free(data);
   1762 
   1763 			if (len == req->len) {
   1764 				TAILQ_REMOVE(&requests, req, tq);
   1765 				free(req);
   1766 				num_req--;
   1767 			} else {
   1768 				/* Resend the request for the missing data */
   1769 				debug3("Short data block, re-requesting "
   1770 				    "%llu -> %llu (%2d)",
   1771 				    (unsigned long long)req->offset + len,
   1772 				    (unsigned long long)req->offset +
   1773 				    req->len - 1, num_req);
   1774 				req->id = conn->msg_id++;
   1775 				req->len -= len;
   1776 				req->offset += len;
   1777 				send_read_request(conn, req->id,
   1778 				    req->offset, req->len, handle, handle_len);
   1779 				/* Reduce the request size */
   1780 				if (len < buflen)
   1781 					buflen = MAXIMUM(MIN_READ_SIZE, len);
   1782 			}
   1783 			if (max_req > 0) { /* max_req = 0 iff EOF received */
   1784 				if (size > 0 && offset > size) {
   1785 					/* Only one request at a time
   1786 					 * after the expected EOF */
   1787 					debug3("Finish at %llu (%2d)",
   1788 					    (unsigned long long)offset,
   1789 					    num_req);
   1790 					max_req = 1;
   1791 				} else if (max_req < conn->num_requests) {
   1792 					++max_req;
   1793 				}
   1794 			}
   1795 			break;
   1796 		default:
   1797 			fatal("Expected SSH2_FXP_DATA(%u) packet, got %u",
   1798 			    SSH2_FXP_DATA, type);
   1799 		}
   1800 	}
   1801 
   1802 	if (showprogress && size)
   1803 		stop_progress_meter();
   1804 
   1805 	/* Sanity check */
   1806 	if (TAILQ_FIRST(&requests) != NULL)
   1807 		fatal("Transfer complete, but requests still in queue");
   1808 
   1809 	if (!read_error && !write_error && !interrupted) {
   1810 		/* we got everything */
   1811 		highwater = maxack;
   1812 	}
   1813 
   1814 	/*
   1815 	 * Truncate at highest contiguous point to avoid holes on interrupt,
   1816 	 * or unconditionally if writing in place.
   1817 	 */
   1818 	if (inplace_flag || read_error || write_error || interrupted) {
   1819 		if (reordered && resume_flag &&
   1820 		    (read_error || write_error || interrupted)) {
   1821 			error("Unable to resume download of \"%s\": "
   1822 			    "server reordered requests", local_path);
   1823 		}
   1824 		debug("truncating at %llu", (unsigned long long)highwater);
   1825 		if (ftruncate(local_fd, highwater) == -1)
   1826 			error("local ftruncate \"%s\": %s", local_path,
   1827 			    strerror(errno));
   1828 	}
   1829 	if (read_error) {
   1830 		error("read remote \"%s\" : %s", remote_path, fx2txt(status));
   1831 		status = -1;
   1832 		sftp_close(conn, handle, handle_len);
   1833 	} else if (write_error) {
   1834 		error("write local \"%s\": %s", local_path,
   1835 		    strerror(write_errno));
   1836 		status = SSH2_FX_FAILURE;
   1837 		sftp_close(conn, handle, handle_len);
   1838 	} else {
   1839 		if (sftp_close(conn, handle, handle_len) != 0 || interrupted)
   1840 			status = SSH2_FX_FAILURE;
   1841 		else
   1842 			status = SSH2_FX_OK;
   1843 		/* Override umask and utimes if asked */
   1844 		if (preserve_flag && fchmod(local_fd, mode) == -1)
   1845 			error("local chmod \"%s\": %s", local_path,
   1846 			    strerror(errno));
   1847 		if (preserve_flag &&
   1848 		    (a->flags & SSH2_FILEXFER_ATTR_ACMODTIME)) {
   1849 			struct timeval tv[2];
   1850 			tv[0].tv_sec = a->atime;
   1851 			tv[1].tv_sec = a->mtime;
   1852 			tv[0].tv_usec = tv[1].tv_usec = 0;
   1853 			if (utimes(local_path, tv) == -1)
   1854 				error("local set times \"%s\": %s",
   1855 				    local_path, strerror(errno));
   1856 		}
   1857 		if (resume_flag && !lmodified)
   1858 			logit("File \"%s\" was not modified", local_path);
   1859 		else if (fsync_flag) {
   1860 			debug("syncing \"%s\"", local_path);
   1861 			if (fsync(local_fd) == -1)
   1862 				error("local sync \"%s\": %s",
   1863 				    local_path, strerror(errno));
   1864 		}
   1865 	}
   1866 	close(local_fd);
   1867 	sshbuf_free(msg);
   1868 	free(handle);
   1869 
   1870 	return status == SSH2_FX_OK ? 0 : -1;
   1871 }
   1872 
   1873 static int
   1874 download_dir_internal(struct sftp_conn *conn, const char *src, const char *dst,
   1875     int depth, Attrib *dirattrib, int preserve_flag, int print_flag,
   1876     int resume_flag, int fsync_flag, int follow_link_flag, int inplace_flag)
   1877 {
   1878 	int i, ret = 0;
   1879 	SFTP_DIRENT **dir_entries;
   1880 	char *filename, *new_src = NULL, *new_dst = NULL;
   1881 	mode_t mode = 0777, tmpmode = mode;
   1882 	Attrib *a, ldirattrib, lsym;
   1883 
   1884 	if (depth >= MAX_DIR_DEPTH) {
   1885 		error("Maximum directory depth exceeded: %d levels", depth);
   1886 		return -1;
   1887 	}
   1888 
   1889 	debug2_f("download dir remote \"%s\" to local \"%s\"", src, dst);
   1890 
   1891 	if (dirattrib == NULL) {
   1892 		if (sftp_stat(conn, src, 1, &ldirattrib) != 0) {
   1893 			error("stat remote \"%s\" directory failed", src);
   1894 			return -1;
   1895 		}
   1896 		dirattrib = &ldirattrib;
   1897 	}
   1898 	if (!S_ISDIR(dirattrib->perm)) {
   1899 		error("\"%s\" is not a directory", src);
   1900 		return -1;
   1901 	}
   1902 	if (print_flag && print_flag != SFTP_PROGRESS_ONLY)
   1903 		mprintf("Retrieving %s\n", src);
   1904 
   1905 	if (dirattrib->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) {
   1906 		mode = dirattrib->perm & 01777;
   1907 		tmpmode = mode | (S_IWUSR|S_IXUSR);
   1908 	} else {
   1909 		debug("download remote \"%s\": server "
   1910 		    "did not send permissions", dst);
   1911 	}
   1912 
   1913 	if (mkdir(dst, tmpmode) == -1 && errno != EEXIST) {
   1914 		error("mkdir %s: %s", dst, strerror(errno));
   1915 		return -1;
   1916 	}
   1917 
   1918 	if (sftp_readdir(conn, src, &dir_entries) == -1) {
   1919 		error("remote readdir \"%s\" failed", src);
   1920 		return -1;
   1921 	}
   1922 
   1923 	for (i = 0; dir_entries[i] != NULL && !interrupted; i++) {
   1924 		free(new_dst);
   1925 		free(new_src);
   1926 
   1927 		filename = dir_entries[i]->filename;
   1928 		new_dst = sftp_path_append(dst, filename);
   1929 		new_src = sftp_path_append(src, filename);
   1930 
   1931 		a = &dir_entries[i]->a;
   1932 		if (S_ISLNK(a->perm)) {
   1933 			if (!follow_link_flag) {
   1934 				logit("download \"%s\": not a regular file",
   1935 				    new_src);
   1936 				continue;
   1937 			}
   1938 			/* Replace the stat contents with the symlink target */
   1939 			if (sftp_stat(conn, new_src, 1, &lsym) != 0) {
   1940 				logit("remote stat \"%s\" failed", new_src);
   1941 				ret = -1;
   1942 				continue;
   1943 			}
   1944 			a = &lsym;
   1945 		}
   1946 
   1947 		if (S_ISDIR(a->perm)) {
   1948 			if (strcmp(filename, ".") == 0 ||
   1949 			    strcmp(filename, "..") == 0)
   1950 				continue;
   1951 			if (download_dir_internal(conn, new_src, new_dst,
   1952 			    depth + 1, a, preserve_flag,
   1953 			    print_flag, resume_flag,
   1954 			    fsync_flag, follow_link_flag, inplace_flag) == -1)
   1955 				ret = -1;
   1956 		} else if (S_ISREG(a->perm)) {
   1957 			if (sftp_download(conn, new_src, new_dst, a,
   1958 			    preserve_flag, resume_flag, fsync_flag,
   1959 			    inplace_flag) == -1) {
   1960 				error("Download of file %s to %s failed",
   1961 				    new_src, new_dst);
   1962 				ret = -1;
   1963 			}
   1964 		} else
   1965 			logit("download \"%s\": not a regular file", new_src);
   1966 
   1967 	}
   1968 	free(new_dst);
   1969 	free(new_src);
   1970 
   1971 	if (preserve_flag) {
   1972 		if (dirattrib->flags & SSH2_FILEXFER_ATTR_ACMODTIME) {
   1973 			struct timeval tv[2];
   1974 			tv[0].tv_sec = dirattrib->atime;
   1975 			tv[1].tv_sec = dirattrib->mtime;
   1976 			tv[0].tv_usec = tv[1].tv_usec = 0;
   1977 			if (utimes(dst, tv) == -1)
   1978 				error("local set times on \"%s\": %s",
   1979 				    dst, strerror(errno));
   1980 		} else
   1981 			debug("Server did not send times for directory "
   1982 			    "\"%s\"", dst);
   1983 	}
   1984 
   1985 	if (mode != tmpmode && chmod(dst, mode) == -1)
   1986 		error("local chmod directory \"%s\": %s", dst,
   1987 		    strerror(errno));
   1988 
   1989 	sftp_free_dirents(dir_entries);
   1990 
   1991 	return ret;
   1992 }
   1993 
   1994 int
   1995 sftp_download_dir(struct sftp_conn *conn, const char *src, const char *dst,
   1996     Attrib *dirattrib, int preserve_flag, int print_flag, int resume_flag,
   1997     int fsync_flag, int follow_link_flag, int inplace_flag)
   1998 {
   1999 	char *src_canon;
   2000 	int ret;
   2001 
   2002 	if ((src_canon = sftp_realpath(conn, src)) == NULL) {
   2003 		error("download \"%s\": path canonicalization failed", src);
   2004 		return -1;
   2005 	}
   2006 
   2007 	ret = download_dir_internal(conn, src_canon, dst, 0,
   2008 	    dirattrib, preserve_flag, print_flag, resume_flag, fsync_flag,
   2009 	    follow_link_flag, inplace_flag);
   2010 	free(src_canon);
   2011 	return ret;
   2012 }
   2013 
   2014 int
   2015 sftp_upload(struct sftp_conn *conn, const char *local_path,
   2016     const char *remote_path, int preserve_flag, int resume,
   2017     int fsync_flag, int inplace_flag)
   2018 {
   2019 	int r, local_fd;
   2020 	u_int openmode, id, status = SSH2_FX_OK, status2, reordered = 0;
   2021 	off_t offset, progress_counter;
   2022 	u_char type, *handle, *data;
   2023 	struct sshbuf *msg;
   2024 	struct stat sb;
   2025 	Attrib a, t, c;
   2026 	uint32_t startid, ackid;
   2027 	uint64_t highwater = 0, maxack = 0;
   2028 	struct request *ack = NULL;
   2029 	struct requests acks;
   2030 	size_t handle_len;
   2031 
   2032 	debug2_f("upload local \"%s\" to remote \"%s\"",
   2033 	    local_path, remote_path);
   2034 
   2035 	TAILQ_INIT(&acks);
   2036 
   2037 	if ((local_fd = open(local_path, O_RDONLY)) == -1) {
   2038 		error("open local \"%s\": %s", local_path, strerror(errno));
   2039 		return(-1);
   2040 	}
   2041 	if (fstat(local_fd, &sb) == -1) {
   2042 		error("fstat local \"%s\": %s", local_path, strerror(errno));
   2043 		close(local_fd);
   2044 		return(-1);
   2045 	}
   2046 	if (!S_ISREG(sb.st_mode)) {
   2047 		error("local \"%s\" is not a regular file", local_path);
   2048 		close(local_fd);
   2049 		return(-1);
   2050 	}
   2051 	stat_to_attrib(&sb, &a);
   2052 
   2053 	a.flags &= ~SSH2_FILEXFER_ATTR_SIZE;
   2054 	a.flags &= ~SSH2_FILEXFER_ATTR_UIDGID;
   2055 	a.perm &= 0777;
   2056 	if (!preserve_flag)
   2057 		a.flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME;
   2058 
   2059 	if (resume) {
   2060 		/* Get remote file size if it exists */
   2061 		if (sftp_stat(conn, remote_path, 0, &c) != 0) {
   2062 			close(local_fd);
   2063 			return -1;
   2064 		}
   2065 
   2066 		if ((off_t)c.size >= sb.st_size) {
   2067 			error("resume \"%s\": destination file "
   2068 			    "same size or larger", local_path);
   2069 			close(local_fd);
   2070 			return -1;
   2071 		}
   2072 
   2073 		if (lseek(local_fd, (off_t)c.size, SEEK_SET) == -1) {
   2074 			close(local_fd);
   2075 			return -1;
   2076 		}
   2077 		highwater = c.size;
   2078 	}
   2079 
   2080 	openmode = SSH2_FXF_WRITE|SSH2_FXF_CREAT;
   2081 	if (resume)
   2082 		openmode |= SSH2_FXF_APPEND;
   2083 	else if (!inplace_flag)
   2084 		openmode |= SSH2_FXF_TRUNC;
   2085 
   2086 	/* Send open request */
   2087 	if (send_open(conn, remote_path, "dest", openmode, &a,
   2088 	    &handle, &handle_len) != 0) {
   2089 		close(local_fd);
   2090 		return -1;
   2091 	}
   2092 
   2093 	id = conn->msg_id;
   2094 	startid = ackid = id + 1;
   2095 	data = xmalloc(conn->upload_buflen);
   2096 
   2097 	/* Read from local and write to remote */
   2098 	offset = progress_counter = (resume ? c.size : 0);
   2099 	if (showprogress) {
   2100 		start_progress_meter(progress_meter_path(local_path),
   2101 		    sb.st_size, &progress_counter);
   2102 	}
   2103 
   2104 	if ((msg = sshbuf_new()) == NULL)
   2105 		fatal_f("sshbuf_new failed");
   2106 	for (;;) {
   2107 		int len;
   2108 
   2109 		/*
   2110 		 * Can't use atomicio here because it returns 0 on EOF,
   2111 		 * thus losing the last block of the file.
   2112 		 * Simulate an EOF on interrupt, allowing ACKs from the
   2113 		 * server to drain.
   2114 		 */
   2115 		if (interrupted || status != SSH2_FX_OK)
   2116 			len = 0;
   2117 		else do
   2118 			len = read(local_fd, data, conn->upload_buflen);
   2119 		while ((len == -1) && (errno == EINTR || errno == EAGAIN));
   2120 
   2121 		if (len == -1) {
   2122 			fatal("read local \"%s\": %s",
   2123 			    local_path, strerror(errno));
   2124 		} else if (len != 0) {
   2125 			ack = request_enqueue(&acks, ++id, len, offset);
   2126 			sshbuf_reset(msg);
   2127 			if ((r = sshbuf_put_u8(msg, SSH2_FXP_WRITE)) != 0 ||
   2128 			    (r = sshbuf_put_u32(msg, ack->id)) != 0 ||
   2129 			    (r = sshbuf_put_string(msg, handle,
   2130 			    handle_len)) != 0 ||
   2131 			    (r = sshbuf_put_u64(msg, offset)) != 0 ||
   2132 			    (r = sshbuf_put_string(msg, data, len)) != 0)
   2133 				fatal_fr(r, "compose");
   2134 			send_msg(conn, msg);
   2135 			debug3("Sent message SSH2_FXP_WRITE I:%u O:%llu S:%u",
   2136 			    id, (unsigned long long)offset, len);
   2137 		} else if (TAILQ_FIRST(&acks) == NULL)
   2138 			break;
   2139 
   2140 		if (ack == NULL)
   2141 			fatal("Unexpected ACK %u", id);
   2142 
   2143 		if (id == startid || len == 0 ||
   2144 		    id - ackid >= conn->num_requests) {
   2145 			u_int rid;
   2146 
   2147 			sshbuf_reset(msg);
   2148 			get_msg(conn, msg);
   2149 			if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
   2150 			    (r = sshbuf_get_u32(msg, &rid)) != 0)
   2151 				fatal_fr(r, "parse");
   2152 
   2153 			if (type != SSH2_FXP_STATUS)
   2154 				fatal("Expected SSH2_FXP_STATUS(%d) packet, "
   2155 				    "got %d", SSH2_FXP_STATUS, type);
   2156 
   2157 			if ((r = sshbuf_get_u32(msg, &status2)) != 0)
   2158 				fatal_fr(r, "parse status");
   2159 			debug3("SSH2_FXP_STATUS %u", status2);
   2160 			if (status2 != SSH2_FX_OK)
   2161 				status = status2; /* remember errors */
   2162 
   2163 			/* Find the request in our queue */
   2164 			if ((ack = request_find(&acks, rid)) == NULL)
   2165 				fatal("Can't find request for ID %u", rid);
   2166 			TAILQ_REMOVE(&acks, ack, tq);
   2167 			debug3("In write loop, ack for %u %zu bytes at %lld",
   2168 			    ack->id, ack->len, (unsigned long long)ack->offset);
   2169 			++ackid;
   2170 			progress_counter += ack->len;
   2171 			/*
   2172 			 * Track both the highest offset acknowledged and the
   2173 			 * highest *contiguous* offset acknowledged.
   2174 			 * We'll need the latter for ftruncate()ing
   2175 			 * interrupted transfers.
   2176 			 */
   2177 			if (maxack < ack->offset + ack->len)
   2178 				maxack = ack->offset + ack->len;
   2179 			if (!reordered && ack->offset <= highwater)
   2180 				highwater = maxack;
   2181 			else if (!reordered && ack->offset > highwater) {
   2182 				debug3_f("server reordered ACKs");
   2183 				reordered = 1;
   2184 			}
   2185 			free(ack);
   2186 		}
   2187 		offset += len;
   2188 		if (offset < 0)
   2189 			fatal_f("offset < 0");
   2190 	}
   2191 	sshbuf_free(msg);
   2192 
   2193 	if (showprogress)
   2194 		stop_progress_meter();
   2195 	free(data);
   2196 
   2197 	if (status == SSH2_FX_OK && !interrupted) {
   2198 		/* we got everything */
   2199 		highwater = maxack;
   2200 	}
   2201 	if (status != SSH2_FX_OK) {
   2202 		error("write remote \"%s\": %s", remote_path, fx2txt(status));
   2203 		status = SSH2_FX_FAILURE;
   2204 	}
   2205 
   2206 	if (inplace_flag || (resume && (status != SSH2_FX_OK || interrupted))) {
   2207 		debug("truncating at %llu", (unsigned long long)highwater);
   2208 		attrib_clear(&t);
   2209 		t.flags = SSH2_FILEXFER_ATTR_SIZE;
   2210 		t.size = highwater;
   2211 		sftp_fsetstat(conn, handle, handle_len, &t);
   2212 	}
   2213 
   2214 	if (close(local_fd) == -1) {
   2215 		error("close local \"%s\": %s", local_path, strerror(errno));
   2216 		status = SSH2_FX_FAILURE;
   2217 	}
   2218 
   2219 	/* Override umask and utimes if asked */
   2220 	if (preserve_flag)
   2221 		sftp_fsetstat(conn, handle, handle_len, &a);
   2222 
   2223 	if (fsync_flag)
   2224 		(void)sftp_fsync(conn, handle, handle_len);
   2225 
   2226 	if (sftp_close(conn, handle, handle_len) != 0)
   2227 		status = SSH2_FX_FAILURE;
   2228 
   2229 	free(handle);
   2230 
   2231 	return status == SSH2_FX_OK ? 0 : -1;
   2232 }
   2233 
   2234 static int
   2235 upload_dir_internal(struct sftp_conn *conn, const char *src, const char *dst,
   2236     int depth, int preserve_flag, int print_flag, int resume, int fsync_flag,
   2237     int follow_link_flag, int inplace_flag)
   2238 {
   2239 	int created = 0, ret = 0;
   2240 	DIR *dirp;
   2241 	struct dirent *dp;
   2242 	char *filename, *new_src = NULL, *new_dst = NULL;
   2243 	struct stat sb;
   2244 	Attrib a, dirattrib;
   2245 	uint32_t saved_perm;
   2246 
   2247 	debug2_f("upload local dir \"%s\" to remote \"%s\"", src, dst);
   2248 
   2249 	if (depth >= MAX_DIR_DEPTH) {
   2250 		error("Maximum directory depth exceeded: %d levels", depth);
   2251 		return -1;
   2252 	}
   2253 
   2254 	if (stat(src, &sb) == -1) {
   2255 		error("stat local \"%s\": %s", src, strerror(errno));
   2256 		return -1;
   2257 	}
   2258 	if (!S_ISDIR(sb.st_mode)) {
   2259 		error("\"%s\" is not a directory", src);
   2260 		return -1;
   2261 	}
   2262 	if (print_flag && print_flag != SFTP_PROGRESS_ONLY)
   2263 		mprintf("Entering %s\n", src);
   2264 
   2265 	stat_to_attrib(&sb, &a);
   2266 	a.flags &= ~SSH2_FILEXFER_ATTR_SIZE;
   2267 	a.flags &= ~SSH2_FILEXFER_ATTR_UIDGID;
   2268 	a.perm &= 01777;
   2269 	if (!preserve_flag)
   2270 		a.flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME;
   2271 
   2272 	/*
   2273 	 * sftp lacks a portable status value to match errno EEXIST,
   2274 	 * so if we get a failure back then we must check whether
   2275 	 * the path already existed and is a directory.  Ensure we can
   2276 	 * write to the directory we create for the duration of the transfer.
   2277 	 */
   2278 	saved_perm = a.perm;
   2279 	a.perm |= (S_IWUSR|S_IXUSR);
   2280 	if (sftp_mkdir(conn, dst, &a, 0) == 0)
   2281 		created = 1;
   2282 	else {
   2283 		if (sftp_stat(conn, dst, 0, &dirattrib) != 0)
   2284 			return -1;
   2285 		if (!S_ISDIR(dirattrib.perm)) {
   2286 			error("\"%s\" exists but is not a directory", dst);
   2287 			return -1;
   2288 		}
   2289 	}
   2290 	a.perm = saved_perm;
   2291 
   2292 	if ((dirp = opendir(src)) == NULL) {
   2293 		error("local opendir \"%s\": %s", src, strerror(errno));
   2294 		return -1;
   2295 	}
   2296 
   2297 	while (((dp = readdir(dirp)) != NULL) && !interrupted) {
   2298 		if (dp->d_ino == 0)
   2299 			continue;
   2300 		free(new_dst);
   2301 		free(new_src);
   2302 		filename = dp->d_name;
   2303 		new_dst = sftp_path_append(dst, filename);
   2304 		new_src = sftp_path_append(src, filename);
   2305 
   2306 		if (strcmp(filename, ".") == 0 || strcmp(filename, "..") == 0)
   2307 			continue;
   2308 		if (lstat(new_src, &sb) == -1) {
   2309 			logit("local lstat \"%s\": %s", filename,
   2310 			    strerror(errno));
   2311 			ret = -1;
   2312 			continue;
   2313 		}
   2314 		if (S_ISLNK(sb.st_mode)) {
   2315 			if (!follow_link_flag) {
   2316 				logit("%s: not a regular file", filename);
   2317 				continue;
   2318 			}
   2319 			/* Replace the stat contents with the symlink target */
   2320 			if (stat(new_src, &sb) == -1) {
   2321 				logit("local stat \"%s\": %s", filename,
   2322 				    strerror(errno));
   2323 				ret = -1;
   2324 				continue;
   2325 			}
   2326 		}
   2327 		if (S_ISDIR(sb.st_mode)) {
   2328 			if (upload_dir_internal(conn, new_src, new_dst,
   2329 			    depth + 1, preserve_flag, print_flag, resume,
   2330 			    fsync_flag, follow_link_flag, inplace_flag) == -1)
   2331 				ret = -1;
   2332 		} else if (S_ISREG(sb.st_mode)) {
   2333 			if (sftp_upload(conn, new_src, new_dst,
   2334 			    preserve_flag, resume, fsync_flag,
   2335 			    inplace_flag) == -1) {
   2336 				error("upload \"%s\" to \"%s\" failed",
   2337 				    new_src, new_dst);
   2338 				ret = -1;
   2339 			}
   2340 		} else
   2341 			logit("%s: not a regular file", filename);
   2342 	}
   2343 	free(new_dst);
   2344 	free(new_src);
   2345 
   2346 	if (created || preserve_flag)
   2347 		sftp_setstat(conn, dst, &a);
   2348 
   2349 	(void) closedir(dirp);
   2350 	return ret;
   2351 }
   2352 
   2353 int
   2354 sftp_upload_dir(struct sftp_conn *conn, const char *src, const char *dst,
   2355     int preserve_flag, int print_flag, int resume, int fsync_flag,
   2356     int follow_link_flag, int inplace_flag)
   2357 {
   2358 	char *dst_canon;
   2359 	int ret;
   2360 
   2361 	if ((dst_canon = sftp_realpath(conn, dst)) == NULL) {
   2362 		error("upload \"%s\": path canonicalization failed", dst);
   2363 		return -1;
   2364 	}
   2365 
   2366 	ret = upload_dir_internal(conn, src, dst_canon, 0, preserve_flag,
   2367 	    print_flag, resume, fsync_flag, follow_link_flag, inplace_flag);
   2368 
   2369 	free(dst_canon);
   2370 	return ret;
   2371 }
   2372 
   2373 static void
   2374 handle_dest_replies(struct sftp_conn *to, const char *to_path, int synchronous,
   2375     u_int *nreqsp, int *write_errorp)
   2376 {
   2377 	struct sshbuf *msg;
   2378 	u_char type;
   2379 	u_int id, status;
   2380 	int r;
   2381 	struct pollfd pfd;
   2382 
   2383 	if ((msg = sshbuf_new()) == NULL)
   2384 		fatal_f("sshbuf_new failed");
   2385 
   2386 	/* Try to eat replies from the upload side */
   2387 	while (*nreqsp > 0) {
   2388 		debug3_f("%u outstanding replies", *nreqsp);
   2389 		if (!synchronous) {
   2390 			/* Bail out if no data is ready to be read */
   2391 			pfd.fd = to->fd_in;
   2392 			pfd.events = POLLIN;
   2393 			if ((r = poll(&pfd, 1, 0)) == -1) {
   2394 				if (errno == EINTR)
   2395 					break;
   2396 				fatal_f("poll: %s", strerror(errno));
   2397 			} else if (r == 0)
   2398 				break; /* fd not ready */
   2399 		}
   2400 		sshbuf_reset(msg);
   2401 		get_msg(to, msg);
   2402 
   2403 		if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
   2404 		    (r = sshbuf_get_u32(msg, &id)) != 0)
   2405 			fatal_fr(r, "dest parse");
   2406 		debug3("Received dest reply T:%u I:%u R:%u", type, id, *nreqsp);
   2407 		if (type != SSH2_FXP_STATUS) {
   2408 			fatal_f("Expected SSH2_FXP_STATUS(%d) packet, got %d",
   2409 			    SSH2_FXP_STATUS, type);
   2410 		}
   2411 		if ((r = sshbuf_get_u32(msg, &status)) != 0)
   2412 			fatal_fr(r, "parse dest status");
   2413 		debug3("dest SSH2_FXP_STATUS %u", status);
   2414 		if (status != SSH2_FX_OK) {
   2415 			/* record first error */
   2416 			if (*write_errorp == 0)
   2417 				*write_errorp = status;
   2418 		}
   2419 		/*
   2420 		 * XXX this doesn't do full reply matching like sftp_upload and
   2421 		 * so cannot gracefully truncate terminated uploads at a
   2422 		 * high-water mark. ATM the only caller of this function (scp)
   2423 		 * doesn't support transfer resumption, so this doesn't matter
   2424 		 * a whole lot.
   2425 		 *
   2426 		 * To be safe, sftp_crossload truncates the destination file to
   2427 		 * zero length on upload failure, since we can't trust the
   2428 		 * server not to have reordered replies that could have
   2429 		 * inserted holes where none existed in the source file.
   2430 		 *
   2431 		 * XXX we could get a more accurate progress bar if we updated
   2432 		 * the counter based on the reply from the destination...
   2433 		 */
   2434 		(*nreqsp)--;
   2435 	}
   2436 	debug3_f("done: %u outstanding replies", *nreqsp);
   2437 	sshbuf_free(msg);
   2438 }
   2439 
   2440 int
   2441 sftp_crossload(struct sftp_conn *from, struct sftp_conn *to,
   2442     const char *from_path, const char *to_path,
   2443     Attrib *a, int preserve_flag)
   2444 {
   2445 	struct sshbuf *msg;
   2446 	int write_error, read_error, r, seen_zerolen = 0;
   2447 	uint64_t offset = 0, size;
   2448 	u_int id, buflen, num_req, max_req, status = SSH2_FX_OK;
   2449 	u_int num_upload_req;
   2450 	off_t progress_counter;
   2451 	u_char *from_handle, *to_handle;
   2452 	size_t from_handle_len, to_handle_len;
   2453 	struct requests requests;
   2454 	struct request *req;
   2455 	u_char type;
   2456 	Attrib attr;
   2457 
   2458 	debug2_f("crossload src \"%s\" to dst \"%s\"", from_path, to_path);
   2459 
   2460 	TAILQ_INIT(&requests);
   2461 
   2462 	if (a == NULL) {
   2463 		if (sftp_stat(from, from_path, 0, &attr) != 0)
   2464 			return -1;
   2465 		a = &attr;
   2466 	}
   2467 
   2468 	if ((a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) &&
   2469 	    (!S_ISREG(a->perm))) {
   2470 		error("download \"%s\": not a regular file", from_path);
   2471 		return(-1);
   2472 	}
   2473 	if (a->flags & SSH2_FILEXFER_ATTR_SIZE)
   2474 		size = a->size;
   2475 	else
   2476 		size = 0;
   2477 
   2478 	buflen = from->download_buflen;
   2479 	if (buflen > to->upload_buflen)
   2480 		buflen = to->upload_buflen;
   2481 
   2482 	/* Send open request to read side */
   2483 	if (send_open(from, from_path, "origin", SSH2_FXF_READ, NULL,
   2484 	    &from_handle, &from_handle_len) != 0)
   2485 		return -1;
   2486 
   2487 	/* Send open request to write side */
   2488 	a->flags &= ~SSH2_FILEXFER_ATTR_SIZE;
   2489 	a->flags &= ~SSH2_FILEXFER_ATTR_UIDGID;
   2490 	a->perm &= 0777;
   2491 	if (!preserve_flag)
   2492 		a->flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME;
   2493 	if (send_open(to, to_path, "dest",
   2494 	    SSH2_FXF_WRITE|SSH2_FXF_CREAT|SSH2_FXF_TRUNC, a,
   2495 	    &to_handle, &to_handle_len) != 0) {
   2496 		sftp_close(from, from_handle, from_handle_len);
   2497 		return -1;
   2498 	}
   2499 
   2500 	/* Read from remote "from" and write to remote "to" */
   2501 	offset = 0;
   2502 	write_error = read_error = num_req = num_upload_req = 0;
   2503 	max_req = 1;
   2504 	progress_counter = 0;
   2505 
   2506 	if (showprogress && size != 0) {
   2507 		start_progress_meter(progress_meter_path(from_path),
   2508 		    size, &progress_counter);
   2509 	}
   2510 	if ((msg = sshbuf_new()) == NULL)
   2511 		fatal_f("sshbuf_new failed");
   2512 	while (num_req > 0 || max_req > 0) {
   2513 		u_char *data;
   2514 		size_t len;
   2515 
   2516 		/*
   2517 		 * Simulate EOF on interrupt: stop sending new requests and
   2518 		 * allow outstanding requests to drain gracefully
   2519 		 */
   2520 		if (interrupted) {
   2521 			if (num_req == 0) /* If we haven't started yet... */
   2522 				break;
   2523 			max_req = 0;
   2524 		}
   2525 
   2526 		/* Send some more requests */
   2527 		while (num_req < max_req) {
   2528 			debug3("Request range %llu -> %llu (%d/%d)",
   2529 			    (unsigned long long)offset,
   2530 			    (unsigned long long)offset + buflen - 1,
   2531 			    num_req, max_req);
   2532 			req = request_enqueue(&requests, from->msg_id++,
   2533 			    buflen, offset);
   2534 			offset += buflen;
   2535 			num_req++;
   2536 			send_read_request(from, req->id, req->offset,
   2537 			    req->len, from_handle, from_handle_len);
   2538 		}
   2539 
   2540 		/* Try to eat replies from the upload side (nonblocking) */
   2541 		handle_dest_replies(to, to_path, 0,
   2542 		    &num_upload_req, &write_error);
   2543 
   2544 		sshbuf_reset(msg);
   2545 		get_msg(from, msg);
   2546 		if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
   2547 		    (r = sshbuf_get_u32(msg, &id)) != 0)
   2548 			fatal_fr(r, "parse");
   2549 		debug3("Received origin reply T:%u I:%u R:%d",
   2550 		    type, id, max_req);
   2551 
   2552 		/* Find the request in our queue */
   2553 		if ((req = request_find(&requests, id)) == NULL)
   2554 			fatal("Unexpected reply %u", id);
   2555 
   2556 		switch (type) {
   2557 		case SSH2_FXP_STATUS:
   2558 			if ((r = sshbuf_get_u32(msg, &status)) != 0)
   2559 				fatal_fr(r, "parse status");
   2560 			if (status != SSH2_FX_EOF)
   2561 				read_error = 1;
   2562 			max_req = 0;
   2563 			TAILQ_REMOVE(&requests, req, tq);
   2564 			free(req);
   2565 			num_req--;
   2566 			break;
   2567 		case SSH2_FXP_DATA:
   2568 			if ((r = sshbuf_get_string(msg, &data, &len)) != 0)
   2569 				fatal_fr(r, "parse data");
   2570 			debug3("Received data %llu -> %llu",
   2571 			    (unsigned long long)req->offset,
   2572 			    (unsigned long long)req->offset + len - 1);
   2573 			if (len > req->len)
   2574 				fatal("Received more data than asked for "
   2575 				    "%zu > %zu", len, req->len);
   2576 			if (len == 0) {
   2577 				if (seen_zerolen)
   2578 					fatal_f("server sent zero data length");
   2579 				seen_zerolen = 1;
   2580 			}
   2581 
   2582 			/* Write this chunk out to the destination */
   2583 			sshbuf_reset(msg);
   2584 			if ((r = sshbuf_put_u8(msg, SSH2_FXP_WRITE)) != 0 ||
   2585 			    (r = sshbuf_put_u32(msg, to->msg_id++)) != 0 ||
   2586 			    (r = sshbuf_put_string(msg, to_handle,
   2587 			    to_handle_len)) != 0 ||
   2588 			    (r = sshbuf_put_u64(msg, req->offset)) != 0 ||
   2589 			    (r = sshbuf_put_string(msg, data, len)) != 0)
   2590 				fatal_fr(r, "compose write");
   2591 			send_msg(to, msg);
   2592 			debug3("Sent message SSH2_FXP_WRITE I:%u O:%llu S:%zu",
   2593 			    id, (unsigned long long)offset, len);
   2594 			num_upload_req++;
   2595 			progress_counter += len;
   2596 			free(data);
   2597 
   2598 			if (len == req->len) {
   2599 				TAILQ_REMOVE(&requests, req, tq);
   2600 				free(req);
   2601 				num_req--;
   2602 			} else {
   2603 				/* Resend the request for the missing data */
   2604 				debug3("Short data block, re-requesting "
   2605 				    "%llu -> %llu (%2d)",
   2606 				    (unsigned long long)req->offset + len,
   2607 				    (unsigned long long)req->offset +
   2608 				    req->len - 1, num_req);
   2609 				req->id = from->msg_id++;
   2610 				req->len -= len;
   2611 				req->offset += len;
   2612 				send_read_request(from, req->id,
   2613 				    req->offset, req->len,
   2614 				    from_handle, from_handle_len);
   2615 				/* Reduce the request size */
   2616 				if (len < buflen)
   2617 					buflen = MAXIMUM(MIN_READ_SIZE, len);
   2618 			}
   2619 			if (max_req > 0) { /* max_req = 0 iff EOF received */
   2620 				if (size > 0 && offset > size) {
   2621 					/* Only one request at a time
   2622 					 * after the expected EOF */
   2623 					debug3("Finish at %llu (%2d)",
   2624 					    (unsigned long long)offset,
   2625 					    num_req);
   2626 					max_req = 1;
   2627 				} else if (max_req < from->num_requests) {
   2628 					++max_req;
   2629 				}
   2630 			}
   2631 			break;
   2632 		default:
   2633 			fatal("Expected SSH2_FXP_DATA(%u) packet, got %u",
   2634 			    SSH2_FXP_DATA, type);
   2635 		}
   2636 	}
   2637 
   2638 	if (showprogress && size)
   2639 		stop_progress_meter();
   2640 
   2641 	/* Drain replies from the server (blocking) */
   2642 	debug3_f("waiting for %u replies from destination", num_upload_req);
   2643 	handle_dest_replies(to, to_path, 1, &num_upload_req, &write_error);
   2644 
   2645 	/* Sanity check */
   2646 	if (TAILQ_FIRST(&requests) != NULL)
   2647 		fatal("Transfer complete, but requests still in queue");
   2648 	/* Truncate at 0 length on interrupt or error to avoid holes at dest */
   2649 	if (read_error || write_error || interrupted) {
   2650 		debug("truncating \"%s\" at 0", to_path);
   2651 		sftp_close(to, to_handle, to_handle_len);
   2652 		free(to_handle);
   2653 		if (send_open(to, to_path, "dest",
   2654 		    SSH2_FXF_WRITE|SSH2_FXF_CREAT|SSH2_FXF_TRUNC, a,
   2655 		    &to_handle, &to_handle_len) != 0) {
   2656 			error("dest truncate \"%s\" failed", to_path);
   2657 			to_handle = NULL;
   2658 		}
   2659 	}
   2660 	if (read_error) {
   2661 		error("read origin \"%s\": %s", from_path, fx2txt(status));
   2662 		status = -1;
   2663 		sftp_close(from, from_handle, from_handle_len);
   2664 		if (to_handle != NULL)
   2665 			sftp_close(to, to_handle, to_handle_len);
   2666 	} else if (write_error) {
   2667 		error("write dest \"%s\": %s", to_path, fx2txt(write_error));
   2668 		status = SSH2_FX_FAILURE;
   2669 		sftp_close(from, from_handle, from_handle_len);
   2670 		if (to_handle != NULL)
   2671 			sftp_close(to, to_handle, to_handle_len);
   2672 	} else {
   2673 		if (sftp_close(from, from_handle, from_handle_len) != 0 ||
   2674 		    interrupted)
   2675 			status = -1;
   2676 		else
   2677 			status = SSH2_FX_OK;
   2678 		if (to_handle != NULL) {
   2679 			/* Need to resend utimes after write */
   2680 			if (preserve_flag)
   2681 				sftp_fsetstat(to, to_handle, to_handle_len, a);
   2682 			sftp_close(to, to_handle, to_handle_len);
   2683 		}
   2684 	}
   2685 	sshbuf_free(msg);
   2686 	free(from_handle);
   2687 	free(to_handle);
   2688 
   2689 	return status == SSH2_FX_OK ? 0 : -1;
   2690 }
   2691 
   2692 static int
   2693 crossload_dir_internal(struct sftp_conn *from, struct sftp_conn *to,
   2694     const char *from_path, const char *to_path,
   2695     int depth, Attrib *dirattrib, int preserve_flag, int print_flag,
   2696     int follow_link_flag)
   2697 {
   2698 	int i, ret = 0, created = 0;
   2699 	SFTP_DIRENT **dir_entries;
   2700 	char *filename, *new_from_path = NULL, *new_to_path = NULL;
   2701 	mode_t mode = 0777;
   2702 	Attrib *a, curdir, ldirattrib, newdir, lsym;
   2703 
   2704 	debug2_f("crossload dir src \"%s\" to dst \"%s\"", from_path, to_path);
   2705 
   2706 	if (depth >= MAX_DIR_DEPTH) {
   2707 		error("Maximum directory depth exceeded: %d levels", depth);
   2708 		return -1;
   2709 	}
   2710 
   2711 	if (dirattrib == NULL) {
   2712 		if (sftp_stat(from, from_path, 1, &ldirattrib) != 0) {
   2713 			error("stat remote \"%s\" failed", from_path);
   2714 			return -1;
   2715 		}
   2716 		dirattrib = &ldirattrib;
   2717 	}
   2718 	if (!S_ISDIR(dirattrib->perm)) {
   2719 		error("\"%s\" is not a directory", from_path);
   2720 		return -1;
   2721 	}
   2722 	if (print_flag && print_flag != SFTP_PROGRESS_ONLY)
   2723 		mprintf("Retrieving %s\n", from_path);
   2724 
   2725 	curdir = *dirattrib; /* dirattrib will be clobbered */
   2726 	curdir.flags &= ~SSH2_FILEXFER_ATTR_SIZE;
   2727 	curdir.flags &= ~SSH2_FILEXFER_ATTR_UIDGID;
   2728 	if ((curdir.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) == 0) {
   2729 		debug("Origin did not send permissions for "
   2730 		    "directory \"%s\"", to_path);
   2731 		curdir.perm = S_IWUSR|S_IXUSR;
   2732 		curdir.flags |= SSH2_FILEXFER_ATTR_PERMISSIONS;
   2733 	}
   2734 	/* We need to be able to write to the directory while we transfer it */
   2735 	mode = curdir.perm & 01777;
   2736 	curdir.perm = mode | (S_IWUSR|S_IXUSR);
   2737 
   2738 	/*
   2739 	 * sftp lacks a portable status value to match errno EEXIST,
   2740 	 * so if we get a failure back then we must check whether
   2741 	 * the path already existed and is a directory.  Ensure we can
   2742 	 * write to the directory we create for the duration of the transfer.
   2743 	 */
   2744 	if (sftp_mkdir(to, to_path, &curdir, 0) == 0)
   2745 		created = 1;
   2746 	else {
   2747 		if (sftp_stat(to, to_path, 0, &newdir) != 0)
   2748 			return -1;
   2749 		if (!S_ISDIR(newdir.perm)) {
   2750 			error("\"%s\" exists but is not a directory", to_path);
   2751 			return -1;
   2752 		}
   2753 	}
   2754 	curdir.perm = mode;
   2755 
   2756 	if (sftp_readdir(from, from_path, &dir_entries) == -1) {
   2757 		error("origin readdir \"%s\" failed", from_path);
   2758 		return -1;
   2759 	}
   2760 
   2761 	for (i = 0; dir_entries[i] != NULL && !interrupted; i++) {
   2762 		free(new_from_path);
   2763 		free(new_to_path);
   2764 
   2765 		filename = dir_entries[i]->filename;
   2766 		new_from_path = sftp_path_append(from_path, filename);
   2767 		new_to_path = sftp_path_append(to_path, filename);
   2768 
   2769 		a = &dir_entries[i]->a;
   2770 		if (S_ISLNK(a->perm)) {
   2771 			if (!follow_link_flag) {
   2772 				logit("%s: not a regular file", filename);
   2773 				continue;
   2774 			}
   2775 			/* Replace the stat contents with the symlink target */
   2776 			if (sftp_stat(from, new_from_path, 1, &lsym) != 0) {
   2777 				logit("remote stat \"%s\" failed",
   2778 				    new_from_path);
   2779 				ret = -1;
   2780 				continue;
   2781 			}
   2782 			a = &lsym;
   2783 		}
   2784 		if (S_ISDIR(a->perm)) {
   2785 			if (strcmp(filename, ".") == 0 ||
   2786 			    strcmp(filename, "..") == 0)
   2787 				continue;
   2788 			if (crossload_dir_internal(from, to,
   2789 			    new_from_path, new_to_path,
   2790 			    depth + 1, a, preserve_flag,
   2791 			    print_flag, follow_link_flag) == -1)
   2792 				ret = -1;
   2793 		} else if (S_ISREG(a->perm)) {
   2794 			if (sftp_crossload(from, to, new_from_path,
   2795 			    new_to_path, a, preserve_flag) == -1) {
   2796 				error("crossload \"%s\" to \"%s\" failed",
   2797 				    new_from_path, new_to_path);
   2798 				ret = -1;
   2799 			}
   2800 		} else {
   2801 			logit("origin \"%s\": not a regular file",
   2802 			    new_from_path);
   2803 		}
   2804 	}
   2805 	free(new_to_path);
   2806 	free(new_from_path);
   2807 
   2808 	if (created || preserve_flag)
   2809 		sftp_setstat(to, to_path, &curdir);
   2810 
   2811 	sftp_free_dirents(dir_entries);
   2812 
   2813 	return ret;
   2814 }
   2815 
   2816 int
   2817 sftp_crossload_dir(struct sftp_conn *from, struct sftp_conn *to,
   2818     const char *from_path, const char *to_path,
   2819     Attrib *dirattrib, int preserve_flag, int print_flag, int follow_link_flag)
   2820 {
   2821 	char *from_path_canon;
   2822 	int ret;
   2823 
   2824 	if ((from_path_canon = sftp_realpath(from, from_path)) == NULL) {
   2825 		error("crossload \"%s\": path canonicalization failed",
   2826 		    from_path);
   2827 		return -1;
   2828 	}
   2829 
   2830 	ret = crossload_dir_internal(from, to, from_path_canon, to_path, 0,
   2831 	    dirattrib, preserve_flag, print_flag, follow_link_flag);
   2832 	free(from_path_canon);
   2833 	return ret;
   2834 }
   2835 
   2836 int
   2837 sftp_can_get_users_groups_by_id(struct sftp_conn *conn)
   2838 {
   2839 	return (conn->exts & SFTP_EXT_GETUSERSGROUPS_BY_ID) != 0;
   2840 }
   2841 
   2842 int
   2843 sftp_get_users_groups_by_id(struct sftp_conn *conn,
   2844     const u_int *uids, u_int nuids,
   2845     const u_int *gids, u_int ngids,
   2846     char ***usernamesp, char ***groupnamesp)
   2847 {
   2848 	struct sshbuf *msg, *uidbuf, *gidbuf;
   2849 	u_int i, expected_id, id;
   2850 	char *name, **usernames = NULL, **groupnames = NULL;
   2851 	u_char type;
   2852 	int r;
   2853 
   2854 	*usernamesp = *groupnamesp = NULL;
   2855 	if (!sftp_can_get_users_groups_by_id(conn))
   2856 		return SSH_ERR_FEATURE_UNSUPPORTED;
   2857 
   2858 	if ((msg = sshbuf_new()) == NULL ||
   2859 	    (uidbuf = sshbuf_new()) == NULL ||
   2860 	    (gidbuf = sshbuf_new()) == NULL)
   2861 		fatal_f("sshbuf_new failed");
   2862 	expected_id = id = conn->msg_id++;
   2863 	debug2("Sending SSH2_FXP_EXTENDED(users-groups-by-id (at) openssh.com)");
   2864 	for (i = 0; i < nuids; i++) {
   2865 		if ((r = sshbuf_put_u32(uidbuf, uids[i])) != 0)
   2866 			fatal_fr(r, "compose uids");
   2867 	}
   2868 	for (i = 0; i < ngids; i++) {
   2869 		if ((r = sshbuf_put_u32(gidbuf, gids[i])) != 0)
   2870 			fatal_fr(r, "compose gids");
   2871 	}
   2872 	if ((r = sshbuf_put_u8(msg, SSH2_FXP_EXTENDED)) != 0 ||
   2873 	    (r = sshbuf_put_u32(msg, id)) != 0 ||
   2874 	    (r = sshbuf_put_cstring(msg,
   2875 	    "users-groups-by-id (at) openssh.com")) != 0 ||
   2876 	    (r = sshbuf_put_stringb(msg, uidbuf)) != 0 ||
   2877 	    (r = sshbuf_put_stringb(msg, gidbuf)) != 0)
   2878 		fatal_fr(r, "compose");
   2879 	send_msg(conn, msg);
   2880 	get_msg(conn, msg);
   2881 	if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
   2882 	    (r = sshbuf_get_u32(msg, &id)) != 0)
   2883 		fatal_fr(r, "parse");
   2884 	if (id != expected_id)
   2885 		fatal("ID mismatch (%u != %u)", id, expected_id);
   2886 	if (type == SSH2_FXP_STATUS) {
   2887 		u_int status;
   2888 		char *errmsg;
   2889 
   2890 		if ((r = sshbuf_get_u32(msg, &status)) != 0 ||
   2891 		    (r = sshbuf_get_cstring(msg, &errmsg, NULL)) != 0)
   2892 			fatal_fr(r, "parse status");
   2893 		error("users-groups-by-id %s",
   2894 		    *errmsg == '\0' ? fx2txt(status) : errmsg);
   2895 		free(errmsg);
   2896 		sshbuf_free(msg);
   2897 		sshbuf_free(uidbuf);
   2898 		sshbuf_free(gidbuf);
   2899 		return -1;
   2900 	} else if (type != SSH2_FXP_EXTENDED_REPLY)
   2901 		fatal("Expected SSH2_FXP_EXTENDED_REPLY(%u) packet, got %u",
   2902 		    SSH2_FXP_EXTENDED_REPLY, type);
   2903 
   2904 	/* reuse */
   2905 	sshbuf_free(uidbuf);
   2906 	sshbuf_free(gidbuf);
   2907 	uidbuf = gidbuf = NULL;
   2908 	if ((r = sshbuf_froms(msg, &uidbuf)) != 0 ||
   2909 	    (r = sshbuf_froms(msg, &gidbuf)) != 0)
   2910 		fatal_fr(r, "parse response");
   2911 	if (nuids > 0) {
   2912 		usernames = xcalloc(nuids, sizeof(*usernames));
   2913 		for (i = 0; i < nuids; i++) {
   2914 			if ((r = sshbuf_get_cstring(uidbuf, &name, NULL)) != 0)
   2915 				fatal_fr(r, "parse user name");
   2916 			/* Handle unresolved names */
   2917 			if (*name == '\0') {
   2918 				free(name);
   2919 				name = NULL;
   2920 			}
   2921 			usernames[i] = name;
   2922 		}
   2923 	}
   2924 	if (ngids > 0) {
   2925 		groupnames = xcalloc(ngids, sizeof(*groupnames));
   2926 		for (i = 0; i < ngids; i++) {
   2927 			if ((r = sshbuf_get_cstring(gidbuf, &name, NULL)) != 0)
   2928 				fatal_fr(r, "parse user name");
   2929 			/* Handle unresolved names */
   2930 			if (*name == '\0') {
   2931 				free(name);
   2932 				name = NULL;
   2933 			}
   2934 			groupnames[i] = name;
   2935 		}
   2936 	}
   2937 	if (sshbuf_len(uidbuf) != 0)
   2938 		fatal_f("unexpected extra username data");
   2939 	if (sshbuf_len(gidbuf) != 0)
   2940 		fatal_f("unexpected extra groupname data");
   2941 	sshbuf_free(uidbuf);
   2942 	sshbuf_free(gidbuf);
   2943 	sshbuf_free(msg);
   2944 	/* success */
   2945 	*usernamesp = usernames;
   2946 	*groupnamesp = groupnames;
   2947 	return 0;
   2948 }
   2949 
   2950 char *
   2951 sftp_path_append(const char *p1, const char *p2)
   2952 {
   2953 	char *ret;
   2954 	size_t len = strlen(p1) + strlen(p2) + 2;
   2955 
   2956 	ret = xmalloc(len);
   2957 	strlcpy(ret, p1, len);
   2958 	if (p1[0] != '\0' && p1[strlen(p1) - 1] != '/')
   2959 		strlcat(ret, "/", len);
   2960 	strlcat(ret, p2, len);
   2961 
   2962 	return(ret);
   2963 }
   2964 
   2965 /*
   2966  * Arg p must be dynamically allocated.  It will either be returned or
   2967  * freed and a replacement allocated.  Caller must free returned string.
   2968  */
   2969 char *
   2970 sftp_make_absolute(char *p, const char *pwd)
   2971 {
   2972 	char *abs_str;
   2973 
   2974 	/* Derelativise */
   2975 	if (p && !path_absolute(p)) {
   2976 		abs_str = sftp_path_append(pwd, p);
   2977 		free(p);
   2978 		return(abs_str);
   2979 	} else
   2980 		return(p);
   2981 }
   2982 
   2983 int
   2984 sftp_remote_is_dir(struct sftp_conn *conn, const char *path)
   2985 {
   2986 	Attrib a;
   2987 
   2988 	/* XXX: report errors? */
   2989 	if (sftp_stat(conn, path, 1, &a) != 0)
   2990 		return(0);
   2991 	if (!(a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS))
   2992 		return(0);
   2993 	return S_ISDIR(a.perm);
   2994 }
   2995 
   2996 
   2997 /* Check whether path returned from glob(..., GLOB_MARK, ...) is a directory */
   2998 int
   2999 sftp_globpath_is_dir(const char *pathname)
   3000 {
   3001 	size_t l = strlen(pathname);
   3002 
   3003 	return l > 0 && pathname[l - 1] == '/';
   3004 }
   3005 
   3006