Deleted Added
full compact
sftp-client.c (181110) sftp-client.c (181111)
1/* $OpenBSD: sftp-client.c,v 1.75 2006/10/22 02:25:50 djm Exp $ */
1/* $OpenBSD: sftp-client.c,v 1.86 2008/06/26 06:10:09 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

--- 9 unchanged lines hidden (view full) ---

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#include <sys/param.h>
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

--- 9 unchanged lines hidden (view full) ---

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#include <sys/param.h>
27#ifdef HAVE_SYS_STATVFS_H
28#include <sys/statvfs.h>
29#endif
27#include "openbsd-compat/sys-queue.h"
28#ifdef HAVE_SYS_STAT_H
29# include <sys/stat.h>
30#endif
31#ifdef HAVE_SYS_TIME_H
32# include <sys/time.h>
33#endif
34#include <sys/uio.h>

--- 25 unchanged lines hidden (view full) ---

60
61struct sftp_conn {
62 int fd_in;
63 int fd_out;
64 u_int transfer_buflen;
65 u_int num_requests;
66 u_int version;
67 u_int msg_id;
30#include "openbsd-compat/sys-queue.h"
31#ifdef HAVE_SYS_STAT_H
32# include <sys/stat.h>
33#endif
34#ifdef HAVE_SYS_TIME_H
35# include <sys/time.h>
36#endif
37#include <sys/uio.h>

--- 25 unchanged lines hidden (view full) ---

63
64struct sftp_conn {
65 int fd_in;
66 int fd_out;
67 u_int transfer_buflen;
68 u_int num_requests;
69 u_int version;
70 u_int msg_id;
71#define SFTP_EXT_POSIX_RENAME 0x00000001
72#define SFTP_EXT_STATVFS 0x00000002
73#define SFTP_EXT_FSTATVFS 0x00000004
74 u_int exts;
68};
69
70static void
71send_msg(int fd, Buffer *m)
72{
73 u_char mlen[4];
74 struct iovec iov[2];
75

--- 155 unchanged lines hidden (view full) ---

231 SSH2_FXP_ATTRS, type);
232 }
233 a = decode_attrib(&msg);
234 buffer_free(&msg);
235
236 return(a);
237}
238
75};
76
77static void
78send_msg(int fd, Buffer *m)
79{
80 u_char mlen[4];
81 struct iovec iov[2];
82

--- 155 unchanged lines hidden (view full) ---

238 SSH2_FXP_ATTRS, type);
239 }
240 a = decode_attrib(&msg);
241 buffer_free(&msg);
242
243 return(a);
244}
245
246static int
247get_decode_statvfs(int fd, struct sftp_statvfs *st, u_int expected_id,
248 int quiet)
249{
250 Buffer msg;
251 u_int type, id, flag;
252
253 buffer_init(&msg);
254 get_msg(fd, &msg);
255
256 type = buffer_get_char(&msg);
257 id = buffer_get_int(&msg);
258
259 debug3("Received statvfs reply T:%u I:%u", type, id);
260 if (id != expected_id)
261 fatal("ID mismatch (%u != %u)", id, expected_id);
262 if (type == SSH2_FXP_STATUS) {
263 int status = buffer_get_int(&msg);
264
265 if (quiet)
266 debug("Couldn't statvfs: %s", fx2txt(status));
267 else
268 error("Couldn't statvfs: %s", fx2txt(status));
269 buffer_free(&msg);
270 return -1;
271 } else if (type != SSH2_FXP_EXTENDED_REPLY) {
272 fatal("Expected SSH2_FXP_EXTENDED_REPLY(%u) packet, got %u",
273 SSH2_FXP_EXTENDED_REPLY, type);
274 }
275
276 bzero(st, sizeof(*st));
277 st->f_bsize = buffer_get_int64(&msg);
278 st->f_frsize = buffer_get_int64(&msg);
279 st->f_blocks = buffer_get_int64(&msg);
280 st->f_bfree = buffer_get_int64(&msg);
281 st->f_bavail = buffer_get_int64(&msg);
282 st->f_files = buffer_get_int64(&msg);
283 st->f_ffree = buffer_get_int64(&msg);
284 st->f_favail = buffer_get_int64(&msg);
285 st->f_fsid = buffer_get_int64(&msg);
286 flag = buffer_get_int64(&msg);
287 st->f_namemax = buffer_get_int64(&msg);
288
289 st->f_flag = (flag & SSH2_FXE_STATVFS_ST_RDONLY) ? ST_RDONLY : 0;
290 st->f_flag |= (flag & SSH2_FXE_STATVFS_ST_NOSUID) ? ST_NOSUID : 0;
291
292 buffer_free(&msg);
293
294 return 0;
295}
296
239struct sftp_conn *
240do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests)
241{
297struct sftp_conn *
298do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests)
299{
242 u_int type;
300 u_int type, exts = 0;
243 int version;
244 Buffer msg;
245 struct sftp_conn *ret;
246
247 buffer_init(&msg);
248 buffer_put_char(&msg, SSH2_FXP_INIT);
249 buffer_put_int(&msg, SSH2_FILEXFER_VERSION);
250 send_msg(fd_out, &msg);

--- 12 unchanged lines hidden (view full) ---

263 version = buffer_get_int(&msg);
264
265 debug2("Remote version: %d", version);
266
267 /* Check for extensions */
268 while (buffer_len(&msg) > 0) {
269 char *name = buffer_get_string(&msg, NULL);
270 char *value = buffer_get_string(&msg, NULL);
301 int version;
302 Buffer msg;
303 struct sftp_conn *ret;
304
305 buffer_init(&msg);
306 buffer_put_char(&msg, SSH2_FXP_INIT);
307 buffer_put_int(&msg, SSH2_FILEXFER_VERSION);
308 send_msg(fd_out, &msg);

--- 12 unchanged lines hidden (view full) ---

321 version = buffer_get_int(&msg);
322
323 debug2("Remote version: %d", version);
324
325 /* Check for extensions */
326 while (buffer_len(&msg) > 0) {
327 char *name = buffer_get_string(&msg, NULL);
328 char *value = buffer_get_string(&msg, NULL);
329 int known = 0;
271
330
272 debug2("Init extension: \"%s\"", name);
331 if (strcmp(name, "posix-rename@openssh.com") == 0 &&
332 strcmp(value, "1") == 0) {
333 exts |= SFTP_EXT_POSIX_RENAME;
334 known = 1;
335 } else if (strcmp(name, "statvfs@openssh.com") == 0 &&
336 strcmp(value, "2") == 0) {
337 exts |= SFTP_EXT_STATVFS;
338 known = 1;
339 } if (strcmp(name, "fstatvfs@openssh.com") == 0 &&
340 strcmp(value, "2") == 0) {
341 exts |= SFTP_EXT_FSTATVFS;
342 known = 1;
343 }
344 if (known) {
345 debug2("Server supports extension \"%s\" revision %s",
346 name, value);
347 } else {
348 debug2("Unrecognised server extension \"%s\"", name);
349 }
273 xfree(name);
274 xfree(value);
275 }
276
277 buffer_free(&msg);
278
279 ret = xmalloc(sizeof(*ret));
280 ret->fd_in = fd_in;
281 ret->fd_out = fd_out;
282 ret->transfer_buflen = transfer_buflen;
283 ret->num_requests = num_requests;
284 ret->version = version;
285 ret->msg_id = 1;
350 xfree(name);
351 xfree(value);
352 }
353
354 buffer_free(&msg);
355
356 ret = xmalloc(sizeof(*ret));
357 ret->fd_in = fd_in;
358 ret->fd_out = fd_out;
359 ret->transfer_buflen = transfer_buflen;
360 ret->num_requests = num_requests;
361 ret->version = version;
362 ret->msg_id = 1;
363 ret->exts = exts;
286
287 /* Some filexfer v.0 servers don't support large packets */
288 if (version == 0)
289 ret->transfer_buflen = MIN(ret->transfer_buflen, 20480);
290
291 return(ret);
292}
293

