diff -Naur ddrescue-1.17-rc4.orig/debug_print.cc ddrescue-1.17-rc4/debug_print.cc --- ddrescue-1.17-rc4.orig/debug_print.cc 1970-01-01 07:00:00.000000000 +0700 +++ ddrescue-1.17-rc4/debug_print.cc 2013-06-29 21:20:31.604099000 +0700 @@ -0,0 +1,73 @@ +/*** + * Debug printf library for C++ + * + * Author: Alexander Sashnov + * License: Boost Software License + */ +#include +#include +#include +#include +#include + +#include "debug_print.h" + + +int DebugFuncEntry::level = 0; + +static const int LOG_LINES_MAXIMUM = 10000; + +void debug_printf(const char *fmt, ...) +{ + va_list args; + + static char *debug_log_filename = getenv("DEBUG_OUTPUT_FILENAME"); + static FILE *fp = NULL; + static int n = 0; + static bool failed = false; + static time_t start_time = time(NULL); + + if (! debug_log_filename) + return; + + if (failed || n > LOG_LINES_MAXIMUM) + return; + + if (!fp) { + fp = fopen(debug_log_filename, "w"); + if (!fp) { + fprintf(stderr, "Unable to create %s: %s\n", debug_log_filename, strerror(errno)); + failed = true; + return; + } + setbuf(fp, NULL); + + fprintf(fp, "This is output from calls of 'debug_printf' function.\n" + "Every time the programm starts it creates new file (output for previous run will be lost)\n" + "\n" + " \n\n"); + } + + time_t cur_time = time(NULL); + + double diff = difftime(cur_time, start_time); + + (void) fprintf (fp, "%5.0f Debug: ", diff); + va_start (args, fmt); + (void) vfprintf (fp, fmt, args); + va_end (args); + + // Put EOL char if it is not into the format string + int i = strlen(fmt); + if (i > 0 && fmt[i-1] != '\n') + fprintf(fp, "\n"); + + // Hint: you can set debugger's breakpoint here: + if (n == 15) { + ; + } + + if (n++ == LOG_LINES_MAXIMUM) { + fprintf(fp, "That's it: maximum number of lines allowed for logging was reached."); + } +} diff -Naur ddrescue-1.17-rc4.orig/debug_print.h ddrescue-1.17-rc4/debug_print.h --- ddrescue-1.17-rc4.orig/debug_print.h 1970-01-01 07:00:00.000000000 +0700 +++ ddrescue-1.17-rc4/debug_print.h 2013-06-29 21:18:18.624102000 +0700 @@ -0,0 +1,119 @@ +/*** + * Debug printf library for C++ + * + * Author: Alexander Sashnov + * License: Boost Software License + */ +#include +#include + +/* + * For using debug log just start your programm with + * DEBUG_OUTPUT_FILENAME environment variable with + * filename to create. + * + * + * Example for using the following macros: + * + * void f(int n) + * { + * DEBUG_FUNC_ENTRY + * + * ... + * + * if (n > 7) + * { + * DEBUG_FUNC_STACKFRAME("n great than 7") + * ... + * + * } + * + * ... + * + * DEBUG_LOG("function bottom, n=%d", n) + * + * ... + * } + * + * + */ + + +#define DEBUG_FUNC_ENTRY DebugFuncEntry debug_func_obj(__FUNCTION__); + +#define DEBUG_FUNC_STACKFRAME(caption) DebugFuctStackFrame debug_func_inner(debug_func_obj, caption) + +#define DEBUG_LOG(fmt, args...) debug_printf("%s:%d:%s(): " fmt "\n", __FILE__, __LINE__, __FUNCTION__, ## args) + + +/*! + * \brief printf-arguments function for print into debug log file. + * \param fmt + */ +extern void debug_printf(const char *fmt, ...); + +/*! + * \brief Print to log function entry and exit records. + * + */ +struct DebugFuncEntry { + static int level; + const char *func; + DebugFuncEntry(const char *f) :func(f) { + level++; + debug_printf("[%d] ---> %s()\n", level, func); + } + ~DebugFuncEntry() { + debug_printf("[%d] <--- %s()\n", level, func); + level--; + } + void enter(const char *caption) { + level++; + debug_printf("[%d] ---> %s() %s\n", level, func, caption); + } + void exit(const char *caption) { + debug_printf("[%d] <--- %s() %s\n", level, func, caption); + level--; + } +}; + + +/*! + * \brief Object life-time logger. + * + * Derive your object from that class + * and you will get creation and delete object records. + */ +class DebugObjCreation { + DebugObjCreation() { + total++; + debug_printf("[create %d] Object created %p\n", total, this); + } + ~DebugObjCreation() { + debug_printf("[delete %d] Object deleted %p\n", total, this); + total--; + } +private: + static int total; +}; + + +/*! + * \brief Log for inner-function stack frames inside big function. + * + */ +class DebugFuncStackFrame { +public: + DebugFuncStackFrame(DebugFuncEntry &obj, const char *capt) + : _obj(obj), _capt(capt) { + _obj.enter(_capt); + } + ~DebugFuncStackFrame() { + _obj.exit(_capt); + } +private: + DebugFuncStackFrame(); + DebugFuncEntry &_obj; + const char *_capt; +}; + diff -Naur ddrescue-1.17-rc4.orig/main_common.cc ddrescue-1.17-rc4/main_common.cc --- ddrescue-1.17-rc4.orig/main_common.cc 2013-06-29 21:58:21.204574255 +0700 +++ ddrescue-1.17-rc4/main_common.cc 2013-06-29 22:00:30.792571529 +0700 @@ -176,7 +176,14 @@ const char * const binary_prefix[8] = { "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi", "Yi" }; static bool si = true; - static char buf[16]; + + // get static buffer from circle + const int BUFSIZE = 16; + const int NUMBUFS = 16; + static char bufs[NUMBUFS][BUFSIZE]; + static int cur_buf = 0; + char *buf = bufs[cur_buf++]; + cur_buf %= NUMBUFS; if( set_prefix ) si = ( set_prefix > 0 ); const int factor = ( si ? 1000 : 1024 ); @@ -186,6 +193,6 @@ for( int i = 0; i < 8 && llabs( num ) > limit; ++i ) { num /= factor; p = prefix[i]; } - snprintf( buf, sizeof buf, "%lld %s", num, p ); + snprintf( buf, BUFSIZE, "%lld %s", num, p ); return buf; } diff -Naur ddrescue-1.17-rc4.orig/Makefile.in ddrescue-1.17-rc4/Makefile.in --- ddrescue-1.17-rc4.orig/Makefile.in 2013-06-29 21:58:21.200574255 +0700 +++ ddrescue-1.17-rc4/Makefile.in 2013-06-29 21:59:47.176572446 +0700 @@ -6,9 +6,9 @@ INSTALL_DIR = $(INSTALL) -d -m 755 SHELL = /bin/sh -ddobjs = block.o fillbook.o genbook.o io.o logbook.o rescuebook.o main.o +ddobjs = block.o fillbook.o genbook.o io.o logbook.o rescuebook.o main.o debug_print.o objs = arg_parser.o rational.o $(ddobjs) -logobjs = arg_parser.o block.o logbook.o ddrescuelog.o +logobjs = arg_parser.o block.o logbook.o ddrescuelog.o debug_print.o .PHONY : all install install-bin install-info install-man install-strip \ diff -Naur ddrescue-1.17-rc4.orig/rescuebook.cc ddrescue-1.17-rc4/rescuebook.cc --- ddrescue-1.17-rc4.orig/rescuebook.cc 2013-06-29 21:58:21.204574255 +0700 +++ ddrescue-1.17-rc4/rescuebook.cc 2013-06-29 22:01:35.896570159 +0700 @@ -29,7 +29,7 @@ #include "block.h" #include "ddrescue.h" - +#include "debug_print.h" namespace { @@ -82,6 +82,14 @@ if( errors_or_timeout() ) return 1; if( interrupted() ) return -1; int retval = copy_block( b, copied_size, error_size ); + + debug_printf("copy_and_update(): %10lld %c [0x%08llX,%10sB]: %10sB copied, %10sB errors.", + b.pos() / 512, char(st), + b.pos(), format_num(b.size()), + format_num(copied_size), format_num(error_size)); + if (copied_size + error_size < b.size()) + debug_printf("It has hit the EOF of input device/file"); + if( !retval ) { if( copied_size + error_size < b.size() ) // EOF @@ -118,6 +126,7 @@ // int Rescuebook::copy_non_tried() { + DEBUG_FUNC_ENTRY bool first_post = true; for( bool first_pass = true; ; first_pass = false ) @@ -189,6 +198,7 @@ // int Rescuebook::rcopy_non_tried() { + DEBUG_FUNC_ENTRY bool first_post = true; for( bool first_pass = true; ; first_pass = false ) @@ -261,6 +271,7 @@ // int Rescuebook::trim_errors() { + DEBUG_FUNC_ENTRY const char * const msg = "Trimming failed blocks..."; bool first_post = true; @@ -324,6 +335,7 @@ // int Rescuebook::split_errors( const bool reverse ) { + DEBUG_FUNC_ENTRY const char * const msg = "Splitting failed blocks..."; bool first_post = true; @@ -449,6 +461,7 @@ // int Rescuebook::copy_errors() { + DEBUG_FUNC_ENTRY char msgbuf[80] = "Retrying bad sectors... Retry "; const int msglen = std::strlen( msgbuf ); @@ -494,6 +507,7 @@ // int Rescuebook::rcopy_errors() { + DEBUG_FUNC_ENTRY char msgbuf[80] = "Retrying bad sectors... Retry "; const int msglen = std::strlen( msgbuf ); @@ -584,6 +598,9 @@ // int Rescuebook::do_rescue( const int ides, const int odes, const bool reverse ) { + DEBUG_FUNC_ENTRY; + debug_printf("Debug: copy_and_update(): sector status block_start,block_size : copied_size, errors_size."); + bool copy_pending = false, trim_pending = false, split_pending = false; ides_ = ides; odes_ = odes;