static sig_atomic_t gotsig = 0;
static void sig_handler( int signum ){
- gotsig = 1;
+ gotsig = signum;
fprintf( stderr, "\nReceived signal %d, wrapping up gracefully.\n", signum );
}
#define RESP_HAVE "Have "
#define RESP_COMPLETE "Upload complete, "
#define RESP_SKIP "Skip-to-position: "
+#define RESP_MISMATCH "Partfile initial sequence mismatch"
+#define RESP_NOPERM "<x-alert><h1>No permission!</h1></x-alert>"
static int upload_chunk( CURL *curl, struct file_info_t *fi, off_t csize ) {
int res = -1;
int response_code;
ssize_t br;
char url[2048];
- void *slice;
+ void *chunk;
off_t completed = 0;
CURLcode error;
struct membuf_t reply;
if ( csize > fi->remn )
csize = fi->remn;
- if ( NULL == ( slice = malloc( csize ) ) )
+ if ( NULL == ( chunk = malloc( csize ) ) )
die( "malloc", errno );
lseek( fi->fd, fi->coff, SEEK_SET );
- if ( 0 > ( br = read( fi->fd, slice, csize ) ) ) {
+ if ( 0 > ( br = read( fi->fd, chunk, csize ) ) ) {
err( "read", errno );
goto err_out;
}
curl_easy_reset( curl );
error = curl_easy_setopt( curl, CURLOPT_POST, 1L );
error |= curl_easy_setopt( curl, CURLOPT_POSTFIELDSIZE, (long)csize );
- error |= curl_easy_setopt( curl, CURLOPT_POSTFIELDS, slice );
+ error |= curl_easy_setopt( curl, CURLOPT_POSTFIELDS, chunk );
error |= curl_easy_setopt( curl, CURLOPT_URL, url );
error |= curl_easy_setopt( curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC );
error |= curl_easy_setopt( curl, CURLOPT_USERNAME, cfg.user );
// puts(reply.memory);
switch ( response_code ) {
- case 100:
case 200:
- case 201:
// simplest case, uploaded one chunk
if ( 0 == strncmp( reply.memory, RESP_HAVE, strlen( RESP_HAVE ) ) ) {
fi->coff += csize;
if ( completed == fi->coff && 0 == fi->remn )
res = 0;
}
+ else if ( NULL != strstr( reply.memory, RESP_NOPERM ) ) {
+ // this really should be a 401 or 403 ...
+ err( "no permission, check credentials!", 0 );
+ }
else
- err( "unexpected response, check credentials?", 0 );
+ fprintf( stderr, "ERROR: unexpected response: %s", reply.memory );
+ break;
+ case 201:
+ // upon receiving the first chunk, remote detected a partfile initial
+ // sequence mismatch, refused to skip and scrapped the old partfile
+ if ( 0 == strncmp( reply.memory, RESP_MISMATCH, strlen( RESP_MISMATCH ) ) ) {
+ fi->coff += csize;
+ fi->remn -= csize;
+ res = 0;
+ }
break;
case 428:
// remote already has data up to Skip-to-position
err( "response code 428 w/o 'Skip-to-position'", 0 );
break;
default:
- fprintf( stderr, "ERROR: unexpected response code: %d\n", response_code );
+ fprintf( stderr, "REMOTE ERROR: %d: %s\n", response_code, reply.memory );
break;
}
err_out:
free( reply.memory );
- free( slice );
+ free( chunk );
return res;
}
}
fi.remn = fi.size = stbuf.st_size;
fi.coff = 0;
- printf( "File: %s, %lu bytes\n", fi.name, (unsigned long)fi.size );
+ printf( "File: %s (%lu bytes)\n", fi.name, (unsigned long)fi.size );
while ( fi.remn ) {
if ( gotsig ) {
csize = 2 * fi.speed;
if ( CSIZE_HARDLIMIT < csize )
csize = CSIZE_HARDLIMIT;
- printf( "\r%3.f%% (%5.1f kB/s) ", (double)fi.coff * 100 / fi.size, (double)fi.speed / 1024 );
- // printf( "[csize: %ld] {offset: %ld} ", (long)csize, (long)fi.coff );
- fflush( stdout );
+ fprintf( stderr, "\r%3.f%% (%5.1f kB/s) ", (double)fi.coff * 100 / fi.size, (double)fi.speed / 1024 );
+ // fprintf( stderr, "[csize: %ld] {offset: %ld} ", (long)csize, (long)fi.coff );
+ fflush( stderr );
}
if ( res < 0 ) {
puts( "" );
cfg.url = strdup( getenv( "URL" ) ? getenv( "URL" ) : URL_BASE );
cfg.bwlup = str_to_bwl( getenv( "BWLUP" ) ? getenv( "BWLUP" ) : "0" );
snprintf( confpath, sizeof confpath, "%s/%s", getenv( "HOME" ), CFG_BASE );
- while ( ( c = getopt( argc, argv, ":c:" ) ) != -1 ) {
+ while ( ( c = getopt( argc, argv, "+:c:" ) ) != -1 ) {
switch (c) {
case 'c':
snprintf( confpath, sizeof confpath, "%s", optarg );
}
parse_cfg( confpath );
- optind = 1;
- while ( ( c = getopt( argc, argv, ":c:hl:p:u:U:" ) ) != -1 ) {
+ optind = 0;
+ while ( ( c = getopt( argc, argv, "+:c:hl:p:u:U:" ) ) != -1 ) {
switch (c) {
case 'c':
// already handled above