diff options
Diffstat (limited to 'merge.cc')
-rw-r--r-- | merge.cc | 77 |
1 files changed, 40 insertions, 37 deletions
@@ -1,5 +1,5 @@ /* Lziprecover - Data recovery tool for lzipped files - Copyright (C) 2009, 2010, 2011, 2012 Antonio Diaz Diaz. + Copyright (C) 2009, 2010, 2011, 2012, 2013 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 @@ -30,6 +30,7 @@ #include "lzip.h" #include "decoder.h" +#include "file_index.h" namespace { @@ -39,7 +40,7 @@ bool copy_and_diff_file( const std::vector< int > & infd_vector, { const int buffer_size = 65536; std::vector< uint8_t * > buffer_vector( infd_vector.size() ); - for( unsigned int i = 0; i < infd_vector.size(); ++i ) + for( unsigned i = 0; i < infd_vector.size(); ++i ) buffer_vector[i] = new uint8_t[buffer_size]; Block b( 0, 0 ); long long partial_pos = 0; @@ -53,7 +54,7 @@ bool copy_and_diff_file( const std::vector< int > & infd_vector, { show_error( "Error reading input file", errno ); error = true; break; } if( rd > 0 ) { - for( unsigned int i = 1; i < infd_vector.size(); ++i ) + for( unsigned i = 1; i < infd_vector.size(); ++i ) if( readblock( infd_vector[i], buffer_vector[i], rd ) != rd ) { show_error( "Error reading input file", errno ); error = true; break; } @@ -66,7 +67,7 @@ bool copy_and_diff_file( const std::vector< int > & infd_vector, { while( i < rd && b.pos() == 0 ) { - for( unsigned int j = 1; j < infd_vector.size(); ++j ) + for( unsigned j = 1; j < infd_vector.size(); ++j ) if( buffer_vector[0][i] != buffer_vector[j][i] ) { b.pos( partial_pos + i ); break; } // begin block ++i; @@ -74,7 +75,7 @@ bool copy_and_diff_file( const std::vector< int > & infd_vector, while( i < rd && b.pos() > 0 ) { ++equal_bytes; - for( unsigned int j = 1; j < infd_vector.size(); ++j ) + for( unsigned j = 1; j < infd_vector.size(); ++j ) if( buffer_vector[0][i] != buffer_vector[j][i] ) { equal_bytes = 0; break; } if( equal_bytes >= 2 ) // end block @@ -96,18 +97,18 @@ bool copy_and_diff_file( const std::vector< int > & infd_vector, b.size( partial_pos - b.pos() ); block_vector.push_back( b ); } - for( unsigned int i = 0; i < infd_vector.size(); ++i ) + for( unsigned i = 0; i < infd_vector.size(); ++i ) delete[] buffer_vector[i]; return !error; } -int ipow( const unsigned int base, const unsigned int exponent ) +int ipow( const unsigned base, const unsigned exponent ) { - int result = 1; - for( unsigned int i = 0; i < exponent; ++i ) + unsigned result = 1; + for( unsigned i = 0; i < exponent; ++i ) { - if( INT_MAX / base >= (unsigned int)result ) result *= base; + if( INT_MAX / base >= result ) result *= base; else { result = INT_MAX; break; } } return result; @@ -115,14 +116,15 @@ int ipow( const unsigned int base, const unsigned int exponent ) int open_input_files( const std::vector< std::string > & filenames, - std::vector< int > & infd_vector, long long & isize ) + std::vector< int > & infd_vector, long long & isize, + const int verbosity ) { bool identical = false; - for( unsigned int i = 1; i < filenames.size(); ++i ) + for( unsigned i = 1; i < filenames.size(); ++i ) if( filenames[0] == filenames[i] ) { identical = true; break; } if( !identical ) - for( unsigned int i = 0; i < filenames.size(); ++i ) + for( unsigned i = 0; i < filenames.size(); ++i ) { struct stat in_stats; ino_t st_ino0 = 0; @@ -136,7 +138,7 @@ int open_input_files( const std::vector< std::string > & filenames, if( identical ) { show_error( "Two input files are the same." ); return 1; } isize = 0; - for( unsigned int i = 0; i < filenames.size(); ++i ) + for( unsigned i = 0; i < filenames.size(); ++i ) { const long long tmp = lseek( infd_vector[i], 0, SEEK_END ); if( tmp < 0 ) @@ -155,11 +157,11 @@ int open_input_files( const std::vector< std::string > & filenames, { show_error( "Sizes of input files are different." ); return 1; } } - for( unsigned int i = 0; i < filenames.size(); ++i ) - if( !verify_single_member( infd_vector[i], isize ) ) + for( unsigned i = 0; i < filenames.size(); ++i ) + if( !verify_single_member( infd_vector[i], isize, verbosity ) ) return 2; - for( unsigned int i = 0; i < filenames.size(); ++i ) + for( unsigned i = 0; i < filenames.size(); ++i ) { if( lseek( infd_vector[i], 0, SEEK_SET ) < 0 ) { show_error( "Seek error in input file", errno ); return 1; } @@ -189,19 +191,21 @@ void cleanup_and_fail( const std::string & output_filename, } -bool copy_file( const int infd, const int outfd, const long long size ) +// max_size < 0 means no size limit. +bool copy_file( const int infd, const int outfd, const long long max_size ) { - long long rest = size; const int buffer_size = 65536; + // remaining number of bytes to copy + long long rest = ( ( max_size >= 0 ) ? max_size : buffer_size ); uint8_t * const buffer = new uint8_t[buffer_size]; bool error = false; - while( true ) + while( rest > 0 ) { - const int block_size = std::min( (long long)buffer_size, rest ); - if( block_size <= 0 ) break; - const int rd = readblock( infd, buffer, block_size ); - if( rd != block_size && errno ) + const int size = std::min( (long long)buffer_size, rest ); + if( max_size >= 0 ) rest -= size; + const int rd = readblock( infd, buffer, size ); + if( rd != size && errno ) { show_error( "Error reading input file", errno ); error = true; break; } if( rd > 0 ) { @@ -209,24 +213,21 @@ bool copy_file( const int infd, const int outfd, const long long size ) if( wr != rd ) { show_error( "Error writing output file", errno ); error = true; break; } - rest -= rd; } - if( rd < block_size ) break; // EOF + if( rd < size ) break; // EOF } delete[] buffer; return !error; } -bool try_decompress( const int fd, const long long file_size, +bool try_decompress( const int fd, const unsigned long long file_size, long long * failure_posp ) { try { Range_decoder rdec( fd ); File_header header; - rdec.reset_member_position(); - for( int i = 0; i < File_header::size; ++i ) - header.data[i] = rdec.get_byte(); + rdec.read_data( header.data, File_header::size ); if( !rdec.finished() && // End Of File header.verify_magic() && header.version() == 1 && @@ -251,7 +252,7 @@ bool try_decompress( const int fd, const long long file_size, } -bool verify_header( const File_header & header ) +bool verify_header( const File_header & header, const int verbosity ) { if( !header.verify_magic() ) { @@ -274,13 +275,14 @@ bool verify_header( const File_header & header ) } -bool verify_single_member( const int fd, const long long file_size ) +bool verify_single_member( const int fd, const long long file_size, + const int verbosity ) { File_header header; if( lseek( fd, 0, SEEK_SET ) < 0 || readblock( fd, header.data, File_header::size ) != File_header::size ) { show_error( "Error reading member header", errno ); return false; } - if( !verify_header( header ) ) return false; + if( !verify_header( header, verbosity ) ) return false; File_trailer trailer; if( lseek( fd, -File_trailer::size(), SEEK_END ) < 0 || @@ -292,7 +294,7 @@ bool verify_single_member( const int fd, const long long file_size ) if( member_size < file_size && lseek( fd, -member_size, SEEK_END ) > 0 && readblock( fd, header.data, File_header::size ) == File_header::size && - verify_header( header ) ) + verify_header( header, verbosity ) ) show_error( "Input file has more than 1 member. Split it first." ); else show_error( "Member size in input file trailer is corrupt." ); @@ -303,11 +305,12 @@ bool verify_single_member( const int fd, const long long file_size ) int merge_files( const std::vector< std::string > & filenames, - const std::string & output_filename, const bool force ) + const std::string & output_filename, const int verbosity, + const bool force ) { std::vector< int > infd_vector( filenames.size() ); long long isize = 0; - const int retval = open_input_files( filenames, infd_vector, isize ); + const int retval = open_input_files( filenames, infd_vector, isize, verbosity ); if( retval >= 0 ) return retval; const int outfd = open_outstream_rw( output_filename, force ); @@ -353,7 +356,7 @@ int merge_files( const std::vector< std::string > & filenames, std::fflush( stdout ); } int tmp = var; - for( unsigned int i = 0; i < block_vector.size(); ++i ) + for( unsigned i = 0; i < block_vector.size(); ++i ) { const int infd = infd_vector[tmp % filenames.size()]; tmp /= filenames.size(); |