version 1.27, 2002/03/11 03:19:53 |
version 1.28, 2002/03/19 10:49:35 |
|
|
debug2("Sending SSH2_FXP_REMOVE \"%s\"", path); |
debug2("Sending SSH2_FXP_REMOVE \"%s\"", path); |
|
|
id = conn->msg_id++; |
id = conn->msg_id++; |
send_string_request(conn->fd_out, id, SSH2_FXP_REMOVE, path, |
send_string_request(conn->fd_out, id, SSH2_FXP_REMOVE, path, |
strlen(path)); |
strlen(path)); |
status = get_status(conn->fd_in, id); |
status = get_status(conn->fd_in, id); |
if (status != SSH2_FX_OK) |
if (status != SSH2_FX_OK) |
|
|
|
|
id = conn->msg_id++; |
id = conn->msg_id++; |
|
|
send_string_request(conn->fd_out, id, |
send_string_request(conn->fd_out, id, |
conn->version == 0 ? SSH2_FXP_STAT_VERSION_0 : SSH2_FXP_STAT, |
conn->version == 0 ? SSH2_FXP_STAT_VERSION_0 : SSH2_FXP_STAT, |
path, strlen(path)); |
path, strlen(path)); |
|
|
return(get_decode_stat(conn->fd_in, id, quiet)); |
return(get_decode_stat(conn->fd_in, id, quiet)); |
|
|
char *handle, u_int handle_len) |
char *handle, u_int handle_len) |
{ |
{ |
Buffer msg; |
Buffer msg; |
|
|
buffer_init(&msg); |
buffer_init(&msg); |
buffer_clear(&msg); |
buffer_clear(&msg); |
buffer_put_char(&msg, SSH2_FXP_READ); |
buffer_put_char(&msg, SSH2_FXP_READ); |
|
|
buffer_put_int(&msg, len); |
buffer_put_int(&msg, len); |
send_msg(fd_out, &msg); |
send_msg(fd_out, &msg); |
buffer_free(&msg); |
buffer_free(&msg); |
} |
} |
|
|
int |
int |
do_download(struct sftp_conn *conn, char *remote_path, char *local_path, |
do_download(struct sftp_conn *conn, char *remote_path, char *local_path, |
|
|
u_int id; |
u_int id; |
u_int len; |
u_int len; |
u_int64_t offset; |
u_int64_t offset; |
TAILQ_ENTRY(request) tq; |
TAILQ_ENTRY(request) tq; |
}; |
}; |
TAILQ_HEAD(reqhead, request) requests; |
TAILQ_HEAD(reqhead, request) requests; |
struct request *req; |
struct request *req; |
|
|
|
|
/* Send some more requests */ |
/* Send some more requests */ |
while (num_req < max_req) { |
while (num_req < max_req) { |
debug3("Request range %llu -> %llu (%d/%d)", |
debug3("Request range %llu -> %llu (%d/%d)", |
(unsigned long long)offset, |
(unsigned long long)offset, |
(unsigned long long)offset + buflen - 1, |
(unsigned long long)offset + buflen - 1, |
num_req, max_req); |
num_req, max_req); |
|
|
offset += buflen; |
offset += buflen; |
num_req++; |
num_req++; |
TAILQ_INSERT_TAIL(&requests, req, tq); |
TAILQ_INSERT_TAIL(&requests, req, tq); |
send_read_request(conn->fd_out, req->id, req->offset, |
send_read_request(conn->fd_out, req->id, req->offset, |
req->len, handle, handle_len); |
req->len, handle, handle_len); |
} |
} |
|
|
|
|
case SSH2_FXP_DATA: |
case SSH2_FXP_DATA: |
data = buffer_get_string(&msg, &len); |
data = buffer_get_string(&msg, &len); |
debug3("Received data %llu -> %llu", |
debug3("Received data %llu -> %llu", |
(unsigned long long)req->offset, |
(unsigned long long)req->offset, |
(unsigned long long)req->offset + len - 1); |
(unsigned long long)req->offset + len - 1); |
if (len > req->len) |
if (len > req->len) |
fatal("Received more data than asked for " |
fatal("Received more data than asked for " |
|
|
/* Resend the request for the missing data */ |
/* Resend the request for the missing data */ |
debug3("Short data block, re-requesting " |
debug3("Short data block, re-requesting " |
"%llu -> %llu (%2d)", |
"%llu -> %llu (%2d)", |
(unsigned long long)req->offset + len, |
(unsigned long long)req->offset + len, |
(unsigned long long)req->offset + |
(unsigned long long)req->offset + |
req->len - 1, num_req); |
req->len - 1, num_req); |
req->id = conn->msg_id++; |
req->id = conn->msg_id++; |
req->len -= len; |
req->len -= len; |
req->offset += len; |
req->offset += len; |
send_read_request(conn->fd_out, req->id, |
send_read_request(conn->fd_out, req->id, |
req->offset, req->len, handle, handle_len); |
req->offset, req->len, handle, handle_len); |
/* Reduce the request size */ |
/* Reduce the request size */ |
if (len < buflen) |
if (len < buflen) |
|
|
fatal("Transfer complete, but requests still in queue"); |
fatal("Transfer complete, but requests still in queue"); |
|
|
if (read_error) { |
if (read_error) { |
error("Couldn't read from remote file \"%s\" : %s", |
error("Couldn't read from remote file \"%s\" : %s", |
remote_path, fx2txt(status)); |
remote_path, fx2txt(status)); |
do_close(conn, handle, handle_len); |
do_close(conn, handle, handle_len); |
} else if (write_error) { |
} else if (write_error) { |
|
|
u_int id; |
u_int id; |
u_int len; |
u_int len; |
u_int64_t offset; |
u_int64_t offset; |
TAILQ_ENTRY(outstanding_ack) tq; |
TAILQ_ENTRY(outstanding_ack) tq; |
}; |
}; |
TAILQ_HEAD(ackhead, outstanding_ack) acks; |
TAILQ_HEAD(ackhead, outstanding_ack) acks; |
struct outstanding_ack *ack; |
struct outstanding_ack *ack; |
|
|
if (ack == NULL) |
if (ack == NULL) |
fatal("Unexpected ACK %u", id); |
fatal("Unexpected ACK %u", id); |
|
|
if (id == startid || len == 0 || |
if (id == startid || len == 0 || |
id - ackid >= conn->num_requests) { |
id - ackid >= conn->num_requests) { |
buffer_clear(&msg); |
buffer_clear(&msg); |
get_msg(conn->fd_in, &msg); |
get_msg(conn->fd_in, &msg); |
|
|
close(local_fd); |
close(local_fd); |
goto done; |
goto done; |
} |
} |
debug3("In write loop, ack for %u %d bytes at %llu", |
debug3("In write loop, ack for %u %d bytes at %llu", |
ack->id, ack->len, (unsigned long long)ack->offset); |
ack->id, ack->len, (unsigned long long)ack->offset); |
++ackid; |
++ackid; |
free(ack); |
free(ack); |