aboutsummaryrefslogtreecommitdiff
path: root/libssh/sftp.c
diff options
context:
space:
mode:
authorAndreas Schneider <mail@cynapses.org>2009-04-24 09:33:47 +0000
committerAndreas Schneider <mail@cynapses.org>2009-04-24 09:33:47 +0000
commitac724eb3fb7ab2bf0554a497dd8d63633722ada8 (patch)
tree287197a18b900f3c93dc842230b28a2d52fdc8e8 /libssh/sftp.c
parent8ba57619fd247eebff3aea864f8bb7df5b83349a (diff)
downloadlibssh-ac724eb3fb7ab2bf0554a497dd8d63633722ada8.tar.gz
libssh-ac724eb3fb7ab2bf0554a497dd8d63633722ada8.tar.xz
libssh-ac724eb3fb7ab2bf0554a497dd8d63633722ada8.zip
Improve the sftp async read functions.
git-svn-id: svn+ssh://svn.berlios.de/svnroot/repos/libssh/trunk@602 7dcaeef0-15fb-0310-b436-a5af3365683c
Diffstat (limited to 'libssh/sftp.c')
-rw-r--r--libssh/sftp.c202
1 files changed, 112 insertions, 90 deletions
diff --git a/libssh/sftp.c b/libssh/sftp.c
index 646f6b63..a2049a6d 100644
--- a/libssh/sftp.c
+++ b/libssh/sftp.c
@@ -1543,102 +1543,124 @@ ssize_t sftp_read(SFTP_FILE *handle, void *buf, size_t count) {
}
/* Start an asynchronous read from a file using an opened sftp file handle. */
-u32 sftp_async_read_begin(SFTP_FILE *file, u32 len){
- SFTP_SESSION *sftp=file->sftp;
- BUFFER *buffer;
- u32 id;
- sftp_enter_function();
- buffer=buffer_new();
- id=sftp_get_new_id(sftp);
- buffer_add_u32(buffer,id);
- buffer_add_ssh_string(buffer,file->handle);
- buffer_add_u64(buffer,htonll(file->offset));
- buffer_add_u32(buffer,htonl(len));
- sftp_packet_write(sftp,SSH_FXP_READ,buffer);
- buffer_free(buffer);
- file->offset += len; // assume we'll read len bytes
- sftp_leave_function();
- return id;
+int sftp_async_read_begin(SFTP_FILE *file, u32 len){
+ SFTP_SESSION *sftp = file->sftp;
+ BUFFER *buffer;
+ u32 id;
+
+ sftp_enter_function();
+
+ buffer = buffer_new();
+ if (buffer == NULL) {
+ return -1;
+ }
+
+ id = sftp_get_new_id(sftp);
+ if (buffer_add_u32(buffer, id) < 0 ||
+ buffer_add_ssh_string(buffer, file->handle) < 0 ||
+ buffer_add_u64(buffer, htonll(file->offset)) < 0 ||
+ buffer_add_u32(buffer, htonl(len)) < 0 ||
+ sftp_packet_write(sftp, SSH_FXP_READ, buffer) < 0) {
+ buffer_free(buffer);
+ return -1;
+ }
+ buffer_free(buffer);
+
+ file->offset += len; /* assume we'll read len bytes */
+
+ sftp_leave_function();
+ return id;
}
/* Wait for an asynchronous read to complete and save the data. */
int sftp_async_read(SFTP_FILE *file, void *data, u32 size, u32 id){
- SFTP_MESSAGE *msg=NULL;
- STATUS_MESSAGE *status;
- SFTP_SESSION *sftp=file->sftp;
- STRING *datastring;
- int err=0;
- u32 len;
- sftp_enter_function();
- if(file->eof){
- sftp_leave_function();
- return 0;
+ SFTP_SESSION *sftp = file->sftp;
+ SFTP_MESSAGE *msg = NULL;
+ STATUS_MESSAGE *status;
+ STRING *datastring;
+ int err = SSH_OK;
+ u32 len;
+
+ sftp_enter_function();
+
+ if (file->eof) {
+ sftp_leave_function();
+ return 0;
+ }
+
+ /* handle an existing request */
+ while (msg == NULL) {
+ if (file->nonblocking){
+ if (channel_poll(sftp->channel, 0) == 0) {
+ /* we cannot block */
+ return SSH_AGAIN;
+ }
}
- // handle an existing request
- while(!msg){
- if (file->nonblocking){
- if(channel_poll(sftp->channel,0)==0){
- /* we cannot block */
- return SSH_AGAIN;
- }
- }
- if(sftp_read_and_dispatch(sftp)){
- /* something nasty has happened */
- sftp_leave_function();
- return SSH_ERROR;
- }
- msg=sftp_dequeue(sftp,id);
- }
- switch (msg->packet_type){
- case SSH_FXP_STATUS:
- status=parse_status_msg(msg);
- sftp_message_free(msg);
- if(!status){
- sftp_leave_function();
- return -1;
- }
- sftp_set_error(sftp, status->status);
- if(status->status != SSH_FX_EOF){
- ssh_set_error(sftp->session,SSH_REQUEST_DENIED,"sftp server : %s",status->errormsg);
- sftp_leave_function();
- err=-1;
- } else
- file->eof=1;
- status_msg_free(status);
- sftp_leave_function();
- return err?err:0;
- case SSH_FXP_DATA:
- datastring=buffer_get_ssh_string(msg->payload);
- sftp_message_free(msg);
- if(!datastring){
- ssh_set_error(sftp->session,SSH_FATAL,"Received invalid DATA packet from sftp server");
- sftp_leave_function();
- return -1;
- }
- if(string_len(datastring)>size){
- ssh_set_error(sftp->session, SSH_FATAL,
- "Received a too big DATA packet from sftp server: %zu and asked for %u",
- string_len(datastring),size);
- free(datastring);
- sftp_leave_function();
- return SSH_ERROR;
- }
- len=string_len(datastring);
- //handle->offset+=len;
- /* We already have set the offset previously. All we can do is warn that the expected len
- * and effective lengths are different */
- memcpy(data,datastring->string,len);
- free(datastring);
- sftp_leave_function();
- return len;
- default:
- ssh_set_error(sftp->session,SSH_FATAL,"Received message %d during read!",msg->packet_type);
- sftp_message_free(msg);
- sftp_leave_function();
- return SSH_ERROR;
- }
- sftp_leave_function();
+ if (sftp_read_and_dispatch(sftp) < 0) {
+ /* something nasty has happened */
+ sftp_leave_function();
+ return SSH_ERROR;
+ }
+
+ msg = sftp_dequeue(sftp,id);
+ }
+
+ switch (msg->packet_type) {
+ case SSH_FXP_STATUS:
+ status = parse_status_msg(msg);
+ sftp_message_free(msg);
+ if (status == NULL) {
+ sftp_leave_function();
+ return -1;
+ }
+ sftp_set_error(sftp, status->status);
+ if (status->status != SSH_FX_EOF) {
+ ssh_set_error(sftp->session, SSH_REQUEST_DENIED,
+ "SFTP server : %s", status->errormsg);
+ sftp_leave_function();
+ err = SSH_ERROR;
+ } else {
+ file->eof = 1;
+ }
+ status_msg_free(status);
+ sftp_leave_function();
+ return err;
+ case SSH_FXP_DATA:
+ datastring = buffer_get_ssh_string(msg->payload);
+ sftp_message_free(msg);
+ if (datastring == NULL) {
+ ssh_set_error(sftp->session, SSH_FATAL,
+ "Received invalid DATA packet from sftp server");
+ sftp_leave_function();
+ return SSH_ERROR;
+ }
+ if (string_len(datastring) > size) {
+ ssh_set_error(sftp->session, SSH_FATAL,
+ "Received a too big DATA packet from sftp server: "
+ "%zu and asked for %u",
+ string_len(datastring), size);
+ string_free(datastring);
+ sftp_leave_function();
+ return SSH_ERROR;
+ }
+ len = string_len(datastring);
+ //handle->offset+=len;
+ /* We already have set the offset previously. All we can do is warn that the expected len
+ * and effective lengths are different */
+ memcpy(data, datastring->string, len);
+ string_free(datastring);
+ sftp_leave_function();
+ return len;
+ default:
+ ssh_set_error(sftp->session,SSH_FATAL,"Received message %d during read!",msg->packet_type);
+ sftp_message_free(msg);
+ sftp_leave_function();
+ return SSH_ERROR;
+ }
+
+ sftp_leave_function();
+ return SSH_ERROR;
}
ssize_t sftp_write(SFTP_FILE *file, const void *buf, size_t count){