From: Urban Wallasch Date: Thu, 22 Apr 2021 14:36:11 +0000 (+0200) Subject: * Minor tweaks to kaoupload.c (error handling, display). X-Git-Url: https://git.packet-gain.de/?a=commitdiff_plain;h=e8e9b8265c15203c2f0c36ea2875801fcc83d90f;p=kaotools.git * Minor tweaks to kaoupload.c (error handling, display). --- diff --git a/Makefile b/Makefile index d412d9e..cecc748 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ .PHONY: all clean -CFLAGS += -W -Wall +CFLAGS += -W -Wall -Wextra -std=gnu99 CFLAGS += `pkg-config --cflags libcurl` LDFLAGS += `pkg-config --libs libcurl` diff --git a/kaoupload.c b/kaoupload.c index 8a9a8d8..882a513 100644 --- a/kaoupload.c +++ b/kaoupload.c @@ -109,12 +109,14 @@ static uint64_t time_ms( void ) { return (uint64_t)tv.tv_sec * 1000 + ( tv.tv_nsec / 1000000L ); } -static void parse_cfg( const char *confpath ) { +static int parse_cfg( const char *confpath ) { FILE *fp; char buf[256]; - if ( NULL == confpath || NULL == ( fp = fopen( confpath, "r" ) ) ) - return; + if ( NULL == confpath ) + return EINVAL; + if ( NULL == ( fp = fopen( confpath, "r" ) ) ) + return errno; while ( fgets( buf, sizeof buf - 1, fp ) ) { char *key, *val, *x; key = buf; @@ -152,6 +154,7 @@ static void parse_cfg( const char *confpath ) { cfg.bwlup = str_to_bwl( val ); } fclose( fp ); + return 0; } static size_t write_memory_cb( void *contents, size_t size, size_t nmemb, void *userp ) { @@ -175,7 +178,7 @@ static size_t write_memory_cb( void *contents, size_t size, size_t nmemb, void * #define RESP_MISMATCH "Partfile initial sequence mismatch" static int upload_chunk( CURL *curl, struct file_info_t *fi, off_t csize ) { - int res = -1; + int n, res = -1; long http_code; ssize_t br; char url[2048]; @@ -198,8 +201,15 @@ static int upload_chunk( CURL *curl, struct file_info_t *fi, off_t csize ) { } if ( csize > br ) csize = br; - snprintf( url, sizeof url, "%s?fname=%s&fpos=%lu&fsize=%lu", cfg.url, fi->esc_name, fi->coff, fi->size ); - + n = snprintf( url, sizeof url, "%s?fname=%s&fpos=%lu&fsize=%lu", + cfg.url, fi->esc_name, fi->coff, fi->size ); + if ( sizeof url <= (size_t)n ) { + if ( 0 > n ) + err( "snprintf(url, ...)", errno ); + else + err( "snprintf(url, ...): URL too long", 0 ); + goto err_out; + } curl_easy_reset( curl ); error = curl_easy_setopt( curl, CURLOPT_POST, 1L ); error |= curl_easy_setopt( curl, CURLOPT_POSTFIELDSIZE, (long)csize ); @@ -224,9 +234,13 @@ static int upload_chunk( CURL *curl, struct file_info_t *fi, off_t csize ) { goto err_out; } - curl_easy_getinfo( curl, CURLINFO_SPEED_UPLOAD_T, &fi->speed ); - curl_easy_getinfo( curl, CURLINFO_RESPONSE_CODE, &http_code ); fi->sent += csize; + error = curl_easy_getinfo( curl, CURLINFO_SPEED_UPLOAD_T, &fi->speed ); + error |= curl_easy_getinfo( curl, CURLINFO_RESPONSE_CODE, &http_code ); + if ( CURLE_OK != error ) { + cerr( "curl_easy_getinfo", error ); + goto err_out; + } // puts(reply.memory); @@ -248,7 +262,7 @@ static int upload_chunk( CURL *curl, struct file_info_t *fi, off_t csize ) { res = 0; } else - fprintf( stderr, "ERROR: unexpected response: %s", reply.memory ); + fprintf( stderr, "\rERROR: unexpected response: %ld %.80s\n", http_code, reply.memory ); break; case 201: // upon receiving the first chunk, remote detected a partfile initial @@ -258,6 +272,8 @@ static int upload_chunk( CURL *curl, struct file_info_t *fi, off_t csize ) { fi->remn -= csize; res = 0; } + else + fprintf( stderr, "\rERROR: unexpected response: %ld %.80s\n", http_code, reply.memory ); break; case 428: // remote already has data up to Skip-to-position @@ -267,11 +283,11 @@ static int upload_chunk( CURL *curl, struct file_info_t *fi, off_t csize ) { res = 0; } else - err( "response code 428 w/o 'Skip-to-position'", 0 ); + fprintf( stderr, "\rERROR: unexpected response: %ld %.80s\n", http_code, reply.memory ); break; default: - fprintf( stderr, "REMOTE ERROR: %ld %s", http_code, - 100 > reply.size ? reply.memory : ( 403 == http_code ? "Forbidden" : "" ) ); + fprintf( stderr, "\rREMOTE ERROR: %ld %.80s\n", http_code, + 403 == http_code ? "Forbidden" : reply.memory ); break; } @@ -320,13 +336,13 @@ static int upload_file( const char *fn ) { csize = 2 * fi.speed; if ( CSIZE_HARDLIMIT < csize ) csize = CSIZE_HARDLIMIT; - fprintf( stderr, "\r%3.f%% (%5.1f kB/s) ", (double)fi.coff * 100 / fi.size, (double)fi.speed / 1024 ); + fprintf( stderr, "\r%3.f%% (%5.1f KiB/s) ", (double)fi.coff * 100 / fi.size, (double)fi.speed / 1024 ); // fprintf( stderr, "[csize: %ld] {offset: %ld} ", (long)csize, (long)fi.coff ); fflush( stderr ); } xfrtime = time_ms() - starttime + 1; - printf( "\rSent %.1f kB in %.1f seconds (%.1f kB/s).\n", + printf( "\rSent %.1f KiB in %.1f seconds (%.1f KiB/s).\n", (double)fi.sent / 1024, (double)xfrtime / 1000, (double)fi.sent / xfrtime * 1000 / 1024 ); if ( res < 0 ) err( "file upload incomplete", 0 ); @@ -340,56 +356,67 @@ static int upload_file( const char *fn ) { return res; } -static void usage( char *pname ) { +static void usage( char *pname, int ec ) { printf( "%s - upload files to Kaotan\n", basename( pname ) ); printf( "USAGE: %s [OPTIONS] FILE ...\n", basename( pname ) ); printf( "OPTIONS:\n" " -h display this help text and exit\n" - " -c file specify configuration file (default: ~/%s)\n" - " -l maxbps upload speed limit in bytes per second, e.g. 100k\n" + " -c file specify configuration file; default: ~/%s\n" + " -l maxbps upload speed limit in bytes per second, e.g. 100k; default: 0 (== no limit)\n" " -u user set user name\n" " -p passwd set password\n" - " -U URL set base URL\n" - , CFG_BASE + " -U URL set base URL (default: %s)\n" + , CFG_BASE, URL_BASE ); - printf( "Defaults for bandwidth limit, user, password and URL are taken " - "from environment and configuration file, in this order.\n" ); - doExit( EXIT_FAILURE ); + printf( + "\nDefaults for bandwidth limit ($BWLUP), user ($USER), password ($PASS) and base URL ($URL)\n" + "are taken from the environment and the configuration file, in this order. Values set on\n" + "the command line always take precedence over default values.\n" + ); + doExit( ec ); } int main( int argc, char *argv[] ) { int res = 0; int c; - char confpath[256]; + char confpath[PATH_MAX]; + + signal( SIGINT, sig_handler ); + signal( SIGTERM, sig_handler ); + signal( SIGHUP, sig_handler ); cfg.user = strdup( getenv( "USER" ) ? getenv( "USER" ) : "" ); cfg.pass = strdup( getenv( "PASS" ) ? getenv( "PASS" ) : "" ); 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:h" ) ) != -1 ) { switch (c) { case 'c': - snprintf( confpath, sizeof confpath, "%s", optarg ); + res = snprintf( confpath, sizeof confpath, "%s", optarg ); + if ( sizeof confpath <= (size_t)res ) + die( optarg, res < 0 ? errno : ENAMETOOLONG ); + break; + case 'h': + usage( argv[0], EXIT_SUCCESS ); break; case ':': fprintf( stderr, "ERROR: missing argument for option '-%c'\n", optopt ); - usage( argv[0] ); + usage( argv[0], EXIT_FAILURE ); break; default: break; } } - parse_cfg( confpath ); + if ( 0 != ( res = parse_cfg( confpath ) ) ) + err( confpath, res ); optind = 0; while ( ( c = getopt( argc, argv, "+:c:hl:p:u:U:" ) ) != -1 ) { switch (c) { case 'c': - // already handled above - break; case 'h': - usage( argv[0] ); + // already handled above break; case 'l': cfg.bwlup = str_to_bwl( optarg ); @@ -408,30 +435,27 @@ int main( int argc, char *argv[] ) { break; case ':': fprintf( stderr, "ERROR: missing argument for option '-%c'\n", optopt ); - usage( argv[0] ); + usage( argv[0], EXIT_FAILURE ); break; case '?': fprintf( stderr, "ERROR: unknown option '-%c'\n", optopt ); - usage( argv[0] ); + usage( argv[0], EXIT_FAILURE ); break; default: - fprintf( stderr, "ERROR: option '-%c' not implemented, programmer PEBKAC.\n", c ); + fprintf( stderr, "WARNING: option '-%c' not implemented, programmer PEBKAC.\n", c ); break; } } if ( optind >= argc ) { err( "no file to upload", 0 ); - usage( argv[0] ); + usage( argv[0], EXIT_FAILURE ); } if ( CURLE_OK != curl_global_init( CURL_GLOBAL_SSL ) ) die( "curl_global_init", 0 ); - signal( SIGINT, sig_handler ); - signal( SIGTERM, sig_handler ); - signal( SIGHUP, sig_handler ); - + res = 0; while ( optind < argc && !gotsig && 0 == res ) res = upload_file( argv[optind++] );