"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "main.c" between
lzlib-1.11.tar.lz and lzlib-1.12-rc1.tar.lz

About: Lzlib is a data compression library providing in-memory LZMA compression and decompression functions using the lzip format. Release candidate.

main.c  (lzlib-1.11.tar.lz):main.c  (lzlib-1.12-rc1.tar.lz)
/* Minilzip - Test program for the lzlib library /* Minilzip - Test program for the library lzlib
Copyright (C) 2009-2019 Antonio Diaz Diaz. Copyright (C) 2009-2020 Antonio Diaz Diaz.
This program is free software: you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or the Free Software Foundation, either version 2 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
/* /*
Exit status: 0 for a normal exit, 1 for environmental problems Exit status: 0 for a normal exit, 1 for environmental problems
(file not found, invalid flags, I/O errors, etc), 2 to indicate a (file not found, invalid flags, I/O errors, etc), 2 to indicate a
corrupt or invalid input file, 3 for an internal consistency error corrupt or invalid input file, 3 for an internal consistency error
(eg, bug) which caused minilzip to panic. (eg, bug) which caused minilzip to panic.
*/ */
#define _FILE_OFFSET_BITS 64 #define _FILE_OFFSET_BITS 64
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <limits.h> #include <limits.h>
#include <signal.h> #include <signal.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
skipping to change at line 77 skipping to change at line 77
#error "Environments where CHAR_BIT != 8 are not supported." #error "Environments where CHAR_BIT != 8 are not supported."
#endif #endif
#ifndef max #ifndef max
#define max(x,y) ((x) >= (y) ? (x) : (y)) #define max(x,y) ((x) >= (y) ? (x) : (y))
#endif #endif
#ifndef min #ifndef min
#define min(x,y) ((x) <= (y) ? (x) : (y)) #define min(x,y) ((x) <= (y) ? (x) : (y))
#endif #endif
void cleanup_and_fail( const int retval ); static void cleanup_and_fail( const int retval );
void show_error( const char * const msg, const int errcode, const bool help ); static void show_error( const char * const msg, const int errcode,
void show_file_error( const char * const filename, const char * const msg, const bool help );
const int errcode ); static void show_file_error( const char * const filename,
void internal_error( const char * const msg ); const char * const msg, const int errcode );
static void internal_error( const char * const msg );
static const char * const mem_msg = "Not enough memory.";
int verbosity = 0; int verbosity = 0;
const char * const program_name = "minilzip"; static const char * const program_name = "minilzip";
const char * const program_year = "2019"; static const char * const program_year = "2020";
const char * invocation_name = 0; static const char * invocation_name = "minilzip"; /* default value */
const struct { const char * from; const char * to; } known_extensions[] = { static const struct { const char * from; const char * to; } known_extensions[] = {
{ ".lz", "" }, { ".lz", "" },
{ ".tlz", ".tar" }, { ".tlz", ".tar" },
{ 0, 0 } }; { 0, 0 } };
struct Lzma_options struct Lzma_options
{ {
int dictionary_size; /* 4 KiB .. 512 MiB */ int dictionary_size; /* 4 KiB .. 512 MiB */
int match_len_limit; /* 5 .. 273 */ int match_len_limit; /* 5 .. 273 */
}; };
enum Mode { m_compress, m_decompress, m_test }; enum Mode { m_compress, m_decompress, m_test };
/* Variables used in signal handler context. /* Variables used in signal handler context.
They are not declared volatile because the handler never returns. */ They are not declared volatile because the handler never returns. */
char * output_filename = 0; static char * output_filename = 0;
int outfd = -1; static int outfd = -1;
bool delete_output_on_interrupt = false; static bool delete_output_on_interrupt = false;
static void show_help( void ) static void show_help( void )
{ {
printf( "Minilzip is a test program for the lzlib compression library, fully\n " printf( "Minilzip is a test program for the compression library lzlib, fully\n "
"compatible with lzip 1.4 or newer.\n" "compatible with lzip 1.4 or newer.\n"
"\nLzip is a lossless data compressor with a user interface similar to
the one\n"
"of gzip or bzip2. Lzip uses a simplified form of the 'Lempel-Ziv-Mark
ov\n"
"chain-Algorithm' (LZMA) stream format, chosen to maximize safety and\
n"
"interoperability. Lzip can compress about as fast as gzip (lzip -0) o
r\n"
"compress most files more than bzip2 (lzip -9). Decompression speed is
\n"
"intermediate between gzip and bzip2. Lzip is better than gzip and bzi
p2 from\n"
"a data recovery perspective. Lzip has been designed, written, and tes
ted\n"
"with great care to replace gzip and bzip2 as the standard general-pur
pose\n"
"compressed format for unix-like systems.\n"
"\nUsage: %s [options] [files]\n", invocation_name ); "\nUsage: %s [options] [files]\n", invocation_name );
printf( "\nOptions:\n" printf( "\nOptions:\n"
" -h, --help display this help and exit\n" " -h, --help display this help and exit\n"
" -V, --version output version information and exit\ n" " -V, --version output version information and exit\ n"
" -a, --trailing-error exit with error status if trailing d ata\n" " -a, --trailing-error exit with error status if trailing d ata\n"
" -b, --member-size=<bytes> set member size limit in bytes\n" " -b, --member-size=<bytes> set member size limit in bytes\n"
" -c, --stdout write to standard output, keep input files\n" " -c, --stdout write to standard output, keep input files\n"
" -d, --decompress decompress\n" " -d, --decompress decompress\n"
" -f, --force overwrite existing output files\n" " -f, --force overwrite existing output files\n"
" -F, --recompress force re-compression of compressed f iles\n" " -F, --recompress force re-compression of compressed f iles\n"
" -k, --keep keep (don't delete) input files\n" " -k, --keep keep (don't delete) input files\n"
" -m, --match-length=<bytes> set match length limit in bytes [36] \n" " -m, --match-length=<bytes> set match length limit in bytes [36] \n"
" -o, --output=<file> if reading standard input, write to <file>\n" " -o, --output=<file> write to <file>, keep input files\n"
" -q, --quiet suppress all messages\n" " -q, --quiet suppress all messages\n"
" -s, --dictionary-size=<bytes> set dictionary size limit in bytes [ 8 MiB]\n" " -s, --dictionary-size=<bytes> set dictionary size limit in bytes [ 8 MiB]\n"
" -S, --volume-size=<bytes> set volume size limit in bytes\n" " -S, --volume-size=<bytes> set volume size limit in bytes\n"
" -t, --test test compressed file integrity\n" " -t, --test test compressed file integrity\n"
" -v, --verbose be verbose (a 2nd -v gives more)\n" " -v, --verbose be verbose (a 2nd -v gives more)\n"
" -0 .. -9 set compression level [default 6]\n" " -0 .. -9 set compression level [default 6]\n"
" --fast alias for -0\n" " --fast alias for -0\n"
" --best alias for -9\n" " --best alias for -9\n"
" --loose-trailing allow trailing data seeming corrupt header\n" " --loose-trailing allow trailing data seeming corrupt header\n"
"If no file names are given, or if a file is '-', minilzip compresses or\n" "\nIf no file names are given, or if a file is '-', minilzip compresse s or\n"
"decompresses from standard input to standard output.\n" "decompresses from standard input to standard output.\n"
"Numbers may be followed by a multiplier: k = kB = 10^3 = 1000,\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" "Ki = KiB = 2^10 = 1024, M = 10^6, Mi = 2^20, G = 10^9, Gi = 2^30, etc ...\n"
"Dictionary sizes 12 to 29 are interpreted as powers of two, meaning 2 ^12\n" "Dictionary sizes 12 to 29 are interpreted as powers of two, meaning 2 ^12\n"
"to 2^29 bytes.\n" "to 2^29 bytes.\n"
"\nThe bidimensional parameter space of LZMA can't be mapped to a line ar\n" "\nThe bidimensional parameter space of LZMA can't be mapped to a line ar\n"
"scale optimal for all files. If your files are large, very repetitive ,\n" "scale optimal for all files. If your files are large, very repetitive ,\n"
"etc, you may need to use the --dictionary-size and --match-length\n" "etc, you may need to use the options --dictionary-size and --match-le
"options directly to achieve optimal performance.\n" ngth\n"
"directly to achieve optimal performance.\n"
"\nTo extract all the files from archive 'foo.tar.lz', use the command
s\n"
"'tar -xf foo.tar.lz' or 'minilzip -cd foo.tar.lz | tar -xf -'.\n"
"\nExit status: 0 for a normal exit, 1 for environmental problems (fil e\n" "\nExit status: 0 for a normal exit, 1 for environmental problems (fil e\n"
"not found, invalid flags, I/O errors, etc), 2 to indicate a corrupt o r\n" "not found, invalid flags, I/O errors, etc), 2 to indicate a corrupt o r\n"
"invalid input file, 3 for an internal consistency error (eg, bug) whi ch\n" "invalid input file, 3 for an internal consistency error (eg, bug) whi ch\n"
"caused minilzip to panic.\n" "caused minilzip to panic.\n"
"\nThe ideas embodied in lzlib are due to (at least) the following peo
ple:\n"
"Abraham Lempel and Jacob Ziv (for the LZ algorithm), Andrey Markov (f
or the\n"
"definition of Markov chains), G.N.N. Martin (for the definition of ra
nge\n"
"encoding), Igor Pavlov (for putting all the above together in LZMA),
and\n"
"Julian Seward (for bzip2's CLI).\n"
"\nReport bugs to lzip-bug@nongnu.org\n" "\nReport bugs to lzip-bug@nongnu.org\n"
"Lzlib home page: http://www.nongnu.org/lzip/lzlib.html\n" ); "Lzlib home page: http://www.nongnu.org/lzip/lzlib.html\n" );
} }
static void show_version( void ) static void show_version( void )
{ {
printf( "%s %s\n", program_name, PROGVERSION ); printf( "%s %s\n", program_name, PROGVERSION );
printf( "Copyright (C) %s Antonio Diaz Diaz.\n", program_year ); printf( "Copyright (C) %s Antonio Diaz Diaz.\n", program_year );
printf( "Using lzlib %s\n", LZ_version() ); printf( "Using lzlib %s\n", LZ_version() );
printf( "License GPLv2+: GNU GPL version 2 or later <http://gnu.org/licenses/g pl.html>\n" printf( "License GPLv2+: GNU GPL version 2 or later <http://gnu.org/licenses/g pl.html>\n"
"This is free software: you are free to change and redistribute it.\n" "This is free software: you are free to change and redistribute it.\n"
"There is NO WARRANTY, to the extent permitted by law.\n" ); "There is NO WARRANTY, to the extent permitted by law.\n" );
} }
/* assure at least a minimum size for buffer 'buf' */ /* assure at least a minimum size for buffer 'buf' */
static 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 ); if( buf ) buf = realloc( buf, min_size );
else buf = malloc( min_size ); else buf = malloc( min_size );
if( !buf ) if( !buf ) { show_error( mem_msg, 0, false ); cleanup_and_fail( 1 ); }
{
show_error( "Not enough memory.", 0, false );
cleanup_and_fail( 1 );
}
return buf; return buf;
} }
struct Pretty_print struct Pretty_print
{ {
const char * name; const char * name;
char * padded_name; char * padded_name;
const char * stdin_name; const char * stdin_name;
unsigned longest_name; unsigned longest_name;
bool first_post; bool first_post;
}; };
static void Pp_init( struct Pretty_print * const pp, static void Pp_init( struct Pretty_print * const pp,
const char * const filenames[], const char * const filenames[], const int num_filenames )
const int num_filenames )
{ {
unsigned stdin_name_len; unsigned stdin_name_len;
int i; int i;
pp->name = 0; pp->name = 0;
pp->padded_name = 0; pp->padded_name = 0;
pp->stdin_name = "(stdin)"; pp->stdin_name = "(stdin)";
pp->longest_name = 0; pp->longest_name = 0;
pp->first_post = false; pp->first_post = false;
if( verbosity <= 0 ) return; if( verbosity <= 0 ) return;
stdin_name_len = strlen( pp->stdin_name ); stdin_name_len = strlen( pp->stdin_name );
for( i = 0; i < num_filenames; ++i ) for( i = 0; i < num_filenames; ++i )
{ {
const char * const s = filenames[i]; const char * const s = filenames[i];
const unsigned len = (strcmp( s, "-" ) == 0) ? stdin_name_len : strlen( s ); const unsigned len = (strcmp( s, "-" ) == 0) ? stdin_name_len : strlen( s );
if( pp->longest_name < len ) pp->longest_name = len; if( pp->longest_name < len ) pp->longest_name = len;
} }
if( pp->longest_name == 0 ) pp->longest_name = stdin_name_len; if( pp->longest_name == 0 ) pp->longest_name = stdin_name_len;
} }
static inline void Pp_set_name( struct Pretty_print * const pp, static void Pp_set_name( struct Pretty_print * const pp,
const char * const filename ) const char * const filename )
{ {
unsigned name_len, padded_name_len, i = 0; unsigned name_len, padded_name_len, i = 0;
if( filename && filename[0] && strcmp( filename, "-" ) != 0 ) if( filename && filename[0] && strcmp( filename, "-" ) != 0 )
pp->name = filename; pp->name = filename;
else pp->name = pp->stdin_name; else pp->name = pp->stdin_name;
name_len = strlen( pp->name ); name_len = strlen( pp->name );
padded_name_len = max( name_len, pp->longest_name ) + 4; padded_name_len = max( name_len, pp->longest_name ) + 4;
pp->padded_name = resize_buffer( pp->padded_name, padded_name_len + 1 ); pp->padded_name = resize_buffer( pp->padded_name, padded_name_len + 1 );
while( i < 2 ) pp->padded_name[i++] = ' '; while( i < 2 ) pp->padded_name[i++] = ' ';
while( i < name_len + 2 ) { pp->padded_name[i] = pp->name[i-2]; ++i; } while( i < name_len + 2 ) { pp->padded_name[i] = pp->name[i-2]; ++i; }
pp->padded_name[i++] = ':'; pp->padded_name[i++] = ':';
while( i < padded_name_len ) pp->padded_name[i++] = ' '; while( i < padded_name_len ) pp->padded_name[i++] = ' ';
pp->padded_name[i] = 0; pp->padded_name[i] = 0;
pp->first_post = true; pp->first_post = true;
} }
static inline void Pp_reset( struct Pretty_print * const pp ) static void Pp_reset( struct Pretty_print * const pp )
{ if( pp->name && pp->name[0] ) pp->first_post = true; } { if( pp->name && pp->name[0] ) pp->first_post = true; }
static void Pp_show_msg( struct Pretty_print * const pp, const char * const msg ) static void Pp_show_msg( struct Pretty_print * const pp, const char * const msg )
{ {
if( verbosity >= 0 ) if( verbosity >= 0 )
{ {
if( pp->first_post ) if( pp->first_post )
{ {
pp->first_post = false; pp->first_post = false;
fputs( pp->padded_name, stderr ); fputs( pp->padded_name, stderr );
skipping to change at line 256 skipping to change at line 269
const char * const prefix[8] = const char * const prefix[8] =
{ "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi", "Yi" }; { "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi", "Yi" };
const char * p = ""; const char * p = "";
const char * np = " "; const char * np = " ";
unsigned num = dictionary_size; unsigned num = dictionary_size;
bool exact = ( num % factor == 0 ); bool exact = ( num % factor == 0 );
int i; for( i = 0; i < 8 && ( num > 9999 || ( exact && num >= factor ) ); ++i ) int i; for( i = 0; i < 8 && ( num > 9999 || ( exact && num >= factor ) ); ++i )
{ num /= factor; if( num % factor != 0 ) exact = false; { num /= factor; if( num % factor != 0 ) exact = false;
p = prefix[i]; np = ""; } p = prefix[i]; np = ""; }
fprintf( stderr, "dictionary %s%4u %sB, ", np, num, p ); fprintf( stderr, "dict %s%4u %sB, ", np, num, p );
} }
static unsigned long long getnum( const char * const ptr, static unsigned long long getnum( const char * const ptr,
const unsigned long long llimit, const unsigned long long llimit,
const unsigned long long ulimit ) const unsigned long long ulimit )
{ {
unsigned long long result; unsigned long long result;
char * tail; char * tail;
errno = 0; errno = 0;
result = strtoull( ptr, &tail, 0 ); result = strtoull( ptr, &tail, 0 );
skipping to change at line 317 skipping to change at line 330
return result; return result;
} }
static int get_dict_size( const char * const arg ) static int get_dict_size( const char * const arg )
{ {
char * tail; char * tail;
int dictionary_size; int dictionary_size;
const long bits = strtol( arg, &tail, 0 ); const long bits = strtol( arg, &tail, 0 );
if( bits >= LZ_min_dictionary_bits() && if( bits >= LZ_min_dictionary_bits() &&
bits <= LZ_max_dictionary_bits() && *tail == 0 ) bits <= LZ_max_dictionary_bits() && *tail == 0 )
return ( 1 << bits ); return 1 << bits;
dictionary_size = getnum( arg, LZ_min_dictionary_size(), dictionary_size = getnum( arg, LZ_min_dictionary_size(),
LZ_max_dictionary_size() ); LZ_max_dictionary_size() );
if( dictionary_size == 65535 ) ++dictionary_size; /* no fast encoder */ if( dictionary_size == 65535 ) ++dictionary_size; /* no fast encoder */
return dictionary_size; return dictionary_size;
} }
void set_mode( enum Mode * const program_modep, const enum Mode new_mode ) static void set_mode( enum Mode * const program_modep, const enum Mode new_mode )
{ {
if( *program_modep != m_compress && *program_modep != new_mode ) if( *program_modep != m_compress && *program_modep != new_mode )
{ {
show_error( "Only one operation can be specified.", 0, true ); show_error( "Only one operation can be specified.", 0, true );
exit( 1 ); exit( 1 );
} }
*program_modep = new_mode; *program_modep = new_mode;
} }
static int extension_index( const char * const name ) static int extension_index( const char * const name )
skipping to change at line 356 skipping to change at line 369
return -1; return -1;
} }
static void set_c_outname( const char * const name, const bool force_ext, static void set_c_outname( const char * const name, const bool force_ext,
const bool multifile ) const bool multifile )
{ {
output_filename = resize_buffer( output_filename, strlen( name ) + 5 + output_filename = resize_buffer( output_filename, strlen( name ) + 5 +
strlen( known_extensions[0].from ) + 1 ); strlen( known_extensions[0].from ) + 1 );
strcpy( output_filename, name ); strcpy( output_filename, name );
if( multifile ) strcat( output_filename, "00001" ); if( multifile ) strcat( output_filename, "00001" );
if( force_ext || multifile || extension_index( output_filename ) < 0 ) if( force_ext || multifile )
strcat( output_filename, known_extensions[0].from ); strcat( output_filename, known_extensions[0].from );
} }
static void set_d_outname( const char * const name, const int eindex ) static void set_d_outname( const char * const name, const int eindex )
{ {
const unsigned name_len = strlen( name ); const unsigned name_len = strlen( name );
if( eindex >= 0 ) if( eindex >= 0 )
{ {
const char * const from = known_extensions[eindex].from; const char * const from = known_extensions[eindex].from;
const unsigned from_len = strlen( from ); const unsigned from_len = strlen( from );
skipping to change at line 386 skipping to change at line 399
output_filename = resize_buffer( output_filename, name_len + 4 + 1 ); output_filename = resize_buffer( output_filename, name_len + 4 + 1 );
strcpy( output_filename, name ); strcpy( output_filename, name );
strcat( output_filename, ".out" ); strcat( output_filename, ".out" );
if( verbosity >= 1 ) if( verbosity >= 1 )
fprintf( stderr, "%s: Can't guess original name for '%s' -- using '%s'\n", fprintf( stderr, "%s: Can't guess original name for '%s' -- using '%s'\n",
program_name, name, output_filename ); program_name, name, output_filename );
} }
static int open_instream( const char * const name, struct stat * const in_statsp , static int open_instream( const char * const name, struct stat * const in_statsp ,
const enum Mode program_mode, const int eindex, const enum Mode program_mode, const int eindex,
const bool recompress, const bool to_stdout ) const bool one_to_one, const bool recompress )
{ {
int infd = -1; int infd = -1;
if( program_mode == m_compress && !recompress && eindex >= 0 ) if( program_mode == m_compress && !recompress && eindex >= 0 )
{ {
if( verbosity >= 0 ) if( verbosity >= 0 )
fprintf( stderr, "%s: Input file '%s' already has '%s' suffix.\n", fprintf( stderr, "%s: Input file '%s' already has '%s' suffix.\n",
program_name, name, known_extensions[eindex].from ); program_name, name, known_extensions[eindex].from );
} }
else else
{ {
infd = open( name, O_RDONLY | O_BINARY ); infd = open( name, O_RDONLY | O_BINARY );
if( infd < 0 ) if( infd < 0 )
show_file_error( name, "Can't open input file", errno ); show_file_error( name, "Can't open input file", errno );
else else
{ {
const int i = fstat( infd, in_statsp ); const int i = fstat( infd, in_statsp );
const mode_t mode = in_statsp->st_mode; const mode_t mode = in_statsp->st_mode;
const bool can_read = ( i == 0 && const bool can_read = ( i == 0 &&
( S_ISBLK( mode ) || S_ISCHR( mode ) || ( S_ISBLK( mode ) || S_ISCHR( mode ) ||
S_ISFIFO( mode ) || S_ISSOCK( mode ) ) ); S_ISFIFO( mode ) || S_ISSOCK( mode ) ) );
const bool no_ofile = ( to_stdout || program_mode == m_test ); if( i != 0 || ( !S_ISREG( mode ) && ( !can_read || one_to_one ) ) )
if( i != 0 || ( !S_ISREG( mode ) && ( !can_read || !no_ofile ) ) )
{ {
if( verbosity >= 0 ) if( verbosity >= 0 )
fprintf( stderr, "%s: Input file '%s' is not a regular file%s.\n", fprintf( stderr, "%s: Input file '%s' is not a regular file%s.\n",
program_name, name, program_name, name, ( can_read && one_to_one ) ?
( can_read && !no_ofile ) ? ",\n and neither '-c' nor '-o' were specified" : ""
",\n and '--stdout' was not specified" : "" ); );
close( infd ); close( infd );
infd = -1; infd = -1;
} }
} }
} }
return infd; return infd;
} }
static bool open_outstream( const bool force, const bool from_stdin ) static bool open_outstream( const bool force, const bool protect )
{ {
const mode_t usr_rw = S_IRUSR | S_IWUSR; const mode_t usr_rw = S_IRUSR | S_IWUSR;
const mode_t all_rw = usr_rw | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; const mode_t all_rw = usr_rw | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
const mode_t outfd_mode = from_stdin ? all_rw : usr_rw; const mode_t outfd_mode = protect ? usr_rw : all_rw;
int flags = O_CREAT | O_WRONLY | O_BINARY; int flags = O_CREAT | O_WRONLY | O_BINARY;
if( force ) flags |= O_TRUNC; else flags |= O_EXCL; if( force ) flags |= O_TRUNC; else flags |= O_EXCL;
outfd = open( output_filename, flags, outfd_mode ); outfd = open( output_filename, flags, outfd_mode );
if( outfd >= 0 ) delete_output_on_interrupt = true; if( outfd >= 0 ) delete_output_on_interrupt = true;
else if( verbosity >= 0 ) else if( verbosity >= 0 )
{ {
if( errno == EEXIST ) if( errno == EEXIST )
fprintf( stderr, "%s: Output file '%s' already exists, skipping.\n", fprintf( stderr, "%s: Output file '%s' already exists, skipping.\n",
program_name, output_filename ); program_name, output_filename );
else else
fprintf( stderr, "%s: Can't create output file '%s': %s\n", fprintf( stderr, "%s: Can't create output file '%s': %s\n",
program_name, output_filename, strerror( errno ) ); program_name, output_filename, strerror( errno ) );
} }
return ( outfd >= 0 ); return ( outfd >= 0 );
} }
static bool check_tty( const char * const input_filename, const int infd, static bool check_tty_in( const char * const input_filename, const int infd,
const enum Mode program_mode ) const enum Mode program_mode )
{ {
if( program_mode == m_compress && isatty( outfd ) )
{
show_error( "I won't write compressed data to a terminal.", 0, true );
return false;
}
if( ( program_mode == m_decompress || program_mode == m_test ) && if( ( program_mode == m_decompress || program_mode == m_test ) &&
isatty( infd ) ) isatty( infd ) ) /* for example /dev/tty */
{ { show_file_error( input_filename,
show_file_error( input_filename, "I won't read compressed data from a terminal.", 0 );
"I won't read compressed data from a terminal.", 0 ); return false; }
return false; return true;
} }
static bool check_tty_out( const enum Mode program_mode )
{
if( program_mode == m_compress && isatty( outfd ) )
{ show_file_error( output_filename[0] ?
output_filename : "(stdout)",
"I won't write compressed data to a terminal.", 0 );
return false; }
return true; return true;
} }
static void set_signals( void (*action)(int) ) static void set_signals( void (*action)(int) )
{ {
signal( SIGHUP, action ); signal( SIGHUP, action );
signal( SIGINT, action ); signal( SIGINT, action );
signal( SIGTERM, action ); signal( SIGTERM, action );
} }
void cleanup_and_fail( const int retval ) static void cleanup_and_fail( const int retval )
{ {
set_signals( SIG_IGN ); /* ignore signals */ set_signals( SIG_IGN ); /* ignore signals */
if( delete_output_on_interrupt ) if( delete_output_on_interrupt )
{ {
delete_output_on_interrupt = false; delete_output_on_interrupt = false;
if( verbosity >= 0 ) if( verbosity >= 0 )
fprintf( stderr, "%s: Deleting output file '%s', if it exists.\n", fprintf( stderr, "%s: Deleting output file '%s', if it exists.\n",
program_name, output_filename ); program_name, output_filename );
if( outfd >= 0 ) { close( outfd ); outfd = -1; } if( outfd >= 0 ) { close( outfd ); outfd = -1; }
if( remove( output_filename ) != 0 && errno != ENOENT ) if( remove( output_filename ) != 0 && errno != ENOENT )
show_error( "WARNING: deletion of output file (apparently) failed.", 0, fa lse ); show_error( "WARNING: deletion of output file (apparently) failed.", 0, fa lse );
} }
exit( retval ); exit( retval );
} }
void signal_handler( int sig ) static void signal_handler( int sig )
{ {
if( sig ) {} /* keep compiler happy */ if( sig ) {} /* keep compiler happy */
show_error( "Control-C or similar caught, quitting.", 0, false ); show_error( "Control-C or similar caught, quitting.", 0, false );
cleanup_and_fail( 1 ); cleanup_and_fail( 1 );
} }
/* Set permissions, owner and times. */ /* Set permissions, owner, and times. */
static void close_and_set_permissions( const struct stat * const in_statsp ) static void close_and_set_permissions( const struct stat * const in_statsp )
{ {
bool warning = false; bool warning = false;
if( in_statsp ) if( in_statsp )
{ {
const mode_t mode = in_statsp->st_mode; const mode_t mode = in_statsp->st_mode;
/* fchown will in many cases return with EPERM, which can be safely ignored. */ /* fchown will in many cases return with EPERM, which can be safely ignored. */
if( fchown( outfd, in_statsp->st_uid, in_statsp->st_gid ) == 0 ) if( fchown( outfd, in_statsp->st_uid, in_statsp->st_gid ) == 0 )
{ if( fchmod( outfd, mode ) != 0 ) warning = true; } { if( fchmod( outfd, mode ) != 0 ) warning = true; }
else else
skipping to change at line 639 skipping to change at line 653
{ {
partial_volume_size += LZ_compress_member_position( encoder ); partial_volume_size += LZ_compress_member_position( encoder );
if( partial_volume_size >= volume_size - LZ_min_dictionary_size() ) if( partial_volume_size >= volume_size - LZ_min_dictionary_size() )
{ {
partial_volume_size = 0; partial_volume_size = 0;
if( delete_output_on_interrupt ) if( delete_output_on_interrupt )
{ {
close_and_set_permissions( in_statsp ); close_and_set_permissions( in_statsp );
if( !next_filename() ) if( !next_filename() )
{ Pp_show_msg( pp, "Too many volume files." ); return 1; } { Pp_show_msg( pp, "Too many volume files." ); return 1; }
if( !open_outstream( true, !in_statsp ) ) return 1; if( !open_outstream( true, in_statsp ) ) return 1;
} }
} }
size = min( member_size, volume_size - partial_volume_size ); size = min( member_size, volume_size - partial_volume_size );
} }
else else
size = member_size; size = member_size;
if( LZ_compress_restart_member( encoder, size ) < 0 ) if( LZ_compress_restart_member( encoder, size ) < 0 )
{ {
Pp_show_msg( pp, 0 ); Pp_show_msg( pp, 0 );
if( verbosity >= 0 ) if( verbosity >= 0 )
skipping to change at line 706 skipping to change at line 720
LZ_compress_close( encoder ); LZ_compress_close( encoder );
return retval; return retval;
} }
static int do_decompress( struct LZ_Decoder * const decoder, const int infd, static int do_decompress( struct LZ_Decoder * const decoder, const int infd,
struct Pretty_print * const pp, const bool ignore_trailing, struct Pretty_print * const pp, const bool ignore_trailing,
const bool loose_trailing, const bool testing ) const bool loose_trailing, const bool testing )
{ {
enum { buffer_size = 65536 }; enum { buffer_size = 65536 };
uint8_t buffer[buffer_size]; uint8_t buffer[buffer_size];
unsigned long long total_in = 0; /* to detect library stall */
bool first_member; bool first_member;
for( first_member = true; ; ) for( first_member = true; ; )
{ {
const int max_in_size = const int max_in_size =
min( LZ_decompress_write_size( decoder ), buffer_size ); min( LZ_decompress_write_size( decoder ), buffer_size );
int in_size = 0, out_size = 0; int in_size = 0, out_size = 0;
if( max_in_size > 0 ) if( max_in_size > 0 )
{ {
in_size = readblock( infd, buffer, max_in_size ); in_size = readblock( infd, buffer, max_in_size );
skipping to change at line 756 skipping to change at line 771
{ {
const unsigned long long data_size = LZ_decompress_data_position( deco der ); const unsigned long long data_size = LZ_decompress_data_position( deco der );
const unsigned long long member_size = LZ_decompress_member_position( decoder ); const unsigned long long member_size = LZ_decompress_member_position( decoder );
if( verbosity >= 2 || ( verbosity == 1 && first_member ) ) if( verbosity >= 2 || ( verbosity == 1 && first_member ) )
Pp_show_msg( pp, 0 ); Pp_show_msg( pp, 0 );
if( verbosity >= 2 ) if( verbosity >= 2 )
{ {
if( verbosity >= 4 ) if( verbosity >= 4 )
show_header( LZ_decompress_dictionary_size( decoder ) ); show_header( LZ_decompress_dictionary_size( decoder ) );
if( data_size == 0 || member_size == 0 ) if( data_size == 0 || member_size == 0 )
fputs( "no data compressed. ", stderr ); fputs( "no data compressed. ", stderr );
else else
fprintf( stderr, "%6.3f:1, %5.2f%% ratio, %5.2f%% saved. ", fprintf( stderr, "%6.3f:1, %5.2f%% ratio, %5.2f%% saved. ",
(double)data_size / member_size, (double)data_size / member_size,
( 100.0 * member_size ) / data_size, ( 100.0 * member_size ) / data_size,
100.0 - ( ( 100.0 * member_size ) / data_size ) ); 100.0 - ( ( 100.0 * member_size ) / data_size ) );
if( verbosity >= 4 ) if( verbosity >= 4 )
fprintf( stderr, "CRC %08X, ", LZ_decompress_data_crc( decoder ) ) ; fprintf( stderr, "CRC %08X, ", LZ_decompress_data_crc( decoder ) ) ;
if( verbosity >= 3 ) if( verbosity >= 3 )
fprintf( stderr, "decompressed %9llu, compressed %8llu. ", fprintf( stderr, "%9llu out, %8llu in. ", data_size, member_size )
data_size, member_size ); ;
fputs( testing ? "ok\n" : "done\n", stderr ); Pp_reset( pp ); fputs( testing ? "ok\n" : "done\n", stderr ); Pp_reset( pp );
} }
} }
first_member = false; first_member = false;
} }
if( rd <= 0 ) break; if( rd <= 0 ) break;
} }
if( out_size < 0 || ( first_member && out_size == 0 ) ) if( out_size < 0 || ( first_member && out_size == 0 ) )
{ {
const unsigned long long member_pos = LZ_decompress_member_position( decod er ); const unsigned long long member_pos = LZ_decompress_member_position( decod er );
skipping to change at line 819 skipping to change at line 833
if( lz_errno == LZ_header_error ) if( lz_errno == LZ_header_error )
{ {
if( first_member ) if( first_member )
show_file_error( pp->name, show_file_error( pp->name,
"Bad magic number (file not in lzip format).", 0 ); "Bad magic number (file not in lzip format).", 0 );
else if( !ignore_trailing ) else if( !ignore_trailing )
Pp_show_msg( pp, "Trailing data not allowed." ); Pp_show_msg( pp, "Trailing data not allowed." );
else break; /* trailing data */ else break; /* trailing data */
return 2; return 2;
} }
if( lz_errno == LZ_mem_error ) if( lz_errno == LZ_mem_error ) { Pp_show_msg( pp, mem_msg ); return 1; }
{ Pp_show_msg( pp, "Not enough memory." ); return 1; }
if( verbosity >= 0 ) if( verbosity >= 0 )
{ {
Pp_show_msg( pp, 0 ); Pp_show_msg( pp, 0 );
fprintf( stderr, "%s at pos %llu\n", ( lz_errno == LZ_unexpected_eof ) ? fprintf( stderr, "%s at pos %llu\n", ( lz_errno == LZ_unexpected_eof ) ?
"File ends unexpectedly" : "Decoder error", "File ends unexpectedly" : "Decoder error",
LZ_decompress_total_in_size( decoder ) ); LZ_decompress_total_in_size( decoder ) );
} }
return 2; return 2;
} }
if( LZ_decompress_finished( decoder ) == 1 ) break; if( LZ_decompress_finished( decoder ) == 1 ) break;
if( in_size == 0 && out_size == 0 ) if( in_size == 0 && out_size == 0 )
internal_error( "library error (stalled)." ); {
const unsigned long long size = LZ_decompress_total_in_size( decoder );
if( total_in == size ) internal_error( "library error (stalled)." );
total_in = size;
}
} }
if( verbosity == 1 ) fputs( testing ? "ok\n" : "done\n", stderr ); if( verbosity == 1 ) fputs( testing ? "ok\n" : "done\n", stderr );
return 0; return 0;
} }
static int decompress( const int infd, struct Pretty_print * const pp, static int decompress( const int infd, struct Pretty_print * const pp,
const bool ignore_trailing, const bool ignore_trailing,
const bool loose_trailing, const bool testing ) const bool loose_trailing, const bool testing )
{ {
struct LZ_Decoder * const decoder = LZ_decompress_open(); struct LZ_Decoder * const decoder = LZ_decompress_open();
int retval; int retval;
if( !decoder || LZ_decompress_errno( decoder ) != LZ_ok ) if( !decoder || LZ_decompress_errno( decoder ) != LZ_ok )
{ Pp_show_msg( pp, "Not enough memory." ); retval = 1; } { Pp_show_msg( pp, mem_msg ); retval = 1; }
else retval = do_decompress( decoder, infd, pp, ignore_trailing, else retval = do_decompress( decoder, infd, pp, ignore_trailing,
loose_trailing, testing ); loose_trailing, testing );
LZ_decompress_close( decoder ); LZ_decompress_close( decoder );
return retval; return retval;
} }
void show_error( const char * const msg, const int errcode, const bool help ) static inline void set_retval( int * retval, const int new_val )
{ if( *retval < new_val ) *retval = new_val; }
static void show_error( const char * const msg, const int errcode,
const bool help )
{ {
if( verbosity < 0 ) return; if( verbosity < 0 ) return;
if( msg && msg[0] ) if( msg && msg[0] )
fprintf( stderr, "%s: %s%s%s\n", program_name, msg, fprintf( stderr, "%s: %s%s%s\n", program_name, msg,
( errcode > 0 ) ? ": " : "", ( errcode > 0 ) ? ": " : "",
( errcode > 0 ) ? strerror( errcode ) : "" ); ( errcode > 0 ) ? strerror( errcode ) : "" );
if( help ) if( help )
fprintf( stderr, "Try '%s --help' for more information.\n", fprintf( stderr, "Try '%s --help' for more information.\n",
invocation_name ); invocation_name );
} }
void show_file_error( const char * const filename, const char * const msg, static void show_file_error( const char * const filename,
const int errcode ) const char * const msg, const int errcode )
{ {
if( verbosity >= 0 ) if( verbosity >= 0 )
fprintf( stderr, "%s: %s: %s%s%s\n", program_name, filename, msg, fprintf( stderr, "%s: %s: %s%s%s\n", program_name, filename, msg,
( errcode > 0 ) ? ": " : "", ( errcode > 0 ) ? ": " : "",
( errcode > 0 ) ? strerror( errcode ) : "" ); ( errcode > 0 ) ? strerror( errcode ) : "" );
} }
void internal_error( const char * const msg ) static void internal_error( const char * const msg )
{ {
if( verbosity >= 0 ) if( verbosity >= 0 )
fprintf( stderr, "%s: internal error: %s\n", program_name, msg ); fprintf( stderr, "%s: internal error: %s\n", program_name, msg );
exit( 3 ); exit( 3 );
} }
int main( const int argc, const char * const argv[] ) int main( const int argc, const char * const argv[] )
{ {
/* Mapping from gzip/bzip2 style 1..9 compression modes /* Mapping from gzip/bzip2 style 1..9 compression modes
to the corresponding LZMA compression modes. */ to the corresponding LZMA compression modes. */
skipping to change at line 898 skipping to change at line 919
{ 1 << 20, 5 }, /* -1 */ { 1 << 20, 5 }, /* -1 */
{ 3 << 19, 6 }, /* -2 */ { 3 << 19, 6 }, /* -2 */
{ 1 << 21, 8 }, /* -3 */ { 1 << 21, 8 }, /* -3 */
{ 3 << 20, 12 }, /* -4 */ { 3 << 20, 12 }, /* -4 */
{ 1 << 22, 20 }, /* -5 */ { 1 << 22, 20 }, /* -5 */
{ 1 << 23, 36 }, /* -6 */ { 1 << 23, 36 }, /* -6 */
{ 1 << 24, 68 }, /* -7 */ { 1 << 24, 68 }, /* -7 */
{ 3 << 23, 132 }, /* -8 */ { 3 << 23, 132 }, /* -8 */
{ 1 << 25, 273 } }; /* -9 */ { 1 << 25, 273 } }; /* -9 */
struct Lzma_options encoder_options = option_mapping[6]; /* default = "-6" */ struct Lzma_options encoder_options = option_mapping[6]; /* default = "-6" */
const unsigned long long max_member_size = 0x0008000000000000ULL; const unsigned long long max_member_size = 0x0008000000000000ULL; /* 2 PiB */
const unsigned long long max_volume_size = 0x4000000000000000ULL; const unsigned long long max_volume_size = 0x4000000000000000ULL; /* 4 EiB */
unsigned long long member_size = max_member_size; unsigned long long member_size = max_member_size;
unsigned long long volume_size = 0; unsigned long long volume_size = 0;
const char * default_output_filename = ""; 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;
int num_filenames = 0; int num_filenames = 0;
enum Mode program_mode = m_compress; enum Mode program_mode = m_compress;
int argind = 0; int argind = 0;
int failed_tests = 0; int failed_tests = 0;
int retval = 0; int retval = 0;
int i; int i;
bool filenames_given = false; bool filenames_given = false;
bool force = false; bool force = false;
bool ignore_trailing = true; bool ignore_trailing = true;
bool keep_input_files = false; bool keep_input_files = false;
bool loose_trailing = false; bool loose_trailing = false;
bool recompress = false; bool recompress = false;
bool stdin_used = false; bool stdin_used = false;
bool to_stdout = false; bool to_stdout = false;
struct Pretty_print pp;
enum { opt_lt = 256 }; enum { opt_lt = 256 };
const struct ap_Option options[] = const struct ap_Option options[] =
{ {
{ '0', "fast", ap_no }, { '0', "fast", ap_no },
{ '1', 0, ap_no }, { '1', 0, ap_no },
{ '2', 0, ap_no }, { '2', 0, ap_no },
{ '3', 0, ap_no }, { '3', 0, ap_no },
{ '4', 0, ap_no }, { '4', 0, ap_no },
{ '5', 0, ap_no }, { '5', 0, ap_no },
skipping to change at line 953 skipping to change at line 975
{ 'o', "output", ap_yes }, { 'o', "output", ap_yes },
{ 'q', "quiet", ap_no }, { 'q', "quiet", ap_no },
{ 's', "dictionary-size", ap_yes }, { 's', "dictionary-size", ap_yes },
{ 'S', "volume-size", ap_yes }, { 'S', "volume-size", ap_yes },
{ 't', "test", ap_no }, { 't', "test", ap_no },
{ 'v', "verbose", ap_no }, { 'v', "verbose", ap_no },
{ 'V', "version", ap_no }, { 'V', "version", ap_no },
{ opt_lt, "loose-trailing", ap_no }, { opt_lt, "loose-trailing", ap_no },
{ 0 , 0, ap_no } }; { 0 , 0, ap_no } };
struct Arg_parser parser; if( argc > 0 ) invocation_name = argv[0];
invocation_name = argv[0];
#if !defined LZ_API_VERSION || LZ_API_VERSION != 1
#error "Wrong LZ_API_VERSION."
#endif
if( LZ_version()[0] != LZ_version_string[0] ) if( LZ_version()[0] != LZ_version_string[0] )
internal_error( "bad library version." ); internal_error( "wrong library version." );
if( strcmp( PROGVERSION, LZ_version_string ) != 0 ) if( strcmp( PROGVERSION, LZ_version_string ) != 0 )
internal_error( "bad library version_string." ); internal_error( "wrong library version_string." );
if( !ap_init( &parser, argc, argv, options, 0 ) ) if( !ap_init( &parser, argc, argv, options, 0 ) )
{ show_error( "Not enough memory.", 0, false ); return 1; } { show_error( mem_msg, 0, false ); return 1; }
if( ap_error( &parser ) ) /* bad option */ if( ap_error( &parser ) ) /* bad option */
{ show_error( ap_error( &parser ), 0, true ); return 1; } { show_error( ap_error( &parser ), 0, true ); return 1; }
for( ; argind < ap_arguments( &parser ); ++argind ) for( ; argind < ap_arguments( &parser ); ++argind )
{ {
const int code = ap_code( &parser, argind ); const int code = ap_code( &parser, argind );
const char * const arg = ap_argument( &parser, argind ); const char * const arg = ap_argument( &parser, argind );
if( !code ) break; /* no more options */ if( !code ) break; /* no more options */
switch( code ) switch( code )
{ {
skipping to change at line 989 skipping to change at line 1012
case 'c': to_stdout = true; break; case 'c': to_stdout = true; break;
case 'd': set_mode( &program_mode, m_decompress ); break; case 'd': set_mode( &program_mode, m_decompress ); break;
case 'f': force = true; break; case 'f': force = true; break;
case 'F': recompress = true; break; case 'F': recompress = true; break;
case 'h': show_help(); return 0; case 'h': show_help(); return 0;
case 'k': keep_input_files = true; break; case 'k': keep_input_files = true; break;
case 'm': encoder_options.match_len_limit = case 'm': encoder_options.match_len_limit =
getnum( arg, LZ_min_match_len_limit(), getnum( arg, LZ_min_match_len_limit(),
LZ_max_match_len_limit() ); break; LZ_max_match_len_limit() ); break;
case 'n': break; case 'n': break;
case 'o': default_output_filename = arg; break; case 'o': if( strcmp( arg, "-" ) == 0 ) to_stdout = true;
else { default_output_filename = arg; } break;
case 'q': verbosity = -1; break; case 'q': verbosity = -1; break;
case 's': encoder_options.dictionary_size = get_dict_size( arg ); case 's': encoder_options.dictionary_size = get_dict_size( arg );
break; break;
case 'S': volume_size = getnum( arg, 100000, max_volume_size ); break; case 'S': volume_size = getnum( arg, 100000, max_volume_size ); break;
case 't': set_mode( &program_mode, m_test ); break; case 't': set_mode( &program_mode, m_test ); break;
case 'v': if( verbosity < 4 ) ++verbosity; break; case 'v': if( verbosity < 4 ) ++verbosity; break;
case 'V': show_version(); return 0; case 'V': show_version(); return 0;
case opt_lt: loose_trailing = true; break; case opt_lt: loose_trailing = true; break;
default : internal_error( "uncaught option." ); default : internal_error( "uncaught option." );
} }
skipping to change at line 1017 skipping to change at line 1041
num_filenames = max( 1, ap_arguments( &parser ) - argind ); num_filenames = max( 1, ap_arguments( &parser ) - argind );
filenames = resize_buffer( filenames, num_filenames * sizeof filenames[0] ); filenames = resize_buffer( filenames, num_filenames * sizeof filenames[0] );
filenames[0] = "-"; filenames[0] = "-";
for( i = 0; argind + i < ap_arguments( &parser ); ++i ) for( i = 0; argind + i < ap_arguments( &parser ); ++i )
{ {
filenames[i] = ap_argument( &parser, argind + i ); filenames[i] = ap_argument( &parser, argind + i );
if( strcmp( filenames[i], "-" ) != 0 ) filenames_given = true; if( strcmp( filenames[i], "-" ) != 0 ) filenames_given = true;
} }
if( program_mode == m_test ) if( program_mode == m_compress )
outfd = -1; {
if( volume_size > 0 && !to_stdout && default_output_filename[0] &&
num_filenames > 1 )
{ show_error( "Only can compress one file when using '-o' and '-S'.",
0, true ); return 1; }
}
else volume_size = 0;
if( program_mode == m_test ) to_stdout = false; /* apply overrides */
if( program_mode == m_test || to_stdout ) default_output_filename = "";
if( !to_stdout && program_mode != m_test && output_filename = resize_buffer( output_filename, 1 );
( filenames_given || default_output_filename[0] ) ) output_filename[0] = 0;
if( to_stdout && program_mode != m_test ) /* check tty only once */
{ outfd = STDOUT_FILENO; if( !check_tty_out( program_mode ) ) return 1; }
else outfd = -1;
const bool to_file = !to_stdout && program_mode != m_test &&
default_output_filename[0];
if( !to_stdout && program_mode != m_test && ( filenames_given || to_file ) )
set_signals( signal_handler ); set_signals( signal_handler );
Pp_init( &pp, filenames, num_filenames ); Pp_init( &pp, filenames, num_filenames );
output_filename = resize_buffer( output_filename, 1 ); const bool one_to_one = !to_stdout && program_mode != m_test && !to_file;
for( i = 0; i < num_filenames; ++i ) for( i = 0; i < num_filenames; ++i )
{ {
const char * input_filename = ""; const char * input_filename = "";
int infd; int infd;
int tmp; int tmp;
struct stat in_stats; struct stat in_stats;
const struct stat * in_statsp; 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; if( stdin_used ) continue; else stdin_used = true;
infd = STDIN_FILENO; infd = STDIN_FILENO;
if( program_mode != m_test ) if( one_to_one ) { outfd = STDOUT_FILENO; output_filename[0] = 0; }
{
if( to_stdout || !default_output_filename[0] )
outfd = STDOUT_FILENO;
else
{
if( program_mode == m_compress )
set_c_outname( default_output_filename, false, volume_size > 0 );
else
{
output_filename = resize_buffer( output_filename,
strlen( default_output_filename ) + 1 );
strcpy( output_filename, default_output_filename );
}
if( !open_outstream( force, true ) )
{
if( retval < 1 ) retval = 1;
close( infd );
continue;
}
}
}
} }
else else
{ {
const int eindex = extension_index( input_filename = filenames[i] ); const int eindex = extension_index( input_filename = filenames[i] );
infd = open_instream( input_filename, &in_stats, program_mode, infd = open_instream( input_filename, &in_stats, program_mode,
eindex, recompress, to_stdout ); eindex, one_to_one, recompress );
if( infd < 0 ) { if( retval < 1 ) retval = 1; continue; } if( infd < 0 ) { set_retval( &retval, 1 ); continue; }
if( program_mode != m_test ) if( one_to_one )
{ {
if( to_stdout ) outfd = STDOUT_FILENO; if( program_mode == m_compress )
else set_c_outname( input_filename, true, volume_size > 0 );
{ else set_d_outname( input_filename, eindex );
if( program_mode == m_compress ) if( !open_outstream( force, true ) )
set_c_outname( input_filename, true, volume_size > 0 ); { set_retval( &retval, 1 ); close( infd ); continue; }
else set_d_outname( input_filename, eindex );
if( !open_outstream( force, false ) )
{
if( retval < 1 ) retval = 1;
close( infd );
continue;
}
}
} }
} }
Pp_set_name( &pp, input_filename ); Pp_set_name( &pp, input_filename );
if( !check_tty( pp.name, infd, program_mode ) ) if( !check_tty_in( pp.name, infd, program_mode ) )
{ {
if( retval < 1 ) retval = 1; set_retval( &retval, 1 );
if( program_mode == m_test ) { close( infd ); continue; } if( program_mode == m_test ) { close( infd ); continue; }
cleanup_and_fail( retval ); cleanup_and_fail( retval );
} }
if( one_to_one && !check_tty_out( program_mode ) )
{ set_retval( &retval, 1 ); return retval; }
if( to_file && outfd < 0 ) /* open outfd after verifying infd */
{
if( program_mode == m_compress ) set_c_outname( default_output_filename,
false, volume_size > 0 );
else
{ output_filename = resize_buffer( output_filename,
strlen( default_output_filename ) + 1 );
strcpy( output_filename, default_output_filename ); }
if( !open_outstream( force, false ) || !check_tty_out( program_mode ) )
return 1; /* check tty only once and don't try to delete a tty */
}
in_statsp = input_filename[0] ? &in_stats : 0; in_statsp = ( input_filename[0] && one_to_one ) ? &in_stats : 0;
if( program_mode == m_compress ) if( program_mode == m_compress )
tmp = compress( member_size, volume_size, infd, &encoder_options, &pp, tmp = compress( member_size, volume_size, infd, &encoder_options, &pp,
in_statsp ); in_statsp );
else else
tmp = decompress( infd, &pp, ignore_trailing, tmp = decompress( infd, &pp, ignore_trailing,
loose_trailing, program_mode == m_test ); loose_trailing, program_mode == m_test );
if( close( infd ) != 0 ) if( close( infd ) != 0 )
{ { show_file_error( pp.name, "Error closing input file", errno );
show_error( input_filename[0] ? "Error closing input file" : set_retval( &tmp, 1 ); }
"Error closing stdin", errno, false ); set_retval( &retval, tmp );
if( tmp < 1 ) tmp = 1;
}
if( tmp > retval ) retval = tmp;
if( tmp ) if( tmp )
{ if( program_mode != m_test ) cleanup_and_fail( retval ); { if( program_mode != m_test ) cleanup_and_fail( retval );
else ++failed_tests; } else ++failed_tests; }
if( delete_output_on_interrupt ) if( delete_output_on_interrupt && one_to_one )
close_and_set_permissions( in_statsp ); close_and_set_permissions( in_statsp );
if( input_filename[0] ) if( input_filename[0] && !keep_input_files && one_to_one &&
{ ( program_mode != m_compress || volume_size == 0 ) )
if( !keep_input_files && !to_stdout && program_mode != m_test && remove( input_filename );
( program_mode != m_compress || volume_size == 0 ) )
remove( input_filename );
}
} }
if( outfd >= 0 && close( outfd ) != 0 ) if( delete_output_on_interrupt ) close_and_set_permissions( 0 ); /* -o */
else if( outfd >= 0 && close( outfd ) != 0 ) /* -c */
{ {
show_error( "Error closing stdout", errno, false ); show_error( "Error closing stdout", errno, false );
if( retval < 1 ) retval = 1; set_retval( &retval, 1 );
} }
if( failed_tests > 0 && verbosity >= 1 && num_filenames > 1 ) if( failed_tests > 0 && verbosity >= 1 && num_filenames > 1 )
fprintf( stderr, "%s: warning: %d %s failed the test.\n", fprintf( stderr, "%s: warning: %d %s failed the test.\n",
program_name, failed_tests, program_name, failed_tests,
( failed_tests == 1 ) ? "file" : "files" ); ( failed_tests == 1 ) ? "file" : "files" );
free( output_filename ); free( output_filename );
free( filenames ); free( filenames );
ap_free( &parser ); ap_free( &parser );
return retval; return retval;
} }
 End of changes. 70 change blocks. 
159 lines changed or deleted 193 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)