From baa87c84edd812698e37703a897a4a40323b70e4 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 3 May 2020 17:08:43 +0200 Subject: Merging upstream version 0.5. Signed-off-by: Daniel Baumann --- main.c | 142 ++++++++++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 97 insertions(+), 45 deletions(-) (limited to 'main.c') diff --git a/main.c b/main.c index 9b4241d..f267c15 100644 --- a/main.c +++ b/main.c @@ -1,5 +1,5 @@ /* Xlunzip - Test tool for the lzip_decompress linux module - Copyright (C) 2016-2018 Antonio Diaz Diaz. + Copyright (C) 2016-2020 Antonio Diaz Diaz. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -36,8 +36,9 @@ #include #include #include -#if defined(__MSVCRT__) +#if defined(__MSVCRT__) || defined(__OS2__) || defined(__DJGPP__) #include +#if defined(__MSVCRT__) #define fchmod(x,y) 0 #define fchown(x,y,z) 0 #define SIGHUP SIGTERM @@ -49,8 +50,10 @@ #define S_IWOTH 0 #endif #endif -#if defined(__OS2__) -#include +#if defined(__DJGPP__) +#define S_ISSOCK(x) 0 +#define S_ISVTX 0 +#endif #endif #include "carg_parser.h" @@ -66,25 +69,27 @@ #error "Environments where CHAR_BIT != 8 are not supported." #endif -int verbosity = 0; -void cleanup_and_fail( const int retval ); +static int verbosity = 0; +static void cleanup_and_fail( const int retval ); +static void show_error( const char * const msg, const int errcode, + const bool help ); -const char * const Program_name = "Xlunzip"; -const char * const program_name = "xlunzip"; -const char * const program_year = "2018"; -const char * invocation_name = 0; +static const char * const program_name = "xlunzip"; +static const char * const program_year = "2020"; +static const char * invocation_name = "xlunzip"; /* default value */ -const struct { const char * from; const char * to; } known_extensions[] = { +static const struct { const char * from; const char * to; } known_extensions[] = { { ".lz", "" }, { ".tlz", ".tar" }, { 0, 0 } }; -int infd = -1; /* needed by the fill function */ +static int infd = -1; /* needed by the fill function */ + /* Variables used in signal handler context. They are not declared volatile because the handler never returns. */ -char * output_filename = 0; -int outfd = -1; -bool delete_output_on_interrupt = false; +static char * output_filename = 0; +static int outfd = -1; +static bool delete_output_on_interrupt = false; static void show_help( void ) @@ -102,7 +107,8 @@ static void show_help( void ) "\nNote that the in-place decompression of concatenated files can't be\n" "guaranteed to work because an arbitrarily low compression ratio of the\n" "last part of the data can be achieved by appending enough empty\n" - "compressed members to a file.\n" + "compressed members to a file, masking a high compression ratio at the\n" + "beginning of the data.\n" "\nUsage: %s [options] [files]\n", invocation_name ); printf( "\nOptions:\n" " -h, --help display this help and exit\n" @@ -121,10 +127,12 @@ static void show_help( void ) " --outsize[=] pre-allocate outbuf [default 512 MiB]\n" " --nofill do not pass a fill function; requires --insize\n" " --noflush do not pass a flush function; requires --outsize\n" - "If no file names are given, or if a file is '-', xlunzip decompresses\n" + "\nIf no file names are given, or if a file is '-', xlunzip decompresses\n" "from standard input to standard output.\n" "Numbers may be followed by a multiplier: k = kB = 10^3 = 1000,\n" "Ki = KiB = 2^10 = 1024, M = 10^6, Mi = 2^20, G = 10^9, Gi = 2^30, etc...\n" + "\nTo extract all the files from archive 'foo.tar.lz', use the commands\n" + "'tar -xf foo.tar.lz' or 'xlunzip -cd foo.tar.lz | tar -xf -'.\n" "\nExit status: 0 for a normal exit, 1 for environmental problems (file\n" "not found, invalid flags, I/O errors, etc), 2 to indicate a corrupt or\n" "invalid input file, 3 for an internal consistency error (eg, bug) which\n" @@ -145,7 +153,7 @@ static void show_version( void ) /* assure at least a minimum size for buffer 'buf' */ -void * resize_buffer( void * buf, const unsigned min_size ) +static void * resize_buffer( void * buf, const unsigned min_size ) { if( buf ) buf = realloc( buf, min_size ); else buf = malloc( min_size ); @@ -158,7 +166,48 @@ void * resize_buffer( void * buf, const unsigned min_size ) } -void Pp_show_msg( struct Pretty_print * const pp, const char * const msg ) +static void Pp_init( struct Pretty_print * const pp, + const char * const filenames[], const int num_filenames ) + { + unsigned stdin_name_len; + int i; + pp->name = 0; + pp->padded_name = 0; + pp->stdin_name = "(stdin)"; + pp->longest_name = 0; + pp->first_post = false; + + if( verbosity <= 0 ) return; + stdin_name_len = strlen( pp->stdin_name ); + for( i = 0; i < num_filenames; ++i ) + { + const char * const s = filenames[i]; + const unsigned len = (strcmp( s, "-" ) == 0) ? stdin_name_len : strlen( s ); + if( pp->longest_name < len ) pp->longest_name = len; + } + if( pp->longest_name == 0 ) pp->longest_name = stdin_name_len; + } + +static void Pp_set_name( struct Pretty_print * const pp, + const char * const filename ) + { + unsigned name_len, padded_name_len, i = 0; + + if( filename && filename[0] && strcmp( filename, "-" ) != 0 ) + pp->name = filename; + else pp->name = pp->stdin_name; + name_len = strlen( pp->name ); + padded_name_len = max( name_len, pp->longest_name ) + 4; + pp->padded_name = resize_buffer( pp->padded_name, padded_name_len + 1 ); + while( i < 2 ) pp->padded_name[i++] = ' '; + while( i < name_len + 2 ) { pp->padded_name[i] = pp->name[i-2]; ++i; } + pp->padded_name[i++] = ':'; + while( i < padded_name_len ) pp->padded_name[i++] = ' '; + pp->padded_name[i] = 0; + pp->first_post = true; + } + +static void Pp_show_msg( struct Pretty_print * const pp, const char * const msg ) { if( verbosity >= 0 ) { @@ -325,7 +374,7 @@ static void set_signals( void (*action)(int) ) } -void cleanup_and_fail( const int retval ) +static void cleanup_and_fail( const int retval ) { set_signals( SIG_IGN ); /* ignore signals */ if( delete_output_on_interrupt ) @@ -342,7 +391,7 @@ void cleanup_and_fail( const int retval ) } -void signal_handler( int sig ) +static void signal_handler( int sig ) { if( sig ) {} /* keep compiler happy */ show_error( "Control-C or similar caught, quitting.", 0, false ); @@ -350,7 +399,7 @@ void signal_handler( int sig ) } - /* Set permissions, owner and times. */ + /* Set permissions, owner, and times. */ static void close_and_set_permissions( const struct stat * const in_statsp ) { bool warning = false; @@ -435,7 +484,7 @@ long flush( void * buf, unsigned long size ) return sz; } -const char * global_name; /* copy of filename for 'error' */ +static const char * global_name; /* copy of filename for 'error' */ static void error(char *x) { show_file_error( global_name, x, 0 ); } @@ -470,27 +519,33 @@ static int decompress( struct Pretty_print * const pp, const long cl_insize, if( len < out_pos ) { show_file_error( pp->name, "Write error", errno ); return 1; } } + show_results( pp, in_pos, out_pos, testing ); + return 0; + } + + +void show_results( struct Pretty_print * const pp, const long in_pos, + const long out_pos, const bool testing ) + { if( verbosity >= 1 ) Pp_show_msg( pp, 0 ); if( verbosity >= 2 ) { if( out_pos <= 0 || in_pos <= 0 ) - fputs( "no data compressed. ", stderr ); + fputs( "no data compressed. ", stderr ); else - fprintf( stderr, "%6.3f:1, %5.2f%% ratio, %5.2f%% saved. ", + fprintf( stderr, "%6.3f:1, %5.2f%% ratio, %5.2f%% saved. ", (double)out_pos / in_pos, ( 100.0 * in_pos ) / out_pos, 100.0 - ( ( 100.0 * in_pos ) / out_pos ) ); if( verbosity >= 3 ) - fprintf( stderr, "decompressed %9lu, compressed %8lu. ", - out_pos, in_pos ); + fprintf( stderr, "%9lu out, %8lu in. ", out_pos, in_pos ); } - if( verbosity >= 1 ) - fputs( testing ? "ok\n" : "done\n", stderr ); - return 0; + if( verbosity >= 1 ) fputs( testing ? "ok\n" : "done\n", stderr ); } -void show_error( const char * const msg, const int errcode, const bool help ) +static void show_error( const char * const msg, const int errcode, + const bool help ) { if( verbosity < 0 ) return; if( msg && msg[0] ) @@ -513,7 +568,7 @@ void show_file_error( const char * const filename, const char * const msg, } -void internal_error( const char * const msg ) +static void internal_error( const char * const msg ) { if( verbosity >= 0 ) fprintf( stderr, "%s: internal error: %s\n", program_name, msg ); @@ -524,7 +579,9 @@ void internal_error( const char * const msg ) int main( const int argc, const char * const argv[] ) { const char * default_output_filename = ""; - const char ** filenames = 0; + static struct Arg_parser parser; /* static because valgrind complains */ + static struct Pretty_print pp; /* and memory management in C sucks */ + static const char ** filenames = 0; long cl_insize = 0; long cl_outsize = 0; int num_filenames = 0; @@ -541,7 +598,6 @@ int main( const int argc, const char * const argv[] ) bool stdin_used = false; bool testing = false; bool to_stdout = false; - struct Pretty_print pp; enum { opt_insize = 256, opt_outsize, opt_nofill, opt_noflush }; const struct ap_Option options[] = @@ -562,10 +618,9 @@ int main( const int argc, const char * const argv[] ) { opt_outsize, "outsize", ap_maybe }, { opt_nofill, "nofill", ap_no }, { opt_noflush, "noflush", ap_no }, - { 0 , 0, ap_no } }; + { 0 , 0, ap_no } }; - struct Arg_parser parser; - invocation_name = argv[0]; + if( argc > 0 ) invocation_name = argv[0]; if( !ap_init( &parser, argc, argv, options, 0 ) ) { show_error( "Not enough memory.", 0, false ); return 1; } @@ -602,7 +657,7 @@ int main( const int argc, const char * const argv[] ) } } /* end process options */ -#if defined(__MSVCRT__) || defined(__OS2__) +#if defined(__MSVCRT__) || defined(__OS2__) || defined(__DJGPP__) setmode( STDIN_FILENO, O_BINARY ); setmode( STDOUT_FILENO, O_BINARY ); #endif @@ -635,7 +690,7 @@ int main( const int argc, const char * const argv[] ) const struct stat * in_statsp; output_filename[0] = 0; - if( !filenames[i][0] || strcmp( filenames[i], "-" ) == 0 ) + if( strcmp( filenames[i], "-" ) == 0 ) { if( stdin_used ) continue; else stdin_used = true; infd = STDIN_FILENO; @@ -679,7 +734,7 @@ int main( const int argc, const char * const argv[] ) } Pp_set_name( &pp, input_filename ); - if( isatty( infd ) ) + if( isatty( infd ) ) /* for example /dev/tty */ { show_file_error( pp.name, "I won't read compressed data from a terminal.", 0 ); @@ -707,11 +762,8 @@ int main( const int argc, const char * const argv[] ) if( delete_output_on_interrupt ) close_and_set_permissions( in_statsp ); - if( input_filename[0] ) - { - if( !keep_input_files && !to_stdout && !testing ) - remove( input_filename ); - } + if( input_filename[0] && !keep_input_files && !to_stdout && !testing ) + remove( input_filename ); } if( outfd >= 0 && close( outfd ) != 0 ) { -- cgit v1.2.3