X-Git-Url: http://git.jankratochvil.net/?p=badblock-guess.git;a=blobdiff_plain;f=badblock-guess.c;h=eb1642c26d9f92814b0bcd5504a54d7a6228b347;hp=f715cd12806a5e9a6752857a1cf05bc8962cc237;hb=b1d726be4e97b55f4390e60873596659688d8e7d;hpb=bf17104b55bd5232d6564047ecd6dc8cbb397328 diff --git a/badblock-guess.c b/badblock-guess.c index f715cd1..eb1642c 100644 --- a/badblock-guess.c +++ b/badblock-guess.c @@ -56,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; @@ -175,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); @@ -274,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, @@ -284,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; @@ -337,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; @@ -453,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