diff options
Diffstat (limited to 'main.c')
-rw-r--r-- | main.c | 153 |
1 files changed, 87 insertions, 66 deletions
@@ -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 ); } |