diff options
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | NEWS | 2 | ||||
-rwxr-xr-x | configure | 2 | ||||
-rw-r--r-- | decoder.cc | 67 | ||||
-rw-r--r-- | decoder.h | 51 | ||||
-rw-r--r-- | doc/lziprecover.1 | 2 | ||||
-rw-r--r-- | doc/lziprecover.info | 22 | ||||
-rw-r--r-- | doc/lziprecover.texinfo | 9 | ||||
-rw-r--r-- | lzip.h | 9 | ||||
-rw-r--r-- | main.cc | 12 | ||||
-rwxr-xr-x | testsuite/check.sh | 86 |
11 files changed, 141 insertions, 127 deletions
@@ -1,3 +1,9 @@ +2013-03-25 Antonio Diaz Diaz <ant_diaz@teleline.es> + + * Version 1.14-rc2 released. + * Minor fixes. + * main.cc (show_header): Show header version if verbosity >= 4. + 2013-02-27 Antonio Diaz Diaz <ant_diaz@teleline.es> * Version 1.14-rc1 released. @@ -4,6 +4,8 @@ Option "-l, --list" now accepts more than one file. Decompression time has been reduced by 12%. +File version is now shown only if verbosity >= 4. + The target "install-as-lzip" has been added to the Makefile. The target "install-bin" has been added to the Makefile. @@ -8,7 +8,7 @@ args= no_create= pkgname=lziprecover -pkgversion=1.14-rc1 +pkgversion=1.14-rc2 progname=lziprecover srctrigger=doc/lziprecover.texinfo @@ -128,10 +128,10 @@ bool LZ_decoder::verify_trailer( const Pretty_print & pp ) const File_trailer trailer; const int trailer_size = File_trailer::size( member_version ); const unsigned long long member_size = - range_decoder.member_position() + trailer_size; + rdec.member_position() + trailer_size; bool error = false; - int size = range_decoder.read_data( trailer.data, trailer_size ); + int size = rdec.read_data( trailer.data, trailer_size ); if( size < trailer_size ) { error = true; @@ -146,7 +146,7 @@ bool LZ_decoder::verify_trailer( const Pretty_print & pp ) const if( member_version == 0 ) trailer.member_size( member_size ); - if( !range_decoder.code_is_zero() ) + if( !rdec.code_is_zero() ) { error = true; pp( "Range decoder final code is not zero" ); @@ -207,82 +207,79 @@ int LZ_decoder::decode_member( const Pretty_print & pp ) Bit_model bm_dis_slot[max_dis_states][1<<dis_slot_bits]; Bit_model bm_dis[modeled_distances-end_dis_model]; Bit_model bm_align[dis_align_size]; - Len_decoder len_decoder; - Len_decoder rep_match_len_decoder; + Len_model match_len_model; + Len_model rep_len_model; unsigned rep0 = 0; // rep[0-3] latest four distances unsigned rep1 = 0; // used for efficient coding of unsigned rep2 = 0; // repeated distances unsigned rep3 = 0; - State state; - range_decoder.load(); - while( !range_decoder.finished() ) + rdec.load(); + while( !rdec.finished() ) { const int pos_state = data_position() & pos_state_mask; - if( range_decoder.decode_bit( bm_match[state()][pos_state] ) == 0 ) + if( rdec.decode_bit( bm_match[state()][pos_state] ) == 0 ) { const uint8_t prev_byte = get_prev_byte(); if( state.is_char() ) - put_byte( range_decoder.decode_tree( bm_literal[get_lit_state(prev_byte)], 8 ) ); + put_byte( rdec.decode_tree( bm_literal[get_lit_state(prev_byte)], 8 ) ); else - put_byte( range_decoder.decode_matched( bm_literal[get_lit_state(prev_byte)], - get_byte( rep0 ) ) ); + put_byte( rdec.decode_matched( bm_literal[get_lit_state(prev_byte)], + get_byte( rep0 ) ) ); state.set_char(); } else { int len; - if( range_decoder.decode_bit( bm_rep[state()] ) == 1 ) + if( rdec.decode_bit( bm_rep[state()] ) == 1 ) { - len = 0; - if( range_decoder.decode_bit( bm_rep0[state()] ) == 1 ) + if( rdec.decode_bit( bm_rep0[state()] ) == 0 ) + { + if( rdec.decode_bit( bm_len[state()][pos_state] ) == 0 ) + { state.set_short_rep(); put_byte( get_byte( rep0 ) ); continue; } + } + else { unsigned distance; - if( range_decoder.decode_bit( bm_rep1[state()] ) == 0 ) + if( rdec.decode_bit( bm_rep1[state()] ) == 0 ) distance = rep1; else { - if( range_decoder.decode_bit( bm_rep2[state()] ) == 0 ) + if( rdec.decode_bit( bm_rep2[state()] ) == 0 ) distance = rep2; - else { distance = rep3; rep3 = rep2; } + else + { distance = rep3; rep3 = rep2; } rep2 = rep1; } rep1 = rep0; rep0 = distance; } - else - { - if( range_decoder.decode_bit( bm_len[state()][pos_state] ) == 0 ) - { state.set_short_rep(); len = 1; } - } - if( len == 0 ) - { - state.set_rep(); - len = min_match_len + rep_match_len_decoder.decode( range_decoder, pos_state ); - } + len = min_match_len + rdec.decode_len( rep_len_model, pos_state ); + state.set_rep(); } else { const unsigned rep0_saved = rep0; - len = min_match_len + len_decoder.decode( range_decoder, pos_state ); - const int dis_slot = range_decoder.decode_tree6( bm_dis_slot[get_dis_state(len)] ); + len = min_match_len + rdec.decode_len( match_len_model, pos_state ); + const int dis_slot = rdec.decode_tree6( bm_dis_slot[get_dis_state(len)] ); if( dis_slot < start_dis_model ) rep0 = dis_slot; else { const int direct_bits = ( dis_slot >> 1 ) - 1; rep0 = ( 2 | ( dis_slot & 1 ) ) << direct_bits; if( dis_slot < end_dis_model ) - rep0 += range_decoder.decode_tree_reversed( bm_dis + rep0 - dis_slot - 1, direct_bits ); + rep0 += rdec.decode_tree_reversed( bm_dis + rep0 - dis_slot - 1, + direct_bits ); else { - rep0 += range_decoder.decode( direct_bits - dis_align_bits ) << dis_align_bits; - rep0 += range_decoder.decode_tree_reversed4( bm_align ); + rep0 += rdec.decode( direct_bits - dis_align_bits ) << dis_align_bits; + rep0 += rdec.decode_tree_reversed4( bm_align ); if( rep0 == 0xFFFFFFFFU ) // Marker found { rep0 = rep0_saved; - range_decoder.normalize(); + rdec.normalize(); flush_data(); if( len == min_match_len ) // End Of Stream marker { @@ -290,7 +287,7 @@ int LZ_decoder::decode_member( const Pretty_print & pp ) } if( len == min_match_len + 1 ) // Sync Flush marker { - range_decoder.load(); continue; + rdec.load(); continue; } if( pp.verbosity() >= 0 ) { @@ -122,22 +122,22 @@ public: int decode_tree( Bit_model bm[], const int num_bits ) { - int model = 1; + int symbol = 1; for( int i = num_bits; i > 0; --i ) - model = ( model << 1 ) | decode_bit( bm[model] ); - return model - (1 << num_bits); + symbol = ( symbol << 1 ) | decode_bit( bm[symbol] ); + return symbol - (1 << num_bits); } int decode_tree6( Bit_model bm[] ) { - int model = 1; - model = ( model << 1 ) | decode_bit( bm[model] ); - model = ( model << 1 ) | decode_bit( bm[model] ); - model = ( model << 1 ) | decode_bit( bm[model] ); - model = ( model << 1 ) | decode_bit( bm[model] ); - model = ( model << 1 ) | decode_bit( bm[model] ); - model = ( model << 1 ) | decode_bit( bm[model] ); - return model - (1 << 6); + int symbol = 1; + symbol = ( symbol << 1 ) | decode_bit( bm[symbol] ); + symbol = ( symbol << 1 ) | decode_bit( bm[symbol] ); + symbol = ( symbol << 1 ) | decode_bit( bm[symbol] ); + symbol = ( symbol << 1 ) | decode_bit( bm[symbol] ); + symbol = ( symbol << 1 ) | decode_bit( bm[symbol] ); + symbol = ( symbol << 1 ) | decode_bit( bm[symbol] ); + return symbol - (1 << 6); } int decode_tree_reversed( Bit_model bm[], const int num_bits ) @@ -186,27 +186,16 @@ public: } return symbol - 0x100; } - }; - -class Len_decoder - { - Bit_model choice1; - Bit_model choice2; - Bit_model bm_low[pos_states][len_low_symbols]; - Bit_model bm_mid[pos_states][len_mid_symbols]; - Bit_model bm_high[len_high_symbols]; - -public: - int decode( Range_decoder & range_decoder, const int pos_state ) + int decode_len( Len_model & lm, const int pos_state ) { - if( range_decoder.decode_bit( choice1 ) == 0 ) - return range_decoder.decode_tree( bm_low[pos_state], len_low_bits ); - if( range_decoder.decode_bit( choice2 ) == 0 ) + if( decode_bit( lm.choice1 ) == 0 ) + return decode_tree( lm.bm_low[pos_state], len_low_bits ); + if( decode_bit( lm.choice2 ) == 0 ) return len_low_symbols + - range_decoder.decode_tree( bm_mid[pos_state], len_mid_bits ); + decode_tree( lm.bm_mid[pos_state], len_mid_bits ); return len_low_symbols + len_mid_symbols + - range_decoder.decode_tree( bm_high, len_high_bits ); + decode_tree( lm.bm_high, len_high_bits ); } }; @@ -216,7 +205,7 @@ class LZ_decoder const unsigned long long outskip; const unsigned long long outend; unsigned long long partial_data_pos; - Range_decoder & range_decoder; + Range_decoder & rdec; const int dictionary_size; const int buffer_size; uint8_t * const buffer; // output buffer @@ -270,14 +259,14 @@ class LZ_decoder void operator=( const LZ_decoder & ); // declared as private public: - LZ_decoder( const File_header & header, Range_decoder & rdec, const int ofd, + LZ_decoder( const File_header & header, Range_decoder & rde, const int ofd, const unsigned long long oskip = 0, const unsigned long long oend = -1ULL ) : outskip( oskip ), outend( oend ), partial_data_pos( 0 ), - range_decoder( rdec ), + rdec( rde ), dictionary_size( header.dictionary_size() ), buffer_size( std::max( 65536, dictionary_size ) ), buffer( new uint8_t[buffer_size] ), diff --git a/doc/lziprecover.1 b/doc/lziprecover.1 index d63f6ab..6470174 100644 --- a/doc/lziprecover.1 +++ b/doc/lziprecover.1 @@ -1,5 +1,5 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.37.1. -.TH LZIPRECOVER "1" "February 2013" "Lziprecover 1.14-rc1" "User Commands" +.TH LZIPRECOVER "1" "March 2013" "Lziprecover 1.14-rc2" "User Commands" .SH NAME Lziprecover \- recovers data from damaged lzip files .SH SYNOPSIS diff --git a/doc/lziprecover.info b/doc/lziprecover.info index 7b24dcb..dd9a65e 100644 --- a/doc/lziprecover.info +++ b/doc/lziprecover.info @@ -12,7 +12,7 @@ File: lziprecover.info, Node: Top, Next: Introduction, Up: (dir) Lziprecover Manual ****************** -This manual is for Lziprecover (version 1.14-rc1, 27 February 2013). +This manual is for Lziprecover (version 1.14-rc2, 25 March 2013). * Menu: @@ -268,6 +268,7 @@ additional information before, between, or after them. Bits 4-0 contain the base 2 logarithm of the base size (12 to 29). Bits 7-5 contain the number of wedges (0 to 7) to substract from the base size to obtain the dictionary size. + Example: 0xD3 = (2^19 - 6 * 2^15) = (512KiB - 6 * 32KiB) = 320KiB Valid values for dictionary size range from 4KiB to 512MiB. `Lzma stream' @@ -282,8 +283,9 @@ additional information before, between, or after them. `Member size (8 bytes)' Total size of the member, including header and trailer. This field - acts as a distributed index, and facilitates safe recovery of - undamaged members from multi-member files. + acts as a distributed index, allows the verification of stream + integrity, and facilitates safe recovery of undamaged members from + multi-member files. @@ -408,13 +410,13 @@ Concept Index Tag Table: Node: Top231 -Node: Introduction910 -Node: Invoking Lziprecover2947 -Node: File Format8073 -Node: Examples10394 -Ref: ddrescue-example11612 -Node: Problems13443 -Node: Concept Index13993 +Node: Introduction907 +Node: Invoking Lziprecover2944 +Node: File Format8070 +Node: Examples10512 +Ref: ddrescue-example11730 +Node: Problems13561 +Node: Concept Index14111 End Tag Table diff --git a/doc/lziprecover.texinfo b/doc/lziprecover.texinfo index 872abb4..676e8d6 100644 --- a/doc/lziprecover.texinfo +++ b/doc/lziprecover.texinfo @@ -6,8 +6,8 @@ @finalout @c %**end of header -@set UPDATED 27 February 2013 -@set VERSION 1.14-rc1 +@set UPDATED 25 March 2013 +@set VERSION 1.14-rc2 @dircategory Data Compression @direntry @@ -297,6 +297,7 @@ wedges between 0 and 7. The size of a wedge is (base_size / 16).@* Bits 4-0 contain the base 2 logarithm of the base size (12 to 29).@* Bits 7-5 contain the number of wedges (0 to 7) to substract from the base size to obtain the dictionary size.@* +Example: 0xD3 = (2^19 - 6 * 2^15) = (512KiB - 6 * 32KiB) = 320KiB@* Valid values for dictionary size range from 4KiB to 512MiB. @item Lzma stream @@ -311,8 +312,8 @@ Size of the uncompressed original data. @item Member size (8 bytes) Total size of the member, including header and trailer. This field acts -as a distributed index, and facilitates safe recovery of undamaged -members from multi-member files. +as a distributed index, allows the verification of stream integrity, and +facilitates safe recovery of undamaged members from multi-member files. @end table @@ -86,6 +86,15 @@ struct Bit_model Bit_model() : probability( bit_model_total / 2 ) {} }; +struct Len_model + { + Bit_model choice1; + Bit_model choice2; + Bit_model bm_low[pos_states][len_low_symbols]; + Bit_model bm_mid[pos_states][len_mid_symbols]; + Bit_model bm_high[len_high_symbols]; + }; + class Pretty_print { @@ -145,8 +145,9 @@ void show_header( const File_header & header ) for( int i = 0; i < 8 && ( num > 9999 || ( exact && num >= factor ) ); ++i ) { num /= factor; if( num % factor != 0 ) exact = false; p = prefix[i]; np = ""; } - std::fprintf( stderr, "version %d, dictionary size %s%4u %sB. ", - header.version(), np, num, p ); + if( verbosity >= 4 ) + std::fprintf( stderr, "version %d, ", header.version() ); + std::fprintf( stderr, "dictionary size %s%4u %sB. ", np, num, p ); } namespace { @@ -359,7 +360,6 @@ void show_trailing_garbage( const uint8_t * const data, const int size, int decompress( const int infd, const Pretty_print & pp, const bool testing ) { - const char * const ok_msg = ( testing ? "ok\n" : "done\n" ); int retval = 0; try { @@ -418,7 +418,8 @@ int decompress( const int infd, const Pretty_print & pp, const bool testing ) } retval = 2; break; } - if( verbosity >= 2 ) { std::fprintf( stderr, ok_msg ); pp.reset(); } + if( verbosity >= 2 ) + { std::fprintf( stderr, testing ? "ok\n" : "done\n" ); pp.reset(); } } } catch( std::bad_alloc ) @@ -427,7 +428,8 @@ int decompress( const int infd, const Pretty_print & pp, const bool testing ) retval = 1; } catch( Error e ) { pp(); show_error( e.msg, errno ); retval = 1; } - if( verbosity == 1 && retval == 0 ) std::fprintf( stderr, ok_msg ); + if( verbosity == 1 && retval == 0 ) + std::fprintf( stderr, testing ? "ok\n" : "done\n" ); return retval; } diff --git a/testsuite/check.sh b/testsuite/check.sh index bd77f02..f208067 100755 --- a/testsuite/check.sh +++ b/testsuite/check.sh @@ -41,92 +41,98 @@ fail=0 printf "testing lziprecover-%s..." "$2" +"${LZIPRECOVER}" -lq +if [ $? != 1 ] ; then fail=1 ; printf - ; else printf . ; fi +"${LZIPRECOVER}" -mq "${bad1_lz}" +if [ $? != 1 ] ; then fail=1 ; printf - ; else printf . ; fi +"${LZIPRECOVER}" -Rq +if [ $? != 1 ] ; then fail=1 ; printf - ; else printf . ; fi +"${LZIPRECOVER}" -sq +if [ $? != 1 ] ; then fail=1 ; printf - ; else printf . ; fi + "${LZIP}" -t "${testdir}"/test_v0.lz || fail=1 printf . "${LZIP}" -cd "${testdir}"/test_v0.lz > copy || fail=1 -cmp ${in} copy || fail=1 +cmp "${in}" copy || fail=1 printf . "${LZIP}" -t "${testdir}"/test_v1.lz || fail=1 printf . "${LZIP}" -cd "${testdir}"/test_v1.lz > copy || fail=1 -cmp ${in} copy || fail=1 +cmp "${in}" copy || fail=1 printf . -"${LZIPRECOVER}" -lq -if [ $? != 1 ] ; then fail=1 ; printf - ; else printf . ; fi -"${LZIPRECOVER}" -mq ${bad1_lz} -if [ $? != 1 ] ; then fail=1 ; printf - ; else printf . ; fi -"${LZIPRECOVER}" -Rq -if [ $? != 1 ] ; then fail=1 ; printf - ; else printf . ; fi -"${LZIPRECOVER}" -sq -if [ $? != 1 ] ; then fail=1 ; printf - ; else printf . ; fi - -"${LZIPRECOVER}" -D 921-1921 -fo copy ${in_lz} || fail=1 -cmp ${inD} copy || fail=1 +"${LZIPRECOVER}" -D 921-1921 -fo copy "${in_lz}" || fail=1 +cmp "${inD}" copy || fail=1 printf . -"${LZIPRECOVER}" -D 921,1000 ${in_lz} > copy || fail=1 -cmp ${inD} copy || fail=1 +"${LZIPRECOVER}" -D 921,1000 "${in_lz}" > copy || fail=1 +cmp "${inD}" copy || fail=1 printf . -"${LZIPRECOVER}" -m -o copy.lz ${bad1_lz} ${bad2_lz} ${bad1_lz} -q +"${LZIPRECOVER}" -m -o copy.lz "${bad1_lz}" "${bad2_lz}" "${bad1_lz}" -q if [ $? != 1 ] ; then fail=1 ; printf - ; else printf . ; fi -"${LZIPRECOVER}" -m -o copy.lz ${bad1_lz} ${bad2_lz} || fail=1 +"${LZIPRECOVER}" -m -o copy.lz "${bad1_lz}" "${bad2_lz}" || fail=1 "${LZIPRECOVER}" -df copy.lz || fail=1 -cmp ${in} copy || fail=1 +cmp "${in}" copy || fail=1 printf . -"${LZIPRECOVER}" -m -o copy.lz ${bad2_lz} ${bad1_lz} || fail=1 +"${LZIPRECOVER}" -m -o copy.lz "${bad2_lz}" "${bad1_lz}" || fail=1 "${LZIPRECOVER}" -df copy.lz || fail=1 -cmp ${in} copy || fail=1 +cmp "${in}" copy || fail=1 printf . -for i in ${bad1_lz} ${bad2_lz} ; do - for j in ${bad3_lz} ${bad4_lz} ${bad5_lz} ; do - "${LZIPRECOVER}" -m -o copy.lz ${i} ${j} || fail=1 +for i in "${bad1_lz}" "${bad2_lz}" ; do + for j in "${bad3_lz}" "${bad4_lz}" "${bad5_lz}" ; do + "${LZIPRECOVER}" -m -o copy.lz "${i}" "${j}" || fail=1 "${LZIPRECOVER}" -df copy.lz || fail=1 - cmp ${in} copy || fail=1 + cmp "${in}" copy || fail=1 printf . - "${LZIPRECOVER}" -m -o copy.lz ${j} ${i} || fail=1 + "${LZIPRECOVER}" -m -o copy.lz "${j}" "${i}" || fail=1 "${LZIPRECOVER}" -df copy.lz || fail=1 - cmp ${in} copy || fail=1 + cmp "${in}" copy || fail=1 printf . done done -"${LZIPRECOVER}" -m -o copy.lz ${bad3_lz} ${bad4_lz} ${bad5_lz} || fail=1 +"${LZIPRECOVER}" -m -o copy.lz "${bad3_lz}" "${bad4_lz}" "${bad5_lz}" || fail=1 "${LZIPRECOVER}" -df copy.lz || fail=1 -cmp ${in} copy || fail=1 +cmp "${in}" copy || fail=1 printf . -"${LZIPRECOVER}" -m -o copy.lz ${bad4_lz} ${bad5_lz} ${bad3_lz} || fail=1 +"${LZIPRECOVER}" -m -o copy.lz "${bad4_lz}" "${bad5_lz}" "${bad3_lz}" || fail=1 "${LZIPRECOVER}" -df copy.lz || fail=1 -cmp ${in} copy || fail=1 +cmp "${in}" copy || fail=1 printf . -"${LZIPRECOVER}" -m -o copy.lz ${bad5_lz} ${bad3_lz} ${bad4_lz} || fail=1 +"${LZIPRECOVER}" -m -o copy.lz "${bad5_lz}" "${bad3_lz}" "${bad4_lz}" || fail=1 "${LZIPRECOVER}" -df copy.lz || fail=1 -cmp ${in} copy || fail=1 +cmp "${in}" copy || fail=1 printf . -"${LZIPRECOVER}" -R ${in_lz} || fail=1 +"${LZIPRECOVER}" -R "${in_lz}" || fail=1 printf . -"${LZIPRECOVER}" -R -o copy.lz ${bad2_lz} -q +"${LZIPRECOVER}" -R -o copy.lz "${bad2_lz}" -q if [ $? != 2 ] ; then fail=1 ; printf - ; else printf . ; fi -"${LZIPRECOVER}" -R -o copy.lz ${bad1_lz} || fail=1 +"${LZIPRECOVER}" -R -o copy.lz "${bad1_lz}" || fail=1 "${LZIPRECOVER}" -df copy.lz || fail=1 -cmp ${in} copy || fail=1 +cmp "${in}" copy || fail=1 printf . -cat ${in_lz} ${in_lz} ${in_lz} > copy || framework_failure +cat "${in_lz}" "${in_lz}" "${in_lz}" > copy || framework_failure printf "garbage" >> copy || fail=1 "${LZIPRECOVER}" -s -o copy.lz copy || fail=1 for i in 1 2 3 ; do "${LZIPRECOVER}" -cd rec0000${i}copy.lz > copy || fail=1 - cmp ${in} copy || fail=1 + cmp "${in}" copy || fail=1 printf . done -cat ${in_lz} > anyothername || framework_failure +cat "${in_lz}" > anyothername || framework_failure "${LZIP}" -d anyothername || fail=1 -cmp ${in} anyothername.out || fail=1 +cmp "${in}" anyothername.out || fail=1 +printf . + +cat "${in}" "${in}" > in2 || framework_failure +cat "${in_lz}" "${in_lz}" > out2 || framework_failure +"${LZIP}" -d < out2 > copy2 || fail=1 +cmp in2 copy2 || fail=1 printf . echo |