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
!!
This commit is contained in:
Aris Adamantiadis
2009-08-23 22:04:51 +02:00
parent d4bc6fa954
commit 385b640d1d
3 changed files with 113 additions and 22 deletions

View File

@@ -120,7 +120,6 @@ typedef struct ssh_agent_struct* ssh_agent;
typedef struct ssh_session_struct* ssh_session; typedef struct ssh_session_struct* ssh_session;
typedef struct ssh_kbdint_struct* ssh_kbdint; typedef struct ssh_kbdint_struct* ssh_kbdint;
typedef struct ssh_scp_struct* ssh_scp; typedef struct ssh_scp_struct* ssh_scp;
typedef struct ssh_scp_request_struct* ssh_scp_request;
/* Socket type */ /* Socket type */
#ifdef _WIN32 #ifdef _WIN32
@@ -471,10 +470,11 @@ enum {
enum ssh_scp_request_types { enum ssh_scp_request_types {
/** A new directory is going to be pulled */ /** A new directory is going to be pulled */
SSH_SCP_REQUEST_NEWDIR, SSH_SCP_REQUEST_NEWDIR=1,
/** A new file is going to be pulled */ /** A new file is going to be pulled */
SSH_SCP_REQUEST_NEWFILE SSH_SCP_REQUEST_NEWFILE
}; };
LIBSSH_API ssh_scp ssh_scp_new(ssh_session session, int mode, const char *location); LIBSSH_API ssh_scp ssh_scp_new(ssh_session session, int mode, const char *location);
LIBSSH_API int ssh_scp_init(ssh_scp scp); LIBSSH_API int ssh_scp_init(ssh_scp scp);
LIBSSH_API int ssh_scp_close(ssh_scp scp); LIBSSH_API int ssh_scp_close(ssh_scp scp);
@@ -483,8 +483,9 @@ LIBSSH_API int ssh_scp_push_directory(ssh_scp scp, const char *dirname, const ch
LIBSSH_API int ssh_scp_leave_directory(ssh_scp scp); LIBSSH_API int ssh_scp_leave_directory(ssh_scp scp);
LIBSSH_API int ssh_scp_push_file(ssh_scp scp, const char *filename, size_t size, const char *perms); LIBSSH_API int ssh_scp_push_file(ssh_scp scp, const char *filename, size_t size, const char *perms);
LIBSSH_API int ssh_scp_write(ssh_scp scp, const void *buffer, size_t len); LIBSSH_API int ssh_scp_write(ssh_scp scp, const void *buffer, size_t len);
LIBSSH_API ssh_scp_request ssh_scp_pull_request(ssh_scp scp); LIBSSH_API int ssh_scp_pull_request(ssh_scp scp);
LIBSSH_API int ssh_scp_deny_request(ssh_scp scp, ssh_scp_request request, const char *reason); LIBSSH_API int ssh_scp_deny_request(ssh_scp scp, const char *reason);
LIBSSH_API int ssh_scp_accept_request(ssh_scp scp);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@@ -356,6 +356,7 @@ enum ssh_scp_states {
SSH_SCP_WRITE_INITED, //Gave our intention to write SSH_SCP_WRITE_INITED, //Gave our intention to write
SSH_SCP_WRITE_WRITING,//File was opened and currently writing SSH_SCP_WRITE_WRITING,//File was opened and currently writing
SSH_SCP_READ_INITED, //Gave our intention to read SSH_SCP_READ_INITED, //Gave our intention to read
SSH_SCP_READ_REQUESTED, //We got a read request
SSH_SCP_READ_READING, //File is opened and reading SSH_SCP_READ_READING, //File is opened and reading
SSH_SCP_ERROR //Something bad happened SSH_SCP_ERROR //Something bad happened
}; };
@@ -368,16 +369,9 @@ struct ssh_scp_struct {
enum ssh_scp_states state; enum ssh_scp_states state;
size_t filelen; size_t filelen;
size_t processed; size_t processed;
}; enum ssh_scp_request_types request_type;
char *request_name;
char *request_mode;
struct ssh_scp_request_struct {
ssh_scp scp;
enum ssh_scp_request_types type;
char *name;
char *mode;
size_t size;
int acked;
}; };
struct ssh_message_struct; struct ssh_message_struct;
@@ -869,8 +863,7 @@ void message_handle(SSH_SESSION *session, uint32_t type);
int ssh_execute_message_callbacks(SSH_SESSION *session); int ssh_execute_message_callbacks(SSH_SESSION *session);
/* scp.c */ /* scp.c */
int ssh_scp_read_string(ssh_scp scp, char *buffer, size_t len);
ssh_scp_request ssh_scp_request_new(void);
/* log.c */ /* log.c */

View File

@@ -120,6 +120,8 @@ void ssh_scp_free(ssh_scp scp){
if(scp->channel) if(scp->channel)
channel_free(scp->channel); channel_free(scp->channel);
SAFE_FREE(scp->location); SAFE_FREE(scp->location);
SAFE_FREE(scp->request_mode);
SAFE_FREE(scp->request_name);
SAFE_FREE(scp); SAFE_FREE(scp);
} }
@@ -267,11 +269,106 @@ int ssh_scp_write(ssh_scp scp, const void *buffer, size_t len){
return SSH_OK; return SSH_OK;
} }
ssh_scp_request ssh_scp_request_new(void){ /**
ssh_scp_request r=malloc(sizeof(struct ssh_scp_request_struct)); * @brief reads a string on a channel, terminated by '\n'
if(r==NULL) * @param buffer pointer to a buffer to place the string
return NULL; * @param len size of the buffer in bytes. If the string is bigger
ZERO_STRUCTP(r); * than len-1, only len-1 bytes are read and the string
return r; * 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;
}