Hi,

here comes another patch (0003-*.patch). With it, ddrescue -E 1 aborts
after one additional error occurred.

My problem is that my hard drive stops responding after certain sectors
are accessed, causing ddrescue to mark all following sectors as bad. I
used this parameter to run ddrescue in a loop, examining kernel messages
after each invokation to know when a power cycle is required to make the
drive respond again.

This is useful when ddrescue runs for the first time. However, when
splitting, ddrescue apparently doesn't increase the error counter.

Because of that, I created another patch to exit on fatal errors, which
however depends on two things:

1. ddrescue runs on Linux
2. The input file is a hard drive (possibly limited to ATA drives)

Therefore I don't recommend to apply this second patch (0004-*.patch) as
is. You could, maybe, add an option to enable this feature on demand.

Regards,
Andreas
>From 450aaeda98a3e37c50d2a8e3b12330bbea2a86ac Mon Sep 17 00:00:00 2001
From: Andreas Oberritter <[email protected]>
Date: Mon, 11 Oct 2010 03:54:08 +0200
Subject: [PATCH 3/4] Add new command-line option -E to specifiy maximum amount of new errors

---
 ddrescue.h     |    8 ++++----
 doc/ddrescue.1 |    7 +++++--
 main.cc        |   22 ++++++++++++++--------
 rescuebook.cc  |    5 +++--
 4 files changed, 26 insertions(+), 16 deletions(-)

diff --git a/ddrescue.h b/ddrescue.h
index 6fb3cd7..13793e2 100644
--- a/ddrescue.h
+++ b/ddrescue.h
@@ -125,9 +125,9 @@ class Rescuebook : public Logbook
   long long sparse_size;		// end position of pending writes
   long long recsize, errsize;		// total recovered and error sizes
   const char * const iname_;
-  int errors;				// error areas found so far
+  int errors, old_errors;		// error areas found so far
   int ides_, odes_;			// input and output file descriptors
-  const int max_errors_, max_retries_, skipbs_;
+  const int max_errors_, max_new_errors_, max_retries_, skipbs_;
   const bool nosplit_, sparse_, synchronous_;
 					// variables for show_status
   long long a_rate, c_rate, first_size, last_size;
@@ -142,7 +142,7 @@ class Rescuebook : public Logbook
   int check_all();
   void count_errors() throw();
   bool too_many_errors() const throw()
-    { return ( max_errors_ >= 0 && errors > max_errors_ ); }
+    { return ( max_errors_ >= 0 && errors > max_errors_ ) || ( max_new_errors_ >= 0 && errors - old_errors >= max_new_errors_ ); }
   int copy_and_update( const Block & b, const Sblock::Status st,
                        int & copied_size, int & error_size,
                        const char * const msg, bool & first_post );
@@ -156,7 +156,7 @@ public:
   Rescuebook( const long long ipos, const long long opos,
               Domain & dom, const long long isize, const char * const iname,
               const char * const logname, const int cluster, const int hardbs,
-              const int max_errors = -1, const int max_retries = 0,
+              const int max_errors = -1, const int max_new_errors = -1, const int max_retries = 0,
               const bool complete_only = false, const bool nosplit = false,
               const bool retrim = false, const bool sparse = false,
               const bool synchronous = false, const bool try_again = false );
diff --git a/doc/ddrescue.1 b/doc/ddrescue.1
index f74e6f0..f87642c 100644
--- a/doc/ddrescue.1
+++ b/doc/ddrescue.1
@@ -1,5 +1,5 @@
 .\" DO NOT MODIFY THIS FILE!  It was generated by help2man 1.37.1.
-.TH DDRESCUE "1" "August 2010" "ddrescue 1.13" "User Commands"
+.TH DDRESCUE "1" "October 2010" "ddrescue 1.13" "User Commands"
 .SH NAME
 ddrescue \- data recovery tool
 .SH SYNOPSIS
@@ -38,7 +38,10 @@ use direct disc access for input file
 use synchronous writes for output file
 .TP
 \fB\-e\fR, \fB\-\-max\-errors=\fR<n>
-maximum number of error areas allowed
+maximum number of total error areas allowed
+.TP
+\fB\-E\fR, \fB\-\-max\-new\-errors=\fR<n>
+maximum number of additional error areas allowed
 .TP
 \fB\-f\fR, \fB\-\-force\fR
 overwrite output device or partition
