From e5df74714e130abb49721c06857de75f48f56489 Mon Sep 17 00:00:00 2001 From: Christophe Grenier Date: Fri, 12 Jun 2009 09:48:02 +0200 Subject: [PATCH] TestDisk: Skip 10MB if a read error occurs during image creation. --- src/dimage.c | 112 ++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 89 insertions(+), 23 deletions(-) diff --git a/src/dimage.c b/src/dimage.c index d3b9cca4..9e8ca557 100644 --- a/src/dimage.c +++ b/src/dimage.c @@ -2,7 +2,7 @@ File: dimage.c - Copyright (C) 2007-2008 Christophe GRENIER + Copyright (C) 2007-2009 Christophe GRENIER This software is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -20,26 +20,29 @@ */ -#include #ifdef HAVE_CONFIG_H #include #endif + +#include #ifdef HAVE_STDLIB_H #include #endif +#ifdef HAVE_UNISTD_H +#include +#endif #include #include #include "types.h" #include "common.h" #include "intrf.h" #include "intrfn.h" -#ifdef HAVE_UNISTD_H -#include -#endif #include "log.h" #include "dimage.h" #define READ_SIZE 256*512 +/* Skip 10Mb when there is a read error */ +#define SKIP_SIZE 10*1024*1024 #ifndef O_LARGEFILE #define O_LARGEFILE 0 @@ -48,15 +51,52 @@ #define O_BINARY 0 #endif -int disk_image(disk_t *disk_car, const partition_t *partition, const char *image_dd) +static void disk_image_backward(int disk_dst, disk_t *disk, const uint64_t offset_start, const uint64_t offset_end) +{ + uint64_t offset; + unsigned char *buffer=(unsigned char *)MALLOC(disk->sector_size); + for(offset=offset_end-disk->sector_size; offset > offset_start; offset-=disk->sector_size) + { + ssize_t pread_res; + pread_res=disk->pread(disk, buffer, disk->sector_size, offset); + if((unsigned)pread_res != disk->sector_size) + { + free(buffer); + return; + } +#if defined(HAVE_PWRITE) + if(pwrite(disk_dst, buffer, pread_res, offset)<0) + { + free(buffer); + return; + } +#else + if(lseek(disk_dst, offset, SEEK_SET)<0) + { + free(buffer); + return; + } + if(write(disk_dst, buffer, pread_res) != pread_res) + { + free(buffer); + return; + } +#endif + } + free(buffer); +} + +int disk_image(disk_t *disk, const partition_t *partition, const char *image_dd) { int ind_stop=0; uint64_t nbr_read_error=0; uint64_t offset=partition->part_offset; + uint64_t offset_old=offset; const uint64_t offset_end=partition->part_offset+partition->part_size; const uint64_t offset_inc=(offset_end-offset)/100; uint64_t offset_next=offset; - unsigned char *buffer_disk=(unsigned char *)MALLOC(READ_SIZE); + unsigned char *buffer=(unsigned char *)MALLOC(READ_SIZE); + unsigned int readsize=READ_SIZE; int disk_dst; #ifdef HAVE_NCURSES WINDOW *window; @@ -65,16 +105,16 @@ int disk_image(disk_t *disk_car, const partition_t *partition, const char *image { log_error("Can't create file %s.\n",image_dd); display_message("Can't create file!\n"); - free(buffer_disk); + free(buffer); return -1; } #ifdef HAVE_NCURSES window=newwin(0,0,0,0); /* full screen */ aff_copy(window); wmove(window,5,0); - wprintw(window,"%s\n",disk_car->description_short(disk_car)); + wprintw(window,"%s\n",disk->description_short(disk)); wmove(window,6,0); - aff_part(window,AFF_PART_ORDER|AFF_PART_STATUS,disk_car,partition); + aff_part(window,AFF_PART_ORDER|AFF_PART_STATUS,disk,partition); wmove(window,22,0); wattrset(window, A_REVERSE); waddstr(window," Stop "); @@ -82,26 +122,56 @@ int disk_image(disk_t *disk_car, const partition_t *partition, const char *image #endif while(ind_stop==0 && offset < offset_end) { - unsigned int readsize=READ_SIZE; + ssize_t pread_res; int update=0; - if(offset_end-offset < READ_SIZE) + if(offset_end-offset < readsize) readsize=offset_end-offset; - if((unsigned)disk_car->pread(disk_car, buffer_disk, readsize, offset) != readsize) + pread_res=disk->pread(disk, buffer, readsize, offset); + if(pread_res > 0) + { +#if defined(HAVE_PWRITE) + if(pwrite(disk_dst, buffer, pread_res, offset)<0) + { + ind_stop=2; + } +#else + if(lseek(disk_dst, offset, SEEK_SET)<0) + { + ind_stop=2; + } + if(write(disk_dst, buffer, pread_res) != pread_res) + { + ind_stop=2; + } +#endif + if(offset_old + SKIP_SIZE==offset) + { + disk_image_backward(disk_dst, disk, offset_old, offset); + } + } + offset_old=offset; + if((unsigned)pread_res == readsize) + { + offset+=readsize; + readsize=READ_SIZE; + } + else { update=1; nbr_read_error++; + readsize=disk->sector_size; + offset+=SKIP_SIZE; } - offset+=READ_SIZE; if(offset>offset_next) { update=1; - offset_next+=offset_inc; + offset_next=offset+offset_inc; } if(update) { #ifdef HAVE_NCURSES unsigned int i; - unsigned int percent=(offset-partition->part_offset)*100/partition->part_size; + const unsigned int percent=(offset-partition->part_offset)*100/partition->part_size; wmove(window,7,0); wprintw(window,"%3u %% ", percent); for(i=0;i