1
0
Fork 0

Merging upstream version 1.6~rc1.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-02-23 19:20:27 +01:00
parent 4d14b4402a
commit b60eef59a3
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
18 changed files with 954 additions and 870 deletions

196
main.c
View file

@ -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 */