diff --git a/main.cc b/main.cc
index 9129e6f..845bdc8 100644
--- a/main.cc
+++ b/main.cc
@@ -73,7 +73,8 @@ void show_help( const int cluster, const int hardbs ) throw()
   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( "  -D, --synchronous             use synchronous writes for output file\n" );
-  std::printf( "  -e, --max-errors=<n>          maximum number of error areas allowed\n" );
+  std::printf( "  -e, --max-errors=<n>          maximum number of total error areas allowed\n" );
+  std::printf( "  -E, --max-new-errors=<n>      maximum number of additional error areas allowed\n" );
   std::printf( "  -f, --force                   overwrite output device or partition\n" );
   std::printf( "  -F, --fill=<types>            fill given type blocks with infile data (?*/-+)\n" );
   std::printf( "  -g, --generate-logfile        generate approximate logfile from partial copy\n" );
@@ -318,7 +319,7 @@ int do_generate( const long long ipos, const long long opos, Domain & domain,
 int do_rescue( const long long ipos, const long long opos, Domain & domain,
                const char *iname, const char *oname, const char *logname,
                const int cluster, const int hardbs,
-               const int max_errors, const int max_retries,
+               const int max_errors, const int max_new_errors, const int max_retries,
                const int o_direct, const int o_trunc,
                const bool complete_only, const bool nosplit,
                const bool preallocate, const bool retrim, const bool sparse,
@@ -332,7 +333,7 @@ int do_rescue( const long long ipos, const long long opos, Domain & domain,
     { show_error( "Input file is not seekable." ); return 1; }
 
   Rescuebook rescuebook( ipos, opos, domain, isize, iname, logname, cluster,
-                         hardbs, max_errors, max_retries, complete_only,
+                         hardbs, max_errors, max_new_errors, max_retries, complete_only,
                          nosplit, retrim, sparse, synchronous, try_again );
   if( rescuebook.domain().in_size() == 0 )
     { show_error( "Nothing to do." ); return 0; }
@@ -375,6 +376,8 @@ int do_rescue( const long long ipos, const long long opos, Domain & domain,
     bool nl = false;
     if( max_errors >= 0 )
       { nl = true; std::printf( "Max_errors: %d    ", max_errors ); }
+    if( max_new_errors >= 0 )
+      { nl = true; std::printf( "Max_new_errors: %d    ", max_new_errors ); }
     if( max_retries >= 0 )
       { nl = true; std::printf( "Max_retries: %d    ", max_retries ); }
     if( nl ) std::printf( "\n" );
@@ -438,6 +441,7 @@ int main( const int argc, const char * const argv[] )
   int cluster = 0;
   int hardbs = 512;
   int max_errors = -1;
+  int max_new_errors = -1;
   int max_retries = 0;
   int o_direct = 0;
   int o_trunc = 0;
@@ -465,6 +469,7 @@ int main( const int argc, const char * const argv[] )
     { 'd', "direct",           Arg_parser::no  },
     { 'D', "synchronous",      Arg_parser::no  },
     { 'e', "max-errors",       Arg_parser::yes },
+    { 'E', "max-new-errors",   Arg_parser::yes },
     { 'f', "force",            Arg_parser::no  },
     { 'F', "fill",             Arg_parser::yes },
     { 'g', "generate-logfile", Arg_parser::no  },
@@ -510,6 +515,7 @@ int main( const int argc, const char * const argv[] )
                 break;
       case 'D': synchronous = true; break;
       case 'e': max_errors = getnum( arg, 0, -1, INT_MAX ); break;
+      case 'E': max_new_errors = getnum( arg, 0, -1, INT_MAX ); break;
       case 'f': force = true; break;
       case 'F': filltypes = arg; check_fill_types( filltypes ); break;
       case 'g': generate = true; break;
@@ -554,11 +560,11 @@ int main( const int argc, const char * const argv[] )
 
   if( filltypes.size() )
     {
-    if( max_errors >= 0 || max_retries || o_direct || o_trunc ||
+    if( max_errors >= 0 || max_new_errors >= 0 || max_retries || o_direct || o_trunc ||
         complete_only || generate || nosplit || preallocate || retrim ||
         sparse || synchronous || try_again )
       {
-      show_error( "warning: Options -C -d -D -e -g -n -p -r -R -S -t and -T" );
+      show_error( "warning: Options -C -d -D -e -E -g -n -p -r -R -S -t and -T" );
       show_error( "are ignored in fill mode." );
       }
 
@@ -567,11 +573,11 @@ int main( const int argc, const char * const argv[] )
     }
   if( generate )
     {
-    if( max_errors >= 0 || max_retries || o_direct || o_trunc ||
+    if( max_errors >= 0 || max_new_errors >= 0 || max_retries || o_direct || o_trunc ||
         complete_only || nosplit || preallocate || retrim ||
         sparse || synchronous || try_again )
       {
-      show_error( "warning: Options -C -d -D -e -n -p -r -R -S -t and -T" );
+      show_error( "warning: Options -C -d -D -e -E -n -p -r -R -S -t and -T" );
       show_error( "are ignored in generate-logfile mode." );
       }
 
@@ -579,7 +585,7 @@ int main( const int argc, const char * const argv[] )
                         cluster, hardbs );
     }
   return do_rescue( ipos, opos, domain, iname, oname, logname, cluster,
-                    hardbs, max_errors, max_retries, o_direct, o_trunc,
+                    hardbs, max_errors, max_new_errors, max_retries, o_direct, o_trunc,
                     complete_only, nosplit, preallocate, retrim, sparse,
                     synchronous, try_again );
   }
diff --git a/rescuebook.cc b/rescuebook.cc
index bdd8d43..b54fa40 100644
--- a/rescuebook.cc
+++ b/rescuebook.cc
@@ -289,14 +289,14 @@ int Rescuebook::copy_errors()
 Rescuebook::Rescuebook( const long long ipos, const long long opos,
                         Domain & dom, const long long isize, const char * const iname,
                         const char * const logname, const int cluster, const int hardbs,
-                        const int max_errors, const int max_retries,
+                        const int max_errors, const int max_new_errors, const int max_retries,
                         const bool complete_only, const bool nosplit,
                         const bool retrim, const bool sparse,
                         const bool synchronous, const bool try_again )
   : Logbook( ipos, opos, dom, isize, logname, cluster, hardbs, complete_only ),
     sparse_size( 0 ),
     iname_( ( iname && access( iname, F_OK ) == 0 ) ? iname : 0 ),
-    max_errors_( max_errors ), max_retries_( max_retries ),
+    max_errors_( max_errors ), max_new_errors_( max_new_errors ), max_retries_( max_retries ),
     skipbs_( std::max( 65536, hardbs ) ),
     nosplit_( nosplit ), sparse_( sparse ), synchronous_( synchronous ),
     a_rate( 0 ), c_rate( 0 ), first_size( 0 ), last_size( 0 ),
@@ -404,6 +404,7 @@ int Rescuebook::do_rescue( const int ides, const int odes )
     }
   count_errors();
   set_signals();
+  old_errors = errors;
   if( verbosity >= 0 )
     {
     std::printf( "Press Ctrl-C to interrupt\n" );
-- 
1.7.0.4

>From f3e1018d306f607676e6695ea8864b77bbddcb58 Mon Sep 17 00:00:00 2001
From: Andreas Oberritter <[email protected]>
Date: Tue, 12 Oct 2010 00:42:59 +0200
Subject: [PATCH 4/4] linux: fail if drive does not respond to identify command

---
 rescuebook.cc |   20 ++++++++++++++++++++
 1 files changed, 20 insertions(+), 0 deletions(-)

diff --git a/rescuebook.cc b/rescuebook.cc
index b54fa40..0774f6f 100644
--- a/rescuebook.cc
+++ b/rescuebook.cc
@@ -29,6 +29,10 @@
 #include "block.h"
 #include "ddrescue.h"
 
+#if defined(__linux__)
+#include <sys/ioctl.h>
+#include <linux/hdreg.h>
+#endif
 
 // Return values: 0 OK, -1 interrupted, -2 logfile error.
 //
@@ -118,6 +122,22 @@ int Rescuebook::copy_and_update( const Block & b, const Sblock::Status st,
         final_msg( "input file disappeared" ); final_errno( errno );
         retval = 1;
         }
+#if defined(__linux__)
+      else
+        {
+        unsigned char args[4 + 512];
+        args[0] = 0xec; // COMMAND
+        args[1] = 0;    // SECTOR
+        args[2] = 0;    // FEATURE
+        args[3] = 1;    // NSECTOR
+        memset(&args[4], 0, 512);
+        if(ioctl(ides_, HDIO_DRIVE_CMD, args) < 0)
+          {
+          final_msg( "input drive does not identify" ); final_errno( errno );
+          retval = 1;
+          }
+        }
+#endif
       }
     }
   return retval;
-- 
1.7.0.4

_______________________________________________
Bug-ddrescue mailing list
[email protected]
http://lists.gnu.org/mailman/listinfo/bug-ddrescue

Reply via email to