summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Baumann <mail@andreasbaumann.cc>2015-09-06 11:03:07 +0200
committerAndreas Baumann <mail@andreasbaumann.cc>2015-09-06 11:03:07 +0200
commit85e3c2b1a065f7bab008a824aeb981caf10e192b (patch)
tree6a2b339c3772b26263b8976f77815593f4dfd2ff
parentb2ca2930a80d738c1aa455569850ed98cd722000 (diff)
downloadcssh-85e3c2b1a065f7bab008a824aeb981caf10e192b.tar.gz
cssh-85e3c2b1a065f7bab008a824aeb981caf10e192b.tar.bz2
do not call ssh_scp_pull_request after EOF on a SCP session again
-rw-r--r--src/cssh.c333
1 files changed, 169 insertions, 164 deletions
diff --git a/src/cssh.c b/src/cssh.c
index 5197d0b..cf92ad5 100644
--- a/src/cssh.c
+++ b/src/cssh.c
@@ -1150,184 +1150,189 @@ int main( int argc, char *argv[] )
} break;
case CSSH_COPY_DIRECTION_DOWNLOAD: {
- // TODO: we receive files from N hosts, so we should
- // have a method to create separate directories or
- // files, e.g. file.host1, file.host2, etc.
- // or dirs host1/file host2/file. Maybe this depends
- // also on whether we specify recursive mode or not
for( unsigned int i = 0; i < nof_sessions; i++ ) {
- rc = ssh_scp_pull_request( scp[i] );
- switch( rc ) {
- case SSH_SCP_REQUEST_NEWDIR: {
- 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 );
- }
+ switch( read_state[i] ) {
+ case CSSH_SCP_READ_STATE_IDLE:
+ rc = ssh_scp_pull_request( scp[i] );
+ switch( rc ) {
+ case SSH_SCP_REQUEST_NEWDIR: {
+ 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",
- filename, mode );
- rc = ssh_scp_accept_request( scp[i] );
- 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, &dir_stack, host, port, nof_sessions, args_info.verbose_given > 0 );
- exit( EXIT_FAILURE );
- }
-
- 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:
- pop_dir_stack( &dir_stack[i] );
- break;
+ 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",
+ filename, mode );
+ rc = ssh_scp_accept_request( scp[i] );
+ 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, &dir_stack, host, port, nof_sessions, args_info.verbose_given > 0 );
+ exit( EXIT_FAILURE );
+ }
+
+ 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_NEWFILE: {
- const char *filename = ssh_scp_request_get_filename( scp[i] );
- int mode = ssh_scp_request_get_permissions( scp[i] );
- uint64_t size = ssh_scp_request_get_size64( scp[i] );
- fprintf( stderr, "Receiving file '%s' with permissions '0%o' of size '%"PRIu64"'\n",
- filename, mode, size );
- rc = ssh_scp_accept_request( scp[i] );
- 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, &dir_stack, host, port, nof_sessions, args_info.verbose_given > 0 );
- exit( EXIT_FAILURE );
- }
+ case SSH_SCP_REQUEST_ENDDIR:
+ pop_dir_stack( &dir_stack[i] );
+ break;
- 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 );
- 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
- // TODO: write buffer to received file in workdir of host[i]
- // TODO: slurping it all for one connection is not fair to other connections,
- // we should read a buffer and then check the states of the other and hit the
- // loop again, this needs a state machine..
- uint64_t bytesReceived = 0;
- while( bytesReceived < size ) {
- rc = ssh_scp_read( scp[i], buf[i], BUFSIZE );
- 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, &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",
+ case SSH_SCP_REQUEST_NEWFILE: {
+ const char *filename = ssh_scp_request_get_filename( scp[i] );
+ int mode = ssh_scp_request_get_permissions( scp[i] );
+ uint64_t size = ssh_scp_request_get_size64( scp[i] );
+ fprintf( stderr, "Receiving file '%s' with permissions '0%o' of size '%"PRIu64"'\n",
+ filename, mode, size );
+ rc = ssh_scp_accept_request( scp[i] );
+ 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, &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 );
+ 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
+ // TODO: write buffer to received file in workdir of host[i]
+ // TODO: slurping it all for one connection is not fair to other connections,
+ // we should read a buffer and then check the states of the other and hit the
+ // loop again, this needs a state machine..
+ uint64_t bytesReceived = 0;
+ while( bytesReceived < size ) {
+ rc = ssh_scp_read( scp[i], buf[i], BUFSIZE );
+ 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, &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 );
}
- }
- }
-
- 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;
-
- case SSH_SCP_REQUEST_EOF:
- read_state[i] = CSSH_SCP_READ_STATE_EOF;
- all_eof = true;
- for( unsigned int i = 0; i < nof_sessions; i++ ) {
- if( read_state[i] != CSSH_SCP_READ_STATE_EOF ) {
- all_eof = false;
+ } break;
+
+ case SSH_SCP_REQUEST_EOF:
+ read_state[i] = CSSH_SCP_READ_STATE_EOF;
+ all_eof = true;
+ for( unsigned int i = 0; i < nof_sessions; i++ ) {
+ if( read_state[i] != CSSH_SCP_READ_STATE_EOF ) {
+ all_eof = false;
+ break;
+ }
+ }
+ break;
+
+ 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, &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, &dir_stack, host, port, nof_sessions, args_info.verbose_given > 0 );
+ exit( EXIT_FAILURE );
break;
- }
}
break;
-
- 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, &dir_stack, host, port, nof_sessions, args_info.verbose_given > 0 );
- exit( EXIT_FAILURE );
+
+ case CSSH_SCP_READ_STATE_READING:
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, &dir_stack, host, port, nof_sessions, args_info.verbose_given > 0 );
- exit( EXIT_FAILURE );
+
+ case CSSH_SCP_READ_STATE_EOF:
break;
}
- }
+ }
} break;
}
}