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