|
Lines 15-20
Link Here
|
| 15 |
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 |
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
| 16 |
*/ |
16 |
*/ |
| 17 |
|
17 |
|
|
|
18 |
/* |
| 19 |
* Copyright (c) 2012 Loganaden Velvindron |
| 20 |
* |
| 21 |
* Permission to use, copy, modify, and distribute this software for any |
| 22 |
* purpose with or without fee is hereby granted, provided that the above |
| 23 |
* copyright notice and this permission notice appear in all copies. |
| 24 |
* |
| 25 |
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
| 26 |
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
| 27 |
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
| 28 |
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
| 29 |
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
| 30 |
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
| 31 |
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
| 32 |
* |
| 33 |
* Sponsored by AfriNIC. |
| 34 |
*/ |
| 35 |
|
| 18 |
/* XXX: memleaks */ |
36 |
/* XXX: memleaks */ |
| 19 |
/* XXX: signed vs unsigned */ |
37 |
/* XXX: signed vs unsigned */ |
| 20 |
/* XXX: remove all logging, only return status codes */ |
38 |
/* XXX: remove all logging, only return status codes */ |
|
Lines 988-1003
send_read_request(struct sftp_conn *conn
Link Here
|
| 988 |
|
1006 |
|
| 989 |
int |
1007 |
int |
| 990 |
do_download(struct sftp_conn *conn, char *remote_path, char *local_path, |
1008 |
do_download(struct sftp_conn *conn, char *remote_path, char *local_path, |
| 991 |
Attrib *a, int pflag) |
1009 |
Attrib *a, int pflag, int resume) |
| 992 |
{ |
1010 |
{ |
| 993 |
Attrib junk; |
1011 |
Attrib junk; |
| 994 |
Buffer msg; |
1012 |
Buffer msg; |
| 995 |
char *handle; |
1013 |
char *handle; |
| 996 |
int local_fd, status = 0, write_error; |
1014 |
int local_fd = -1, status = 0, write_error, bigger; |
| 997 |
int read_error, write_errno; |
1015 |
int read_error, write_errno; |
| 998 |
u_int64_t offset, size; |
1016 |
u_int64_t offset = 0, size, highwater; |
| 999 |
u_int handle_len, mode, type, id, buflen, num_req, max_req; |
1017 |
u_int handle_len, mode, type, id, buflen, num_req, max_req; |
| 1000 |
off_t progress_counter; |
1018 |
off_t progress_counter; |
|
|
1019 |
struct stat st; |
| 1001 |
struct request { |
1020 |
struct request { |
| 1002 |
u_int id; |
1021 |
u_int id; |
| 1003 |
u_int len; |
1022 |
u_int len; |
|
Lines 1050-1060
do_download(struct sftp_conn *conn, char
Link Here
|
| 1050 |
return(-1); |
1069 |
return(-1); |
| 1051 |
} |
1070 |
} |
| 1052 |
|
1071 |
|
| 1053 |
local_fd = open(local_path, O_WRONLY | O_CREAT | O_TRUNC, |
1072 |
if (resume) { |
| 1054 |
mode | S_IWRITE); |
1073 |
if (stat(local_path, &st) == -1) { |
|
|
1074 |
offset = 0; |
| 1075 |
highwater = 0; |
| 1076 |
local_fd = open(local_path, O_WRONLY | O_CREAT, |
| 1077 |
mode | S_IWRITE); |
| 1078 |
} |
| 1079 |
else { |
| 1080 |
if ((size_t)st.st_size > size) { |
| 1081 |
bigger = 1; |
| 1082 |
local_fd = -1; |
| 1083 |
} |
| 1084 |
else { |
| 1085 |
offset = st.st_size; |
| 1086 |
highwater = st.st_size; |
| 1087 |
local_fd = open(local_path, |
| 1088 |
O_WRONLY | O_CREAT, |
| 1089 |
mode | S_IWRITE); |
| 1090 |
} |
| 1091 |
} |
| 1092 |
} |
| 1093 |
else |
| 1094 |
local_fd = open(local_path, O_WRONLY | O_CREAT | O_TRUNC, |
| 1095 |
mode | S_IWRITE); |
| 1055 |
if (local_fd == -1) { |
1096 |
if (local_fd == -1) { |
| 1056 |
error("Couldn't open local file \"%s\" for writing: %s", |
1097 |
if (bigger) |
| 1057 |
local_path, strerror(errno)); |
1098 |
error("destination file bigger than source file"); |
|
|
1099 |
else |
| 1100 |
error("Couldn't open local file \"%s\" for writing: %s", |
| 1101 |
local_path, strerror(errno)); |
| 1058 |
do_close(conn, handle, handle_len); |
1102 |
do_close(conn, handle, handle_len); |
| 1059 |
buffer_free(&msg); |
1103 |
buffer_free(&msg); |
| 1060 |
xfree(handle); |
1104 |
xfree(handle); |
|
Lines 1062-1070
do_download(struct sftp_conn *conn, char
Link Here
|
| 1062 |
} |
1106 |
} |
| 1063 |
|
1107 |
|
| 1064 |
/* Read from remote and write to local */ |
1108 |
/* Read from remote and write to local */ |
| 1065 |
write_error = read_error = write_errno = num_req = offset = 0; |
1109 |
write_error = read_error = write_errno = num_req = 0; |
| 1066 |
max_req = 1; |
1110 |
max_req = 1; |
| 1067 |
progress_counter = 0; |
1111 |
progress_counter = offset; |
| 1068 |
|
1112 |
|
| 1069 |
if (showprogress && size != 0) |
1113 |
if (showprogress && size != 0) |
| 1070 |
start_progress_meter(remote_path, size, &progress_counter); |
1114 |
start_progress_meter(remote_path, size, &progress_counter); |
|
Lines 1139-1144
do_download(struct sftp_conn *conn, char
Link Here
|
| 1139 |
write_error = 1; |
1183 |
write_error = 1; |
| 1140 |
max_req = 0; |
1184 |
max_req = 0; |
| 1141 |
} |
1185 |
} |
|
|
1186 |
else if (req->offset <= highwater) |
| 1187 |
highwater = req->offset + len; |
| 1188 |
else if (req->offset > highwater) { |
| 1189 |
ftruncate(local_fd, 0); |
| 1190 |
printf("reordered blocks detected"); |
| 1191 |
} |
| 1142 |
progress_counter += len; |
1192 |
progress_counter += len; |
| 1143 |
xfree(data); |
1193 |
xfree(data); |
| 1144 |
|
1194 |
|
|
Lines 1187-1192
do_download(struct sftp_conn *conn, char
Link Here
|
| 1187 |
/* Sanity check */ |
1237 |
/* Sanity check */ |
| 1188 |
if (TAILQ_FIRST(&requests) != NULL) |
1238 |
if (TAILQ_FIRST(&requests) != NULL) |
| 1189 |
fatal("Transfer complete, but requests still in queue"); |
1239 |
fatal("Transfer complete, but requests still in queue"); |
|
|
1240 |
/* Truncate at highest contiguous point to avoid holes on interrupt */ |
| 1241 |
if (read_error || write_error || interrupted) { |
| 1242 |
debug("truncating at %llu", highwater); |
| 1243 |
ftruncate(local_fd, highwater); |
| 1244 |
} |
| 1190 |
|
1245 |
|
| 1191 |
if (read_error) { |
1246 |
if (read_error) { |
| 1192 |
error("Couldn't read from remote file \"%s\" : %s", |
1247 |
error("Couldn't read from remote file \"%s\" : %s", |
|
Lines 1233-1238
download_dir_internal(struct sftp_conn *
Link Here
|
| 1233 |
SFTP_DIRENT **dir_entries; |
1288 |
SFTP_DIRENT **dir_entries; |
| 1234 |
char *filename, *new_src, *new_dst; |
1289 |
char *filename, *new_src, *new_dst; |
| 1235 |
mode_t mode = 0777; |
1290 |
mode_t mode = 0777; |
|
|
1291 |
int resume = 0; |
| 1236 |
|
1292 |
|
| 1237 |
if (depth >= MAX_DIR_DEPTH) { |
1293 |
if (depth >= MAX_DIR_DEPTH) { |
| 1238 |
error("Maximum directory depth exceeded: %d levels", depth); |
1294 |
error("Maximum directory depth exceeded: %d levels", depth); |
|
Lines 1284-1290
download_dir_internal(struct sftp_conn *
Link Here
|
| 1284 |
ret = -1; |
1340 |
ret = -1; |
| 1285 |
} else if (S_ISREG(dir_entries[i]->a.perm) ) { |
1341 |
} else if (S_ISREG(dir_entries[i]->a.perm) ) { |
| 1286 |
if (do_download(conn, new_src, new_dst, |
1342 |
if (do_download(conn, new_src, new_dst, |
| 1287 |
&(dir_entries[i]->a), pflag) == -1) { |
1343 |
&(dir_entries[i]->a), pflag, resume) == -1) { |
| 1288 |
error("Download of file %s to %s failed", |
1344 |
error("Download of file %s to %s failed", |
| 1289 |
new_src, new_dst); |
1345 |
new_src, new_dst); |
| 1290 |
ret = -1; |
1346 |
ret = -1; |
|
Lines 1638-1641
path_append(char *p1, char *p2)
Link Here
|
| 1638 |
|
1694 |
|
| 1639 |
return(ret); |
1695 |
return(ret); |
| 1640 |
} |
1696 |
} |
| 1641 |
|
|
|