diff options
Diffstat (limited to '')
-rw-r--r-- | trailing_data.cc | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/trailing_data.cc b/trailing_data.cc new file mode 100644 index 0000000..e03b145 --- /dev/null +++ b/trailing_data.cc @@ -0,0 +1,144 @@ +/* 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 <http://www.gnu.org/licenses/>. +*/ + +#define _FILE_OFFSET_BITS 64 + +#include <cerrno> +#include <cstdio> +#include <cstring> +#include <string> +#include <vector> +#include <stdint.h> +#include <unistd.h> +#include <utime.h> +#include <sys/stat.h> + +#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; + } |