--- 235 unchanged lines hidden (view full) ---

529
530 id = conn->msg_id++;
531 send_string_request(conn->fd_out, id, SSH2_FXP_LSTAT, path,
532 strlen(path));
533
534 return(get_decode_stat(conn->fd_in, id, quiet));
535}
536
364
365 /* Some filexfer v.0 servers don't support large packets */
366 if (version == 0)
367 ret->transfer_buflen = MIN(ret->transfer_buflen, 20480);
368
369 return(ret);
370}
371

--- 235 unchanged lines hidden (view full) ---

607
608 id = conn->msg_id++;
609 send_string_request(conn->fd_out, id, SSH2_FXP_LSTAT, path,
610 strlen(path));
611
612 return(get_decode_stat(conn->fd_in, id, quiet));
613}
614
615#ifdef notyet
537Attrib *
538do_fstat(struct sftp_conn *conn, char *handle, u_int handle_len, int quiet)
539{
540 u_int id;
541
542 id = conn->msg_id++;
543 send_string_request(conn->fd_out, id, SSH2_FXP_FSTAT, handle,
544 handle_len);
545
546 return(get_decode_stat(conn->fd_in, id, quiet));
547}
616Attrib *
617do_fstat(struct sftp_conn *conn, char *handle, u_int handle_len, int quiet)
618{
619 u_int id;
620
621 id = conn->msg_id++;
622 send_string_request(conn->fd_out, id, SSH2_FXP_FSTAT, handle,
623 handle_len);
624
625 return(get_decode_stat(conn->fd_in, id, quiet));
626}
627#endif
548
549int
550do_setstat(struct sftp_conn *conn, char *path, Attrib *a)
551{
552 u_int status, id;
553
554 id = conn->msg_id++;
555 send_string_attrs_request(conn->fd_out, id, SSH2_FXP_SETSTAT, path,

--- 76 unchanged lines hidden (view full) ---

632{
633 Buffer msg;
634 u_int status, id;
635
636 buffer_init(&msg);
637
638 /* Send rename request */
639 id = conn->msg_id++;
628
629int
630do_setstat(struct sftp_conn *conn, char *path, Attrib *a)
631{
632 u_int status, id;
633
634 id = conn->msg_id++;
635 send_string_attrs_request(conn->fd_out, id, SSH2_FXP_SETSTAT, path,

--- 76 unchanged lines hidden (view full) ---

712{
713 Buffer msg;
714 u_int status, id;
715
716 buffer_init(&msg);
717
718 /* Send rename request */
719 id = conn->msg_id++;
640 buffer_put_char(&msg, SSH2_FXP_RENAME);
641 buffer_put_int(&msg, id);
720 if ((conn->exts & SFTP_EXT_POSIX_RENAME)) {
721 buffer_put_char(&msg, SSH2_FXP_EXTENDED);
722 buffer_put_int(&msg, id);
723 buffer_put_cstring(&msg, "posix-rename@openssh.com");
724 } else {
725 buffer_put_char(&msg, SSH2_FXP_RENAME);
726 buffer_put_int(&msg, id);
727 }
642 buffer_put_cstring(&msg, oldpath);
643 buffer_put_cstring(&msg, newpath);
644 send_msg(conn->fd_out, &msg);
728 buffer_put_cstring(&msg, oldpath);
729 buffer_put_cstring(&msg, newpath);
730 send_msg(conn->fd_out, &msg);
645 debug3("Sent message SSH2_FXP_RENAME \"%s\" -> \"%s\"", oldpath,
646 newpath);
731 debug3("Sent message %s \"%s\" -> \"%s\"",
732 (conn->exts & SFTP_EXT_POSIX_RENAME) ? "posix-rename@openssh.com" :
733 "SSH2_FXP_RENAME", oldpath, newpath);
647 buffer_free(&msg);
648
649 status = get_status(conn->fd_in, id);
650 if (status != SSH2_FX_OK)
651 error("Couldn't rename file \"%s\" to \"%s\": %s", oldpath,
652 newpath, fx2txt(status));
653
654 return(status);

--- 26 unchanged lines hidden (view full) ---

681 status = get_status(conn->fd_in, id);
682 if (status != SSH2_FX_OK)
683 error("Couldn't symlink file \"%s\" to \"%s\": %s", oldpath,
684 newpath, fx2txt(status));
685
686 return(status);
687}
688
734 buffer_free(&msg);
735
736 status = get_status(conn->fd_in, id);
737 if (status != SSH2_FX_OK)
738 error("Couldn't rename file \"%s\" to \"%s\": %s", oldpath,
739 newpath, fx2txt(status));
740
741 return(status);

--- 26 unchanged lines hidden (view full) ---

768 status = get_status(conn->fd_in, id);
769 if (status != SSH2_FX_OK)
770 error("Couldn't symlink file \"%s\" to \"%s\": %s", oldpath,
771 newpath, fx2txt(status));
772
773 return(status);
774}
775
776#ifdef notyet
689char *
690do_readlink(struct sftp_conn *conn, char *path)
691{
692 Buffer msg;
693 u_int type, expected_id, count, id;
694 char *filename, *longname;
695 Attrib *a;
696

--- 30 unchanged lines hidden (view full) ---

727 debug3("SSH_FXP_READLINK %s -> %s", path, filename);
728
729 xfree(longname);
730
731 buffer_free(&msg);
732
733 return(filename);
734}
777char *
778do_readlink(struct sftp_conn *conn, char *path)
779{
780 Buffer msg;
781 u_int type, expected_id, count, id;
782 char *filename, *longname;
783 Attrib *a;
784

--- 30 unchanged lines hidden (view full) ---

815 debug3("SSH_FXP_READLINK %s -> %s", path, filename);
816
817 xfree(longname);
818
819 buffer_free(&msg);
820
821 return(filename);
822}
823#endif
735
824
825int
826do_statvfs(struct sftp_conn *conn, const char *path, struct sftp_statvfs *st,
827 int quiet)
828{
829 Buffer msg;
830 u_int id;
831
832 if ((conn->exts & SFTP_EXT_STATVFS) == 0) {
833 error("Server does not support statvfs@openssh.com extension");
834 return -1;
835 }
836
837 id = conn->msg_id++;
838
839 buffer_init(&msg);
840 buffer_clear(&msg);
841 buffer_put_char(&msg, SSH2_FXP_EXTENDED);
842 buffer_put_int(&msg, id);
843 buffer_put_cstring(&msg, "statvfs@openssh.com");
844 buffer_put_cstring(&msg, path);
845 send_msg(conn->fd_out, &msg);
846 buffer_free(&msg);
847
848 return get_decode_statvfs(conn->fd_in, st, id, quiet);
849}
850
851#ifdef notyet
852int
853do_fstatvfs(struct sftp_conn *conn, const char *handle, u_int handle_len,
854 struct sftp_statvfs *st, int quiet)
855{
856 Buffer msg;
857 u_int id;
858
859 if ((conn->exts & SFTP_EXT_FSTATVFS) == 0) {
860 error("Server does not support fstatvfs@openssh.com extension");
861 return -1;
862 }
863
864 id = conn->msg_id++;
865
866 buffer_init(&msg);
867 buffer_clear(&msg);
868 buffer_put_char(&msg, SSH2_FXP_EXTENDED);
869 buffer_put_int(&msg, id);
870 buffer_put_cstring(&msg, "fstatvfs@openssh.com");
871 buffer_put_string(&msg, handle, handle_len);
872 send_msg(conn->fd_out, &msg);
873 buffer_free(&msg);
874
875 return get_decode_statvfs(conn->fd_in, st, id, quiet);
876}
877#endif
878
736static void
737send_read_request(int fd_out, u_int id, u_int64_t offset, u_int len,
738 char *handle, u_int handle_len)
739{
740 Buffer msg;
741
742 buffer_init(&msg);
743 buffer_clear(&msg);

--- 28 unchanged lines hidden (view full) ---

772 struct request *req;
773
774 TAILQ_INIT(&requests);
775
776 a = do_stat(conn, remote_path, 0);
777 if (a == NULL)
778 return(-1);
779
879static void
880send_read_request(int fd_out, u_int id, u_int64_t offset, u_int len,
881 char *handle, u_int handle_len)
882{
883 Buffer msg;
884
885 buffer_init(&msg);
886 buffer_clear(&msg);

--- 28 unchanged lines hidden (view full) ---

915 struct request *req;
916
917 TAILQ_INIT(&requests);
918
919 a = do_stat(conn, remote_path, 0);
920 if (a == NULL)
921 return(-1);
922
780 /* XXX: should we preserve set[ug]id? */
923 /* Do not preserve set[ug]id here, as we do not preserve ownership */
781 if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS)
782 mode = a->perm & 0777;
783 else
784 mode = 0666;
785
786 if ((a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) &&
787 (!S_ISREG(a->perm))) {
788 error("Cannot download non-regular file: %s", remote_path);

--- 25 unchanged lines hidden (view full) ---

814 return(-1);
815 }
816
817 local_fd = open(local_path, O_WRONLY | O_CREAT | O_TRUNC,
818 mode | S_IWRITE);
819 if (local_fd == -1) {
820 error("Couldn't open local file \"%s\" for writing: %s",
821 local_path, strerror(errno));
924 if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS)
925 mode = a->perm & 0777;
926 else
927 mode = 0666;
928
929 if ((a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS) &&
930 (!S_ISREG(a->perm))) {
931 error("Cannot download non-regular file: %s", remote_path);

--- 25 unchanged lines hidden (view full) ---

957 return(-1);
958 }
959
960 local_fd = open(local_path, O_WRONLY | O_CREAT | O_TRUNC,
961 mode | S_IWRITE);
962 if (local_fd == -1) {
963 error("Couldn't open local file \"%s\" for writing: %s",
964 local_path, strerror(errno));
965 do_close(conn, handle, handle_len);
822 buffer_free(&msg);
823 xfree(handle);
824 return(-1);
825 }
826
827 /* Read from remote and write to local */
828 write_error = read_error = write_errno = num_req = offset = 0;
829 max_req = 1;

--- 157 unchanged lines hidden (view full) ---

987
988 return(status);
989}
990
991int
992do_upload(struct sftp_conn *conn, char *local_path, char *remote_path,
993 int pflag)
994{
966 buffer_free(&msg);
967 xfree(handle);
968 return(-1);
969 }
970
971 /* Read from remote and write to local */
972 write_error = read_error = write_errno = num_req = offset = 0;
973 max_req = 1;

--- 157 unchanged lines hidden (view full) ---

1131
1132 return(status);
1133}
1134
1135int
1136do_upload(struct sftp_conn *conn, char *local_path, char *remote_path,
1137 int pflag)
1138{
995 int local_fd, status;
1139 int local_fd;
1140 int status = SSH2_FX_OK;
996 u_int handle_len, id, type;
1141 u_int handle_len, id, type;
997 u_int64_t offset;
1142 off_t offset;
998 char *handle, *data;
999 Buffer msg;
1000 struct stat sb;
1001 Attrib a;
1002 u_int32_t startid;
1003 u_int32_t ackid;
1004 struct outstanding_ack {
1005 u_int id;
1006 u_int len;
1143 char *handle, *data;
1144 Buffer msg;
1145 struct stat sb;
1146 Attrib a;
1147 u_int32_t startid;
1148 u_int32_t ackid;
1149 struct outstanding_ack {
1150 u_int id;
1151 u_int len;
1007 u_int64_t offset;
1152 off_t offset;
1008 TAILQ_ENTRY(outstanding_ack) tq;
1009 };
1010 TAILQ_HEAD(ackhead, outstanding_ack) acks;
1011 struct outstanding_ack *ack = NULL;
1012
1013 TAILQ_INIT(&acks);
1014
1015 if ((local_fd = open(local_path, O_RDONLY, 0)) == -1) {

--- 33 unchanged lines hidden (view full) ---

1049 debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, remote_path);
1050
1051 buffer_clear(&msg);
1052
1053 handle = get_handle(conn->fd_in, id, &handle_len);
1054 if (handle == NULL) {
1055 close(local_fd);
1056 buffer_free(&msg);
1153 TAILQ_ENTRY(outstanding_ack) tq;
1154 };
1155 TAILQ_HEAD(ackhead, outstanding_ack) acks;
1156 struct outstanding_ack *ack = NULL;
1157
1158 TAILQ_INIT(&acks);
1159
1160 if ((local_fd = open(local_path, O_RDONLY, 0)) == -1) {

--- 33 unchanged lines hidden (view full) ---

1194 debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, remote_path);
1195
1196 buffer_clear(&msg);
1197
1198 handle = get_handle(conn->fd_in, id, &handle_len);
1199 if (handle == NULL) {
1200 close(local_fd);
1201 buffer_free(&msg);
1057 return(-1);
1202 return -1;
1058 }
1059
1060 startid = ackid = id + 1;
1061 data = xmalloc(conn->transfer_buflen);
1062
1063 /* Read from local and write to remote */
1064 offset = 0;
1065 if (showprogress)
1066 start_progress_meter(local_path, sb.st_size, &offset);
1067
1068 for (;;) {
1069 int len;
1070
1071 /*
1072 * Can't use atomicio here because it returns 0 on EOF,
1073 * thus losing the last block of the file.
1074 * Simulate an EOF on interrupt, allowing ACKs from the
1075 * server to drain.
1076 */
1203 }
1204
1205 startid = ackid = id + 1;
1206 data = xmalloc(conn->transfer_buflen);
1207
1208 /* Read from local and write to remote */
1209 offset = 0;
1210 if (showprogress)
1211 start_progress_meter(local_path, sb.st_size, &offset);
1212
1213 for (;;) {
1214 int len;
1215
1216 /*
1217 * Can't use atomicio here because it returns 0 on EOF,
1218 * thus losing the last block of the file.
1219 * Simulate an EOF on interrupt, allowing ACKs from the
1220 * server to drain.
1221 */
1077 if (interrupted)
1222 if (interrupted || status != SSH2_FX_OK)
1078 len = 0;
1079 else do
1080 len = read(local_fd, data, conn->transfer_buflen);
1223 len = 0;
1224 else do
1225 len = read(local_fd, data, conn->transfer_buflen);
1081 while ((len == -1) && (errno == EINTR || errno == EAGAIN));
1226 while ((len == -1) &&
1227 (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
1082
1083 if (len == -1)
1084 fatal("Couldn't read from \"%s\": %s", local_path,
1085 strerror(errno));
1086
1087 if (len != 0) {
1088 ack = xmalloc(sizeof(*ack));
1089 ack->id = ++id;

--- 35 unchanged lines hidden (view full) ---

1125 /* Find the request in our queue */
1126 for (ack = TAILQ_FIRST(&acks);
1127 ack != NULL && ack->id != r_id;
1128 ack = TAILQ_NEXT(ack, tq))
1129 ;
1130 if (ack == NULL)
1131 fatal("Can't find request for ID %u", r_id);
1132 TAILQ_REMOVE(&acks, ack, tq);
1228
1229 if (len == -1)
1230 fatal("Couldn't read from \"%s\": %s", local_path,
1231 strerror(errno));
1232
1233 if (len != 0) {
1234 ack = xmalloc(sizeof(*ack));
1235 ack->id = ++id;

--- 35 unchanged lines hidden (view full) ---

1271 /* Find the request in our queue */
1272 for (ack = TAILQ_FIRST(&acks);
1273 ack != NULL && ack->id != r_id;
1274 ack = TAILQ_NEXT(ack, tq))
1275 ;
1276 if (ack == NULL)
1277 fatal("Can't find request for ID %u", r_id);
1278 TAILQ_REMOVE(&acks, ack, tq);
1133
1134 if (status != SSH2_FX_OK) {
1135 error("Couldn't write to remote file \"%s\": %s",
1136 remote_path, fx2txt(status));
1137 if (showprogress)
1138 stop_progress_meter();
1139 do_close(conn, handle, handle_len);
1140 close(local_fd);
1141 xfree(data);
1142 xfree(ack);
1143 goto done;
1144 }
1145 debug3("In write loop, ack for %u %u bytes at %llu",
1146 ack->id, ack->len, (unsigned long long)ack->offset);
1279 debug3("In write loop, ack for %u %u bytes at %lld",
1280 ack->id, ack->len, (long long)ack->offset);
1147 ++ackid;
1148 xfree(ack);
1149 }
1150 offset += len;
1281 ++ackid;
1282 xfree(ack);
1283 }
1284 offset += len;
1285 if (offset < 0)
1286 fatal("%s: offset < 0", __func__);
1151 }
1287 }
1288 buffer_free(&msg);
1289
1152 if (showprogress)
1153 stop_progress_meter();
1154 xfree(data);
1155
1290 if (showprogress)
1291 stop_progress_meter();
1292 xfree(data);
1293
1294 if (status != SSH2_FX_OK) {
1295 error("Couldn't write to remote file \"%s\": %s",
1296 remote_path, fx2txt(status));
1297 status = -1;
1298 }
1299
1156 if (close(local_fd) == -1) {
1157 error("Couldn't close local file \"%s\": %s", local_path,
1158 strerror(errno));
1300 if (close(local_fd) == -1) {
1301 error("Couldn't close local file \"%s\": %s", local_path,
1302 strerror(errno));
1159 do_close(conn, handle, handle_len);
1160 status = -1;
1303 status = -1;
1161 goto done;
1162 }
1163
1164 /* Override umask and utimes if asked */
1165 if (pflag)
1166 do_fsetstat(conn, handle, handle_len, &a);
1167
1304 }
1305
1306 /* Override umask and utimes if asked */
1307 if (pflag)
1308 do_fsetstat(conn, handle, handle_len, &a);
1309
1168 status = do_close(conn, handle, handle_len);
1169
1170done:
1310 if (do_close(conn, handle, handle_len) != SSH2_FX_OK)
1311 status = -1;
1171 xfree(handle);
1312 xfree(handle);
1172 buffer_free(&msg);
1173 return(status);
1313
1314 return status;
1174}
1315}