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