summaryrefslogtreecommitdiffstats
path: root/dump_remove.cc
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2023-06-16 11:13:28 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2023-06-16 11:13:28 +0000
commitbfe1c9e528f1db429020e40e15b2483d1ec32b75 (patch)
tree36aee5c76f09362bad7adc8d4163e902fae81a39 /dump_remove.cc
parentReleasing debian version 1.23-5. (diff)
downloadlziprecover-bfe1c9e528f1db429020e40e15b2483d1ec32b75.tar.xz
lziprecover-bfe1c9e528f1db429020e40e15b2483d1ec32b75.zip
Merging upstream version 1.24~pre1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'dump_remove.cc')
-rw-r--r--dump_remove.cc136
1 files changed, 102 insertions, 34 deletions
diff --git a/dump_remove.cc b/dump_remove.cc
index 37f7f00..92b5e3d 100644
--- a/dump_remove.cc
+++ b/dump_remove.cc
@@ -1,5 +1,5 @@
/* Lziprecover - Data recovery tool for the lzip format
- Copyright (C) 2009-2022 Antonio Diaz Diaz.
+ Copyright (C) 2009-2023 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
@@ -32,14 +32,12 @@
#include "lzip_index.h"
-// If strip is false, dump to outfd members/gaps/tdata in member_list.
-// If strip is true, dump to outfd members/gaps/tdata not in member_list.
+/* If strip is false, dump to outfd members/gaps/tdata in member_list.
+ If strip is true, dump to outfd members/gaps/tdata not in member_list. */
int dump_members( const std::vector< std::string > & filenames,
const std::string & default_output_filename,
- const Member_list & member_list, const bool force,
- bool ignore_errors, bool ignore_trailing,
- const bool loose_trailing, const bool strip,
- const bool to_stdout )
+ const Cl_options & cl_opts, const Member_list & member_list,
+ const bool force, const bool strip, const bool to_stdout )
{
if( to_stdout || default_output_filename.empty() ) outfd = STDOUT_FILENO;
else
@@ -48,14 +46,13 @@ int dump_members( const std::vector< std::string > & filenames,
set_signal_handler();
if( !open_outstream( force, false, false, false ) ) return 1;
}
- if( ( strip || !member_list.tdata || member_list.damaged || member_list.range() ) &&
+ if( ( strip || !member_list.tdata || member_list.damaged ||
+ member_list.empty || member_list.range() ) &&
!check_tty_out() ) return 1; // check tty except for --dump=tdata
unsigned long long copied_size = 0, stripped_size = 0;
unsigned long long copied_tsize = 0, stripped_tsize = 0;
long members = 0, smembers = 0;
int files = 0, tfiles = 0, retval = 0;
- if( member_list.damaged ) ignore_errors = true;
- if( member_list.tdata ) ignore_trailing = true;
bool stdin_used = false;
for( unsigned i = 0; i < filenames.size(); ++i )
{
@@ -68,8 +65,8 @@ int dump_members( const std::vector< std::string > & filenames,
open_instream( input_filename, &in_stats, false, true );
if( infd < 0 ) { set_retval( retval, 1 ); continue; }
- const Lzip_index lzip_index( infd, ignore_trailing, loose_trailing,
- ignore_errors, ignore_errors );
+ const Lzip_index lzip_index( infd, cl_opts, cl_opts.ignore_errors,
+ cl_opts.ignore_errors );
if( lzip_index.retval() != 0 )
{
show_file_error( input_filename, lzip_index.error().c_str() );
@@ -77,7 +74,7 @@ int dump_members( const std::vector< std::string > & filenames,
close( infd );
continue;
}
- if( !safe_seek( infd, 0 ) ) cleanup_and_fail( 1 );
+ if( !safe_seek( infd, 0, input_filename ) ) cleanup_and_fail( 1 );
const long blocks = lzip_index.blocks( false ); // not counting tdata
long long stream_pos = 0; // first pos not yet read from file
long gaps = 0;
@@ -92,7 +89,7 @@ int dump_members( const std::vector< std::string > & filenames,
member_list.includes( j + gaps, blocks );
if( in == !strip )
{
- if( !safe_seek( infd, stream_pos ) ||
+ if( !safe_seek( infd, stream_pos, input_filename ) ||
!copy_file( infd, outfd, mb.pos() - stream_pos ) )
cleanup_and_fail( 1 );
copied_size += mb.pos() - stream_pos; ++members;
@@ -101,14 +98,16 @@ int dump_members( const std::vector< std::string > & filenames,
++gaps;
}
bool in = member_list.includes( j + gaps, blocks ); // member
+ if( !in && member_list.empty && lzip_index.dblock( j ).size() == 0 )
+ in = true;
if( !in && member_list.damaged )
{
- if( !safe_seek( infd, mb.pos() ) ) cleanup_and_fail( 1 );
+ if( !safe_seek( infd, mb.pos(), input_filename ) ) cleanup_and_fail( 1 );
in = ( test_member_from_file( infd, mb.size() ) != 0 ); // damaged
}
if( in == !strip )
{
- if( !safe_seek( infd, mb.pos() ) ||
+ if( !safe_seek( infd, mb.pos(), input_filename ) ||
!copy_file( infd, outfd, mb.size() ) ) cleanup_and_fail( 1 );
copied_size += mb.size(); ++members;
}
@@ -128,7 +127,7 @@ int dump_members( const std::vector< std::string > & filenames,
if( member_list.tdata == !strip && trailing_size > 0 &&
( !strip || i + 1 >= filenames.size() ) ) // strip all but last
{
- if( !safe_seek( infd, cdata_size ) ||
+ if( !safe_seek( infd, cdata_size, input_filename ) ||
!copy_file( infd, outfd, trailing_size ) ) cleanup_and_fail( 1 );
copied_tsize += trailing_size;
}
@@ -140,7 +139,7 @@ int dump_members( const std::vector< std::string > & filenames,
{
if( !strip )
{
- if( member_list.damaged || member_list.range() )
+ if( member_list.damaged || member_list.empty || member_list.range() )
std::fprintf( stderr, "%llu bytes dumped from %ld %s from %d %s.\n",
copied_size,
members, ( members == 1 ) ? "member" : "members",
@@ -150,7 +149,7 @@ int dump_members( const std::vector< std::string > & filenames,
}
else
{
- if( member_list.damaged || member_list.range() )
+ if( member_list.damaged || member_list.empty || member_list.range() )
std::fprintf( stderr, "%llu bytes stripped from %ld %s from %d %s.\n",
stripped_size,
smembers, ( smembers == 1 ) ? "member" : "members",
@@ -164,15 +163,14 @@ int dump_members( const std::vector< std::string > & filenames,
}
+/* Remove members, tdata from files in place by opening two descriptors for
+ each file. */
int remove_members( const std::vector< std::string > & filenames,
- const Member_list & member_list, bool ignore_errors,
- bool ignore_trailing, const bool loose_trailing )
+ const Cl_options & cl_opts, const Member_list & member_list )
{
unsigned long long removed_size = 0, removed_tsize = 0;
long members = 0;
int files = 0, tfiles = 0, retval = 0;
- if( member_list.damaged ) ignore_errors = true;
- if( member_list.tdata ) ignore_trailing = true;
for( unsigned i = 0; i < filenames.size(); ++i )
{
const char * const filename = filenames[i].c_str();
@@ -180,8 +178,8 @@ int remove_members( const std::vector< std::string > & filenames,
const int infd = open_instream( filename, &in_stats, false, true );
if( infd < 0 ) { set_retval( retval, 1 ); continue; }
- const Lzip_index lzip_index( infd, ignore_trailing, loose_trailing,
- ignore_errors, ignore_errors );
+ const Lzip_index lzip_index( infd, cl_opts, cl_opts.ignore_errors,
+ cl_opts.ignore_errors );
if( lzip_index.retval() != 0 )
{
show_file_error( filename, lzip_index.error().c_str() );
@@ -192,7 +190,7 @@ int remove_members( const std::vector< std::string > & filenames,
const int fd = open_truncable_stream( filename, &dummy_stats );
if( fd < 0 ) { close( infd ); set_retval( retval, 1 ); continue; }
- if( !safe_seek( infd, 0 ) ) return 1;
+ if( !safe_seek( infd, 0, filename ) ) return 1;
const long blocks = lzip_index.blocks( false ); // not counting tdata
long long stream_pos = 0; // first pos not yet written to file
long gaps = 0;
@@ -207,8 +205,8 @@ int remove_members( const std::vector< std::string > & filenames,
if( !member_list.damaged && !member_list.includes( j + gaps, blocks ) )
{
if( stream_pos != prev_end &&
- ( !safe_seek( infd, prev_end ) ||
- !safe_seek( fd, stream_pos ) ||
+ ( !safe_seek( infd, prev_end, filename ) ||
+ !safe_seek( fd, stream_pos, filename ) ||
!copy_file( infd, fd, mb.pos() - prev_end ) ) )
{ error = true; set_retval( retval, 1 ); break; }
stream_pos += mb.pos() - prev_end;
@@ -217,17 +215,19 @@ int remove_members( const std::vector< std::string > & filenames,
++gaps;
}
bool in = member_list.includes( j + gaps, blocks ); // member
+ if( !in && member_list.empty && lzip_index.dblock( j ).size() == 0 )
+ in = true;
if( !in && member_list.damaged )
{
- if( !safe_seek( infd, mb.pos() ) )
+ if( !safe_seek( infd, mb.pos(), filename ) )
{ error = true; set_retval( retval, 1 ); break; }
in = ( test_member_from_file( infd, mb.size() ) != 0 ); // damaged
}
if( !in )
{
if( stream_pos != mb.pos() &&
- ( !safe_seek( infd, mb.pos() ) ||
- !safe_seek( fd, stream_pos ) ||
+ ( !safe_seek( infd, mb.pos(), filename ) ||
+ !safe_seek( fd, stream_pos, filename ) ||
!copy_file( infd, fd, mb.size() ) ) )
{ error = true; set_retval( retval, 1 ); break; }
stream_pos += mb.size();
@@ -249,8 +249,8 @@ int remove_members( const std::vector< std::string > & filenames,
if( !member_list.tdata ) // copy trailing data
{
if( stream_pos != cdata_size &&
- ( !safe_seek( infd, cdata_size ) ||
- !safe_seek( fd, stream_pos ) ||
+ ( !safe_seek( infd, cdata_size, filename ) ||
+ !safe_seek( fd, stream_pos, filename ) ||
!copy_file( infd, fd, trailing_size ) ) )
{ close( fd ); close( infd ); set_retval( retval, 1 ); break; }
stream_pos += trailing_size;
@@ -279,7 +279,7 @@ int remove_members( const std::vector< std::string > & filenames,
}
if( verbosity >= 1 )
{
- if( member_list.damaged || member_list.range() )
+ if( member_list.damaged || member_list.empty || member_list.range() )
std::fprintf( stderr, "%llu bytes removed from %ld %s from %d %s.\n",
removed_size,
members, ( members == 1 ) ? "member" : "members",
@@ -290,3 +290,71 @@ int remove_members( const std::vector< std::string > & filenames,
}
return retval;
}
+
+
+/* Set to zero in place the first LZMA byte of each member in each file by
+ opening one rw descriptor for each file. */
+int clear_marking( const std::vector< std::string > & filenames,
+ const Cl_options & cl_opts )
+ {
+ long cleared_members = 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 fd = open_truncable_stream( filename, &in_stats );
+ if( fd < 0 ) { set_retval( retval, 1 ); continue; }
+
+ const Lzip_index lzip_index( fd, cl_opts, cl_opts.ignore_errors,
+ cl_opts.ignore_errors );
+ if( lzip_index.retval() != 0 )
+ {
+ show_file_error( filename, lzip_index.error().c_str() );
+ set_retval( retval, lzip_index.retval() );
+ close( fd );
+ continue;
+ }
+
+ enum { bufsize = Lzip_header::size + 1 };
+ uint8_t header_buf[bufsize];
+ const uint8_t * const p = header_buf; // keep gcc 6.1.0 quiet
+ const Lzip_header & header = *(const Lzip_header *)p;
+ uint8_t * const mark = header_buf + Lzip_header::size;
+ bool write_attempted = false;
+ for( long j = 0; j < lzip_index.members(); ++j ) // clear the members
+ {
+ const Block & mb = lzip_index.mblock( j );
+ if( seek_read( fd, header_buf, bufsize, mb.pos() ) != bufsize )
+ { show_file_error( filename, "Error reading member header", errno );
+ set_retval( retval, 1 ); break; }
+ if( !header.check( cl_opts.ignore_errors ) )
+ { show_file_error( filename, "Member header became corrupt as we read it." );
+ set_retval( retval, 2 ); break; }
+ if( *mark == 0 ) continue;
+ *mark = 0; write_attempted = true;
+ if( seek_write( fd, mark, 1, mb.pos() + Lzip_header::size ) != 1 )
+ { show_file_error( filename, "Error writing to file", errno );
+ set_retval( retval, 1 ); break; }
+ ++cleared_members;
+ }
+ if( close( fd ) != 0 )
+ {
+ show_file_error( filename, "Error closing file", errno );
+ set_retval( retval, 1 ); break;
+ }
+ if( write_attempted )
+ {
+ struct utimbuf t;
+ t.actime = in_stats.st_atime;
+ t.modtime = in_stats.st_mtime;
+ utime( filename, &t );
+ ++files;
+ }
+ }
+ if( verbosity >= 1 )
+ std::fprintf( stderr, "%lu %s cleared in %d %s.\n", cleared_members,
+ ( cleared_members == 1 ) ? "member" : "members",
+ files, ( files == 1 ) ? "file" : "files" );
+ return retval;
+ }