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