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} |