1
0
Fork 0

Merging upstream version 0.5.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-02-17 22:51:25 +01:00
parent 2365d73c24
commit caa83acf9d
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
25 changed files with 264 additions and 251 deletions

160
main.c
View file

@ -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 <unistd.h>
#include <utime.h>
#include <sys/stat.h>
#if defined(__MSVCRT__)
#if defined(__MSVCRT__) || defined(__OS2__) || defined(__DJGPP__)
#include <io.h>
#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 <io.h>
#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[=<size>] 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; }
}
if( verbosity >= 1 ) Pp_show_msg( pp, 0 );
if( verbosity >= 2 )
{
if( out_pos <= 0 || in_pos <= 0 )
fputs( "no data compressed. ", stderr );
else
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 );
}
if( verbosity >= 1 )
fputs( testing ? "ok\n" : "done\n", stderr );
show_results( pp, in_pos, out_pos, testing );
return 0;
}
void show_error( const char * const msg, const int errcode, const bool help )
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 );
else
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, "%9lu out, %8lu in. ", out_pos, in_pos );
}
if( verbosity >= 1 ) fputs( testing ? "ok\n" : "done\n", stderr );
}
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 )
{