1 /* $OpenBSD: sftp-client.c,v 1.124 2016/05/25 23:48:45 schwarze Exp $ */
3 * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
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.
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.
19 /* XXX: signed vs unsigned */
20 /* XXX: remove all logging, only return status codes */
21 /* XXX: copy between two remote sites */
25 #include <sys/param.h> /* MIN MAX */
26 #include <sys/types.h>
27 #ifdef HAVE_SYS_STATVFS_H
28 #include <sys/statvfs.h>
30 #include "openbsd-compat/sys-queue.h"
31 #ifdef HAVE_SYS_STAT_H
32 # include <sys/stat.h>
34 #ifdef HAVE_SYS_TIME_H
35 # include <sys/time.h>
54 #include "progressmeter.h"
59 #include "sftp-common.h"
60 #include "sftp-client.h"
62 extern volatile sig_atomic_t interrupted
;
63 extern int showprogress
;
65 /* Minimum amount of data to read at a time */
66 #define MIN_READ_SIZE 512
68 /* Maximum depth to descend in directory trees */
69 #define MAX_DIR_DEPTH 64
74 u_int transfer_buflen
;
78 #define SFTP_EXT_POSIX_RENAME 0x00000001
79 #define SFTP_EXT_STATVFS 0x00000002
80 #define SFTP_EXT_FSTATVFS 0x00000004
81 #define SFTP_EXT_HARDLINK 0x00000008
82 #define SFTP_EXT_FSYNC 0x00000010
85 struct bwlimit bwlimit_in
, bwlimit_out
;
89 get_handle(struct sftp_conn
*conn
, u_int expected_id
, size_t *len
,
90 const char *errfmt
, ...) __attribute__((format(printf
, 4, 5)));
94 sftpio(void *_bwlimit
, size_t amount
)
96 struct bwlimit
*bwlimit
= (struct bwlimit
*)_bwlimit
;
98 bandwidth_limit(bwlimit
, amount
);
103 send_msg(struct sftp_conn
*conn
, struct sshbuf
*m
)
108 if (sshbuf_len(m
) > SFTP_MAX_MSG_LENGTH
)
109 fatal("Outbound message too long %zu", sshbuf_len(m
));
111 /* Send length first */
112 put_u32(mlen
, sshbuf_len(m
));
113 iov
[0].iov_base
= mlen
;
114 iov
[0].iov_len
= sizeof(mlen
);
115 iov
[1].iov_base
= (u_char
*)sshbuf_ptr(m
);
116 iov
[1].iov_len
= sshbuf_len(m
);
118 if (atomiciov6(writev
, conn
->fd_out
, iov
, 2,
119 conn
->limit_kbps
> 0 ? sftpio
: NULL
, &conn
->bwlimit_out
) !=
120 sshbuf_len(m
) + sizeof(mlen
))
121 fatal("Couldn't send packet: %s", strerror(errno
));
127 get_msg(struct sftp_conn
*conn
, struct sshbuf
*m
)
133 if ((r
= sshbuf_reserve(m
, 4, &p
)) != 0)
134 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
135 if (atomicio6(read
, conn
->fd_in
, p
, 4,
136 conn
->limit_kbps
> 0 ? sftpio
: NULL
, &conn
->bwlimit_in
) != 4) {
138 fatal("Connection closed");
140 fatal("Couldn't read packet: %s", strerror(errno
));
143 if ((r
= sshbuf_get_u32(m
, &msg_len
)) != 0)
144 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
145 if (msg_len
> SFTP_MAX_MSG_LENGTH
)
146 fatal("Received message too long %u", msg_len
);
148 if ((r
= sshbuf_reserve(m
, msg_len
, &p
)) != 0)
149 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
150 if (atomicio6(read
, conn
->fd_in
, p
, msg_len
,
151 conn
->limit_kbps
> 0 ? sftpio
: NULL
, &conn
->bwlimit_in
)
154 fatal("Connection closed");
156 fatal("Read packet: %s", strerror(errno
));
161 send_string_request(struct sftp_conn
*conn
, u_int id
, u_int code
, const char *s
,
167 if ((msg
= sshbuf_new()) == NULL
)
168 fatal("%s: sshbuf_new failed", __func__
);
169 if ((r
= sshbuf_put_u8(msg
, code
)) != 0 ||
170 (r
= sshbuf_put_u32(msg
, id
)) != 0 ||
171 (r
= sshbuf_put_string(msg
, s
, len
)) != 0)
172 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
174 debug3("Sent message fd %d T:%u I:%u", conn
->fd_out
, code
, id
);
179 send_string_attrs_request(struct sftp_conn
*conn
, u_int id
, u_int code
,
180 const void *s
, u_int len
, Attrib
*a
)
185 if ((msg
= sshbuf_new()) == NULL
)
186 fatal("%s: sshbuf_new failed", __func__
);
187 if ((r
= sshbuf_put_u8(msg
, code
)) != 0 ||
188 (r
= sshbuf_put_u32(msg
, id
)) != 0 ||
189 (r
= sshbuf_put_string(msg
, s
, len
)) != 0 ||
190 (r
= encode_attrib(msg
, a
)) != 0)
191 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
193 debug3("Sent message fd %d T:%u I:%u", conn
->fd_out
, code
, id
);
198 get_status(struct sftp_conn
*conn
, u_int expected_id
)
205 if ((msg
= sshbuf_new()) == NULL
)
206 fatal("%s: sshbuf_new failed", __func__
);
208 if ((r
= sshbuf_get_u8(msg
, &type
)) != 0 ||
209 (r
= sshbuf_get_u32(msg
, &id
)) != 0)
210 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
212 if (id
!= expected_id
)
213 fatal("ID mismatch (%u != %u)", id
, expected_id
);
214 if (type
!= SSH2_FXP_STATUS
)
215 fatal("Expected SSH2_FXP_STATUS(%u) packet, got %u",
216 SSH2_FXP_STATUS
, type
);
218 if ((r
= sshbuf_get_u32(msg
, &status
)) != 0)
219 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
222 debug3("SSH2_FXP_STATUS %u", status
);
228 get_handle(struct sftp_conn
*conn
, u_int expected_id
, size_t *len
,
229 const char *errfmt
, ...)
239 va_start(args
, errfmt
);
241 vsnprintf(errmsg
, sizeof(errmsg
), errfmt
, args
);
244 if ((msg
= sshbuf_new()) == NULL
)
245 fatal("%s: sshbuf_new failed", __func__
);
247 if ((r
= sshbuf_get_u8(msg
, &type
)) != 0 ||
248 (r
= sshbuf_get_u32(msg
, &id
)) != 0)
249 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
251 if (id
!= expected_id
)
252 fatal("%s: ID mismatch (%u != %u)",
253 errfmt
== NULL
? __func__
: errmsg
, id
, expected_id
);
254 if (type
== SSH2_FXP_STATUS
) {
255 if ((r
= sshbuf_get_u32(msg
, &status
)) != 0)
256 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
258 error("%s: %s", errmsg
, fx2txt(status
));
261 } else if (type
!= SSH2_FXP_HANDLE
)
262 fatal("%s: Expected SSH2_FXP_HANDLE(%u) packet, got %u",
263 errfmt
== NULL
? __func__
: errmsg
, SSH2_FXP_HANDLE
, type
);
265 if ((r
= sshbuf_get_string(msg
, &handle
, len
)) != 0)
266 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
273 get_decode_stat(struct sftp_conn
*conn
, u_int expected_id
, int quiet
)
281 if ((msg
= sshbuf_new()) == NULL
)
282 fatal("%s: sshbuf_new failed", __func__
);
285 if ((r
= sshbuf_get_u8(msg
, &type
)) != 0 ||
286 (r
= sshbuf_get_u32(msg
, &id
)) != 0)
287 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
289 debug3("Received stat reply T:%u I:%u", type
, id
);
290 if (id
!= expected_id
)
291 fatal("ID mismatch (%u != %u)", id
, expected_id
);
292 if (type
== SSH2_FXP_STATUS
) {
295 if ((r
= sshbuf_get_u32(msg
, &status
)) != 0)
296 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
298 debug("Couldn't stat remote file: %s", fx2txt(status
));
300 error("Couldn't stat remote file: %s", fx2txt(status
));
303 } else if (type
!= SSH2_FXP_ATTRS
) {
304 fatal("Expected SSH2_FXP_ATTRS(%u) packet, got %u",
305 SSH2_FXP_ATTRS
, type
);
307 if ((r
= decode_attrib(msg
, &a
)) != 0) {
308 error("%s: couldn't decode attrib: %s", __func__
, ssh_err(r
));
318 get_decode_statvfs(struct sftp_conn
*conn
, struct sftp_statvfs
*st
,
319 u_int expected_id
, int quiet
)
327 if ((msg
= sshbuf_new()) == NULL
)
328 fatal("%s: sshbuf_new failed", __func__
);
331 if ((r
= sshbuf_get_u8(msg
, &type
)) != 0 ||
332 (r
= sshbuf_get_u32(msg
, &id
)) != 0)
333 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
335 debug3("Received statvfs reply T:%u I:%u", type
, id
);
336 if (id
!= expected_id
)
337 fatal("ID mismatch (%u != %u)", id
, expected_id
);
338 if (type
== SSH2_FXP_STATUS
) {
341 if ((r
= sshbuf_get_u32(msg
, &status
)) != 0)
342 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
344 debug("Couldn't statvfs: %s", fx2txt(status
));
346 error("Couldn't statvfs: %s", fx2txt(status
));
349 } else if (type
!= SSH2_FXP_EXTENDED_REPLY
) {
350 fatal("Expected SSH2_FXP_EXTENDED_REPLY(%u) packet, got %u",
351 SSH2_FXP_EXTENDED_REPLY
, type
);
354 memset(st
, 0, sizeof(*st
));
355 if ((r
= sshbuf_get_u64(msg
, &st
->f_bsize
)) != 0 ||
356 (r
= sshbuf_get_u64(msg
, &st
->f_frsize
)) != 0 ||
357 (r
= sshbuf_get_u64(msg
, &st
->f_blocks
)) != 0 ||
358 (r
= sshbuf_get_u64(msg
, &st
->f_bfree
)) != 0 ||
359 (r
= sshbuf_get_u64(msg
, &st
->f_bavail
)) != 0 ||
360 (r
= sshbuf_get_u64(msg
, &st
->f_files
)) != 0 ||
361 (r
= sshbuf_get_u64(msg
, &st
->f_ffree
)) != 0 ||
362 (r
= sshbuf_get_u64(msg
, &st
->f_favail
)) != 0 ||
363 (r
= sshbuf_get_u64(msg
, &st
->f_fsid
)) != 0 ||
364 (r
= sshbuf_get_u64(msg
, &flag
)) != 0 ||
365 (r
= sshbuf_get_u64(msg
, &st
->f_namemax
)) != 0)
366 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
368 st
->f_flag
= (flag
& SSH2_FXE_STATVFS_ST_RDONLY
) ? ST_RDONLY
: 0;
369 st
->f_flag
|= (flag
& SSH2_FXE_STATVFS_ST_NOSUID
) ? ST_NOSUID
: 0;
377 do_init(int fd_in
, int fd_out
, u_int transfer_buflen
, u_int num_requests
,
378 u_int64_t limit_kbps
)
382 struct sftp_conn
*ret
;
385 ret
= xcalloc(1, sizeof(*ret
));
388 ret
->fd_out
= fd_out
;
389 ret
->transfer_buflen
= transfer_buflen
;
390 ret
->num_requests
= num_requests
;
394 if ((msg
= sshbuf_new()) == NULL
)
395 fatal("%s: sshbuf_new failed", __func__
);
396 if ((r
= sshbuf_put_u8(msg
, SSH2_FXP_INIT
)) != 0 ||
397 (r
= sshbuf_put_u32(msg
, SSH2_FILEXFER_VERSION
)) != 0)
398 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
405 /* Expecting a VERSION reply */
406 if ((r
= sshbuf_get_u8(msg
, &type
)) != 0)
407 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
408 if (type
!= SSH2_FXP_VERSION
) {
409 error("Invalid packet back from SSH2_FXP_INIT (type %u)",
415 if ((r
= sshbuf_get_u32(msg
, &ret
->version
)) != 0)
416 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
418 debug2("Remote version: %u", ret
->version
);
420 /* Check for extensions */
421 while (sshbuf_len(msg
) > 0) {
427 if ((r
= sshbuf_get_cstring(msg
, &name
, NULL
)) != 0 ||
428 (r
= sshbuf_get_string(msg
, &value
, &vlen
)) != 0)
429 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
430 if (strcmp(name
, "posix-rename@openssh.com") == 0 &&
431 strcmp((char *)value
, "1") == 0) {
432 ret
->exts
|= SFTP_EXT_POSIX_RENAME
;
434 } else if (strcmp(name
, "statvfs@openssh.com") == 0 &&
435 strcmp((char *)value
, "2") == 0) {
436 ret
->exts
|= SFTP_EXT_STATVFS
;
438 } else if (strcmp(name
, "fstatvfs@openssh.com") == 0 &&
439 strcmp((char *)value
, "2") == 0) {
440 ret
->exts
|= SFTP_EXT_FSTATVFS
;
442 } else if (strcmp(name
, "hardlink@openssh.com") == 0 &&
443 strcmp((char *)value
, "1") == 0) {
444 ret
->exts
|= SFTP_EXT_HARDLINK
;
446 } else if (strcmp(name
, "fsync@openssh.com") == 0 &&
447 strcmp((char *)value
, "1") == 0) {
448 ret
->exts
|= SFTP_EXT_FSYNC
;
452 debug2("Server supports extension \"%s\" revision %s",
455 debug2("Unrecognised server extension \"%s\"", name
);
463 /* Some filexfer v.0 servers don't support large packets */
464 if (ret
->version
== 0)
465 ret
->transfer_buflen
= MIN(ret
->transfer_buflen
, 20480);
467 ret
->limit_kbps
= limit_kbps
;
468 if (ret
->limit_kbps
> 0) {
469 bandwidth_limit_init(&ret
->bwlimit_in
, ret
->limit_kbps
,
470 ret
->transfer_buflen
);
471 bandwidth_limit_init(&ret
->bwlimit_out
, ret
->limit_kbps
,
472 ret
->transfer_buflen
);
479 sftp_proto_version(struct sftp_conn
*conn
)
481 return conn
->version
;
485 do_close(struct sftp_conn
*conn
, const u_char
*handle
, u_int handle_len
)
491 if ((msg
= sshbuf_new()) == NULL
)
492 fatal("%s: sshbuf_new failed", __func__
);
495 if ((r
= sshbuf_put_u8(msg
, SSH2_FXP_CLOSE
)) != 0 ||
496 (r
= sshbuf_put_u32(msg
, id
)) != 0 ||
497 (r
= sshbuf_put_string(msg
, handle
, handle_len
)) != 0)
498 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
500 debug3("Sent message SSH2_FXP_CLOSE I:%u", id
);
502 status
= get_status(conn
, id
);
503 if (status
!= SSH2_FX_OK
)
504 error("Couldn't close file: %s", fx2txt(status
));
508 return status
== SSH2_FX_OK
? 0 : -1;
513 do_lsreaddir(struct sftp_conn
*conn
, const char *path
, int print_flag
,
517 u_int count
, id
, i
, expected_id
, ents
= 0;
519 u_char type
, *handle
;
520 int status
= SSH2_FX_FAILURE
;
528 if ((msg
= sshbuf_new()) == NULL
)
529 fatal("%s: sshbuf_new failed", __func__
);
530 if ((r
= sshbuf_put_u8(msg
, SSH2_FXP_OPENDIR
)) != 0 ||
531 (r
= sshbuf_put_u32(msg
, id
)) != 0 ||
532 (r
= sshbuf_put_cstring(msg
, path
)) != 0)
533 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
536 handle
= get_handle(conn
, id
, &handle_len
,
537 "remote readdir(\"%s\")", path
);
538 if (handle
== NULL
) {
545 *dir
= xcalloc(1, sizeof(**dir
));
549 for (; !interrupted
;) {
550 id
= expected_id
= conn
->msg_id
++;
552 debug3("Sending SSH2_FXP_READDIR I:%u", id
);
555 if ((r
= sshbuf_put_u8(msg
, SSH2_FXP_READDIR
)) != 0 ||
556 (r
= sshbuf_put_u32(msg
, id
)) != 0 ||
557 (r
= sshbuf_put_string(msg
, handle
, handle_len
)) != 0)
558 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
565 if ((r
= sshbuf_get_u8(msg
, &type
)) != 0 ||
566 (r
= sshbuf_get_u32(msg
, &id
)) != 0)
567 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
569 debug3("Received reply T:%u I:%u", type
, id
);
571 if (id
!= expected_id
)
572 fatal("ID mismatch (%u != %u)", id
, expected_id
);
574 if (type
== SSH2_FXP_STATUS
) {
577 if ((r
= sshbuf_get_u32(msg
, &rstatus
)) != 0)
578 fatal("%s: buffer error: %s",
579 __func__
, ssh_err(r
));
580 debug3("Received SSH2_FXP_STATUS %d", rstatus
);
581 if (rstatus
== SSH2_FX_EOF
)
583 error("Couldn't read directory: %s", fx2txt(rstatus
));
585 } else if (type
!= SSH2_FXP_NAME
)
586 fatal("Expected SSH2_FXP_NAME(%u) packet, got %u",
587 SSH2_FXP_NAME
, type
);
589 if ((r
= sshbuf_get_u32(msg
, &count
)) != 0)
590 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
593 debug3("Received %d SSH2_FXP_NAME responses", count
);
594 for (i
= 0; i
< count
; i
++) {
595 char *filename
, *longname
;
598 if ((r
= sshbuf_get_cstring(msg
, &filename
,
600 (r
= sshbuf_get_cstring(msg
, &longname
,
602 fatal("%s: buffer error: %s",
603 __func__
, ssh_err(r
));
604 if ((r
= decode_attrib(msg
, &a
)) != 0) {
605 error("%s: couldn't decode attrib: %s",
606 __func__
, ssh_err(r
));
614 mprintf("%s\n", longname
);
617 * Directory entries should never contain '/'
618 * These can be used to attack recursive ops
619 * (e.g. send '../../../../etc/passwd')
621 if (strchr(filename
, '/') != NULL
) {
622 error("Server sent suspect path \"%s\" "
623 "during readdir of \"%s\"", filename
, path
);
625 *dir
= xreallocarray(*dir
, ents
+ 2, sizeof(**dir
));
626 (*dir
)[ents
] = xcalloc(1, sizeof(***dir
));
627 (*dir
)[ents
]->filename
= xstrdup(filename
);
628 (*dir
)[ents
]->longname
= xstrdup(longname
);
629 memcpy(&(*dir
)[ents
]->a
, &a
, sizeof(a
));
630 (*dir
)[++ents
] = NULL
;
640 do_close(conn
, handle
, handle_len
);
643 if (status
!= 0 && dir
!= NULL
) {
644 /* Don't return results on error */
645 free_sftp_dirents(*dir
);
647 } else if (interrupted
&& dir
!= NULL
&& *dir
!= NULL
) {
648 /* Don't return partial matches on interrupt */
649 free_sftp_dirents(*dir
);
650 *dir
= xcalloc(1, sizeof(**dir
));
658 do_readdir(struct sftp_conn
*conn
, const char *path
, SFTP_DIRENT
***dir
)
660 return(do_lsreaddir(conn
, path
, 0, dir
));
663 void free_sftp_dirents(SFTP_DIRENT
**s
)
669 for (i
= 0; s
[i
]; i
++) {
670 free(s
[i
]->filename
);
671 free(s
[i
]->longname
);
678 do_rm(struct sftp_conn
*conn
, const char *path
)
682 debug2("Sending SSH2_FXP_REMOVE \"%s\"", path
);
685 send_string_request(conn
, id
, SSH2_FXP_REMOVE
, path
, strlen(path
));
686 status
= get_status(conn
, id
);
687 if (status
!= SSH2_FX_OK
)
688 error("Couldn't delete file: %s", fx2txt(status
));
689 return status
== SSH2_FX_OK
? 0 : -1;
693 do_mkdir(struct sftp_conn
*conn
, const char *path
, Attrib
*a
, int print_flag
)
698 send_string_attrs_request(conn
, id
, SSH2_FXP_MKDIR
, path
,
701 status
= get_status(conn
, id
);
702 if (status
!= SSH2_FX_OK
&& print_flag
)
703 error("Couldn't create directory: %s", fx2txt(status
));
705 return status
== SSH2_FX_OK
? 0 : -1;
709 do_rmdir(struct sftp_conn
*conn
, const char *path
)
714 send_string_request(conn
, id
, SSH2_FXP_RMDIR
, path
,
717 status
= get_status(conn
, id
);
718 if (status
!= SSH2_FX_OK
)
719 error("Couldn't remove directory: %s", fx2txt(status
));
721 return status
== SSH2_FX_OK
? 0 : -1;
725 do_stat(struct sftp_conn
*conn
, const char *path
, int quiet
)
731 send_string_request(conn
, id
,
732 conn
->version
== 0 ? SSH2_FXP_STAT_VERSION_0
: SSH2_FXP_STAT
,
735 return(get_decode_stat(conn
, id
, quiet
));
739 do_lstat(struct sftp_conn
*conn
, const char *path
, int quiet
)
743 if (conn
->version
== 0) {
745 debug("Server version does not support lstat operation");
747 logit("Server version does not support lstat operation");
748 return(do_stat(conn
, path
, quiet
));
752 send_string_request(conn
, id
, SSH2_FXP_LSTAT
, path
,
755 return(get_decode_stat(conn
, id
, quiet
));
760 do_fstat(struct sftp_conn
*conn
, const u_char
*handle
, u_int handle_len
,
766 send_string_request(conn
, id
, SSH2_FXP_FSTAT
, handle
,
769 return(get_decode_stat(conn
, id
, quiet
));
774 do_setstat(struct sftp_conn
*conn
, const char *path
, Attrib
*a
)
779 send_string_attrs_request(conn
, id
, SSH2_FXP_SETSTAT
, path
,
782 status
= get_status(conn
, id
);
783 if (status
!= SSH2_FX_OK
)
784 error("Couldn't setstat on \"%s\": %s", path
,
787 return status
== SSH2_FX_OK
? 0 : -1;
791 do_fsetstat(struct sftp_conn
*conn
, const u_char
*handle
, u_int handle_len
,
797 send_string_attrs_request(conn
, id
, SSH2_FXP_FSETSTAT
, handle
,
800 status
= get_status(conn
, id
);
801 if (status
!= SSH2_FX_OK
)
802 error("Couldn't fsetstat: %s", fx2txt(status
));
804 return status
== SSH2_FX_OK
? 0 : -1;
808 do_realpath(struct sftp_conn
*conn
, const char *path
)
811 u_int expected_id
, count
, id
;
812 char *filename
, *longname
;
817 expected_id
= id
= conn
->msg_id
++;
818 send_string_request(conn
, id
, SSH2_FXP_REALPATH
, path
,
821 if ((msg
= sshbuf_new()) == NULL
)
822 fatal("%s: sshbuf_new failed", __func__
);
825 if ((r
= sshbuf_get_u8(msg
, &type
)) != 0 ||
826 (r
= sshbuf_get_u32(msg
, &id
)) != 0)
827 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
829 if (id
!= expected_id
)
830 fatal("ID mismatch (%u != %u)", id
, expected_id
);
832 if (type
== SSH2_FXP_STATUS
) {
835 if ((r
= sshbuf_get_u32(msg
, &status
)) != 0)
836 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
837 error("Couldn't canonicalize: %s", fx2txt(status
));
840 } else if (type
!= SSH2_FXP_NAME
)
841 fatal("Expected SSH2_FXP_NAME(%u) packet, got %u",
842 SSH2_FXP_NAME
, type
);
844 if ((r
= sshbuf_get_u32(msg
, &count
)) != 0)
845 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
847 fatal("Got multiple names (%d) from SSH_FXP_REALPATH", count
);
849 if ((r
= sshbuf_get_cstring(msg
, &filename
, NULL
)) != 0 ||
850 (r
= sshbuf_get_cstring(msg
, &longname
, NULL
)) != 0 ||
851 (r
= decode_attrib(msg
, &a
)) != 0)
852 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
854 debug3("SSH_FXP_REALPATH %s -> %s size %lu", path
, filename
,
855 (unsigned long)a
.size
);
865 do_rename(struct sftp_conn
*conn
, const char *oldpath
, const char *newpath
,
870 int r
, use_ext
= (conn
->exts
& SFTP_EXT_POSIX_RENAME
) && !force_legacy
;
872 if ((msg
= sshbuf_new()) == NULL
)
873 fatal("%s: sshbuf_new failed", __func__
);
875 /* Send rename request */
878 if ((r
= sshbuf_put_u8(msg
, SSH2_FXP_EXTENDED
)) != 0 ||
879 (r
= sshbuf_put_u32(msg
, id
)) != 0 ||
880 (r
= sshbuf_put_cstring(msg
,
881 "posix-rename@openssh.com")) != 0)
882 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
884 if ((r
= sshbuf_put_u8(msg
, SSH2_FXP_RENAME
)) != 0 ||
885 (r
= sshbuf_put_u32(msg
, id
)) != 0)
886 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
888 if ((r
= sshbuf_put_cstring(msg
, oldpath
)) != 0 ||
889 (r
= sshbuf_put_cstring(msg
, newpath
)) != 0)
890 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
892 debug3("Sent message %s \"%s\" -> \"%s\"",
893 use_ext
? "posix-rename@openssh.com" :
894 "SSH2_FXP_RENAME", oldpath
, newpath
);
897 status
= get_status(conn
, id
);
898 if (status
!= SSH2_FX_OK
)
899 error("Couldn't rename file \"%s\" to \"%s\": %s", oldpath
,
900 newpath
, fx2txt(status
));
902 return status
== SSH2_FX_OK
? 0 : -1;
906 do_hardlink(struct sftp_conn
*conn
, const char *oldpath
, const char *newpath
)
912 if ((conn
->exts
& SFTP_EXT_HARDLINK
) == 0) {
913 error("Server does not support hardlink@openssh.com extension");
917 if ((msg
= sshbuf_new()) == NULL
)
918 fatal("%s: sshbuf_new failed", __func__
);
920 /* Send link request */
922 if ((r
= sshbuf_put_u8(msg
, SSH2_FXP_EXTENDED
)) != 0 ||
923 (r
= sshbuf_put_u32(msg
, id
)) != 0 ||
924 (r
= sshbuf_put_cstring(msg
, "hardlink@openssh.com")) != 0 ||
925 (r
= sshbuf_put_cstring(msg
, oldpath
)) != 0 ||
926 (r
= sshbuf_put_cstring(msg
, newpath
)) != 0)
927 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
929 debug3("Sent message hardlink@openssh.com \"%s\" -> \"%s\"",
933 status
= get_status(conn
, id
);
934 if (status
!= SSH2_FX_OK
)
935 error("Couldn't link file \"%s\" to \"%s\": %s", oldpath
,
936 newpath
, fx2txt(status
));
938 return status
== SSH2_FX_OK
? 0 : -1;
942 do_symlink(struct sftp_conn
*conn
, const char *oldpath
, const char *newpath
)
948 if (conn
->version
< 3) {
949 error("This server does not support the symlink operation");
950 return(SSH2_FX_OP_UNSUPPORTED
);
953 if ((msg
= sshbuf_new()) == NULL
)
954 fatal("%s: sshbuf_new failed", __func__
);
956 /* Send symlink request */
958 if ((r
= sshbuf_put_u8(msg
, SSH2_FXP_SYMLINK
)) != 0 ||
959 (r
= sshbuf_put_u32(msg
, id
)) != 0 ||
960 (r
= sshbuf_put_cstring(msg
, oldpath
)) != 0 ||
961 (r
= sshbuf_put_cstring(msg
, newpath
)) != 0)
962 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
964 debug3("Sent message SSH2_FXP_SYMLINK \"%s\" -> \"%s\"", oldpath
,
968 status
= get_status(conn
, id
);
969 if (status
!= SSH2_FX_OK
)
970 error("Couldn't symlink file \"%s\" to \"%s\": %s", oldpath
,
971 newpath
, fx2txt(status
));
973 return status
== SSH2_FX_OK
? 0 : -1;
977 do_fsync(struct sftp_conn
*conn
, u_char
*handle
, u_int handle_len
)
983 /* Silently return if the extension is not supported */
984 if ((conn
->exts
& SFTP_EXT_FSYNC
) == 0)
987 /* Send fsync request */
988 if ((msg
= sshbuf_new()) == NULL
)
989 fatal("%s: sshbuf_new failed", __func__
);
991 if ((r
= sshbuf_put_u8(msg
, SSH2_FXP_EXTENDED
)) != 0 ||
992 (r
= sshbuf_put_u32(msg
, id
)) != 0 ||
993 (r
= sshbuf_put_cstring(msg
, "fsync@openssh.com")) != 0 ||
994 (r
= sshbuf_put_string(msg
, handle
, handle_len
)) != 0)
995 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
997 debug3("Sent message fsync@openssh.com I:%u", id
);
1000 status
= get_status(conn
, id
);
1001 if (status
!= SSH2_FX_OK
)
1002 error("Couldn't sync file: %s", fx2txt(status
));
1009 do_readlink(struct sftp_conn
*conn
, const char *path
)
1012 u_int expected_id
, count
, id
;
1013 char *filename
, *longname
;
1018 expected_id
= id
= conn
->msg_id
++;
1019 send_string_request(conn
, id
, SSH2_FXP_READLINK
, path
, strlen(path
));
1021 if ((msg
= sshbuf_new()) == NULL
)
1022 fatal("%s: sshbuf_new failed", __func__
);
1025 if ((r
= sshbuf_get_u8(msg
, &type
)) != 0 ||
1026 (r
= sshbuf_get_u32(msg
, &id
)) != 0)
1027 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
1029 if (id
!= expected_id
)
1030 fatal("ID mismatch (%u != %u)", id
, expected_id
);
1032 if (type
== SSH2_FXP_STATUS
) {
1035 if ((r
= sshbuf_get_u32(msg
, &status
)) != 0)
1036 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
1037 error("Couldn't readlink: %s", fx2txt(status
));
1040 } else if (type
!= SSH2_FXP_NAME
)
1041 fatal("Expected SSH2_FXP_NAME(%u) packet, got %u",
1042 SSH2_FXP_NAME
, type
);
1044 if ((r
= sshbuf_get_u32(msg
, &count
)) != 0)
1045 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
1047 fatal("Got multiple names (%d) from SSH_FXP_READLINK", count
);
1049 if ((r
= sshbuf_get_cstring(msg
, &filename
, NULL
)) != 0 ||
1050 (r
= sshbuf_get_cstring(msg
, &longname
, NULL
)) != 0 ||
1051 (r
= decode_attrib(msg
, &a
)) != 0)
1052 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
1054 debug3("SSH_FXP_READLINK %s -> %s", path
, filename
);
1065 do_statvfs(struct sftp_conn
*conn
, const char *path
, struct sftp_statvfs
*st
,
1072 if ((conn
->exts
& SFTP_EXT_STATVFS
) == 0) {
1073 error("Server does not support statvfs@openssh.com extension");
1077 id
= conn
->msg_id
++;
1079 if ((msg
= sshbuf_new()) == NULL
)
1080 fatal("%s: sshbuf_new failed", __func__
);
1082 if ((r
= sshbuf_put_u8(msg
, SSH2_FXP_EXTENDED
)) != 0 ||
1083 (r
= sshbuf_put_u32(msg
, id
)) != 0 ||
1084 (r
= sshbuf_put_cstring(msg
, "statvfs@openssh.com")) != 0 ||
1085 (r
= sshbuf_put_cstring(msg
, path
)) != 0)
1086 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
1087 send_msg(conn
, msg
);
1090 return get_decode_statvfs(conn
, st
, id
, quiet
);
1095 do_fstatvfs(struct sftp_conn
*conn
, const u_char
*handle
, u_int handle_len
,
1096 struct sftp_statvfs
*st
, int quiet
)
1101 if ((conn
->exts
& SFTP_EXT_FSTATVFS
) == 0) {
1102 error("Server does not support fstatvfs@openssh.com extension");
1106 id
= conn
->msg_id
++;
1108 if ((msg
= sshbuf_new()) == NULL
)
1109 fatal("%s: sshbuf_new failed", __func__
);
1111 if ((r
= sshbuf_put_u8(msg
, SSH2_FXP_EXTENDED
)) != 0 ||
1112 (r
= sshbuf_put_u32(msg
, id
)) != 0 ||
1113 (r
= sshbuf_put_cstring(msg
, "fstatvfs@openssh.com")) != 0 ||
1114 (r
= sshbuf_put_string(msg
, handle
, handle_len
)) != 0)
1115 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
1116 send_msg(conn
, msg
);
1119 return get_decode_statvfs(conn
, st
, id
, quiet
);
1124 send_read_request(struct sftp_conn
*conn
, u_int id
, u_int64_t offset
,
1125 u_int len
, const u_char
*handle
, u_int handle_len
)
1130 if ((msg
= sshbuf_new()) == NULL
)
1131 fatal("%s: sshbuf_new failed", __func__
);
1133 if ((r
= sshbuf_put_u8(msg
, SSH2_FXP_READ
)) != 0 ||
1134 (r
= sshbuf_put_u32(msg
, id
)) != 0 ||
1135 (r
= sshbuf_put_string(msg
, handle
, handle_len
)) != 0 ||
1136 (r
= sshbuf_put_u64(msg
, offset
)) != 0 ||
1137 (r
= sshbuf_put_u32(msg
, len
)) != 0)
1138 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
1139 send_msg(conn
, msg
);
1144 do_download(struct sftp_conn
*conn
, const char *remote_path
,
1145 const char *local_path
, Attrib
*a
, int preserve_flag
, int resume_flag
,
1151 int local_fd
= -1, write_error
;
1152 int read_error
, write_errno
, reordered
= 0, r
;
1153 u_int64_t offset
= 0, size
, highwater
;
1154 u_int mode
, id
, buflen
, num_req
, max_req
, status
= SSH2_FX_OK
;
1155 off_t progress_counter
;
1162 TAILQ_ENTRY(request
) tq
;
1164 TAILQ_HEAD(reqhead
, request
) requests
;
1165 struct request
*req
;
1168 TAILQ_INIT(&requests
);
1170 if (a
== NULL
&& (a
= do_stat(conn
, remote_path
, 0)) == NULL
)
1173 /* Do not preserve set[ug]id here, as we do not preserve ownership */
1174 if (a
->flags
& SSH2_FILEXFER_ATTR_PERMISSIONS
)
1175 mode
= a
->perm
& 0777;
1179 if ((a
->flags
& SSH2_FILEXFER_ATTR_PERMISSIONS
) &&
1180 (!S_ISREG(a
->perm
))) {
1181 error("Cannot download non-regular file: %s", remote_path
);
1185 if (a
->flags
& SSH2_FILEXFER_ATTR_SIZE
)
1190 buflen
= conn
->transfer_buflen
;
1191 if ((msg
= sshbuf_new()) == NULL
)
1192 fatal("%s: sshbuf_new failed", __func__
);
1194 attrib_clear(&junk
); /* Send empty attributes */
1196 /* Send open request */
1197 id
= conn
->msg_id
++;
1198 if ((r
= sshbuf_put_u8(msg
, SSH2_FXP_OPEN
)) != 0 ||
1199 (r
= sshbuf_put_u32(msg
, id
)) != 0 ||
1200 (r
= sshbuf_put_cstring(msg
, remote_path
)) != 0 ||
1201 (r
= sshbuf_put_u32(msg
, SSH2_FXF_READ
)) != 0 ||
1202 (r
= encode_attrib(msg
, &junk
)) != 0)
1203 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
1204 send_msg(conn
, msg
);
1205 debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id
, remote_path
);
1207 handle
= get_handle(conn
, id
, &handle_len
,
1208 "remote open(\"%s\")", remote_path
);
1209 if (handle
== NULL
) {
1214 local_fd
= open(local_path
,
1215 O_WRONLY
| O_CREAT
| (resume_flag
? 0 : O_TRUNC
), mode
| S_IWUSR
);
1216 if (local_fd
== -1) {
1217 error("Couldn't open local file \"%s\" for writing: %s",
1218 local_path
, strerror(errno
));
1221 offset
= highwater
= 0;
1223 if (fstat(local_fd
, &st
) == -1) {
1224 error("Unable to stat local file \"%s\": %s",
1225 local_path
, strerror(errno
));
1228 if (st
.st_size
< 0) {
1229 error("\"%s\" has negative size", local_path
);
1232 if ((u_int64_t
)st
.st_size
> size
) {
1233 error("Unable to resume download of \"%s\": "
1234 "local file is larger than remote", local_path
);
1236 do_close(conn
, handle
, handle_len
);
1243 offset
= highwater
= st
.st_size
;
1246 /* Read from remote and write to local */
1247 write_error
= read_error
= write_errno
= num_req
= 0;
1249 progress_counter
= offset
;
1251 if (showprogress
&& size
!= 0)
1252 start_progress_meter(remote_path
, size
, &progress_counter
);
1254 while (num_req
> 0 || max_req
> 0) {
1259 * Simulate EOF on interrupt: stop sending new requests and
1260 * allow outstanding requests to drain gracefully
1263 if (num_req
== 0) /* If we haven't started yet... */
1268 /* Send some more requests */
1269 while (num_req
< max_req
) {
1270 debug3("Request range %llu -> %llu (%d/%d)",
1271 (unsigned long long)offset
,
1272 (unsigned long long)offset
+ buflen
- 1,
1274 req
= xcalloc(1, sizeof(*req
));
1275 req
->id
= conn
->msg_id
++;
1277 req
->offset
= offset
;
1280 TAILQ_INSERT_TAIL(&requests
, req
, tq
);
1281 send_read_request(conn
, req
->id
, req
->offset
,
1282 req
->len
, handle
, handle_len
);
1287 if ((r
= sshbuf_get_u8(msg
, &type
)) != 0 ||
1288 (r
= sshbuf_get_u32(msg
, &id
)) != 0)
1289 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
1290 debug3("Received reply T:%u I:%u R:%d", type
, id
, max_req
);
1292 /* Find the request in our queue */
1293 for (req
= TAILQ_FIRST(&requests
);
1294 req
!= NULL
&& req
->id
!= id
;
1295 req
= TAILQ_NEXT(req
, tq
))
1298 fatal("Unexpected reply %u", id
);
1301 case SSH2_FXP_STATUS
:
1302 if ((r
= sshbuf_get_u32(msg
, &status
)) != 0)
1303 fatal("%s: buffer error: %s",
1304 __func__
, ssh_err(r
));
1305 if (status
!= SSH2_FX_EOF
)
1308 TAILQ_REMOVE(&requests
, req
, tq
);
1313 if ((r
= sshbuf_get_string(msg
, &data
, &len
)) != 0)
1314 fatal("%s: buffer error: %s",
1315 __func__
, ssh_err(r
));
1316 debug3("Received data %llu -> %llu",
1317 (unsigned long long)req
->offset
,
1318 (unsigned long long)req
->offset
+ len
- 1);
1320 fatal("Received more data than asked for "
1321 "%zu > %zu", len
, req
->len
);
1322 if ((lseek(local_fd
, req
->offset
, SEEK_SET
) == -1 ||
1323 atomicio(vwrite
, local_fd
, data
, len
) != len
) &&
1325 write_errno
= errno
;
1329 else if (!reordered
&& req
->offset
<= highwater
)
1330 highwater
= req
->offset
+ len
;
1331 else if (!reordered
&& req
->offset
> highwater
)
1333 progress_counter
+= len
;
1336 if (len
== req
->len
) {
1337 TAILQ_REMOVE(&requests
, req
, tq
);
1341 /* Resend the request for the missing data */
1342 debug3("Short data block, re-requesting "
1343 "%llu -> %llu (%2d)",
1344 (unsigned long long)req
->offset
+ len
,
1345 (unsigned long long)req
->offset
+
1346 req
->len
- 1, num_req
);
1347 req
->id
= conn
->msg_id
++;
1350 send_read_request(conn
, req
->id
,
1351 req
->offset
, req
->len
, handle
, handle_len
);
1352 /* Reduce the request size */
1354 buflen
= MAX(MIN_READ_SIZE
, len
);
1356 if (max_req
> 0) { /* max_req = 0 iff EOF received */
1357 if (size
> 0 && offset
> size
) {
1358 /* Only one request at a time
1359 * after the expected EOF */
1360 debug3("Finish at %llu (%2d)",
1361 (unsigned long long)offset
,
1364 } else if (max_req
<= conn
->num_requests
) {
1370 fatal("Expected SSH2_FXP_DATA(%u) packet, got %u",
1371 SSH2_FXP_DATA
, type
);
1375 if (showprogress
&& size
)
1376 stop_progress_meter();
1379 if (TAILQ_FIRST(&requests
) != NULL
)
1380 fatal("Transfer complete, but requests still in queue");
1381 /* Truncate at highest contiguous point to avoid holes on interrupt */
1382 if (read_error
|| write_error
|| interrupted
) {
1383 if (reordered
&& resume_flag
) {
1384 error("Unable to resume download of \"%s\": "
1385 "server reordered requests", local_path
);
1387 debug("truncating at %llu", (unsigned long long)highwater
);
1388 if (ftruncate(local_fd
, highwater
) == -1)
1389 error("ftruncate \"%s\": %s", local_path
,
1393 error("Couldn't read from remote file \"%s\" : %s",
1394 remote_path
, fx2txt(status
));
1396 do_close(conn
, handle
, handle_len
);
1397 } else if (write_error
) {
1398 error("Couldn't write to \"%s\": %s", local_path
,
1399 strerror(write_errno
));
1400 status
= SSH2_FX_FAILURE
;
1401 do_close(conn
, handle
, handle_len
);
1403 if (do_close(conn
, handle
, handle_len
) != 0 || interrupted
)
1404 status
= SSH2_FX_FAILURE
;
1406 status
= SSH2_FX_OK
;
1407 /* Override umask and utimes if asked */
1409 if (preserve_flag
&& fchmod(local_fd
, mode
) == -1)
1411 if (preserve_flag
&& chmod(local_path
, mode
) == -1)
1412 #endif /* HAVE_FCHMOD */
1413 error("Couldn't set mode on \"%s\": %s", local_path
,
1415 if (preserve_flag
&&
1416 (a
->flags
& SSH2_FILEXFER_ATTR_ACMODTIME
)) {
1417 struct timeval tv
[2];
1418 tv
[0].tv_sec
= a
->atime
;
1419 tv
[1].tv_sec
= a
->mtime
;
1420 tv
[0].tv_usec
= tv
[1].tv_usec
= 0;
1421 if (utimes(local_path
, tv
) == -1)
1422 error("Can't set times on \"%s\": %s",
1423 local_path
, strerror(errno
));
1426 debug("syncing \"%s\"", local_path
);
1427 if (fsync(local_fd
) == -1)
1428 error("Couldn't sync file \"%s\": %s",
1429 local_path
, strerror(errno
));
1440 download_dir_internal(struct sftp_conn
*conn
, const char *src
, const char *dst
,
1441 int depth
, Attrib
*dirattrib
, int preserve_flag
, int print_flag
,
1442 int resume_flag
, int fsync_flag
)
1445 SFTP_DIRENT
**dir_entries
;
1446 char *filename
, *new_src
, *new_dst
;
1449 if (depth
>= MAX_DIR_DEPTH
) {
1450 error("Maximum directory depth exceeded: %d levels", depth
);
1454 if (dirattrib
== NULL
&&
1455 (dirattrib
= do_stat(conn
, src
, 1)) == NULL
) {
1456 error("Unable to stat remote directory \"%s\"", src
);
1459 if (!S_ISDIR(dirattrib
->perm
)) {
1460 error("\"%s\" is not a directory", src
);
1464 mprintf("Retrieving %s\n", src
);
1466 if (dirattrib
->flags
& SSH2_FILEXFER_ATTR_PERMISSIONS
)
1467 mode
= dirattrib
->perm
& 01777;
1469 debug("Server did not send permissions for "
1470 "directory \"%s\"", dst
);
1473 if (mkdir(dst
, mode
) == -1 && errno
!= EEXIST
) {
1474 error("mkdir %s: %s", dst
, strerror(errno
));
1478 if (do_readdir(conn
, src
, &dir_entries
) == -1) {
1479 error("%s: Failed to get directory contents", src
);
1483 for (i
= 0; dir_entries
[i
] != NULL
&& !interrupted
; i
++) {
1484 filename
= dir_entries
[i
]->filename
;
1486 new_dst
= path_append(dst
, filename
);
1487 new_src
= path_append(src
, filename
);
1489 if (S_ISDIR(dir_entries
[i
]->a
.perm
)) {
1490 if (strcmp(filename
, ".") == 0 ||
1491 strcmp(filename
, "..") == 0)
1493 if (download_dir_internal(conn
, new_src
, new_dst
,
1494 depth
+ 1, &(dir_entries
[i
]->a
), preserve_flag
,
1495 print_flag
, resume_flag
, fsync_flag
) == -1)
1497 } else if (S_ISREG(dir_entries
[i
]->a
.perm
) ) {
1498 if (do_download(conn
, new_src
, new_dst
,
1499 &(dir_entries
[i
]->a
), preserve_flag
,
1500 resume_flag
, fsync_flag
) == -1) {
1501 error("Download of file %s to %s failed",
1506 logit("%s: not a regular file\n", new_src
);
1512 if (preserve_flag
) {
1513 if (dirattrib
->flags
& SSH2_FILEXFER_ATTR_ACMODTIME
) {
1514 struct timeval tv
[2];
1515 tv
[0].tv_sec
= dirattrib
->atime
;
1516 tv
[1].tv_sec
= dirattrib
->mtime
;
1517 tv
[0].tv_usec
= tv
[1].tv_usec
= 0;
1518 if (utimes(dst
, tv
) == -1)
1519 error("Can't set times on \"%s\": %s",
1520 dst
, strerror(errno
));
1522 debug("Server did not send times for directory "
1526 free_sftp_dirents(dir_entries
);
1532 download_dir(struct sftp_conn
*conn
, const char *src
, const char *dst
,
1533 Attrib
*dirattrib
, int preserve_flag
, int print_flag
, int resume_flag
,
1539 if ((src_canon
= do_realpath(conn
, src
)) == NULL
) {
1540 error("Unable to canonicalize path \"%s\"", src
);
1544 ret
= download_dir_internal(conn
, src_canon
, dst
, 0,
1545 dirattrib
, preserve_flag
, print_flag
, resume_flag
, fsync_flag
);
1551 do_upload(struct sftp_conn
*conn
, const char *local_path
,
1552 const char *remote_path
, int preserve_flag
, int resume
, int fsync_flag
)
1555 u_int status
= SSH2_FX_OK
;
1558 off_t offset
, progress_counter
;
1559 u_char
*handle
, *data
;
1562 Attrib a
, *c
= NULL
;
1565 struct outstanding_ack
{
1569 TAILQ_ENTRY(outstanding_ack
) tq
;
1571 TAILQ_HEAD(ackhead
, outstanding_ack
) acks
;
1572 struct outstanding_ack
*ack
= NULL
;
1577 if ((local_fd
= open(local_path
, O_RDONLY
, 0)) == -1) {
1578 error("Couldn't open local file \"%s\" for reading: %s",
1579 local_path
, strerror(errno
));
1582 if (fstat(local_fd
, &sb
) == -1) {
1583 error("Couldn't fstat local file \"%s\": %s",
1584 local_path
, strerror(errno
));
1588 if (!S_ISREG(sb
.st_mode
)) {
1589 error("%s is not a regular file", local_path
);
1593 stat_to_attrib(&sb
, &a
);
1595 a
.flags
&= ~SSH2_FILEXFER_ATTR_SIZE
;
1596 a
.flags
&= ~SSH2_FILEXFER_ATTR_UIDGID
;
1599 a
.flags
&= ~SSH2_FILEXFER_ATTR_ACMODTIME
;
1602 /* Get remote file size if it exists */
1603 if ((c
= do_stat(conn
, remote_path
, 0)) == NULL
) {
1608 if ((off_t
)c
->size
>= sb
.st_size
) {
1609 error("destination file bigger or same size as "
1615 if (lseek(local_fd
, (off_t
)c
->size
, SEEK_SET
) == -1) {
1621 if ((msg
= sshbuf_new()) == NULL
)
1622 fatal("%s: sshbuf_new failed", __func__
);
1624 /* Send open request */
1625 id
= conn
->msg_id
++;
1626 if ((r
= sshbuf_put_u8(msg
, SSH2_FXP_OPEN
)) != 0 ||
1627 (r
= sshbuf_put_u32(msg
, id
)) != 0 ||
1628 (r
= sshbuf_put_cstring(msg
, remote_path
)) != 0 ||
1629 (r
= sshbuf_put_u32(msg
, SSH2_FXF_WRITE
|SSH2_FXF_CREAT
|
1630 (resume
? SSH2_FXF_APPEND
: SSH2_FXF_TRUNC
))) != 0 ||
1631 (r
= encode_attrib(msg
, &a
)) != 0)
1632 fatal("%s: buffer error: %s", __func__
, ssh_err(r
));
1633 send_msg(conn
, msg
);
1634 debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id
, remote_path
);
1638 handle
= get_handle(conn
, id
, &handle_len
,
1639 "remote open(\"%s\")", remote_path
);
1640 if (handle
== NULL
) {
1646 startid
= ackid
= id
+ 1;
1647 data
= xmalloc(conn
->transfer_buflen
);
1649 /* Read from local and write to remote */
1650 offset
= progress_counter
= (resume
? c
->size
: 0);
1652 start_progress_meter(local_path
, sb
.st_size
,
1659 * Can't use atomicio here because it returns 0 on EOF,
1660 * thus losing the last block of the file.
1661 * Simulate an EOF on interrupt, allowing ACKs from the
1664 if (interrupted
|| status
!= SSH2_FX_OK
)
1667 len
= read(local_fd
, data
, conn
->transfer_buflen
);
1668 while ((len
== -1) &&
1669 (errno
== EINTR
|| errno
== EAGAIN
|| errno
== EWOULDBLOCK
));
1672 fatal("Couldn't read from \"%s\": %s", local_path
,
1676 ack
= xcalloc(1, sizeof(*ack
));
1678 ack
->offset
= offset
;
1680 TAILQ_INSERT_TAIL(&acks
, ack
, tq
);
1683 if ((r
= sshbuf_put_u8(msg
, SSH2_FXP_WRITE
)) != 0 ||
1684 (r
= sshbuf_put_u32(msg
, ack
->id
)) != 0 ||
1685 (r
= sshbuf_put_string(msg
, handle
,
1686 handle_len
)) != 0 ||
1687 (r
= sshbuf_put_u64(msg
, offset
)) != 0 ||
1688 (r
= sshbuf_put_string(msg
, data
, len
)) != 0)
1689 fatal("%s: buffer error: %s",
1690 __func__
, ssh_err(r
));
1691 send_msg(conn
, msg
);
1692 debug3("Sent message SSH2_FXP_WRITE I:%u O:%llu S:%u",
1693 id
, (unsigned long long)offset
, len
);
1694 } else if (TAILQ_FIRST(&acks
) == NULL
)
1698 fatal("Unexpected ACK %u", id
);
1700 if (id
== startid
|| len
== 0 ||
1701 id
- ackid
>= conn
->num_requests
) {
1706 if ((r
= sshbuf_get_u8(msg
, &type
)) != 0 ||
1707 (r
= sshbuf_get_u32(msg
, &rid
)) != 0)
1708 fatal("%s: buffer error: %s",
1709 __func__
, ssh_err(r
));
1711 if (type
!= SSH2_FXP_STATUS
)
1712 fatal("Expected SSH2_FXP_STATUS(%d) packet, "
1713 "got %d", SSH2_FXP_STATUS
, type
);
1715 if ((r
= sshbuf_get_u32(msg
, &status
)) != 0)
1716 fatal("%s: buffer error: %s",
1717 __func__
, ssh_err(r
));
1718 debug3("SSH2_FXP_STATUS %u", status
);
1720 /* Find the request in our queue */
1721 for (ack
= TAILQ_FIRST(&acks
);
1722 ack
!= NULL
&& ack
->id
!= rid
;
1723 ack
= TAILQ_NEXT(ack
, tq
))
1726 fatal("Can't find request for ID %u", rid
);
1727 TAILQ_REMOVE(&acks
, ack
, tq
);
1728 debug3("In write loop, ack for %u %u bytes at %lld",
1729 ack
->id
, ack
->len
, (long long)ack
->offset
);
1731 progress_counter
+= ack
->len
;
1736 fatal("%s: offset < 0", __func__
);
1741 stop_progress_meter();
1744 if (status
!= SSH2_FX_OK
) {
1745 error("Couldn't write to remote file \"%s\": %s",
1746 remote_path
, fx2txt(status
));
1747 status
= SSH2_FX_FAILURE
;
1750 if (close(local_fd
) == -1) {
1751 error("Couldn't close local file \"%s\": %s", local_path
,
1753 status
= SSH2_FX_FAILURE
;
1756 /* Override umask and utimes if asked */
1758 do_fsetstat(conn
, handle
, handle_len
, &a
);
1761 (void)do_fsync(conn
, handle
, handle_len
);
1763 if (do_close(conn
, handle
, handle_len
) != 0)
1764 status
= SSH2_FX_FAILURE
;
1768 return status
== SSH2_FX_OK
? 0 : -1;
1772 upload_dir_internal(struct sftp_conn
*conn
, const char *src
, const char *dst
,
1773 int depth
, int preserve_flag
, int print_flag
, int resume
, int fsync_flag
)
1778 char *filename
, *new_src
, *new_dst
;
1780 Attrib a
, *dirattrib
;
1782 if (depth
>= MAX_DIR_DEPTH
) {
1783 error("Maximum directory depth exceeded: %d levels", depth
);
1787 if (stat(src
, &sb
) == -1) {
1788 error("Couldn't stat directory \"%s\": %s",
1789 src
, strerror(errno
));
1792 if (!S_ISDIR(sb
.st_mode
)) {
1793 error("\"%s\" is not a directory", src
);
1797 mprintf("Entering %s\n", src
);
1800 stat_to_attrib(&sb
, &a
);
1801 a
.flags
&= ~SSH2_FILEXFER_ATTR_SIZE
;
1802 a
.flags
&= ~SSH2_FILEXFER_ATTR_UIDGID
;
1805 a
.flags
&= ~SSH2_FILEXFER_ATTR_ACMODTIME
;
1808 * sftp lacks a portable status value to match errno EEXIST,
1809 * so if we get a failure back then we must check whether
1810 * the path already existed and is a directory.
1812 if (do_mkdir(conn
, dst
, &a
, 0) != 0) {
1813 if ((dirattrib
= do_stat(conn
, dst
, 0)) == NULL
)
1815 if (!S_ISDIR(dirattrib
->perm
)) {
1816 error("\"%s\" exists but is not a directory", dst
);
1821 if ((dirp
= opendir(src
)) == NULL
) {
1822 error("Failed to open dir \"%s\": %s", src
, strerror(errno
));
1826 while (((dp
= readdir(dirp
)) != NULL
) && !interrupted
) {
1829 filename
= dp
->d_name
;
1830 new_dst
= path_append(dst
, filename
);
1831 new_src
= path_append(src
, filename
);
1833 if (lstat(new_src
, &sb
) == -1) {
1834 logit("%s: lstat failed: %s", filename
,
1837 } else if (S_ISDIR(sb
.st_mode
)) {
1838 if (strcmp(filename
, ".") == 0 ||
1839 strcmp(filename
, "..") == 0)
1842 if (upload_dir_internal(conn
, new_src
, new_dst
,
1843 depth
+ 1, preserve_flag
, print_flag
, resume
,
1846 } else if (S_ISREG(sb
.st_mode
)) {
1847 if (do_upload(conn
, new_src
, new_dst
,
1848 preserve_flag
, resume
, fsync_flag
) == -1) {
1849 error("Uploading of file %s to %s failed!",
1854 logit("%s: not a regular file\n", filename
);
1859 do_setstat(conn
, dst
, &a
);
1861 (void) closedir(dirp
);
1866 upload_dir(struct sftp_conn
*conn
, const char *src
, const char *dst
,
1867 int preserve_flag
, int print_flag
, int resume
, int fsync_flag
)
1872 if ((dst_canon
= do_realpath(conn
, dst
)) == NULL
) {
1873 error("Unable to canonicalize path \"%s\"", dst
);
1877 ret
= upload_dir_internal(conn
, src
, dst_canon
, 0, preserve_flag
,
1878 print_flag
, resume
, fsync_flag
);
1885 path_append(const char *p1
, const char *p2
)
1888 size_t len
= strlen(p1
) + strlen(p2
) + 2;
1891 strlcpy(ret
, p1
, len
);
1892 if (p1
[0] != '\0' && p1
[strlen(p1
) - 1] != '/')
1893 strlcat(ret
, "/", len
);
1894 strlcat(ret
, p2
, len
);