1
0
Fork 0

Merging upstream version 1.10.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-02-23 19:24:41 +01:00
parent b2b52b515a
commit 9ad9f8e387
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
12 changed files with 276 additions and 193 deletions

153
main.c
View file

@ -1,6 +1,6 @@
/* Pdlzip - LZMA lossless data compressor
2009-08-14 : Igor Pavlov : Public domain
Copyright (C) 2010-2018 Antonio Diaz Diaz.
Copyright (C) 2010-2019 Antonio Diaz Diaz.
This program is free software. Redistribution and use in source and
binary forms, with or without modification, are permitted provided
@ -38,19 +38,24 @@
#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
#define S_ISSOCK(x) 0
#ifndef S_IRGRP
#define S_IRGRP 0
#define S_IWGRP 0
#define S_IROTH 0
#define S_IWOTH 0
#endif
#if defined(__OS2__)
#include <io.h>
#endif
#if defined(__DJGPP__)
#define S_ISSOCK(x) 0
#define S_ISVTX 0
#endif
#endif
#include "carg_parser.h"
@ -68,9 +73,8 @@
int verbosity = 0;
const char * const Program_name = "Pdlzip";
const char * const program_name = "pdlzip";
const char * const program_year = "2018";
const char * const program_year = "2019";
const char * invocation_name = 0;
const struct { const char * from; const char * to; } known_extensions[] = {
@ -87,6 +91,8 @@ struct Lzma_options
enum Mode { m_compress, m_decompress, m_test };
/* 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;
@ -94,9 +100,20 @@ bool delete_output_on_interrupt = false;
static void show_help( void )
{
printf( "%s - A permissively licensed implementation of the lzip data\n", Program_name );
printf( "compressor also able to decompress legacy lzma-alone (.lzma) files.\n"
"\nLzma-alone is a very bad format; it is essentially a raw LZMA stream.\n"
printf( "Pdlzip is a permissively licensed implementation of the lzip data\n"
"compressor, intended for those who can't distribute (or even use) GPL\n"
"licensed Free Software. (The name of pdlzip comes from 'public domain\n"
"lzip'). Pdlzip is written in C and is (hope)fully compatible with lzip 1.4\n"
"or newer.\n"
"\nLzip is a lossless data compressor with a user interface similar to the\n"
"one of gzip or bzip2. Lzip can compress about as fast as gzip (lzip -0)\n"
"or compress most files more than bzip2 (lzip -9). Decompression speed is\n"
"intermediate between gzip and bzip2. Lzip is better than gzip and bzip2\n"
"from a data recovery perspective. Lzip has been designed, written and\n"
"tested with great care to replace gzip and bzip2 as the standard\n"
"general-purpose compressed format for unix-like systems.\n"
"\nPdlzip is also able to decompress legacy lzma-alone (.lzma) files.\n"
"Lzma-alone is a very bad format; it is essentially a raw LZMA stream.\n"
"If you keep any lzma-alone files, it is advisable to recompress them to\n"
"lzip format. Lziprecover can convert some lzma-alone files to lzip format\n"
"without recompressing.\n"
@ -116,8 +133,8 @@ static void show_help( void )
" -s, --dictionary-size=<bytes> set dictionary size limit in bytes [8 MiB]\n"
" -t, --test test compressed file integrity\n"
" -v, --verbose be verbose (a 2nd -v gives more)\n"
" -1 .. -9 set compression level [default 6]\n"
" --fast alias for -1\n"
" -0 .. -9 set compression level [default 6]\n"
" --fast alias for -0\n"
" --best alias for -9\n"
" --loose-trailing allow trailing data seeming corrupt header\n"
"If no file names are given, or if a file is '-', pdlzip compresses or\n"
@ -255,7 +272,7 @@ static int get_dict_size( const char * const arg )
const long bits = strtol( arg, &tail, 0 );
if( bits >= min_dictionary_bits &&
bits <= max_dictionary_bits_c && *tail == 0 )
return ( 1 << bits );
return 1 << bits;
return getnum( arg, min_dictionary_size, max_dictionary_size_c );
}
@ -393,8 +410,17 @@ static bool check_tty( const char * const input_filename, const int infd,
}
static void set_signals( void (*action)(int) )
{
signal( SIGHUP, action );
signal( SIGINT, action );
signal( SIGTERM, action );
}
void cleanup_and_fail( const int retval )
{
set_signals( SIG_IGN ); /* ignore signals */
if( delete_output_on_interrupt )
{
delete_output_on_interrupt = false;
@ -409,6 +435,14 @@ void cleanup_and_fail( const int retval )
}
void signal_handler( int sig )
{
if( sig ) {} /* keep compiler happy */
show_error( "Control-C or similar caught, quitting.", 0, false );
cleanup_and_fail( 1 );
}
/* Set permissions, owner and times. */
static void close_and_set_permissions( const struct stat * const in_statsp )
{
@ -448,14 +482,14 @@ static int compress( const struct Lzma_options * const encoder_options,
{
int retval = 0;
CLzmaEncHandle encoder = 0;
File_header header;
Fh_set_magic( header );
Lzip_header header;
Lh_set_magic( header );
if( verbosity >= 1 ) Pp_show_msg( pp, 0 );
if( Fh_set_dictionary_size( header, encoder_options->dictionary_size ) &&
if( Lh_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 = LzmaEnc_Init( Lh_get_dictionary_size( header ),
encoder_options->match_len_limit, infd, outfd );
else internal_error( "invalid argument to encoder." );
@ -465,7 +499,7 @@ static int compress( const struct Lzma_options * const encoder_options,
return 1;
}
if( writeblock( outfd, header, Fh_size ) != Fh_size )
if( writeblock( outfd, header, Lh_size ) != Lh_size )
{ show_error( "Can't write output file", errno, false ); retval = 1; }
else
if( LzmaEnc_Encode( encoder ) != 0 )
@ -578,7 +612,7 @@ static int lzip_decode( CLzmaDec *decoder, const int infd,
int * const inPos, int * const inSize,
const unsigned dictionary_size )
{
unsigned long long member_size = Fh_size, data_size = 0;
unsigned long long member_size = Lh_size, data_size = 0;
uint8_t outBuf[OUT_BUF_SIZE];
int outPos = 0;
uint32_t crc = 0xFFFFFFFFU;
@ -612,7 +646,7 @@ static int lzip_decode( CLzmaDec *decoder, const int infd,
if (inProcessed == 0 && outProcessed == 0)
{
File_trailer trailer;
Lzip_trailer trailer;
int i;
unsigned td_crc;
unsigned long long td_size, tm_size;
@ -620,9 +654,9 @@ static int lzip_decode( CLzmaDec *decoder, const int infd,
if( status != LZMA_STATUS_FINISHED_WITH_MARK )
{ Pp_show_msg( pp, "Data error." ); return 2; }
if( *inSize - *inPos < Ft_size &&
if( *inSize - *inPos < Lt_size &&
!read_inbuf( infd, inBuf, inPos, inSize ) ) return 1;
if( *inSize - *inPos < Ft_size )
if( *inSize - *inPos < Lt_size )
{
error = true;
if( verbosity >= 0 )
@ -632,12 +666,12 @@ static int lzip_decode( CLzmaDec *decoder, const int infd,
" some checks may fail.\n", *inSize - *inPos );
}
}
for( i = 0; i < Ft_size && *inPos < *inSize; ++i )
for( i = 0; i < Lt_size && *inPos < *inSize; ++i )
trailer[i] = inBuf[(*inPos)++];
member_size += i;
while( i < Ft_size ) trailer[i++] = 0;
while( i < Lt_size ) trailer[i++] = 0;
crc ^= 0xFFFFFFFFU;
td_crc = Ft_get_data_crc( trailer );
td_crc = Lt_get_data_crc( trailer );
if( td_crc != crc )
{
error = true;
@ -648,7 +682,7 @@ static int lzip_decode( CLzmaDec *decoder, const int infd,
td_crc, crc );
}
}
td_size = Ft_get_data_size( trailer );
td_size = Lt_get_data_size( trailer );
if( td_size != data_size )
{
error = true;
@ -659,7 +693,7 @@ static int lzip_decode( CLzmaDec *decoder, const int infd,
td_size, td_size, data_size, data_size );
}
}
tm_size = Ft_get_member_size( trailer );
tm_size = Lt_get_member_size( trailer );
if( tm_size != member_size )
{
error = true;
@ -709,38 +743,38 @@ static int decompress( const int infd, struct Pretty_print * const pp,
{
int i, size;
unsigned dictionary_size;
File_header header;
Lzip_header header;
if( inSize - inPos < lzma_header_size &&
!read_inbuf( infd, inBuf, &inPos, &inSize ) ) return 1;
size = inSize - inPos;
for( i = 0; i < size && i < Fh_size; ++i )
for( i = 0; i < size && i < Lh_size; ++i )
raw_props[i] = header[i] = inBuf[inPos++];
if( size <= Fh_size ) /* End Of File */
if( size <= Lh_size ) /* End Of File */
{
if( first_member )
{ show_file_error( pp->name, "File ends unexpectedly at member header.", 0 );
retval = 2; }
else if( Fh_verify_prefix( header, size ) )
else if( Lh_verify_prefix( header, size ) )
{ Pp_show_msg( pp, "Truncated header in multimember file." );
retval = 2; }
else if( size > 0 && !ignore_trailing )
{ Pp_show_msg( pp, trailing_msg ); retval = 2; }
break;
}
if( !Fh_verify_magic( header ) )
if( !Lh_verify_magic( header ) )
{
if( !first_member )
{
if( !loose_trailing && Fh_verify_corrupt( header ) )
if( !loose_trailing && Lh_verify_corrupt( header ) )
{ Pp_show_msg( pp, "Corrupt header in multimember file." );
retval = 2; }
else if( !ignore_trailing )
{ Pp_show_msg( pp, trailing_msg ); retval = 2; }
break;
}
if( inSize - inPos >= lzma_header_size - Fh_size ) /* try lzma-alone */
if( inSize - inPos >= lzma_header_size - Lh_size ) /* try lzma-alone */
{
for( i = Fh_size; i < lzma_header_size; ++i )
for( i = Lh_size; i < lzma_header_size; ++i )
raw_props[i] = inBuf[inPos++];
if( ( raw_props[12] == 0 || raw_props[12] == 0xFF ) &&
raw_props[12] == raw_props[11] && raw_props[0] < (9 * 5 * 5) )
@ -763,15 +797,15 @@ static int decompress( const int infd, struct Pretty_print * const pp,
if( lzip_mode )
{
int ds, i;
if( !Fh_verify_version( header ) )
if( !Lh_verify_version( header ) )
{
if( verbosity >= 0 )
{ Pp_show_msg( pp, 0 );
fprintf( stderr, "Version %d member format not supported.\n",
Fh_version( header ) ); }
Lh_version( header ) ); }
retval = 2; break;
}
dictionary_size = Fh_get_dictionary_size( header );
dictionary_size = Lh_get_dictionary_size( header );
if( !isvalid_ds( dictionary_size ) )
{ Pp_show_msg( pp, "Invalid dictionary size in member header." );
retval = 2; break; }
@ -803,22 +837,6 @@ static int decompress( const int infd, struct Pretty_print * const pp,
}
void signal_handler( int sig )
{
if( sig ) {} /* keep compiler happy */
show_error( "Control-C or similar caught, quitting.", 0, false );
cleanup_and_fail( 1 );
}
static void set_signals( void )
{
signal( SIGHUP, signal_handler );
signal( SIGINT, signal_handler );
signal( SIGTERM, signal_handler );
}
CRC32 crc32;
@ -863,11 +881,9 @@ void show_error( const char * const msg, const int errcode, const bool help )
{
if( verbosity < 0 ) return;
if( msg && msg[0] )
{
fprintf( stderr, "%s: %s", program_name, msg );
if( errcode > 0 ) fprintf( stderr, ": %s", strerror( errcode ) );
fputc( '\n', stderr );
}
fprintf( stderr, "%s: %s%s%s\n", program_name, msg,
( errcode > 0 ) ? ": " : "",
( errcode > 0 ) ? strerror( errcode ) : "" );
if( help )
fprintf( stderr, "Try '%s --help' for more information.\n",
invocation_name );
@ -877,10 +893,10 @@ void show_error( const char * const msg, const int errcode, const bool help )
void show_file_error( const char * const filename, const char * const msg,
const int errcode )
{
if( verbosity < 0 ) return;
fprintf( stderr, "%s: %s: %s", program_name, filename, msg );
if( errcode > 0 ) fprintf( stderr, ": %s", strerror( errcode ) );
fputc( '\n', stderr );
if( verbosity >= 0 )
fprintf( stderr, "%s: %s: %s%s%s\n", program_name, filename, msg,
( errcode > 0 ) ? ": " : "",
( errcode > 0 ) ? strerror( errcode ) : "" );
}
@ -898,7 +914,7 @@ int main( const int argc, const char * const argv[] )
to the corresponding LZMA compression modes. */
const struct Lzma_options option_mapping[] =
{
{ 1 << 20, 5 }, /* -0 */
{ 1 << 16, 5 }, /* -0 */
{ 1 << 20, 5 }, /* -1 */
{ 3 << 19, 6 }, /* -2 */
{ 1 << 21, 8 }, /* -3 */
@ -1004,7 +1020,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
@ -1024,7 +1040,7 @@ int main( const int argc, const char * const argv[] )
if( !to_stdout && program_mode != m_test &&
( filenames_given || default_output_filename[0] ) )
set_signals();
set_signals( signal_handler );
Pp_init( &pp, filenames, num_filenames );
@ -1103,6 +1119,12 @@ int main( const int argc, const char * const argv[] )
else
tmp = decompress( infd, &pp, ignore_trailing,
loose_trailing, program_mode == m_test );
if( close( infd ) != 0 )
{
show_error( input_filename[0] ? "Error closing input file" :
"Error closing stdin", errno, false );
if( tmp < 1 ) tmp = 1;
}
if( tmp > retval ) retval = tmp;
if( tmp )
{ if( program_mode != m_test ) cleanup_and_fail( retval );
@ -1112,7 +1134,6 @@ int main( const int argc, const char * const argv[] )
close_and_set_permissions( in_statsp );
if( input_filename[0] )
{
close( infd );
if( !keep_input_files && !to_stdout && program_mode != m_test )
remove( input_filename );
}