summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndreas Baumann <mail@andreasbaumann.cc>2015-09-06 16:05:24 +0200
committerAndreas Baumann <mail@andreasbaumann.cc>2015-09-06 16:05:24 +0200
commit471a181c3ad4a3fa6267ce13791116121b43725d (patch)
treef4f608496364920b06b9f8c1d5e9e59fe9865df1 /src
parent42dece6021fa1ab8fdc4e8d8a729e5f7aa17fd27 (diff)
downloadcssh-471a181c3ad4a3fa6267ce13791116121b43725d.tar.gz
cssh-471a181c3ad4a3fa6267ce13791116121b43725d.tar.bz2
made writing fair to all session (splitting downloads in pieces)
Diffstat (limited to 'src')
-rw-r--r--src/cssh.c91
1 files changed, 51 insertions, 40 deletions
diff --git a/src/cssh.c b/src/cssh.c
index 5d5ab5f..7e173e3 100644
--- a/src/cssh.c
+++ b/src/cssh.c
@@ -1,3 +1,5 @@
+#define _FILE_OFFSET_BITS 64
+
#include <libssh/libssh.h>
#include <libssh/callbacks.h>
@@ -66,6 +68,8 @@ typedef struct scp_data_t {
ssh_scp scp;
scp_read_state_e read_state;
scp_dir_stack_t dir_stack;
+ int fd;
+ char *filename;
char *buf;
uint64_t size;
uint64_t bytesReceived;
@@ -436,6 +440,11 @@ static void cleanup_sessions( ssh_session **session, ssh_channel **channel, scp_
ssh_scp_free( *scp );
scp = NULL;
}
+ char *filename = (*scp_data)[i].filename;
+ if( filename != NULL ) {
+ free( filename );
+ filename = NULL;
+ }
char *buf = (*scp_data)[i].buf;
if( buf != NULL ) {
free( buf );
@@ -1112,6 +1121,7 @@ int main( int argc, char *argv[] )
}
snprintf( full_path, len, "%s/%s", pwd, host[i] );
rc = push_dir_stack( &scp_data[i].dir_stack, full_path );
+ scp_data[i].filename = full_path;
if( rc < 0 ) {
fprintf( stderr, "ERROR: failed remember initial base directory '%s' in directory stack\n",
@@ -1129,6 +1139,8 @@ int main( int argc, char *argv[] )
cleanup_sessions( &session, NULL, &scp_data, host, port, nof_sessions, args_info.verbose_given > 0 );
exit( EXIT_FAILURE );
}
+ } else {
+ scp_data[i].filename = pwd;
}
}
@@ -1158,7 +1170,7 @@ int main( int argc, char *argv[] )
exit( EXIT_FAILURE );
}
- const char *filename = ssh_scp_request_get_filename( scp_data[i].scp );
+ const char *filename = ssh_scp_request_get_filename( scp_data[i].scp );
int mode = ssh_scp_request_get_permissions( scp_data[i].scp );
fprintf( stderr, "Receiving directory '%s' with permissions '0%o'\n",
filename, mode );
@@ -1203,8 +1215,8 @@ int main( int argc, char *argv[] )
free( full_path );
cleanup_sessions( &session, NULL, &scp_data, host, port, nof_sessions, args_info.verbose_given > 0 );
exit( EXIT_FAILURE );
- }
- free( full_path );
+ }
+ free( full_path );
} break;
case SSH_SCP_REQUEST_ENDDIR:
@@ -1244,51 +1256,19 @@ int main( int argc, char *argv[] )
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_data, 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..
+
+ scp_data[i].fd = fd;
+ scp_data[i].filename = full_path;
scp_data[i].bytesReceived = 0;
- while( scp_data[i].bytesReceived < scp_data[i].size ) {
- rc = ssh_scp_read( scp_data[i].scp, scp_data[i].buf, 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_data, host, port, nof_sessions, args_info.verbose_given > 0 );
- exit( EXIT_FAILURE );
- }
- scp_data[i].bytesReceived += rc;
- if( rc > 0 ) {
- ssize_t r = write( fd, scp_data[i].buf, rc );
- if( r < 0 ) {
- fprintf( stderr, "ERROR: writing data to file '%s' failed: %s\n",
- filename, strerror( errno ) );
- cleanup_sessions( &session, NULL, &scp_data, 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_data, host, port, nof_sessions, args_info.verbose_given > 0 );
- exit( EXIT_FAILURE );
- }
+ scp_data[i].read_state = CSSH_SCP_READ_STATE_READING;
} break;
case SSH_SCP_REQUEST_EOF:
@@ -1319,6 +1299,37 @@ int main( int argc, char *argv[] )
break;
case CSSH_SCP_READ_STATE_READING:
+ if( scp_data[i].bytesReceived < scp_data[i].size ) {
+ rc = ssh_scp_read( scp_data[i].scp, scp_data[i].buf, BUFSIZE );
+ if( rc == SSH_ERROR ) {
+ fprintf( stderr, "ERROR: reading data for file '%s' failed: %s\n",
+ scp_data[i].filename, ssh_get_error( session[i] ) );
+ cleanup_sessions( &session, NULL, &scp_data, host, port, nof_sessions, args_info.verbose_given > 0 );
+ exit( EXIT_FAILURE );
+ }
+ scp_data[i].bytesReceived += rc;
+ if( rc > 0 ) {
+ ssize_t r = write( scp_data[i].fd, scp_data[i].buf, rc );
+ if( r < 0 ) {
+ fprintf( stderr, "ERROR: writing data to file '%s' failed: %s\n",
+ scp_data[i].filename, strerror( errno ) );
+ cleanup_sessions( &session, NULL, &scp_data, host, port, nof_sessions, args_info.verbose_given > 0 );
+ exit( EXIT_FAILURE );
+ }
+ }
+ } else {
+ rc = close( scp_data[i].fd );
+ if( rc < 0 ) {
+ fprintf( stderr, "ERROR: Unable to close file '%s': %s\n",
+ scp_data[i].filename, strerror( errno ) );
+ cleanup_sessions( &session, NULL, &scp_data, host, port, nof_sessions, args_info.verbose_given > 0 );
+ exit( EXIT_FAILURE );
+ }
+ scp_data[i].read_state = CSSH_SCP_READ_STATE_IDLE;
+ scp_data[i].fd = 0;
+ free( scp_data[i].filename );
+ scp_data[i].filename = NULL;
+ }
break;
case CSSH_SCP_READ_STATE_EOF: