summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Baumann <mail@andreasbaumann.cc>2015-08-30 15:26:21 +0200
committerAndreas Baumann <mail@andreasbaumann.cc>2015-08-30 15:26:21 +0200
commit635976a25836e7fd120249a29c7fc70a5e58dc99 (patch)
tree1b6c6b8986cab3bc2c1764b67bf9c40c9808546b
parent8edf3bcfc07914d465cc462b28bb5f8b07a3ec5b (diff)
downloadcssh-635976a25836e7fd120249a29c7fc70a5e58dc99.tar.gz
cssh-635976a25836e7fd120249a29c7fc70a5e58dc99.tar.bz2
indroduced dirstack, first recursive copy successful
-rw-r--r--src/cssh.c265
1 files changed, 225 insertions, 40 deletions
diff --git a/src/cssh.c b/src/cssh.c
index 09b1c3d..66272ef 100644
--- a/src/cssh.c
+++ b/src/cssh.c
@@ -8,8 +8,11 @@
#include <stdbool.h>
#include <unistd.h>
#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
#include <pwd.h>
#include <inttypes.h>
+#include <unistd.h>
#include "msleep.h"
@@ -48,6 +51,60 @@ typedef enum scp_read_state_e {
CSSH_SCP_READ_STATE_EOF
} scp_read_state_e;
+typedef struct scp_dir_stack_entry_t {
+ char *dir;
+ struct scp_dir_stack_entry_t *next;
+} scp_dir_stack_entry_t;
+
+typedef struct scp_dir_stack_t {
+ struct scp_dir_stack_entry_t *head;
+} scp_dir_stack_t;
+
+static int push_dir_stack( scp_dir_stack_t *stack, const char *dir )
+{
+ struct scp_dir_stack_entry_t *e = (struct scp_dir_stack_entry_t *)malloc( sizeof( scp_dir_stack_entry_t ) );
+ if( e == NULL ) {
+ return -1;
+ }
+
+ e->dir = strdup( dir );
+ e->next = stack->head;
+ stack->head = e;
+
+ return 0;
+}
+
+static void pop_dir_stack( scp_dir_stack_t *stack )
+{
+ if( stack->head != NULL ) {
+ struct scp_dir_stack_entry_t *e = stack->head;
+ stack->head = stack->head->next;
+ free( e->dir );
+ free( e );
+ }
+}
+
+static char *top_dir_stack( scp_dir_stack_t *stack )
+{
+ if( stack->head != NULL ) {
+ return stack->head->dir;
+ } else {
+ return NULL;
+ }
+}
+
+static void free_dir_stack( scp_dir_stack_t *stack )
+{
+ while( stack->head != NULL ) {
+ pop_dir_stack( stack );
+ }
+}
+
+static void create_dir_stack( scp_dir_stack_t *stack )
+{
+ stack->head = NULL;
+}
+
static execution_mode_e determine_execution_mode( const char *argv0 )
{
char *b = ssh_basename( argv0 );
@@ -327,7 +384,7 @@ static int read_hosts_file( const char *hosts_file, unsigned short default_port,
return 0;
}
-static void cleanup_sessions( ssh_session **session, ssh_channel **channel, ssh_scp **scp, scp_read_state_e **read_state, char ***buf, char **host, unsigned short *port, const int nof_sessions, bool verbose )
+static void cleanup_sessions( ssh_session **session, ssh_channel **channel, ssh_scp **scp, scp_read_state_e **read_state, char ***buf, scp_dir_stack_t **dir_stack, char **host, unsigned short *port, const int nof_sessions, bool verbose )
{
for( unsigned int i = 0; i < nof_sessions; i++ ) {
if( ssh_is_connected( (*session)[i] ) ) {
@@ -348,6 +405,9 @@ static void cleanup_sessions( ssh_session **session, ssh_channel **channel, ssh_
if( buf != NULL ) {
free( (*buf)[i] );
}
+ if( dir_stack != NULL ) {
+ free_dir_stack( &(*dir_stack)[i] );
+ }
ssh_disconnect( (*session)[i] );
if( verbose ) {
fprintf( stderr, "Disconnected from '%s', port %d..\n", host[i], port[i] );
@@ -367,6 +427,9 @@ static void cleanup_sessions( ssh_session **session, ssh_channel **channel, ssh_
if( buf != NULL ) {
free( *buf );
}
+ if( dir_stack != NULL ) {
+ free( *dir_stack );
+ }
free( *session );
free( *host );
free( port );
@@ -473,7 +536,7 @@ int main( int argc, char *argv[] )
bool *is_connected = (bool *)malloc( ( nof_sessions + 1 ) * sizeof( bool ) );
if( is_connected == NULL ) {
fprintf( stderr, "ERROR: Memory allocation failed for 'is_connected'" );
- cleanup_sessions( &session, NULL, NULL, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
+ cleanup_sessions( &session, NULL, NULL, NULL, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
exit( EXIT_SUCCESS );
}
memset( is_connected, false, ( nof_sessions + 1 ) * sizeof( bool ) );
@@ -492,7 +555,7 @@ int main( int argc, char *argv[] )
} else {
fprintf( stderr, "ERROR: error connecting to '%s', port '%d': %s\n",
host[i], port[i], ssh_get_error( session[i] ) );
- cleanup_sessions( &session, NULL, NULL, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
+ cleanup_sessions( &session, NULL, NULL, NULL, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
exit( EXIT_FAILURE );
}
}
@@ -512,7 +575,7 @@ int main( int argc, char *argv[] )
auth_state_e *auth_state = (auth_state_e *)malloc( ( nof_sessions + 1 ) * sizeof( auth_state_e ) );
if( auth_state == NULL ) {
fprintf( stderr, "ERROR: Memory allocation failed for 'auth_state'" );
- cleanup_sessions( &session, NULL, NULL, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
+ cleanup_sessions( &session, NULL, NULL, NULL, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
exit( EXIT_FAILURE );
}
memset( auth_state, CSSH_AUTH_INIT, ( nof_sessions + 1 ) * sizeof( auth_state_e ) );
@@ -523,7 +586,7 @@ int main( int argc, char *argv[] )
if( verify_knownhost( session[i] ) < 0 ) {
fprintf( stderr, "ERROR: closing connection to '%s', port '%d' due to security reasons\n",
host[i], port[i] );
- cleanup_sessions( &session, NULL, NULL, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
+ cleanup_sessions( &session, NULL, NULL, NULL, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
exit( EXIT_FAILURE );
}
auth_state[i] = CSSH_AUTH_VERIFY_HOST_DONE;
@@ -544,7 +607,7 @@ int main( int argc, char *argv[] )
} else {
fprintf( stderr, "ERROR: ssh_userauth_none to '%s', port '%d' failed: %s\n",
host[i], port[i], ssh_get_error( session[i] ) );
- cleanup_sessions( &session, NULL, NULL, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
+ cleanup_sessions( &session, NULL, NULL, NULL, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
exit( EXIT_FAILURE );
}
break;
@@ -569,7 +632,7 @@ int main( int argc, char *argv[] )
} else if( rc == SSH_AUTH_DENIED ) {
auth_state[i] = CSSH_AUTH_PUBKEY_DONE_FAILED;
} else {
- cleanup_sessions( &session, NULL, NULL, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
+ cleanup_sessions( &session, NULL, NULL, NULL, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
exit( EXIT_FAILURE );
}
break;
@@ -588,7 +651,7 @@ int main( int argc, char *argv[] )
} else if( rc == SSH_AUTH_DENIED ) {
auth_state[i] = CSSH_AUTH_PASSWORD_DONE_FAILED;
} else {
- cleanup_sessions( &session, NULL, NULL, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
+ cleanup_sessions( &session, NULL, NULL, NULL, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
exit( EXIT_FAILURE );
}
break;
@@ -608,7 +671,7 @@ int main( int argc, char *argv[] )
case CSSH_AUTH_DONE_FAILED:
// one authentication failed, bail out for now
fprintf( stderr, "ERROR: authentication failed for one host ('%s'), aborting now", host[i] );
- cleanup_sessions( &session, NULL, NULL, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
+ cleanup_sessions( &session, NULL, NULL, NULL, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
exit( EXIT_FAILURE );
}
}
@@ -631,7 +694,7 @@ int main( int argc, char *argv[] )
memset( channel, 0, nof_sessions + 1 );
if( channel == NULL ) {
fprintf( stderr, "ERROR: Memory allocation failed for ssh_channels" );
- cleanup_sessions( &session, NULL, NULL, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
+ cleanup_sessions( &session, NULL, NULL, NULL, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
exit( EXIT_FAILURE );
}
for( unsigned int i = 0; i < nof_sessions; i++ ) {
@@ -639,7 +702,7 @@ int main( int argc, char *argv[] )
if( channel[i] == NULL ) {
fprintf( stderr, "ERROR: Unable to open SSH channel: %s\n",
ssh_get_error( session[i] ) );
- cleanup_sessions( &session, &channel, NULL, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
+ cleanup_sessions( &session, &channel, NULL, NULL, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
exit( EXIT_FAILURE );
}
}
@@ -647,7 +710,7 @@ int main( int argc, char *argv[] )
for( unsigned int i = 0; i < nof_sessions; i++ ) {
rc = ssh_channel_open_session( channel[i] );
if( rc != SSH_OK ) {
- cleanup_sessions( &session, &channel, NULL, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
+ cleanup_sessions( &session, &channel, NULL, NULL, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
exit( EXIT_FAILURE );
}
}
@@ -665,7 +728,7 @@ int main( int argc, char *argv[] )
}
if( cmd[0] == '\0' ) {
fprintf( stderr, "ERROR: Empty command, no interactive CLI supported currently\n" );
- cleanup_sessions( &session, &channel, NULL, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
+ cleanup_sessions( &session, &channel, NULL, NULL, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
exit( EXIT_FAILURE );
}
@@ -675,7 +738,7 @@ int main( int argc, char *argv[] )
if( rc != SSH_OK ) {
fprintf( stderr, "ERROR: Executing SSH command '%s' failed: %s\n",
cmd, ssh_get_error( session[i] ) );
- cleanup_sessions( &session, &channel, NULL, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
+ cleanup_sessions( &session, &channel, NULL, NULL, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
exit( EXIT_FAILURE );
}
}
@@ -684,7 +747,7 @@ int main( int argc, char *argv[] )
bool *eof_sent = (bool *)malloc( ( nof_sessions + 1 ) * sizeof( bool ) );
if( eof_sent == NULL ) {
fprintf( stderr, "ERROR: Memory allocation failed for 'eof_sent'" );
- cleanup_sessions( &session, &channel, NULL, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
+ cleanup_sessions( &session, &channel, NULL, NULL, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
exit( EXIT_FAILURE );
}
memset( eof_sent, false, ( nof_sessions + 1 ) * sizeof( bool ) );
@@ -692,7 +755,7 @@ int main( int argc, char *argv[] )
if( is_eof == NULL ) {
fprintf( stderr, "ERROR: Memory allocation failed for 'is_eof'" );
free( eof_sent );
- cleanup_sessions( &session, &channel, NULL, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
+ cleanup_sessions( &session, &channel, NULL, NULL, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
exit( EXIT_FAILURE );
}
memset( is_eof, false, ( nof_sessions + 1 ) * sizeof( bool ) );
@@ -723,7 +786,7 @@ int main( int argc, char *argv[] )
ssh_get_error( session[i] ) );
free( eof_sent );
free( is_eof );
- cleanup_sessions( &session, &channel, NULL, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
+ cleanup_sessions( &session, &channel, NULL, NULL, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
exit( EXIT_FAILURE );
}
@@ -734,7 +797,7 @@ int main( int argc, char *argv[] )
ssh_get_error( session[i] ) );
free( eof_sent );
free( is_eof );
- cleanup_sessions( &session, &channel, NULL, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
+ cleanup_sessions( &session, &channel, NULL, NULL, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
exit( EXIT_FAILURE );
}
@@ -749,7 +812,7 @@ int main( int argc, char *argv[] )
strerror( errno ) );
free( eof_sent );
free( is_eof );
- cleanup_sessions( &session, &channel, NULL, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
+ cleanup_sessions( &session, &channel, NULL, NULL, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
exit( EXIT_FAILURE );
}
@@ -758,7 +821,7 @@ int main( int argc, char *argv[] )
wrc, nread );
free( eof_sent );
free( is_eof );
- cleanup_sessions( &session, &channel, NULL, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
+ cleanup_sessions( &session, &channel, NULL, NULL, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
exit( EXIT_FAILURE );
}
}
@@ -770,7 +833,7 @@ int main( int argc, char *argv[] )
ssh_get_error( session[i] ) );
free( eof_sent );
free( is_eof );
- cleanup_sessions( &session, &channel, NULL, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
+ cleanup_sessions( &session, &channel, NULL, NULL, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
exit( EXIT_FAILURE );
}
@@ -781,7 +844,7 @@ int main( int argc, char *argv[] )
ssh_get_error( session[i] ) );
free( eof_sent );
free( is_eof );
- cleanup_sessions( &session, &channel, NULL, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
+ cleanup_sessions( &session, &channel, NULL, NULL, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
exit( EXIT_FAILURE );
}
@@ -792,7 +855,7 @@ int main( int argc, char *argv[] )
strerror( errno ) );
free( eof_sent );
free( is_eof );
- cleanup_sessions( &session, &channel, NULL, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
+ cleanup_sessions( &session, &channel, NULL, NULL, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
exit( EXIT_FAILURE );
}
@@ -801,7 +864,7 @@ int main( int argc, char *argv[] )
wrc, nread );
free( eof_sent );
free( is_eof );
- cleanup_sessions( &session, &channel, NULL, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
+ cleanup_sessions( &session, &channel, NULL, NULL, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
exit( EXIT_FAILURE );
}
}
@@ -817,7 +880,7 @@ int main( int argc, char *argv[] )
free( eof_sent );
free( is_eof );
- cleanup_sessions( &session, &channel, NULL, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
+ cleanup_sessions( &session, &channel, NULL, NULL, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
} break;
@@ -834,7 +897,7 @@ int main( int argc, char *argv[] )
memset( scp, 0, nof_sessions + 1 );
if( scp == NULL ) {
fprintf( stderr, "ERROR: Memory allocation failed for ssh_scp" );
- cleanup_sessions( &session, NULL, NULL, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
+ cleanup_sessions( &session, NULL, NULL, NULL, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
exit( EXIT_FAILURE );
}
for( unsigned int i = 0; i < nof_sessions; i++ ) {
@@ -845,7 +908,7 @@ int main( int argc, char *argv[] )
if( scp[i] == NULL ) {
fprintf( stderr, "ERROR: Unable to open SCP channel: %s\n",
ssh_get_error( session[i] ) );
- cleanup_sessions( &session, NULL, &scp, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
+ cleanup_sessions( &session, NULL, &scp, NULL, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
exit( EXIT_FAILURE );
}
}
@@ -855,7 +918,7 @@ int main( int argc, char *argv[] )
if( rc != SSH_OK ) {
fprintf( stderr, "ERROR: Unable to initialize SCP sessions: %s\n",
ssh_get_error( session[i] ) );
- cleanup_sessions( &session, NULL, &scp, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
+ cleanup_sessions( &session, NULL, &scp, NULL, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
exit( EXIT_FAILURE );
}
}
@@ -863,7 +926,7 @@ int main( int argc, char *argv[] )
char **buf = (char **)malloc( ( nof_sessions + 1 ) * sizeof( char * ) );
if( buf == NULL ) {
fprintf( stderr, "ERROR: Memory allocation failed for receiving buffers of ssh_scp" );
- cleanup_sessions( &session, NULL, &scp, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
+ cleanup_sessions( &session, NULL, &scp, NULL, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
exit( EXIT_FAILURE );
}
memset( buf, 0, ( nof_sessions + 1 ) * sizeof( char * ) );
@@ -871,7 +934,7 @@ int main( int argc, char *argv[] )
buf[i] = (char *)malloc( BUFSIZE );
if( buf[i] == NULL ) {
fprintf( stderr, "ERROR: Memory allocation failed for receiving buffers of ssh_scp" );
- cleanup_sessions( &session, NULL, &scp, NULL, &buf, host, port, nof_sessions, args_info.verbose_given > 0 );
+ cleanup_sessions( &session, NULL, &scp, NULL, &buf, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
exit( EXIT_FAILURE );
}
}
@@ -880,11 +943,42 @@ int main( int argc, char *argv[] )
scp_read_state_e *read_state = (scp_read_state_e *)malloc( ( nof_sessions + 1 ) * sizeof( scp_read_state_e ) );
if( read_state == NULL ) {
fprintf( stderr, "ERROR: Memory allocation failed for 'is_eof'" );
- cleanup_sessions( &session, NULL, &scp, NULL, &buf, host, port, nof_sessions, args_info.verbose_given > 0 );
+ cleanup_sessions( &session, NULL, &scp, NULL, &buf, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
exit( EXIT_FAILURE );
}
memset( read_state, CSSH_SCP_READ_STATE_IDLE, ( nof_sessions + 1 ) * sizeof( scp_read_state_e ) );
+ scp_dir_stack_t *dir_stack = (scp_dir_stack_t *)malloc( ( nof_sessions + 1 ) * sizeof( scp_dir_stack_t ) );
+ if( dir_stack == NULL ) {
+ fprintf( stderr, "ERROR: Memory allocation failed for 'dir_stack'" );
+ cleanup_sessions( &session, NULL, &scp, NULL, &buf, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
+ exit( EXIT_FAILURE );
+ }
+ for( unsigned int i = 0; i < nof_sessions; i++ ) {
+ create_dir_stack( &dir_stack[i] );
+
+ char *pwd = getcwd( NULL, 0 );
+ if( pwd == NULL ) {
+ fprintf( stderr, "ERROR: failed to determine working directory for SCP for host '%s': %s\n",
+ host[i], strerror( errno ) );
+ cleanup_sessions( &session, NULL, &scp, &read_state, &buf, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
+ exit( EXIT_FAILURE );
+ }
+
+ rc = push_dir_stack( &dir_stack[i], pwd );
+
+ // TODO: directory should be a base per hostname[i]
+
+ if( rc < 0 ) {
+ fprintf( stderr, "ERROR: failed remember initial base directory '%s' in directory stack\n",
+ pwd );
+ free( pwd );
+ cleanup_sessions( &session, NULL, &scp, &read_state, &buf, &dir_stack, host, port, nof_sessions, args_info.verbose_given > 0 );
+ exit( EXIT_FAILURE );
+ }
+ free( pwd );
+ }
+
while( !all_eof ) {
switch( copy_direction ) {
@@ -902,6 +996,16 @@ int main( int argc, char *argv[] )
switch( rc ) {
case SSH_SCP_REQUEST_NEWDIR: {
// TODO: mkdir in host[i] workspace
+
+ char *dir = top_dir_stack( &dir_stack[i] );
+ rc = chdir( dir );
+ if( rc < 0 ) {
+ fprintf( stderr, "ERROR: failed to change to directory '%s': %s\n",
+ dir, strerror( errno ) );
+ cleanup_sessions( &session, NULL, &scp, &read_state, &buf, &dir_stack, host, port, nof_sessions, args_info.verbose_given > 0 );
+ exit( EXIT_FAILURE );
+ }
+
const char *filename = ssh_scp_request_get_filename( scp[i] );
int mode = ssh_scp_request_get_permissions( scp[i] );
fprintf( stderr, "Receiving directory '%s' with permissions '0%o'\n",
@@ -910,15 +1014,48 @@ int main( int argc, char *argv[] )
if( rc != SSH_OK ) {
fprintf( stderr, "ERROR: accepting request for directory '%s' failed: %s\n",
filename, ssh_get_error( session[i] ) );
- cleanup_sessions( &session, NULL, &scp, &read_state, &buf, host, port, nof_sessions, args_info.verbose_given > 0 );
+ cleanup_sessions( &session, NULL, &scp, &read_state, &buf, &dir_stack, host, port, nof_sessions, args_info.verbose_given > 0 );
+ exit( EXIT_FAILURE );
+ }
+ // TODO: change dir to workspace of scp[i]
+ rc = mkdir( filename, mode );
+ if( rc < 0 ) {
+ fprintf( stderr, "ERROR: failed to create directory '%s': %s\n",
+ filename, strerror( errno ) );
+ cleanup_sessions( &session, NULL, &scp, &read_state, &buf, &dir_stack, host, port, nof_sessions, args_info.verbose_given > 0 );
exit( EXIT_FAILURE );
}
+ char *pwd = getcwd( NULL, 0 );
+ if( pwd == NULL ) {
+ fprintf( stderr, "ERROR: failed to determine working directory for SCP for host '%s': %s\n",
+ host[i], strerror( errno ) );
+ cleanup_sessions( &session, NULL, &scp, &read_state, &buf, &dir_stack, host, port, nof_sessions, args_info.verbose_given > 0 );
+ exit( EXIT_FAILURE );
+ }
+ size_t len = strlen( pwd ) + 2 + strlen( filename );
+ char *full_path = (char *)malloc( len );
+ if( full_path == NULL ) {
+ fprintf( stderr, "ERROR: Memory allocation failed for full path of directory '%s'\n",
+ filename );
+ free( pwd );
+ cleanup_sessions( &session, NULL, &scp, &read_state, &buf, &dir_stack, host, port, nof_sessions, args_info.verbose_given > 0 );
+ exit( EXIT_FAILURE );
+ }
+ snprintf( full_path, len, "%s/%s", pwd, filename );
+ rc = push_dir_stack( &dir_stack[i], full_path );
+ free( pwd );
+ if( rc < 0 ) {
+ fprintf( stderr, "ERROR: failed remember directory '%s' in directory stack\n",
+ full_path );
+ free( full_path );
+ cleanup_sessions( &session, NULL, &scp, &read_state, &buf, &dir_stack, host, port, nof_sessions, args_info.verbose_given > 0 );
+ exit( EXIT_FAILURE );
+ }
+ free( full_path );
} break;
case SSH_SCP_REQUEST_ENDDIR:
- // TODO: leave current workspace
- // TODO: we need a stack per client connection
- // to remember the current directory we are in
+ pop_dir_stack( &dir_stack[i] );
break;
case SSH_SCP_REQUEST_NEWFILE: {
@@ -931,9 +1068,40 @@ int main( int argc, char *argv[] )
if( rc != SSH_OK ) {
fprintf( stderr, "ERROR: accepting request for file '%s' failed: %s\n",
filename, ssh_get_error( session[i] ) );
- cleanup_sessions( &session, NULL, &scp, &read_state, &buf, host, port, nof_sessions, args_info.verbose_given > 0 );
+ cleanup_sessions( &session, NULL, &scp, &read_state, &buf, &dir_stack, host, port, nof_sessions, args_info.verbose_given > 0 );
exit( EXIT_FAILURE );
}
+
+ char *dir = top_dir_stack( &dir_stack[i] );
+ rc = chdir( dir );
+ if( rc < 0 ) {
+ fprintf( stderr, "ERROR: failed to change to directory '%s': %s\n",
+ dir, strerror( errno ) );
+ cleanup_sessions( &session, NULL, &scp, &read_state, &buf, &dir_stack, host, port, nof_sessions, args_info.verbose_given > 0 );
+ exit( EXIT_FAILURE );
+ }
+
+ size_t len = strlen( dir ) + 2 + strlen( filename );
+ char *full_path = (char *)malloc( len );
+ if( full_path == NULL ) {
+ fprintf( stderr, "ERROR: Memory allocation failed for full path of directory '%s'\n",
+ filename );
+ free( dir );
+ cleanup_sessions( &session, NULL, &scp, &read_state, &buf, &dir_stack, host, port, nof_sessions, args_info.verbose_given > 0 );
+ exit( EXIT_FAILURE );
+ }
+ snprintf( full_path, len, "%s/%s", dir, filename );
+ free( dir );
+ int fd = open( full_path, O_WRONLY | O_CREAT | O_TRUNC, mode );
+ if( fd < 0 ) {
+ fprintf( stderr, "ERROR: Unable to open file '%s': %s\n",
+ full_path, strerror( errno ) );
+ free( full_path );
+ cleanup_sessions( &session, NULL, &scp, &read_state, &buf, &dir_stack, host, port, nof_sessions, args_info.verbose_given > 0 );
+ exit( EXIT_FAILURE );
+ }
+ free( full_path );
+
// TODO: we receive a buffer of data < 65k, so we must introduce a
// state machine here so we know we still have to read or initiate the accept,
// this is also quite handy as we can show some progress bar here or some ETA
@@ -947,10 +1115,27 @@ int main( int argc, char *argv[] )
if( rc == SSH_ERROR ) {
fprintf( stderr, "ERROR: reading data for file '%s' failed: %s\n",
filename, ssh_get_error( session[i] ) );
- cleanup_sessions( &session, NULL, &scp, &read_state, &buf, host, port, nof_sessions, args_info.verbose_given > 0 );
+ cleanup_sessions( &session, NULL, &scp, &read_state, &buf, &dir_stack, host, port, nof_sessions, args_info.verbose_given > 0 );
exit( EXIT_FAILURE );
}
bytesReceived += rc;
+ if( rc > 0 ) {
+ ssize_t r = write( fd, buf[i], rc );
+ if( r < 0 ) {
+ fprintf( stderr, "ERROR: writing data to file '%s' failed: %s\n",
+ filename, strerror( errno ) );
+ cleanup_sessions( &session, NULL, &scp, &read_state, &buf, &dir_stack, host, port, nof_sessions, args_info.verbose_given > 0 );
+ exit( EXIT_FAILURE );
+ }
+ }
+ }
+
+ rc = close( fd );
+ if( rc < 0 ) {
+ fprintf( stderr, "ERROR: Unable to close file '%s': %s\n",
+ filename, strerror( errno ) );
+ cleanup_sessions( &session, NULL, &scp, &read_state, &buf, &dir_stack, host, port, nof_sessions, args_info.verbose_given > 0 );
+ exit( EXIT_FAILURE );
}
} break;
@@ -968,14 +1153,14 @@ int main( int argc, char *argv[] )
case SSH_ERROR:
fprintf( stderr, "ERROR: error from remote host '%s': %s\n",
host[i], ssh_get_error( session[i] ) );
- cleanup_sessions( &session, NULL, &scp, &read_state, &buf, host, port, nof_sessions, args_info.verbose_given > 0 );
+ cleanup_sessions( &session, NULL, &scp, &read_state, &buf, &dir_stack, host, port, nof_sessions, args_info.verbose_given > 0 );
exit( EXIT_FAILURE );
break;
case SSH_SCP_REQUEST_WARNING:
fprintf( stderr, "WARNING: remote host '%s': %s\n",
host[i], ssh_scp_request_get_warning( scp[i] ) );
- cleanup_sessions( &session, NULL, &scp, &read_state, &buf, host, port, nof_sessions, args_info.verbose_given > 0 );
+ cleanup_sessions( &session, NULL, &scp, &read_state, &buf, &dir_stack, host, port, nof_sessions, args_info.verbose_given > 0 );
exit( EXIT_FAILURE );
break;
}
@@ -984,7 +1169,7 @@ int main( int argc, char *argv[] )
}
}
- cleanup_sessions( &session, NULL, &scp, &read_state, &buf, host, port, nof_sessions, args_info.verbose_given > 0 );
+ cleanup_sessions( &session, NULL, &scp, &read_state, &buf, &dir_stack, host, port, nof_sessions, args_info.verbose_given > 0 );
} break;