/* Lziprecover - Data recovery tool for the lzip format 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 the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #define _FILE_OFFSET_BITS 64 #include #include #include #include #include #include #include #include #include #include "lzip.h" #include "block.h" #include "file_index.h" int dump_tdata( const std::vector< std::string > & filenames, const std::string & default_output_filename, const bool force, const bool strip, const bool loose_trailing ) { if( default_output_filename.empty() ) outfd = STDOUT_FILENO; else { output_filename = default_output_filename; if( !open_outstream( force, true, false, false ) ) return 1; } unsigned long long total_size = 0; int files = 0, retval = 0; bool stdin_used = false; for( unsigned i = 0; i < filenames.size(); ++i ) { const bool from_stdin = ( filenames[i] == "-" ); if( from_stdin ) { if( stdin_used ) continue; else stdin_used = true; } const char * const input_filename = from_stdin ? "(stdin)" : filenames[i].c_str(); struct stat in_stats; // not used const int infd = from_stdin ? STDIN_FILENO : open_instream( input_filename, &in_stats, true, true ); if( infd < 0 ) { if( retval < 1 ) retval = 1; continue; } const File_index file_index( infd, false, true, loose_trailing ); if( file_index.retval() != 0 ) { show_file_error( input_filename, file_index.error().c_str() ); if( retval < file_index.retval() ) retval = file_index.retval(); close( infd ); continue; } const unsigned long long cdata_size = file_index.cdata_size(); const long long trailing_size = file_index.file_size() - cdata_size; if( strip ) { total_size += cdata_size; ++files; if( !safe_seek( infd, 0 ) || !copy_file( infd, outfd, cdata_size ) ) cleanup_and_fail( 1 ); } else if( trailing_size > 0 ) { total_size += trailing_size; ++files; if( !safe_seek( infd, cdata_size ) || !copy_file( infd, outfd ) ) cleanup_and_fail( 1 ); } close( infd ); } if( verbosity >= 1 ) { if( strip ) std::fprintf( stderr, "%llu bytes copied from %d file(s).\n", total_size, files ); else std::fprintf( stderr, "%llu trailing bytes dumped from %d file(s).\n", total_size, files ); } if( close_outstream( 0 ) != 0 ) return 1; return retval; } int remove_tdata( const std::vector< std::string > & filenames, const bool loose_trailing ) { unsigned long long total_size = 0; int files = 0, retval = 0; for( unsigned i = 0; i < filenames.size(); ++i ) { const char * const filename = filenames[i].c_str(); struct stat in_stats; const int infd = open_truncable_stream( filename, &in_stats ); if( infd < 0 ) { if( retval < 1 ) retval = 1; continue; } const File_index file_index( infd, false, true, loose_trailing ); if( file_index.retval() != 0 ) { show_file_error( filename, file_index.error().c_str() ); if( retval < file_index.retval() ) retval = file_index.retval(); close( infd ); continue; } const unsigned long long cdata_size = file_index.cdata_size(); const long long trailing_size = file_index.file_size() - cdata_size; if( trailing_size > 0 ) { int i; do i = ftruncate( infd, cdata_size ); while( i != 0 && errno == EINTR ); if( i == 0 ) { struct utimbuf t; t.actime = in_stats.st_atime; t.modtime = in_stats.st_mtime; utime( filename, &t ); total_size += trailing_size; ++files; } else { show_file_error( filename, "Can't truncate file", errno ); if( retval < 1 ) retval = 1; } } close( infd ); } if( verbosity >= 1 ) std::fprintf( stderr, "%llu trailing bytes removed from %d file(s).\n", total_size, files ); return retval; }