diff options
-rw-r--r-- | ChangeLog | 5 | ||||
-rwxr-xr-x | configure | 2 | ||||
-rw-r--r-- | decoder.cc | 20 | ||||
-rw-r--r-- | decoder.h | 20 | ||||
-rw-r--r-- | doc/lziprecover.1 | 2 | ||||
-rw-r--r-- | doc/lziprecover.info | 60 | ||||
-rw-r--r-- | doc/lziprecover.texi | 45 | ||||
-rw-r--r-- | file_index.cc | 8 | ||||
-rw-r--r-- | lzip.h | 24 | ||||
-rw-r--r-- | main.cc | 20 | ||||
-rw-r--r-- | merge.cc | 2 | ||||
-rw-r--r-- | repair.cc | 14 |
12 files changed, 124 insertions, 98 deletions
@@ -1,3 +1,8 @@ +2015-04-08 Antonio Diaz Diaz <antonio@gnu.org> + + * Version 1.17-rc2 released. + * Minor changes. + 2015-01-21 Antonio Diaz Diaz <antonio@gnu.org> * Version 1.17-rc1 released. @@ -6,7 +6,7 @@ # to copy, distribute and modify it. pkgname=lziprecover -pkgversion=1.17-rc1 +pkgversion=1.17-rc2 progname=lziprecover srctrigger=doc/${pkgname}.texi @@ -62,7 +62,7 @@ long readblock( const int fd, uint8_t * const buf, const long size ) { const int n = read( fd, buf + sz, std::min( 1L << 20, size - sz ) ); if( n > 0 ) sz += n; - else if( n == 0 ) break; // EOF + else if( n == 0 ) break; /* EOF */ else if( errno != EINTR ) break; errno = 0; } @@ -206,9 +206,9 @@ int LZ_decoder::decode_member( const Pretty_print & pp ) Bit_model bm_align[dis_align_size]; 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 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; @@ -218,7 +218,7 @@ int LZ_decoder::decode_member( const Pretty_print & pp ) const int pos_state = data_position() & pos_state_mask; if( rdec.decode_bit( bm_match[state()][pos_state] ) == 0 ) // 1st bit { - const uint8_t prev_byte = get_prev_byte(); + const uint8_t prev_byte = peek_prev(); if( state.is_char() ) { state.set_char1(); @@ -228,7 +228,7 @@ int LZ_decoder::decode_member( const Pretty_print & pp ) { state.set_char2(); put_byte( rdec.decode_matched( bm_literal[get_lit_state(prev_byte)], - get_byte( rep0 ) ) ); + peek( rep0 ) ) ); } } else @@ -255,7 +255,7 @@ int LZ_decoder::decode_member( const Pretty_print & pp ) else { if( rdec.decode_bit( bm_len[state()][pos_state] ) == 0 ) // 4th bit - { state.set_short_rep(); put_byte( get_byte( rep0 ) ); continue; } + { state.set_short_rep(); put_byte( peek( rep0 ) ); continue; } } state.set_rep(); len = min_match_len + rdec.decode_len( rep_len_model, pos_state ); @@ -277,16 +277,16 @@ int LZ_decoder::decode_member( const Pretty_print & pp ) { rep0 += rdec.decode( direct_bits - dis_align_bits ) << dis_align_bits; rep0 += rdec.decode_tree_reversed4( bm_align ); - if( rep0 == 0xFFFFFFFFU ) // marker found + if( rep0 == 0xFFFFFFFFU ) /* marker found */ { rep0 = rep0_saved; rdec.normalize(); flush_data(); - if( len == min_match_len ) // End Of Stream marker + if( len == min_match_len ) /* End Of Stream marker */ { if( verify_trailer( pp ) ) return 0; else return 3; } - if( len == min_match_len + 1 ) // Sync Flush marker + if( len == min_match_len + 1 ) /* Sync Flush marker */ { rdec.load(); continue; } @@ -19,12 +19,12 @@ class Range_decoder { enum { buffer_size = 16384 }; unsigned long long partial_member_pos; - uint8_t * const buffer; // input buffer - int pos; // current pos in buffer - int stream_pos; // when reached, a new block must be read + uint8_t * const buffer; /* input buffer */ + int pos; /* current pos in buffer */ + int stream_pos; /* when reached, a new block must be read */ uint32_t code; uint32_t range; - const int infd; // input file descriptor + const int infd; /* input file descriptor */ bool at_stream_end; bool read_block(); @@ -215,24 +215,24 @@ class LZ_decoder Range_decoder & rdec; const unsigned dictionary_size; const int buffer_size; - uint8_t * const buffer; // output buffer - int pos; // current pos in buffer - int stream_pos; // first byte not yet written to file + uint8_t * const buffer; /* output buffer */ + int pos; /* current pos in buffer */ + int stream_pos; /* first byte not yet written to file */ uint32_t crc_; - const int outfd; // output file descriptor + const int outfd; /* output file descriptor */ unsigned long long stream_position() const { return partial_data_pos + stream_pos; } void flush_data(); bool verify_trailer( const Pretty_print & pp ) const; - uint8_t get_prev_byte() const + uint8_t peek_prev() const { const int i = ( ( pos > 0 ) ? pos : buffer_size ) - 1; return buffer[i]; } - uint8_t get_byte( const int distance ) const + uint8_t peek( const int distance ) const { int i = pos - distance - 1; if( i < 0 ) i += buffer_size; diff --git a/doc/lziprecover.1 b/doc/lziprecover.1 index c2f55d7..09e4872 100644 --- a/doc/lziprecover.1 +++ b/doc/lziprecover.1 @@ -1,5 +1,5 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.46.1. -.TH LZIPRECOVER "1" "January 2015" "lziprecover 1.17-rc1" "User Commands" +.TH LZIPRECOVER "1" "April 2015" "lziprecover 1.17-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 05c1196..883ed7e 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.17-rc1, 21 January 2015). +This manual is for Lziprecover (version 1.17-rc2, 8 April 2015). * Menu: @@ -283,10 +283,11 @@ data stream, even if it is just one altered bit, the original data can't be recovered. If you used bzip2, and if the file is large enough to contain more -than one compressed data block (usually larger than 900 kB), and if no -block is damaged in both files, then the data can be manually recovered -by splitting the files with bzip2recover, verifying every block and then -copying the right blocks in the right order in another file. +than one compressed data block (usually larger than 900 kB +uncompressed), and if no block is damaged in both files, then the data +can be manually recovered by splitting the files with bzip2recover, +verifying every block and then copying the right blocks in the right +order in another file. But if you used lzip, the data can be automatically recovered as long as no byte is damaged in both files. @@ -429,21 +430,19 @@ additional information before, between, or after them. now. 'DS (coded dictionary size, 1 byte)' - Lzip divides the distance between any two powers of 2 into 8 - equally spaced intervals, named "wedges". The dictionary size is - calculated by taking a power of 2 (the base size) and substracting - from it a number of wedges between 0 and 7. The size of a wedge is - (base_size / 16). + The dictionary size is calculated by taking a power of 2 (the base + size) and substracting from it a fraction between 0/16 and 7/16 of + the base size. 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. + Bits 7-5 contain the numerator of the fraction (0 to 7) to + substract from the base size to obtain the dictionary size. Example: 0xD3 = 2^19 - 6 * 2^15 = 512 KiB - 6 * 32 KiB = 320 KiB Valid values for dictionary size range from 4 KiB to 512 MiB. 'Lzma stream' The lzma stream, finished by an end of stream marker. Uses default - values for encoder properties. See the lzip manual for a full - description. + values for encoder properties. *Note Stream format: (lzip)Stream + format, for a complete description. 'CRC32 (4 bytes)' CRC of the uncompressed original data. @@ -493,6 +492,8 @@ are abridged diagnostic messages from lziprecover). lziprecover -v -R file.lz Copy of input file repaired successfully. + lziprecover -tv file_fixed.lz + ok mv file_fixed.lz file.lz @@ -518,6 +519,9 @@ error-checked merging of copies (*Note GNU ddrescue manual: cp /mnt/cdimage/backup.tar.lz rescued2.tar.lz umount /mnt/cdimage lziprecover -m -v -o backup.tar.lz rescued1.tar.lz rescued2.tar.lz + Input files merged successfully. + lziprecover -tv backup.tar.lz + ok Example 8: Recover the first volume of those created with the command @@ -527,7 +531,9 @@ damaged in the second copy, and member 12 damaged in both copies. The correct file produced is saved in 'big_db_00001.lz'. lziprecover -m -v -o big_db_00001.lz big_db1_00001.lz big_db2_00001.lz - Input files merged successfully + Input files merged successfully. + lziprecover -tv big_db_00001.lz + ok File: lziprecover.info, Node: Unzcrash, Next: Problems, Prev: Examples, Up: Top @@ -646,18 +652,18 @@ Concept index Tag Table: Node: Top231 -Node: Introduction1216 -Node: Invoking lziprecover4312 -Node: Data safety9745 -Node: Repairing files11661 -Node: Merging files13563 -Node: File names15404 -Node: File format15868 -Node: Examples18375 -Ref: ddrescue-example19576 -Node: Unzcrash20685 -Node: Problems23239 -Node: Concept index23791 +Node: Introduction1213 +Node: Invoking lziprecover4309 +Node: Data safety9742 +Node: Repairing files11671 +Node: Merging files13573 +Node: File names15414 +Node: File format15878 +Node: Examples18282 +Ref: ddrescue-example19528 +Node: Unzcrash20770 +Node: Problems23324 +Node: Concept index23876 End Tag Table diff --git a/doc/lziprecover.texi b/doc/lziprecover.texi index 85f0385..2bcaa0a 100644 --- a/doc/lziprecover.texi +++ b/doc/lziprecover.texi @@ -6,8 +6,8 @@ @finalout @c %**end of header -@set UPDATED 21 January 2015 -@set VERSION 1.17-rc1 +@set UPDATED 8 April 2015 +@set VERSION 1.17-rc2 @dircategory Data Compression @direntry @@ -311,10 +311,11 @@ data stream, even if it is just one altered bit, the original data can't be recovered. If you used bzip2, and if the file is large enough to contain more than -one compressed data block (usually larger than 900 kB), and if no block -is damaged in both files, then the data can be manually recovered by -splitting the files with bzip2recover, verifying every block and then -copying the right blocks in the right order in another file. +one compressed data block (usually larger than 900 kB uncompressed), and +if no block is damaged in both files, then the data can be manually +recovered by splitting the files with bzip2recover, verifying every +block and then copying the right blocks in the right order in another +file. But if you used lzip, the data can be automatically recovered as long as no byte is damaged in both files. @@ -463,19 +464,26 @@ A four byte string, identifying the lzip format, with the value "LZIP" Just in case something needs to be modified in the future. 1 for now. @item DS (coded dictionary size, 1 byte) -Lzip divides the distance between any two powers of 2 into 8 equally -spaced intervals, named "wedges". The dictionary size is calculated by -taking a power of 2 (the base size) and substracting from it a number of -wedges between 0 and 7. The size of a wedge is (base_size / 16).@* +The dictionary size is calculated by taking a power of 2 (the base size) +and substracting from it a fraction between 0/16 and 7/16 of the base +size.@* 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.@* +Bits 7-5 contain the numerator of the fraction (0 to 7) to substract +from the base size to obtain the dictionary size.@* Example: 0xD3 = 2^19 - 6 * 2^15 = 512 KiB - 6 * 32 KiB = 320 KiB@* Valid values for dictionary size range from 4 KiB to 512 MiB. @item Lzma stream -The lzma stream, finished by an end of stream marker. Uses default values -for encoder properties. See the lzip manual for a full description. +The lzma stream, finished by an end of stream marker. Uses default +values for encoder properties. +@ifnothtml +@xref{Stream format,,,lzip}, +@end ifnothtml +@ifhtml +See +@uref{http://www.nongnu.org/lzip/manual/lzip_manual.html#Stream-format,,Stream format} +@end ifhtml +for a complete description. @item CRC32 (4 bytes) CRC of the uncompressed original data. @@ -538,6 +546,8 @@ lines are abridged diagnostic messages from lziprecover). @example lziprecover -v -R file.lz Copy of input file repaired successfully. +lziprecover -tv file_fixed.lz + ok mv file_fixed.lz file.lz @end example @@ -577,6 +587,9 @@ mount -t iso9660 -o loop,ro cdimage2 /mnt/cdimage cp /mnt/cdimage/backup.tar.lz rescued2.tar.lz umount /mnt/cdimage lziprecover -m -v -o backup.tar.lz rescued1.tar.lz rescued2.tar.lz + Input files merged successfully. +lziprecover -tv backup.tar.lz + ok @end example @sp 1 @@ -590,7 +603,9 @@ member 12 damaged in both copies. The correct file produced is saved in @example lziprecover -m -v -o big_db_00001.lz big_db1_00001.lz big_db2_00001.lz - Input files merged successfully + Input files merged successfully. +lziprecover -tv big_db_00001.lz + ok @end example diff --git a/file_index.cc b/file_index.cc index de685a3..49511bf 100644 --- a/file_index.cc +++ b/file_index.cc @@ -85,8 +85,8 @@ File_index::File_index( const int infd ) const long long member_size = trailer.member_size(); if( member_size < min_member_size || member_size > pos ) { - if( member_vector.empty() ) // maybe trailing garbage - { --pos; continue; } + if( member_vector.empty() ) + { --pos; continue; } // maybe trailing garbage set_num_error( "Member size in trailer is corrupt at pos ", pos - 8 ); break; } @@ -95,8 +95,8 @@ File_index::File_index( const int infd ) { set_errno_error( "Error reading member header: " ); break; } if( !header.verify_magic() || !header.verify_version() ) { - if( member_vector.empty() ) // maybe trailing garbage - { --pos; continue; } + if( member_vector.empty() ) + { --pos; continue; } // maybe trailing garbage set_num_error( "Bad header at pos ", pos - member_size ); break; } @@ -40,7 +40,7 @@ public: enum { min_dictionary_bits = 12, - min_dictionary_size = 1 << min_dictionary_bits, // >= modeled_distances + min_dictionary_size = 1 << min_dictionary_bits, /* >= modeled_distances */ max_dictionary_bits = 29, max_dictionary_size = 1 << max_dictionary_bits, min_member_size = 36, @@ -53,7 +53,7 @@ enum { dis_slot_bits = 6, start_dis_model = 4, end_dis_model = 14, - modeled_distances = 1 << (end_dis_model / 2), // 128 + modeled_distances = 1 << (end_dis_model / 2), /* 128 */ dis_align_bits = 4, dis_align_size = 1 << dis_align_bits, @@ -65,8 +65,8 @@ enum { len_high_symbols = 1 << len_high_bits, max_len_symbols = len_low_symbols + len_mid_symbols + len_high_symbols, - min_match_len = 2, // must be 2 - max_match_len = min_match_len + max_len_symbols - 1, // 273 + min_match_len = 2, /* must be 2 */ + max_match_len = min_match_len + max_len_symbols - 1, /* 273 */ min_match_len_limit = 5 }; inline int get_len_state( const int len ) @@ -186,9 +186,9 @@ const uint8_t magic_string[4] = { 0x4C, 0x5A, 0x49, 0x50 }; // "LZIP" struct File_header { - uint8_t data[6]; // 0-3 magic bytes - // 4 version - // 5 coded_dict_size + uint8_t data[6]; /* 0-3 magic bytes */ + /* 4 version */ + /* 5 coded_dict_size */ enum { size = 6 }; void set_magic() { std::memcpy( data, magic_string, 4 ); data[4] = 1; } @@ -214,9 +214,9 @@ struct File_header if( sz > min_dictionary_size ) { const unsigned base_size = 1 << data[5]; - const unsigned wedge = base_size / 16; + const unsigned fraction = base_size / 16; for( int i = 7; i >= 1; --i ) - if( base_size - ( i * wedge ) >= sz ) + if( base_size - ( i * fraction ) >= sz ) { data[5] |= ( i << 5 ); break; } } return true; @@ -228,9 +228,9 @@ struct File_header struct File_trailer { - uint8_t data[20]; // 0-3 CRC32 of the uncompressed data - // 4-11 size of the uncompressed data - // 12-19 member size including header and trailer + uint8_t data[20]; /* 0-3 CRC32 of the uncompressed data */ + /* 4-11 size of the uncompressed data */ + /* 12-19 member size including header and trailer */ enum { size = 20 }; @@ -372,14 +372,14 @@ void cleanup_and_fail( const int retval ) } - // Set permissions, owner and times. + /* Set permissions, owner and times. */ 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. + /* 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 ) { if( fchmod( outfd, mode ) != 0 ) warning = true; } else @@ -579,19 +579,19 @@ void show_error( const char * const msg, const int errcode, const bool help ) } -void show_error2( const char * const msg1, const char * const name, - const char * const msg2 ) +void internal_error( const char * const msg ) { if( verbosity >= 0 ) - std::fprintf( stderr, "%s: %s '%s' %s\n", program_name, msg1, name, msg2 ); + std::fprintf( stderr, "%s: internal error: %s\n", program_name, msg ); + std::exit( 3 ); } -void internal_error( const char * const msg ) +void show_error2( const char * const msg1, const char * const name, + const char * const msg2 ) { if( verbosity >= 0 ) - std::fprintf( stderr, "%s: internal error: %s\n", program_name, msg ); - std::exit( 3 ); + std::fprintf( stderr, "%s: %s '%s' %s\n", program_name, msg1, name, msg2 ); } @@ -642,7 +642,7 @@ int main( const int argc, const char * const argv[] ) for( ; argind < parser.arguments(); ++argind ) { const int code = parser.code( argind ); - if( !code ) break; // no more options + if( !code ) break; /* no more options */ const std::string & arg = parser.argument( argind ); switch( code ) { @@ -670,7 +670,7 @@ int main( const int argc, const char * const argv[] ) parse_pos_value( arg.c_str(), bad_pos, bad_value ); break; default : internal_error( "uncaught option." ); } - } // end process options + } /* end process options */ #if defined(__MSVCRT__) || defined(__OS2__) setmode( STDIN_FILENO, O_BINARY ); @@ -471,7 +471,7 @@ int merge_files( const std::vector< std::string > & filenames, if( verbosity >= 1 && file_index.members() > 1 ) { std::printf( "Merging member %ld of %ld\n", - j + 1, (long)file_index.members() ); + j + 1, file_index.members() ); std::fflush( stdout ); } @@ -77,7 +77,7 @@ int repair_file( const std::string & input_filename, if( verbosity >= 1 ) // damaged member found { std::printf( "Repairing member %ld of %ld (failure pos = %llu)\n", - i + 1, (long)file_index.members(), mpos + failure_pos ); + i + 1, file_index.members(), mpos + failure_pos ); std::fflush( stdout ); } uint8_t * const mbuffer = read_member( infd, mpos, msize ); @@ -173,8 +173,8 @@ int debug_delay( const std::string & input_filename, Block range, const long long msize = file_index.mblock( i ).size(); if( verbosity >= 1 ) // damaged member found { - std::printf( "Finding max delay in member %ld of %ld (member pos = %llu)\n", - i + 1, (long)file_index.members(), mpos ); + std::printf( "Finding max delay in member %ld of %ld (mpos = %llu, msize = %llu)\n", + i + 1, file_index.members(), mpos, msize ); std::fflush( stdout ); } uint8_t * const mbuffer = read_member( infd, mpos, msize ); @@ -253,7 +253,7 @@ int debug_repair( const std::string & input_filename, const long long bad_pos, { if( verbosity >= 0 ) std::printf( "Member %ld of %ld already damaged (failure pos = %llu)\n", - idx + 1, (long)file_index.members(), mpos + failure_pos ); + idx + 1, file_index.members(), mpos + failure_pos ); return 1; } } @@ -275,10 +275,10 @@ int debug_repair( const std::string & input_filename, const long long bad_pos, } if( verbosity >= 1 ) { - std::printf( "Test repairing member %ld of %ld\n" + std::printf( "Test repairing member %ld of %ld (mpos = %llu, msize = %llu)\n" " (damage pos = %llu (0x%02X->0x%02X), failure pos = %llu)\n", - idx + 1, (long)file_index.members(), mpos + bad_pos, - good_value, bad_value, mpos + failure_pos ); + idx + 1, file_index.members(), mpos, msize, + mpos + bad_pos, good_value, bad_value, mpos + failure_pos ); std::fflush( stdout ); } } |