Merging upstream version 1.6~rc1.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
4d14b4402a
commit
b60eef59a3
18 changed files with 954 additions and 870 deletions
196
main.c
196
main.c
|
@ -1,9 +1,17 @@
|
|||
/* Pdlzip - LZMA lossless data compressor
|
||||
2009-08-14 : Igor Pavlov : Public domain
|
||||
Copyright (C) 2010, 2011, 2012, 2013 Antonio Diaz Diaz.
|
||||
Copyright (C) 2010-2015 Antonio Diaz Diaz.
|
||||
|
||||
This program is free software: you have unlimited permission
|
||||
to copy, distribute and modify it.
|
||||
This program is free software. Redistribution and use in source and
|
||||
binary forms, with or without modification, are permitted provided
|
||||
that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
|
@ -49,6 +57,10 @@
|
|||
#include "LzmaDec.h"
|
||||
#include "LzmaEnc.h"
|
||||
|
||||
#ifndef O_BINARY
|
||||
#define O_BINARY 0
|
||||
#endif
|
||||
|
||||
#if CHAR_BIT != 8
|
||||
#error "Environments where CHAR_BIT != 8 are not supported."
|
||||
#endif
|
||||
|
@ -56,15 +68,9 @@
|
|||
|
||||
const char * const Program_name = "Pdlzip";
|
||||
const char * const program_name = "pdlzip";
|
||||
const char * const program_year = "2013";
|
||||
const char * const program_year = "2015";
|
||||
const char * invocation_name = 0;
|
||||
|
||||
#ifdef O_BINARY
|
||||
const int o_binary = O_BINARY;
|
||||
#else
|
||||
const int o_binary = 0;
|
||||
#endif
|
||||
|
||||
struct { const char * from; const char * to; } const known_extensions[] = {
|
||||
{ ".lz", "" },
|
||||
{ ".tlz", ".tar" },
|
||||
|
@ -130,39 +136,23 @@ static void show_help( 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( "Public Domain 2009 Igor Pavlov.\n"
|
||||
"License 2-clause BSD.\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" );
|
||||
}
|
||||
|
||||
|
||||
static const char * format_num( unsigned num )
|
||||
{
|
||||
const char * const prefix[8] =
|
||||
{ "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi", "Yi" };
|
||||
enum { buf_size = 16, factor = 1024 };
|
||||
static char buf[buf_size];
|
||||
const char * p = "";
|
||||
bool exact = ( num % factor == 0 );
|
||||
int i;
|
||||
|
||||
for( i = 0; i < 8 && ( num > 9999 || ( exact && num >= factor ) ); ++i )
|
||||
{ num /= factor; if( num % factor != 0 ) exact = false; p = prefix[i]; }
|
||||
snprintf( buf, buf_size, "%u %s", num, p );
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
static void show_header( const File_header header )
|
||||
static void show_header( const unsigned dictionary_size )
|
||||
{
|
||||
const char * const prefix[8] =
|
||||
{ "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi", "Yi" };
|
||||
enum { factor = 1024 };
|
||||
const char * p = "";
|
||||
const char * np = " ";
|
||||
unsigned num = Fh_get_dictionary_size( header ), i;
|
||||
unsigned num = dictionary_size, i;
|
||||
bool exact = ( num % factor == 0 );
|
||||
|
||||
for( i = 0; i < 8 && ( num > 9999 || ( exact && num >= factor ) ); ++i )
|
||||
|
@ -245,8 +235,10 @@ static int extension_index( const char * const name )
|
|||
for( i = 0; known_extensions[i].from; ++i )
|
||||
{
|
||||
const char * const ext = known_extensions[i].from;
|
||||
if( strlen( name ) > strlen( ext ) &&
|
||||
strncmp( name + strlen( name ) - strlen( ext ), ext, strlen( ext ) ) == 0 )
|
||||
const unsigned name_len = strlen( name );
|
||||
const unsigned ext_len = strlen( ext );
|
||||
if( name_len > ext_len &&
|
||||
strncmp( name + name_len - ext_len, ext, ext_len ) == 0 )
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
|
@ -266,7 +258,7 @@ static int open_instream( const char * const name, struct stat * const in_statsp
|
|||
}
|
||||
else
|
||||
{
|
||||
infd = open( name, O_RDONLY | o_binary );
|
||||
infd = open( name, O_RDONLY | O_BINARY );
|
||||
if( infd < 0 )
|
||||
{
|
||||
if( verbosity >= 0 )
|
||||
|
@ -322,20 +314,21 @@ static void set_c_outname( const char * const name )
|
|||
|
||||
static void set_d_outname( const char * const name, const int i )
|
||||
{
|
||||
const unsigned name_len = strlen( name );
|
||||
if( i >= 0 )
|
||||
{
|
||||
const char * const from = known_extensions[i].from;
|
||||
if( strlen( name ) > strlen( from ) )
|
||||
const unsigned from_len = strlen( from );
|
||||
if( name_len > from_len )
|
||||
{
|
||||
output_filename = resize_buffer( output_filename, strlen( name ) +
|
||||
output_filename = resize_buffer( output_filename, name_len +
|
||||
strlen( known_extensions[0].to ) + 1 );
|
||||
strcpy( output_filename, name );
|
||||
strcpy( output_filename + strlen( name ) - strlen( from ),
|
||||
known_extensions[i].to );
|
||||
strcpy( output_filename + name_len - from_len, known_extensions[i].to );
|
||||
return;
|
||||
}
|
||||
}
|
||||
output_filename = resize_buffer( output_filename, strlen( name ) + 4 + 1 );
|
||||
output_filename = resize_buffer( output_filename, name_len + 4 + 1 );
|
||||
strcpy( output_filename, name );
|
||||
strcat( output_filename, ".out" );
|
||||
if( verbosity >= 1 )
|
||||
|
@ -346,7 +339,7 @@ static void set_d_outname( const char * const name, const int i )
|
|||
|
||||
static bool open_outstream( const bool force )
|
||||
{
|
||||
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;
|
||||
|
||||
outfd = open( output_filename, flags, outfd_mode );
|
||||
|
@ -365,7 +358,7 @@ static bool open_outstream( const bool force )
|
|||
|
||||
static bool check_tty( const int infd, const enum Mode program_mode )
|
||||
{
|
||||
if( program_mode == m_compress && outfd >= 0 && isatty( outfd ) )
|
||||
if( program_mode == m_compress && isatty( outfd ) )
|
||||
{
|
||||
show_error( "I won't write compressed data to a terminal.", 0, true );
|
||||
return false;
|
||||
|
@ -402,10 +395,14 @@ static void close_and_set_permissions( const struct stat * const in_statsp )
|
|||
bool warning = false;
|
||||
if( in_statsp )
|
||||
{
|
||||
const mode_t mode = in_statsp->st_mode;
|
||||
/* 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 &&
|
||||
errno != EPERM ) ||
|
||||
fchmod( outfd, in_statsp->st_mode ) != 0 ) warning = true;
|
||||
if( fchown( outfd, in_statsp->st_uid, in_statsp->st_gid ) == 0 )
|
||||
{ if( fchmod( outfd, mode ) != 0 ) warning = true; }
|
||||
else
|
||||
if( errno != EPERM ||
|
||||
fchmod( outfd, mode & ~( S_ISUID | S_ISGID | S_ISVTX ) ) != 0 )
|
||||
warning = true;
|
||||
}
|
||||
if( close( outfd ) != 0 ) cleanup_and_fail( 1 );
|
||||
outfd = -1;
|
||||
|
@ -426,21 +423,21 @@ static int compress( const struct Lzma_options * const encoder_options,
|
|||
const int infd, struct Pretty_print * const pp )
|
||||
{
|
||||
int retval = 0;
|
||||
CLzmaEncHandle encoder;
|
||||
CLzmaEncHandle encoder = 0;
|
||||
File_header header;
|
||||
Fh_set_magic( header );
|
||||
|
||||
if( verbosity >= 1 ) Pp_show_msg( pp, 0 );
|
||||
if( !Fh_set_dictionary_size( header, encoder_options->dictionary_size ) ||
|
||||
encoder_options->match_len_limit < min_match_len_limit ||
|
||||
encoder_options->match_len_limit > max_match_len )
|
||||
internal_error( "invalid argument to encoder" );
|
||||
if( Fh_set_dictionary_size( header, encoder_options->dictionary_size ) &&
|
||||
encoder_options->match_len_limit >= min_match_len_limit &&
|
||||
encoder_options->match_len_limit <= max_match_len )
|
||||
encoder = LzmaEnc_Init( Fh_get_dictionary_size( header ),
|
||||
encoder_options->match_len_limit, infd, outfd );
|
||||
else internal_error( "invalid argument to encoder." );
|
||||
|
||||
encoder = LzmaEnc_Init( Fh_get_dictionary_size( header ),
|
||||
encoder_options->match_len_limit, infd, outfd );
|
||||
if( !encoder )
|
||||
{
|
||||
Pp_show_msg( pp, "Not enough memory. Try a smaller dictionary size" );
|
||||
Pp_show_msg( pp, "Not enough memory. Try a smaller dictionary size." );
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -448,7 +445,7 @@ static int compress( const struct Lzma_options * const encoder_options,
|
|||
{ show_error( "Can not write output file", errno, false ); retval = 1; }
|
||||
else
|
||||
if( LzmaEnc_Encode( encoder ) != 0 )
|
||||
{ Pp_show_msg( pp, "Encoder error" ); retval = 1; }
|
||||
{ Pp_show_msg( pp, "Encoder error." ); retval = 1; }
|
||||
LzmaEnc_Free( encoder );
|
||||
return retval;
|
||||
}
|
||||
|
@ -529,8 +526,7 @@ static int lzma_decode( uint64_t unpackSize, CLzmaDec *decoder, const int infd,
|
|||
( !thereIsSize && status != LZMA_STATUS_FINISHED_WITH_MARK ) )
|
||||
{ show_error( "Data error.", 0, false ); return 2; }
|
||||
if( verbosity >= 2 )
|
||||
fprintf( stderr, "lzma-alone, dictionary size %7sB. ",
|
||||
format_num( decoder->dicBufSize ) );
|
||||
{ fprintf( stderr, "lzma-alone, " ); show_header( decoder->dicBufSize ); }
|
||||
if( verbosity >= 3 )
|
||||
fprintf( stderr, "uncompressed size %9llu, compressed size %8llu. ",
|
||||
total_out, total_in );
|
||||
|
@ -652,13 +648,14 @@ static int decompress( const int infd, struct Pretty_print * const pp,
|
|||
for( first_member = true; ; first_member = false )
|
||||
{
|
||||
int i;
|
||||
unsigned dictionary_size = 0;
|
||||
File_header header;
|
||||
if( inSize - inPos < lzma_header_size &&
|
||||
!read_inbuf( infd, inBuf, &inPos, &inSize ) ) return 1;
|
||||
if( inSize - inPos <= Fh_size ) /* End Of File */
|
||||
{
|
||||
if( first_member )
|
||||
{ Pp_show_msg( pp, "File ends unexpectedly at member header" );
|
||||
{ Pp_show_msg( pp, "File ends unexpectedly at member header." );
|
||||
retval = 2; }
|
||||
break;
|
||||
}
|
||||
|
@ -678,7 +675,7 @@ static int decompress( const int infd, struct Pretty_print * const pp,
|
|||
}
|
||||
if( lzip_mode )
|
||||
{
|
||||
Pp_show_msg( pp, "Bad magic number (file not in lzip format)" );
|
||||
Pp_show_msg( pp, "Bad magic number (file not in lzip format)." );
|
||||
retval = 2; break;
|
||||
}
|
||||
}
|
||||
|
@ -693,25 +690,24 @@ static int decompress( const int infd, struct Pretty_print * const pp,
|
|||
Fh_version( header ) ); }
|
||||
retval = 2; break;
|
||||
}
|
||||
if( Fh_get_dictionary_size( header ) < min_dictionary_size ||
|
||||
Fh_get_dictionary_size( header ) > max_dictionary_size )
|
||||
{ Pp_show_msg( pp, "Invalid dictionary size in member header" );
|
||||
dictionary_size = Fh_get_dictionary_size( header );
|
||||
if( dictionary_size < min_dictionary_size ||
|
||||
dictionary_size > max_dictionary_size )
|
||||
{ Pp_show_msg( pp, "Invalid dictionary size in member header." );
|
||||
retval = 2; break; }
|
||||
|
||||
raw_props[0] = 93; /* (45 * 2) + (9 * 0) + 3 */
|
||||
ds = Fh_get_dictionary_size( header );
|
||||
ds = dictionary_size;
|
||||
for( i = 1; i <= 4; ++i ) { raw_props[i] = ds & 0xFF; ds >>= 8; }
|
||||
}
|
||||
|
||||
if( verbosity >= 2 || ( verbosity == 1 && first_member ) )
|
||||
{
|
||||
Pp_show_msg( pp, 0 );
|
||||
if( lzip_mode && verbosity >= 3 ) show_header( header );
|
||||
}
|
||||
{ Pp_show_msg( pp, 0 );
|
||||
if( lzip_mode && verbosity >= 3 ) show_header( dictionary_size ); }
|
||||
|
||||
if( !LzmaDec_Init( &decoder, raw_props ) )
|
||||
{
|
||||
show_error( "Not enough memory. Find a machine with more memory.", 0, false );
|
||||
show_error( "Not enough memory.", 0, false );
|
||||
cleanup_and_fail( 1 );
|
||||
}
|
||||
if( lzip_mode )
|
||||
|
@ -746,25 +742,7 @@ static void set_signals( void )
|
|||
}
|
||||
|
||||
|
||||
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->stdin_name = "(stdin)";
|
||||
pp->longest_name = 0;
|
||||
pp->first_post = false;
|
||||
stdin_name_len = strlen( pp->stdin_name );
|
||||
|
||||
for( i = 0; i < num_filenames; ++i )
|
||||
{
|
||||
const char * const s = filenames[i];
|
||||
const int len = ( (strcmp( s, "-" ) == 0) ? stdin_name_len : strlen( s ) );
|
||||
if( len > pp->longest_name ) pp->longest_name = len;
|
||||
}
|
||||
if( pp->longest_name == 0 ) pp->longest_name = stdin_name_len;
|
||||
}
|
||||
CRC32 crc32;
|
||||
|
||||
|
||||
void Pp_show_msg( struct Pretty_print * const pp, const char * const msg )
|
||||
|
@ -780,11 +758,48 @@ void Pp_show_msg( struct Pretty_print * const pp, const char * const msg )
|
|||
for( i = 0; i < len; ++i ) fprintf( stderr, " " );
|
||||
if( !msg ) fflush( stderr );
|
||||
}
|
||||
if( msg ) fprintf( stderr, "%s.\n", msg );
|
||||
if( msg ) fprintf( stderr, "%s\n", msg );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Returns the number of bytes really read.
|
||||
If (returned value < size) and (errno == 0), means EOF was reached.
|
||||
*/
|
||||
int readblock( const int fd, uint8_t * const buf, const int size )
|
||||
{
|
||||
int sz = 0;
|
||||
errno = 0;
|
||||
while( sz < size )
|
||||
{
|
||||
const int n = read( fd, buf + sz, size - sz );
|
||||
if( n > 0 ) sz += n;
|
||||
else if( n == 0 ) break; /* EOF */
|
||||
else if( errno != EINTR ) break;
|
||||
errno = 0;
|
||||
}
|
||||
return sz;
|
||||
}
|
||||
|
||||
|
||||
/* Returns the number of bytes really written.
|
||||
If (returned value < size), it is always an error.
|
||||
*/
|
||||
int writeblock( const int fd, const uint8_t * const buf, const int size )
|
||||
{
|
||||
int sz = 0;
|
||||
errno = 0;
|
||||
while( sz < size )
|
||||
{
|
||||
const int n = write( fd, buf + sz, size - sz );
|
||||
if( n > 0 ) sz += n;
|
||||
else if( n < 0 && errno != EINTR ) break;
|
||||
errno = 0;
|
||||
}
|
||||
return sz;
|
||||
}
|
||||
|
||||
|
||||
void show_error( const char * const msg, const int errcode, const bool help )
|
||||
{
|
||||
if( verbosity >= 0 )
|
||||
|
@ -792,7 +807,7 @@ void show_error( const char * const msg, const int errcode, const bool help )
|
|||
if( msg && msg[0] )
|
||||
{
|
||||
fprintf( stderr, "%s: %s", program_name, msg );
|
||||
if( errcode > 0 ) fprintf( stderr, ": %s", strerror( errcode ) );
|
||||
if( errcode > 0 ) fprintf( stderr, ": %s.", strerror( errcode ) );
|
||||
fprintf( stderr, "\n" );
|
||||
}
|
||||
if( help )
|
||||
|
@ -805,7 +820,7 @@ void show_error( const char * const msg, const int errcode, const bool help )
|
|||
void internal_error( const char * const msg )
|
||||
{
|
||||
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 );
|
||||
}
|
||||
|
||||
|
@ -879,7 +894,7 @@ int main( const int argc, const char * const argv[] )
|
|||
CRC32_init();
|
||||
|
||||
if( !ap_init( &parser, argc, argv, options, 0 ) )
|
||||
{ show_error( "Memory exhausted.", 0, false ); return 1; }
|
||||
{ show_error( "Not enough memory.", 0, false ); return 1; }
|
||||
if( ap_error( &parser ) ) /* bad option */
|
||||
{ show_error( ap_error( &parser ), 0, true ); return 1; }
|
||||
|
||||
|
@ -890,8 +905,7 @@ int main( const int argc, const char * const argv[] )
|
|||
if( !code ) break; /* no more options */
|
||||
switch( code )
|
||||
{
|
||||
case '0':
|
||||
case '1': case '2': case '3': case '4':
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
encoder_options = option_mapping[code-'0']; break;
|
||||
case 'b': break;
|
||||
|
@ -912,7 +926,7 @@ int main( const int argc, const char * const argv[] )
|
|||
case 't': program_mode = m_test; break;
|
||||
case 'v': if( verbosity < 4 ) ++verbosity; break;
|
||||
case 'V': show_version(); return 0;
|
||||
default : internal_error( "uncaught option" );
|
||||
default : internal_error( "uncaught option." );
|
||||
}
|
||||
} /* end process options */
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue