version 1.21, 2002/02/12 12:32:27 |
version 1.22, 2002/02/12 12:44:46 |
|
|
int pflag, size_t buflen, int num_requests) |
int pflag, size_t buflen, int num_requests) |
{ |
{ |
int local_fd, status; |
int local_fd, status; |
u_int handle_len, id; |
u_int handle_len, id, type; |
u_int64_t offset; |
u_int64_t offset; |
char *handle, *data; |
char *handle, *data; |
Buffer msg; |
Buffer msg; |
|
|
Attrib a; |
Attrib a; |
u_int32_t startid; |
u_int32_t startid; |
u_int32_t ackid; |
u_int32_t ackid; |
|
struct outstanding_ack { |
|
u_int id; |
|
u_int len; |
|
u_int64_t offset; |
|
TAILQ_ENTRY(outstanding_ack) tq; |
|
}; |
|
TAILQ_HEAD(ackhead, outstanding_ack) acks; |
|
struct outstanding_ack *ack; |
|
|
|
TAILQ_INIT(&acks); |
|
|
if ((local_fd = open(local_path, O_RDONLY, 0)) == -1) { |
if ((local_fd = open(local_path, O_RDONLY, 0)) == -1) { |
error("Couldn't open local file \"%s\" for reading: %s", |
error("Couldn't open local file \"%s\" for reading: %s", |
local_path, strerror(errno)); |
local_path, strerror(errno)); |
|
|
strerror(errno)); |
strerror(errno)); |
|
|
if (len != 0) { |
if (len != 0) { |
|
ack = xmalloc(sizeof(*ack)); |
|
ack->id = ++id; |
|
ack->offset = offset; |
|
ack->len = len; |
|
TAILQ_INSERT_TAIL(&acks, ack, tq); |
|
|
buffer_clear(&msg); |
buffer_clear(&msg); |
buffer_put_char(&msg, SSH2_FXP_WRITE); |
buffer_put_char(&msg, SSH2_FXP_WRITE); |
buffer_put_int(&msg, ++id); |
buffer_put_int(&msg, ack->id); |
buffer_put_string(&msg, handle, handle_len); |
buffer_put_string(&msg, handle, handle_len); |
buffer_put_int64(&msg, offset); |
buffer_put_int64(&msg, offset); |
buffer_put_string(&msg, data, len); |
buffer_put_string(&msg, data, len); |
send_msg(fd_out, &msg); |
send_msg(fd_out, &msg); |
debug3("Sent message SSH2_FXP_WRITE I:%d O:%llu S:%u", |
debug3("Sent message SSH2_FXP_WRITE I:%d O:%llu S:%u", |
id, (u_int64_t)offset, len); |
id, (u_int64_t)offset, len); |
} else if ( id < ackid ) |
} else if (TAILQ_FIRST(&acks) == NULL) |
break; |
break; |
|
|
if (id == startid || len == 0 || |
if (ack == NULL) |
id - ackid >= num_requests) { |
fatal("Unexpected ACK %u", id); |
status = get_status(fd_in, ackid); |
|
|
if (id == startid || len == 0 || id - ackid >= num_requests) { |
|
buffer_clear(&msg); |
|
get_msg(fd_in, &msg); |
|
type = buffer_get_char(&msg); |
|
id = buffer_get_int(&msg); |
|
|
|
if (type != SSH2_FXP_STATUS) |
|
fatal("Expected SSH2_FXP_STATUS(%d) packet, " |
|
"got %d", SSH2_FXP_STATUS, type); |
|
|
|
status = buffer_get_int(&msg); |
|
debug3("SSH2_FXP_STATUS %d", status); |
|
|
|
/* Find the request in our queue */ |
|
for(ack = TAILQ_FIRST(&acks); |
|
ack != NULL && ack->id != id; |
|
ack = TAILQ_NEXT(ack, tq)) |
|
; |
|
if (ack == NULL) |
|
fatal("Can't find request for ID %d", id); |
|
TAILQ_REMOVE(&acks, ack, tq); |
|
|
if (status != SSH2_FX_OK) { |
if (status != SSH2_FX_OK) { |
error("Couldn't write to remote file \"%s\": %s", |
error("Couldn't write to remote file \"%s\": %s", |
remote_path, fx2txt(status)); |
remote_path, fx2txt(status)); |
|
|
close(local_fd); |
close(local_fd); |
goto done; |
goto done; |
} |
} |
debug3("In write loop, got %d offset %llu", len, |
debug3("In write loop, ack for %u %d bytes at %llu", |
(u_int64_t)offset); |
ack->id, ack->len, ack->offset); |
++ackid; |
++ackid; |
|
free(ack); |
} |
} |
|
|
offset += len; |
offset += len; |