diff options
author | Andreas Baumann <mail@andreasbaumann.cc> | 2015-09-06 11:03:07 +0200 |
---|---|---|
committer | Andreas Baumann <mail@andreasbaumann.cc> | 2015-09-06 11:03:07 +0200 |
commit | 85e3c2b1a065f7bab008a824aeb981caf10e192b (patch) | |
tree | 6a2b339c3772b26263b8976f77815593f4dfd2ff | |
parent | b2ca2930a80d738c1aa455569850ed98cd722000 (diff) | |
download | cssh-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.c | 333 |
1 files changed, 169 insertions, 164 deletions
@@ -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; } } |