aboutsummaryrefslogtreecommitdiff
path: root/libssh/scp.c
diff options
context:
space:
mode:
authorAris Adamantiadis <aris@0xbadc0de.be>2009-08-23 22:04:51 +0200
committerAris Adamantiadis <aris@0xbadc0de.be>2009-08-23 22:04:51 +0200
commit385b640d1dabddb06e389e633c622fb1c7cc664e (patch)
tree4470d6ba5a4bb6333500a1c91d0cf98a7cf6e87d /libssh/scp.c
parentd4bc6fa954f11b1da0c8881c2826ac4a60f8c41e (diff)
downloadlibssh-385b640d1dabddb06e389e633c622fb1c7cc664e.tar.gz
libssh-385b640d1dabddb06e389e633c622fb1c7cc664e.tar.xz
libssh-385b640d1dabddb06e389e633c622fb1c7cc664e.zip
Implementation of ssh_scp_pull_request
Still needed: code in ssh_scp_init, implementation of ssh_scp_read ssh_scp_request_get_filename, ssh_scp_request_get_size, ssh_scp_request_get_mode, ssh_scp_deny_request ssh_scp_accept_request !!
Diffstat (limited to 'libssh/scp.c')
-rw-r--r--libssh/scp.c109
1 files changed, 103 insertions, 6 deletions
diff --git a/libssh/scp.c b/libssh/scp.c
index e4cb348..9cabe30 100644
--- a/libssh/scp.c
+++ b/libssh/scp.c
@@ -120,6 +120,8 @@ void ssh_scp_free(ssh_scp scp){
if(scp->channel)
channel_free(scp->channel);
SAFE_FREE(scp->location);
+ SAFE_FREE(scp->request_mode);
+ SAFE_FREE(scp->request_name);
SAFE_FREE(scp);
}
@@ -267,11 +269,106 @@ int ssh_scp_write(ssh_scp scp, const void *buffer, size_t len){
return SSH_OK;
}
-ssh_scp_request ssh_scp_request_new(void){
- ssh_scp_request r=malloc(sizeof(struct ssh_scp_request_struct));
- if(r==NULL)
- return NULL;
- ZERO_STRUCTP(r);
- return r;
+/**
+ * @brief reads a string on a channel, terminated by '\n'
+ * @param buffer pointer to a buffer to place the string
+ * @param len size of the buffer in bytes. If the string is bigger
+ * than len-1, only len-1 bytes are read and the string
+ * is null-terminated.
+ * @returns SSH_OK The string was read
+ * @returns SSH_ERROR Error happened while reading
+ */
+int ssh_scp_read_string(ssh_scp scp, char *buffer, size_t len){
+ size_t r=0;
+ int err=SSH_OK;
+ while(r<len-1){
+ err=channel_read(scp->channel,&buffer[r],1,0);
+ if(err==SSH_ERROR){
+ break;
+ }
+ if(err==0){
+ ssh_set_error(scp->session,SSH_FATAL,"End of file while reading string");
+ err=SSH_ERROR;
+ break;
+ }
+ r++;
+ if(buffer[r-1] == '\n')
+ break;
+ }
+ buffer[r]=0;
+ return err;
}
+/** @brief waits for a scp request (file, directory)
+ * @returns SSH_ERROR Some error happened
+ * @returns SSH_SCP_REQUEST_FILE The other side is sending a file
+ * @returns SSH_SCP_REQUEST_DIRECTORY The other side is sending a directory
+ * @returns SSH_SCP_REQUEST_END_DIRECTORY The other side has finished with the current directory
+ * @see ssh_scp_read
+ * @see ssh_scp_deny_request
+ * @see ssh_scp_accept_request
+ */
+int ssh_scp_pull_request(ssh_scp scp){
+ char buffer[4096];
+ char *mode=NULL;
+ char *p,*tmp;
+ size_t size;
+ char *name=NULL;
+ int err;
+ if(scp->state != SSH_SCP_READ_INITED){
+ ssh_set_error(scp->session,SSH_FATAL,"ssh_scp_pull_request called under invalid state");
+ return SSH_ERROR;
+ }
+ err=ssh_scp_read_string(scp,buffer,sizeof(buffer));
+ if(err==SSH_ERROR)
+ return err;
+ switch(buffer[0]){
+ case 'C':
+ /* File */
+ case 'D':
+ /* Directory */
+ p=strchr(buffer,' ');
+ if(p==NULL)
+ goto error;
+ *p='\0';
+ p++;
+ mode=strdup(&buffer[1]);
+ tmp=p;
+ p=strchr(p,' ');
+ if(p==NULL)
+ goto error;
+ *p=0;
+ size=strtoull(tmp,NULL,10);
+ p++;
+ tmp=p;
+ p=strchr(p,'\n');
+ if(p==NULL)
+ goto error;
+ *p=0;
+ name=strdup(tmp);
+ scp->request_mode=mode;
+ scp->request_name=name;
+ if(buffer[0]=='C'){
+ scp->filelen=size;
+ scp->request_type=SSH_SCP_REQUEST_NEWFILE;
+ } else {
+ scp->filelen='0';
+ scp->request_type=SSH_SCP_REQUEST_NEWDIR;
+ }
+ scp->state=SSH_SCP_READ_REQUESTED;
+ return scp->request_type;
+ break;
+ case 'T':
+ /* Timestamp */
+ default:
+ ssh_set_error(scp->session,SSH_FATAL,"Unhandled message: %s",buffer);
+ return SSH_ERROR;
+ }
+
+ /* a parsing error occured */
+ error:
+ SAFE_FREE(name);
+ SAFE_FREE(mode);
+ ssh_set_error(scp->session,SSH_FATAL,"Parsing error while parsing message: %s",buffer);
+ return SSH_ERROR;
+}