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