From ac32e8eabf1b97208c4ccdfe908aea863d09d1f3 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Tue, 13 Feb 2018 08:06:07 +0100 Subject: Adding upstream version 1.7. Signed-off-by: Daniel Baumann --- dec_stream.cc | 65 +++++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 45 insertions(+), 20 deletions(-) (limited to 'dec_stream.cc') diff --git a/dec_stream.cc b/dec_stream.cc index 5ec1ff7..36a0ec0 100644 --- a/dec_stream.cc +++ b/dec_stream.cc @@ -1,6 +1,6 @@ /* Plzip - Parallel compressor compatible with lzip Copyright (C) 2009 Laszlo Ersek. - Copyright (C) 2009-2017 Antonio Diaz Diaz. + Copyright (C) 2009-2018 Antonio Diaz Diaz. 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 @@ -101,7 +101,7 @@ public: } // make a packet with data received from splitter - // if data == 0, move to next queue + // if data == 0 (end of member token), move to next queue void receive_packet( uint8_t * const data, const int size ) { Packet * const ipacket = new Packet( data, size ); @@ -237,9 +237,11 @@ int find_magic( const uint8_t * const buffer, const int pos, const int size ) struct Splitter_arg { + unsigned long long cfile_size; Packet_courier * courier; const Pretty_print * pp; int infd; + unsigned dictionary_size; // returned by splitter to main thread }; @@ -247,7 +249,7 @@ struct Splitter_arg // courier for packaging and distribution to workers. extern "C" void * dsplitter_s( void * arg ) { - const Splitter_arg & tmp = *(Splitter_arg *)arg; + Splitter_arg & tmp = *(Splitter_arg *)arg; Packet_courier & courier = *tmp.courier; const Pretty_print & pp = *tmp.pp; const int infd = tmp.infd; @@ -264,16 +266,18 @@ extern "C" void * dsplitter_s( void * arg ) if( size != buffer_size && errno ) { pp(); show_error( "Read error", errno ); cleanup_and_fail(); } if( size + hsize < min_member_size ) - { pp( "Input file is too short." ); cleanup_and_fail( 2 ); } + { show_file_error( pp.name(), "Input file is too short." ); + cleanup_and_fail( 2 ); } const File_header & header = *(File_header *)buffer; if( !header.verify_magic() ) - { pp( bad_magic_msg ); cleanup_and_fail( 2 ); } + { show_file_error( pp.name(), bad_magic_msg ); cleanup_and_fail( 2 ); } if( !header.verify_version() ) { pp( bad_version( header.version() ) ); cleanup_and_fail( 2 ); } - const unsigned dictionary_size = header.dictionary_size(); - if( !isvalid_ds( dictionary_size ) ) + tmp.dictionary_size = header.dictionary_size(); + if( !isvalid_ds( tmp.dictionary_size ) ) { pp( bad_dict_msg ); cleanup_and_fail( 2 ); } - show_header( dictionary_size ); + if( verbosity >= 1 ) pp(); + show_progress( 0, tmp.cfile_size, &pp ); // init unsigned long long partial_member_size = 0; while( true ) @@ -301,6 +305,7 @@ extern "C" void * dsplitter_s( void * arg ) courier.receive_packet( 0, 0 ); // end of member token partial_member_size = 0; pos = newpos; + show_progress( member_size ); } } } @@ -340,6 +345,7 @@ struct Worker_arg const Pretty_print * pp; int worker_id; bool ignore_trailing; + bool loose_trailing; bool testing; }; @@ -353,6 +359,7 @@ extern "C" void * dworker_s( void * arg ) const Pretty_print & pp = *tmp.pp; const int worker_id = tmp.worker_id; const bool ignore_trailing = tmp.ignore_trailing; + const bool loose_trailing = tmp.loose_trailing; const bool testing = tmp.testing; uint8_t * new_data = new( std::nothrow ) uint8_t[max_packet_size]; @@ -387,12 +394,22 @@ extern "C" void * dworker_s( void * arg ) max_packet_size - new_pos ); if( rd < 0 ) { - if( LZ_decompress_errno( decoder ) == LZ_header_error ) + const enum LZ_Errno lz_errno = LZ_decompress_errno( decoder ); + if( lz_errno == LZ_header_error ) { trailing_data_found = true; if( !ignore_trailing ) { pp( trailing_msg ); cleanup_and_fail( 2 ); } } + else if( lz_errno == LZ_data_error && + LZ_decompress_member_position( decoder ) == 0 ) + { + trailing_data_found = true; + if( !loose_trailing ) + { pp( corrupt_mm_msg ); cleanup_and_fail( 2 ); } + else if( !ignore_trailing ) + { pp( trailing_msg ); cleanup_and_fail( 2 ); } + } else cleanup_and_fail( decompress_read_error( decoder, pp, worker_id ) ); } @@ -459,9 +476,10 @@ void muxer( Packet_courier & courier, const Pretty_print & pp, const int outfd ) // init the courier, then start the splitter and the workers and, // if not testing, call the muxer. -int dec_stream( const int num_workers, const int infd, const int outfd, +int dec_stream( const unsigned long long cfile_size, + const int num_workers, const int infd, const int outfd, const Pretty_print & pp, const int debug_level, - const bool ignore_trailing ) + const bool ignore_trailing, const bool loose_trailing ) { const int in_slots_per_worker = 2; const int out_slots = 32; @@ -472,6 +490,7 @@ int dec_stream( const int num_workers, const int infd, const int outfd, Packet_courier courier( num_workers, in_slots, out_slots ); Splitter_arg splitter_arg; + splitter_arg.cfile_size = cfile_size; splitter_arg.courier = &courier; splitter_arg.pp = &pp; splitter_arg.infd = infd; @@ -491,6 +510,7 @@ int dec_stream( const int num_workers, const int infd, const int outfd, worker_args[i].pp = &pp; worker_args[i].worker_id = i; worker_args[i].ignore_trailing = ignore_trailing; + worker_args[i].loose_trailing = loose_trailing; worker_args[i].testing = ( outfd < 0 ); errcode = pthread_create( &worker_threads[i], 0, dworker_s, &worker_args[i] ); if( errcode ) @@ -512,15 +532,20 @@ int dec_stream( const int num_workers, const int infd, const int outfd, if( errcode ) { show_error( "Can't join splitter thread", errcode ); cleanup_and_fail(); } - if( verbosity >= 2 && out_size > 0 && in_size > 0 ) - std::fprintf( stderr, "%6.3f:1, %6.3f bits/byte, %5.2f%% saved. ", - (double)out_size / in_size, - ( 8.0 * in_size ) / out_size, - 100.0 * ( 1.0 - ( (double)in_size / out_size ) ) ); - if( verbosity >= 4 ) - std::fprintf( stderr, "decompressed %9llu, compressed %9llu. ", - out_size, in_size ); - + if( verbosity >= 2 ) + { + if( verbosity >= 4 ) show_header( splitter_arg.dictionary_size ); + if( out_size == 0 || in_size == 0 ) + std::fputs( "no data compressed. ", stderr ); + else + std::fprintf( stderr, "%6.3f:1, %5.2f%% ratio, %5.2f%% saved. ", + (double)out_size / in_size, + ( 100.0 * in_size ) / out_size, + 100.0 - ( ( 100.0 * in_size ) / out_size ) ); + if( verbosity >= 3 ) + std::fprintf( stderr, "decompressed %9llu, compressed %8llu. ", + out_size, in_size ); + } if( verbosity >= 1 ) std::fputs( (outfd < 0) ? "ok\n" : "done\n", stderr ); if( debug_level & 1 ) -- cgit v1.2.3