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