X-Git-Url: http://git.jankratochvil.net/?p=badblock-guess.git;a=blobdiff_plain;f=badblock-guess.c;h=eb1642c26d9f92814b0bcd5504a54d7a6228b347;hp=56ed478a24ca5f9bd19c97f03dd37271563e203d;hb=ad1f5c98ae9185db345a6f3f923941771e4c7bb5;hpb=a5691b6c368c0bf21c558eeacb7c233d7e6272ef diff --git a/badblock-guess.c b/badblock-guess.c index 56ed478..eb1642c 100644 --- a/badblock-guess.c +++ b/badblock-guess.c @@ -1,5 +1,23 @@ /* $Id$ */ +/* + * badblock-guess: Quickly recover most of the data from a damaged disk + * Copyright (C) 2002 Jan Kratochvil + * + * 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 + * the Free Software Foundation; exactly version 2 of the License required + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + #define _LARGEFILE_SOURCE #define _LARGEFILE64_SOURCE @@ -38,8 +56,8 @@ static void finish(void) G_GNUC_NORETURN; static int src_fd=-1,dst_fd=-1; static const char *src_name,*dst_name; -static ext2_loff_t src_len; /* in blocks! */ -static blk_t src_lenblk; /* ==src_len, just a different type */ +static ext2_loff_t src_len,dst_len; /* in blocks! */ +static blk_t src_lenblk,dst_lenblk; /* ==src_len,==dst_len, just a different type */ static ext2_loff_t stat_lastread,stat_todo,stat_bads,stat_largest,stat_todo_hunks; @@ -157,13 +175,13 @@ struct range *key,*neigh_left,*neigh_right; if (start>=end) return; key=node_build(start,end); - if ((neigh_left =g_tree_search(bad_tree,(GSearchFunc)search_end ,&start))) { + if ((neigh_left =g_tree_search(bad_tree,(GCompareFunc)search_end ,&start))) { g_assert(neigh_left->end==key->start); key->start=neigh_left->start; g_tree_remove(bad_tree,neigh_left); g_mem_chunk_free(node_memchunk,neigh_left); } - if ((neigh_right=g_tree_search(bad_tree,(GSearchFunc)search_start,&end ))) { + if ((neigh_right=g_tree_search(bad_tree,(GCompareFunc)search_start,&end ))) { g_assert(neigh_right->start==key->end); key->end=neigh_right->end; g_tree_remove(bad_tree,neigh_right); @@ -256,6 +274,13 @@ ext2_loff_t gotext2_loff; exit(EXIT_FAILURE); } if (len!=(gotssize=write(dst_fd,buf,len))) { + /* see README/"Linux kernel flaw" */ + /* no "start==src_len-1" checking here, we may write larger blocks! */ + if (gotssize==((src_len&~1)-start)*BLOCK + /* -1 instead of 0 is given when no bytes were written */ + || (gotssize==-1 && start==src_len-1 && end==src_len)) + return; /* suppress error message */ + fprintf(stderr,"write(\"%s\",@%llu-@%llu=%llu=%lluB)=%lld: %m\n",dst_name, (unsigned long long)start, (unsigned long long)end, @@ -266,11 +291,29 @@ ext2_loff_t gotext2_loff; } } +static void range_zero(ext2_loff_t start,ext2_loff_t end) +{ +static const unsigned char buf_zero[BUF_ZERO_BLOCKS*BLOCK]; + + g_return_if_fail(startBUF_ZERO_BLOCKS ? start+BUF_ZERO_BLOCKS : end); + g_assert(mid>=start); + g_assert(mid<=end); + + write_dst(start,mid,buf_zero); + + start=mid; + } +} + static void process(ext2_loff_t start,ext2_loff_t end) { unsigned char block_buf[BLOCK]; ext2_loff_t bads; ext2_loff_t gotext2_loff; +ssize_t gotssize; g_return_if_fail(start=end) /* finished */ return; @@ -319,23 +371,6 @@ ext2_loff_t mid=(start+end)/2; } } -static void range_zero(ext2_loff_t start,ext2_loff_t end) -{ -static const unsigned char buf_zero[BUF_ZERO_BLOCKS*BLOCK]; - - g_return_if_fail(startBUF_ZERO_BLOCKS ? start+BUF_ZERO_BLOCKS : end); - g_assert(mid>=start); - g_assert(mid<=end); - - write_dst(start,mid,buf_zero); - - start=mid; - } -} - static void finish(void) { struct range *todo_linear=tree_linearize(todo_tree),*todol; @@ -390,7 +425,15 @@ int main(int argc,char **argv) setlinebuf(stderr); if (argc!=2 && argc!=3) { - fprintf(stderr,"Syntax: badblock-guess []\n"); + fprintf(stderr,"\ +badblock-guess, Copyright (C) 2002 Jan Kratochvil \n\ +$Id$\n\ +badblock-guess comes with ABSOLUTELY NO WARRANTY.\n\ +This is free software, and you are welcome to redistribute it\n\ +under certain conditions.\n\ +\n\ +Syntax: badblock-guess []\n\ +\n"); exit(EXIT_FAILURE); } if (-1==(src_fd=open64((src_name=argv[1]),O_RDONLY|O_BINARY))) { @@ -427,6 +470,23 @@ struct stat src_stat,dst_stat; fprintf(stderr,"\"%s\" length %llu <=0\n",src_name,(unsigned long long)src_len); exit(EXIT_FAILURE); } + if (dst_fd!=-1) { + if (ext2fs_get_device_size(dst_name,BLOCK,&dst_lenblk)) { + fprintf(stderr,"ext2fs_get_device_size(\"%s\",%d,...): %m\n",dst_name,BLOCK); + exit(EXIT_FAILURE); + } + dst_len=dst_lenblk; + if (dst_len<=0) { + fprintf(stderr,"\"%s\" length %llu <=0\n",dst_name,(unsigned long long)dst_len); + exit(EXIT_FAILURE); + } + if (dst_len