[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Bug-ddrescue] patch to fill error areas with specific data (--fill, --
From: |
Christian Franke |
Subject: |
[Bug-ddrescue] patch to fill error areas with specific data (--fill, --fill-from) |
Date: |
Sat, 02 Jun 2007 22:50:16 +0200 |
User-agent: |
Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.2pre) Gecko/20070111 SeaMonkey/1.1 |
Hi,
the attached patch adds a feature I recently missed when I recovered a
damaged DVD with ddrescue:
-f, --fill="STRING" -- Fills error areas with "STRING" instead of nulls.
-F, --fill-from=FILE -- Same, but data is read from FILE.
The fill data is repeated up to the size of the error area.
Data sizes greater than the block size (-b) are silently ignored.
On a failed read retry, the (possibly changed) fill data is rewritten.
Example:
$ ddrescue -f "BAD BLOCK " ...
fills the error areas with "BAD BLOCK BAD BLOCK BAD BLOCK ..."
This allows to find the bad blocks e.g. when the image is examined in a
hex editor.
Thanks for any comment
Christian
diff -rup ddrescue-1.4-rc1.orig/ddrescue.cc ddrescue-1.4-rc1/ddrescue.cc
--- ddrescue-1.4-rc1.orig/ddrescue.cc 2007-06-01 00:31:44.000000000 +0200
+++ ddrescue-1.4-rc1/ddrescue.cc 2007-06-02 21:52:35.046875000 +0200
@@ -76,6 +76,20 @@ int writeblock( const int fd, const char
return ( rest > 0 ) ? size - rest : size;
}
+
+int writebadblock( const int fd, char * buf, const int size, const long long
pos,
+ const char * fill_data, const int fill_size ) throw()
+ {
+ int rest = size;
+ while( rest > 0 )
+ {
+ int n = ( rest <= fill_size ? rest : fill_size );
+ memcpy( buf + size - rest, fill_data, n );
+ rest -= n;
+ }
+ return writeblock( fd, buf, size, pos );
+ }
+
} // end namespace
@@ -119,6 +133,11 @@ int Logbook::copy_non_tried_block( const
result.push_back( Sblock( b, Sblock::bad_cluster ) );
else result.push_back( Sblock( b, Sblock::bad_block ) );
errsize += size - rd;
+ if (_fill_data)
+ {
+ if( writebadblock( _odes, iobuf, size - rd, block.pos() + rd,
_fill_data, _fill_size ) != size - rd )
+ { show_error( "write error", errno ); return 1; }
+ }
}
}
return 0;
@@ -153,7 +172,14 @@ int Logbook::copy_bad_block( const Block
{
if( !errno1 ) { errsize -= size - rd; return -2; } // EOF
else // read_error
+ {
result.push_back( Sblock( block.pos()+rd, size-rd, Sblock::bad_block ) );
+ if (_fill_data)
+ {
+ if( writebadblock( _odes, iobuf, size - rd, block.pos() + rd,
_fill_data, _fill_size ) != size - rd )
+ { show_error( "write error", errno ); return 1; }
+ }
+ }
}
return 0;
}
diff -rup ddrescue-1.4-rc1.orig/ddrescue.h ddrescue-1.4-rc1/ddrescue.h
--- ddrescue-1.4-rc1.orig/ddrescue.h 2007-06-01 00:07:06.000000000 +0200
+++ ddrescue-1.4-rc1/ddrescue.h 2007-06-02 21:11:35.531250000 +0200
@@ -78,6 +78,8 @@ class Logbook
int errors; // errors found so far
int _ides, _odes; // input and output file descriptors
const bool _nosplit;
+ const char *_fill_data; // optional error area fill data
+ int _fill_size;
std::vector< Sblock > sblock_vector; // note: blocks are consecutive
void set_rescue_domain( const long long ipos, const long long opos,
@@ -95,8 +97,9 @@ public:
const long long max_size, const long long isize,
const char * name, const int cluster, const int hardbs,
const int max_errors, const int max_retries, const int verbosity,
- const bool complete_only, const bool nosplit ) throw();
- ~Logbook() throw() { delete[] iobuf_base; }
+ const bool complete_only, const bool nosplit,
+ const char * fill_data, int fill_size ) throw();
+ ~Logbook() throw() { delete[] iobuf_base; delete[] _fill_data; }
long long rescue_ipos() const throw() { return _domain.pos(); }
long long rescue_opos() const throw() { return _domain.pos() + _offset; }
diff -rup ddrescue-1.4-rc1.orig/logbook.cc ddrescue-1.4-rc1/logbook.cc
--- ddrescue-1.4-rc1.orig/logbook.cc 2007-06-01 00:57:20.000000000 +0200
+++ ddrescue-1.4-rc1/logbook.cc 2007-06-02 21:29:00.515625000 +0200
@@ -471,10 +471,12 @@ Logbook::Logbook( const long long ipos,
const long long max_size, const long long isize,
const char * name, const int cluster, const int hardbs,
const int max_errors, const int max_retries, const int
verbosity,
- const bool complete_only, const bool nosplit ) throw()
+ const bool complete_only, const bool nosplit,
+ const char * fill_data, int fill_size ) throw()
: filename( name ), _hardbs( hardbs ), _softbs( cluster * hardbs ),
_max_errors( max_errors ), _max_retries( max_retries ),
- _verbosity( verbosity ), _nosplit( nosplit )
+ _verbosity( verbosity ), _nosplit( nosplit ),
+ _fill_data(fill_data), _fill_size(fill_size)
{
int alignment = sysconf( _SC_PAGESIZE );
if( alignment < _hardbs || alignment % _hardbs ) alignment = _hardbs;
diff -rup ddrescue-1.4-rc1.orig/main.cc ddrescue-1.4-rc1/main.cc
--- ddrescue-1.4-rc1.orig/main.cc 2007-05-31 17:15:56.000000000 +0200
+++ ddrescue-1.4-rc1/main.cc 2007-06-02 21:30:49.500000000 +0200
@@ -62,6 +62,8 @@ void show_help( const int cluster, const
std::printf( " -C, --complete-only do not read new data beyond
logfile limits\n" );
std::printf( " -d, --direct use direct disc access for
input file\n" );
std::printf( " -e, --max-errors=<n> maximum number of error areas
allowed\n" );
+ std::printf( " -f, --fill=<string> fill error areas with string
['\\0']\n" );
+ std::printf( " -F, --fill-from=<file> fill error areas from a file\n"
);
std::printf( " -i, --input-position=<pos> starting position in input file
[0]\n" );
std::printf( " -n, --no-split do not try to split error
areas\n" );
std::printf( " -o, --output-position=<pos> starting position in output
file [ipos]\n" );
@@ -183,6 +185,7 @@ int main( const int argc, const char * a
int max_errors = -1, max_retries = 0;
int o_direct = 0, o_trunc = 0, verbosity = 0;
bool complete_only = false, nosplit = false;
+ const char * fill_string = 0, * fill_file = 0;
invocation_name = argv[0];
const Arg_parser::Option options[] =
@@ -193,6 +196,8 @@ int main( const int argc, const char * a
{ 'C', "complete-only", Arg_parser::no },
{ 'd', "direct", Arg_parser::no },
{ 'e', "max-errors", Arg_parser::yes },
+ { 'f', "fill", Arg_parser::yes },
+ { 'F', "fill-from", Arg_parser::yes },
{ 'h', "help", Arg_parser::no },
{ 'i', "input-position", Arg_parser::yes },
{ 'n', "no-split", Arg_parser::no },
@@ -229,6 +234,8 @@ int main( const int argc, const char * a
{ show_error( "direct disc access not available" ); return
1; }
break;
case 'e': max_errors = getnum( arg, 0, -1, INT_MAX ); break;
+ case 'f': fill_string = arg; break;
+ case 'F': fill_file = arg; break;
case 'h': show_help( cluster_bytes / default_hardbs, default_hardbs );
return 0;
case 'i': ipos = getnum( arg, hardbs, 0 ); break;
case 'n': nosplit = true; break;
@@ -262,13 +269,33 @@ int main( const int argc, const char * a
if( check_identical ( iname, oname ) )
{ show_error( "infile and outfile are identical" ); return 1; }
+ char * fill_data = 0; int fill_size = 0;
+ if( fill_string && *fill_string )
+ {
+ fill_size = strlen(fill_string);
+ if (fill_size > hardbs) fill_size = hardbs;
+ fill_data = new char[fill_size];
+ memcpy( fill_data, fill_string, fill_size );
+ }
+ else if (fill_file)
+ {
+ int fd = open( fill_file, O_RDONLY );
+ if( fd < 0 ) { show_error( "cannot open fill data file", errno ); return
1; }
+ fill_data = new char[hardbs];
+ fill_size = read( fd, fill_data, hardbs );
+ if (fill_size < 0) show_error( "read error on fill data file", errno );
+ close (fd);
+ if (fill_size < 0) return 1;
+ }
+
const int ides = open( iname, O_RDONLY | o_direct );
if( ides < 0 ) { show_error( "cannot open input file", errno ); return 1; }
const long long isize = lseek( ides, 0, SEEK_END );
if( isize < 0 ) { show_error( "input file is not seekable" ); return 1; }
Logbook logbook( ipos, opos, max_size, isize, logname, cluster, hardbs,
- max_errors, max_retries, verbosity, complete_only, nosplit
);
+ max_errors, max_retries, verbosity, complete_only, nosplit,
+ fill_data, fill_size );
if( logbook.rescue_size() == 0 )
{ if( verbosity >= 0 ) { show_error( "Nothing to do" ); } return 0; }
if( o_trunc && !logbook.blank() )
- [Bug-ddrescue] patch to fill error areas with specific data (--fill, --fill-from),
Christian Franke <=
- Re: [Bug-ddrescue] patch to fill error areas with specific data (--fill, --fill-from), Antonio Diaz Diaz, 2007/06/04
- Re: [Bug-ddrescue] patch to fill error areas with specific data (--fill, --fill-from), Christian Franke, 2007/06/04
- Re: [Bug-ddrescue] patch to fill error areas with specific data (--fill, --fill-from), Antonio Diaz Diaz, 2007/06/04
- Re: [Bug-ddrescue] patch to fill error areas with specific data (--fill, --fill-from), Christian Franke, 2007/06/04
- Re: [Bug-ddrescue] patch to fill error areas with specific data (--fill, --fill-from), Christian Franke, 2007/06/05
- Re: [Bug-ddrescue] patch to fill error areas with specific data (--fill, --fill-from), Antonio Diaz Diaz, 2007/06/08