[bb] fix bad blocks check for 64 bit

* 32 bit bad blocks check is too limited for large drives
  and result in erroneous computations
* 32 bit also means that 2TB would be absolute limit, which
  may be too low in case for USB HDD checks
* This fix makes bad blocks check and related calls 64 bit compliant
* also improve on bad block reports
This commit is contained in:
Pete Batard 2012-03-03 22:59:58 +00:00
parent 3721b0a570
commit a9c47a4922
6 changed files with 194 additions and 161 deletions

View file

@ -39,6 +39,7 @@
#include <time.h> #include <time.h>
#include <setjmp.h> #include <setjmp.h>
#include <windows.h> #include <windows.h>
#include <stdint.h>
#include "rufus.h" #include "rufus.h"
#include "badblocks.h" #include "badblocks.h"
@ -47,6 +48,7 @@
FILE* log_fd = NULL; FILE* log_fd = NULL;
static const char* abort_msg = "Too many bad blocks, aborting test\n"; static const char* abort_msg = "Too many bad blocks, aborting test\n";
static const char* bb_prefix = "Bad Blocks: ";
/* /*
*From e2fsprogs/lib/ext2fs/badblocks.c *From e2fsprogs/lib/ext2fs/badblocks.c
@ -55,35 +57,35 @@ static const char* abort_msg = "Too many bad blocks, aborting test\n";
/* /*
* Badblocks list * Badblocks list
*/ */
struct ext2_struct_u32_list { struct bb_struct_u64_list {
int magic; int magic;
int num; int num;
int size; int size;
__u32 *list; uint64_t *list;
int badblocks_flags; int badblocks_flags;
}; };
struct ext2_struct_u32_iterate { struct bb_struct_u64_iterate {
int magic; int magic;
ext2_u32_list bb; bb_u64_list bb;
int ptr; int ptr;
}; };
static errcode_t make_u32_list(int size, int num, __u32 *list, ext2_u32_list *ret) static errcode_t make_u64_list(int size, int num, uint64_t *list, bb_u64_list *ret)
{ {
ext2_u32_list bb; bb_u64_list bb;
bb = calloc(1, sizeof(struct ext2_struct_u32_list)); bb = calloc(1, sizeof(struct bb_struct_u64_list));
if (bb == NULL) if (bb == NULL)
return EXT2_ET_NO_MEMORY; return BB_ET_NO_MEMORY;
bb->magic = EXT2_ET_MAGIC_BADBLOCKS_LIST; bb->magic = BB_ET_MAGIC_BADBLOCKS_LIST;
bb->size = size ? size : 10; bb->size = size ? size : 10;
bb->num = num; bb->num = num;
bb->list = malloc(sizeof(blk_t) * bb->size); bb->list = malloc(sizeof(blk_t) * bb->size);
if (bb->list == NULL) { if (bb->list == NULL) {
free(bb); free(bb);
bb = NULL; bb = NULL;
return EXT2_ET_NO_MEMORY; return BB_ET_NO_MEMORY;
} }
if (list) if (list)
memcpy(bb->list, list, bb->size * sizeof(blk_t)); memcpy(bb->list, list, bb->size * sizeof(blk_t));
@ -96,28 +98,28 @@ static errcode_t make_u32_list(int size, int num, __u32 *list, ext2_u32_list *re
/* /*
* This procedure creates an empty badblocks list. * This procedure creates an empty badblocks list.
*/ */
static errcode_t ext2fs_badblocks_list_create(ext2_badblocks_list *ret, int size) static errcode_t bb_badblocks_list_create(bb_badblocks_list *ret, int size)
{ {
return make_u32_list(size, 0, 0, (ext2_badblocks_list *) ret); return make_u64_list(size, 0, 0, (bb_badblocks_list *) ret);
} }
/* /*
* This procedure adds a block to a badblocks list. * This procedure adds a block to a badblocks list.
*/ */
static errcode_t ext2fs_u32_list_add(ext2_u32_list bb, __u32 blk) static errcode_t bb_u64_list_add(bb_u64_list bb, uint64_t blk)
{ {
int i, j; int i, j;
__u32* old_bb_list = bb->list; uint64_t* old_bb_list = bb->list;
EXT2_CHECK_MAGIC(bb, EXT2_ET_MAGIC_BADBLOCKS_LIST); BB_CHECK_MAGIC(bb, BB_ET_MAGIC_BADBLOCKS_LIST);
if (bb->num >= bb->size) { if (bb->num >= bb->size) {
bb->size += 100; bb->size += 100;
bb->list = realloc(bb->list, bb->size * sizeof(__u32)); bb->list = realloc(bb->list, bb->size * sizeof(uint64_t));
if (bb->list == NULL) { if (bb->list == NULL) {
bb->list = old_bb_list; bb->list = old_bb_list;
bb->size -= 100; bb->size -= 100;
return EXT2_ET_NO_MEMORY; return BB_ET_NO_MEMORY;
} }
} }
@ -148,20 +150,20 @@ static errcode_t ext2fs_u32_list_add(ext2_u32_list bb, __u32 blk)
return 0; return 0;
} }
static errcode_t ext2fs_badblocks_list_add(ext2_badblocks_list bb, blk_t blk) static errcode_t bb_badblocks_list_add(bb_badblocks_list bb, blk_t blk)
{ {
return ext2fs_u32_list_add((ext2_u32_list) bb, (__u32) blk); return bb_u64_list_add((bb_u64_list) bb, blk);
} }
/* /*
* This procedure finds a particular block is on a badblocks * This procedure finds a particular block is on a badblocks
* list. * list.
*/ */
static int ext2fs_u32_list_find(ext2_u32_list bb, __u32 blk) static int bb_u64_list_find(bb_u64_list bb, uint64_t blk)
{ {
int low, high, mid; int low, high, mid;
if (bb->magic != EXT2_ET_MAGIC_BADBLOCKS_LIST) if (bb->magic != BB_ET_MAGIC_BADBLOCKS_LIST)
return -1; return -1;
if (bb->num == 0) if (bb->num == 0)
@ -192,29 +194,29 @@ static int ext2fs_u32_list_find(ext2_u32_list bb, __u32 blk)
* This procedure tests to see if a particular block is on a badblocks * This procedure tests to see if a particular block is on a badblocks
* list. * list.
*/ */
static int ext2fs_u32_list_test(ext2_u32_list bb, __u32 blk) static int bb_u64_list_test(bb_u64_list bb, uint64_t blk)
{ {
if (ext2fs_u32_list_find(bb, blk) < 0) if (bb_u64_list_find(bb, blk) < 0)
return 0; return 0;
else else
return 1; return 1;
} }
static int ext2fs_badblocks_list_test(ext2_badblocks_list bb, blk_t blk) static int bb_badblocks_list_test(bb_badblocks_list bb, blk_t blk)
{ {
return ext2fs_u32_list_test((ext2_u32_list) bb, (__u32) blk); return bb_u64_list_test((bb_u64_list) bb, blk);
} }
static int ext2fs_u32_list_iterate(ext2_u32_iterate iter, __u32 *blk) static int bb_u64_list_iterate(bb_u64_iterate iter, uint64_t *blk)
{ {
ext2_u32_list bb; bb_u64_list bb;
if (iter->magic != EXT2_ET_MAGIC_BADBLOCKS_ITERATE) if (iter->magic != BB_ET_MAGIC_BADBLOCKS_ITERATE)
return 0; return 0;
bb = iter->bb; bb = iter->bb;
if (bb->magic != EXT2_ET_MAGIC_BADBLOCKS_LIST) if (bb->magic != BB_ET_MAGIC_BADBLOCKS_LIST)
return 0; return 0;
if (iter->ptr < bb->num) { if (iter->ptr < bb->num) {
@ -225,10 +227,9 @@ static int ext2fs_u32_list_iterate(ext2_u32_iterate iter, __u32 *blk)
return 0; return 0;
} }
static int ext2fs_badblocks_list_iterate(ext2_badblocks_iterate iter, blk_t *blk) static int bb_badblocks_list_iterate(bb_badblocks_iterate iter, blk_t *blk)
{ {
return ext2fs_u32_list_iterate((ext2_u32_iterate) iter, return bb_u64_list_iterate((bb_u64_iterate) iter, blk);
(__u32 *) blk);
} }
/* /*
@ -240,21 +241,21 @@ static int cancel_ops = 0; /* abort current operation */
static int cur_pattern, nr_pattern; static int cur_pattern, nr_pattern;
static int cur_op; static int cur_op;
/* Abort test if more than this number of bad blocks has been encountered */ /* Abort test if more than this number of bad blocks has been encountered */
static unsigned int max_bb = EXT2_BAD_BLOCKS_THRESHOLD; static unsigned int max_bb = BB_BAD_BLOCKS_THRESHOLD;
static blk_t currently_testing = 0; static blk_t currently_testing = 0;
static blk_t num_blocks = 0; static blk_t num_blocks = 0;
static blk_t num_read_errors = 0; static uint32_t num_read_errors = 0;
static blk_t num_write_errors = 0; static uint32_t num_write_errors = 0;
static blk_t num_corruption_errors = 0; static uint32_t num_corruption_errors = 0;
static ext2_badblocks_list bb_list = NULL; static bb_badblocks_list bb_list = NULL;
static blk_t next_bad = 0; static blk_t next_bad = 0;
static ext2_badblocks_iterate bb_iter = NULL; static bb_badblocks_iterate bb_iter = NULL;
static __inline void *allocate_buffer(size_t size) { static __inline void *allocate_buffer(size_t size) {
#ifdef __MINGW32__ #ifdef __MINGW32__
return __mingw_aligned_malloc(size, EXT2_SYS_PAGE_SIZE); return __mingw_aligned_malloc(size, BB_SYS_PAGE_SIZE);
#else #else
return _aligned_malloc(size, EXT2_SYS_PAGE_SIZE); return _aligned_malloc(size, BB_SYS_PAGE_SIZE);
#endif #endif
} }
@ -274,17 +275,17 @@ static int bb_output (blk_t bad, enum error_types error_type)
{ {
errcode_t error_code; errcode_t error_code;
if (ext2fs_badblocks_list_test(bb_list, bad)) if (bb_badblocks_list_test(bb_list, bad))
return 0; return 0;
uprintf("%lu\n", (unsigned long) bad); uprintf("%s%lu\n", bb_prefix, (unsigned long)bad);
fprintf(log_fd, "Block %lu: %s error\n", (unsigned long)bad, (error_type==READ_ERROR)?"read": fprintf(log_fd, "Block %lu: %s error\n", (unsigned long)bad, (error_type==READ_ERROR)?"read":
((error_type == WRITE_ERROR)?"write":"corruption")); ((error_type == WRITE_ERROR)?"write":"corruption"));
fflush(log_fd); fflush(log_fd);
error_code = ext2fs_badblocks_list_add(bb_list, bad); error_code = bb_badblocks_list_add(bb_list, bad);
if (error_code) { if (error_code) {
uprintf("Error %d adding to in-memory bad block list", error_code); uprintf("%sError %d adding to in-memory bad block list", bb_prefix, error_code);
return 0; return 0;
} }
@ -293,7 +294,7 @@ static int bb_output (blk_t bad, enum error_types error_type)
an element was just added before the current iteration an element was just added before the current iteration
position. This should not cause next_bad to change. */ position. This should not cause next_bad to change. */
if (bb_iter && bad < next_bad) if (bb_iter && bad < next_bad)
ext2fs_badblocks_list_iterate (bb_iter, &next_bad); bb_badblocks_list_iterate (bb_iter, &next_bad);
if (error_type == READ_ERROR) { if (error_type == READ_ERROR) {
num_read_errors++; num_read_errors++;
@ -338,7 +339,7 @@ static void CALLBACK alarm_intr(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dw
if (!num_blocks) if (!num_blocks)
return; return;
if (FormatStatus) { if (FormatStatus) {
uprintf("Interrupting at block %llu\n", uprintf("%sInterrupting at block %llu\n", bb_prefix,
(unsigned long long) currently_testing); (unsigned long long) currently_testing);
cancel_ops = -1; cancel_ops = -1;
} }
@ -355,7 +356,7 @@ static void pattern_fill(unsigned char *buffer, unsigned int pattern,
for (ptr = buffer; ptr < buffer + n; ptr++) { for (ptr = buffer; ptr < buffer + n; ptr++) {
(*ptr) = rand() % (1 << (8 * sizeof(char))); (*ptr) = rand() % (1 << (8 * sizeof(char)));
} }
PrintStatus(3500, TRUE, "Bad Blocks: Testing with random pattern."); PrintStatus(3500, FALSE, "Bad Blocks: Testing with random pattern.");
} else { } else {
bpattern[0] = 0; bpattern[0] = 0;
for (i = 0; i < sizeof(bpattern); i++) { for (i = 0; i < sizeof(bpattern); i++) {
@ -372,7 +373,7 @@ static void pattern_fill(unsigned char *buffer, unsigned int pattern,
else else
i--; i--;
} }
PrintStatus(3500, TRUE, "Bad Blocks: Testing with pattern 0x%02X.", bpattern[i]); PrintStatus(3500, FALSE, "Bad Blocks: Testing with pattern 0x%02X.", bpattern[i]);
cur_pattern++; cur_pattern++;
} }
} }
@ -381,10 +382,10 @@ static void pattern_fill(unsigned char *buffer, unsigned int pattern,
* Perform a read of a sequence of blocks; return the number of blocks * Perform a read of a sequence of blocks; return the number of blocks
* successfully sequentially read. * successfully sequentially read.
*/ */
static int do_read (HANDLE hDrive, unsigned char * buffer, int tryout, int block_size, static int64_t do_read (HANDLE hDrive, unsigned char * buffer, uint64_t tryout, uint64_t block_size,
blk_t current_block) blk_t current_block)
{ {
long got; int64_t got;
if (v_flag > 1) if (v_flag > 1)
print_status(); print_status();
@ -394,7 +395,7 @@ static int do_read (HANDLE hDrive, unsigned char * buffer, int tryout, int block
if (got < 0) if (got < 0)
got = 0; got = 0;
if (got & 511) if (got & 511)
uprintf("Weird value (%ld) in do_read\n", got); uprintf("%sWeird value (%ld) in do_read\n", bb_prefix, got);
got /= block_size; got /= block_size;
return got; return got;
} }
@ -403,10 +404,10 @@ static int do_read (HANDLE hDrive, unsigned char * buffer, int tryout, int block
* Perform a write of a sequence of blocks; return the number of blocks * Perform a write of a sequence of blocks; return the number of blocks
* successfully sequentially written. * successfully sequentially written.
*/ */
static int do_write(HANDLE hDrive, unsigned char * buffer, int tryout, int block_size, static int64_t do_write(HANDLE hDrive, unsigned char * buffer, uint64_t tryout, uint64_t block_size,
unsigned long current_block) blk_t current_block)
{ {
long got; int64_t got;
if (v_flag > 1) if (v_flag > 1)
print_status(); print_status();
@ -416,23 +417,23 @@ static int do_write(HANDLE hDrive, unsigned char * buffer, int tryout, int block
if (got < 0) if (got < 0)
got = 0; got = 0;
if (got & 511) if (got & 511)
uprintf("Weird value (%ld) in do_write\n", got); uprintf("%sWeird value (%ld) in do_write\n", bb_prefix, got);
got /= block_size; got /= block_size;
return got; return got;
} }
static unsigned int test_rw(HANDLE hDrive, blk_t last_block, int block_size, blk_t first_block, static unsigned int test_rw(HANDLE hDrive, blk_t last_block, size_t block_size, blk_t first_block,
unsigned int blocks_at_once, int nb_passes) size_t blocks_at_once, int nb_passes)
{ {
unsigned char *buffer = NULL, *read_buffer; unsigned char *buffer = NULL, *read_buffer;
const unsigned int pattern[] = {0xaa, 0x55, 0xff, 0x00}; const unsigned int pattern[] = {0xaa, 0x55, 0xff, 0x00};
int i, tryout, got, pat_idx; int i, pat_idx;
unsigned int bb_count = 0; unsigned int bb_count = 0;
blk_t recover_block = ~0, *blk_id; blk_t got, tryout, recover_block = ~0, *blk_id;
size_t id_offset; size_t id_offset;
if ((nb_passes < 1) || (nb_passes > 4)) { if ((nb_passes < 1) || (nb_passes > 4)) {
uprintf("Invalid number of passes\n"); uprintf("%sInvalid number of passes\n", bb_prefix);
cancel_ops = -1; cancel_ops = -1;
return 0; return 0;
} }
@ -441,13 +442,13 @@ static unsigned int test_rw(HANDLE hDrive, blk_t last_block, int block_size, blk
read_buffer = buffer + blocks_at_once * block_size; read_buffer = buffer + blocks_at_once * block_size;
if (!buffer) { if (!buffer) {
uprintf("Error while allocating buffers\n"); uprintf("%sError while allocating buffers\n", bb_prefix);
cancel_ops = -1; cancel_ops = -1;
return 0; return 0;
} }
uprintf("Checking for bad blocks in read-write mode\n"); uprintf("%sChecking from block %lu to %lu\n", bb_prefix,
uprintf("From block %lu to %lu\n", (unsigned long) first_block, (unsigned long) last_block - 1); (unsigned long) first_block, (unsigned long) last_block - 1);
nr_pattern = nb_passes; nr_pattern = nb_passes;
cur_pattern = 0; cur_pattern = 0;
@ -456,14 +457,15 @@ static unsigned int test_rw(HANDLE hDrive, blk_t last_block, int block_size, blk
srand((unsigned int)GetTickCount()); srand((unsigned int)GetTickCount());
id_offset = rand()* (block_size-sizeof(blk_t)) / RAND_MAX; id_offset = rand()* (block_size-sizeof(blk_t)) / RAND_MAX;
pattern_fill(buffer, pattern[pat_idx], blocks_at_once * block_size); pattern_fill(buffer, pattern[pat_idx], blocks_at_once * block_size);
uprintf("Block ID at offset: %d\n", id_offset); uprintf("%sBlock ID at offset: %d\n", bb_prefix, id_offset);
num_blocks = last_block - 1; num_blocks = last_block - 1;
currently_testing = first_block; currently_testing = first_block;
if (s_flag | v_flag) if (s_flag | v_flag)
uprintf("Writing\n"); uprintf("%sWriting test pattern 0x%02X\n", bb_prefix, pattern[pat_idx]);
cur_op = OP_WRITE; cur_op = OP_WRITE;
tryout = blocks_at_once; tryout = blocks_at_once;
while (currently_testing < last_block) { while (currently_testing < last_block) {
if (cancel_ops) goto out;
if (max_bb && bb_count >= max_bb) { if (max_bb && bb_count >= max_bb) {
if (s_flag || v_flag) { if (s_flag || v_flag) {
uprintf(abort_msg); uprintf(abort_msg);
@ -471,9 +473,8 @@ static unsigned int test_rw(HANDLE hDrive, blk_t last_block, int block_size, blk
fflush(log_fd); fflush(log_fd);
} }
cancel_ops = -1; cancel_ops = -1;
break; goto out;
} }
if (cancel_ops) goto out;
if (currently_testing + tryout > last_block) if (currently_testing + tryout > last_block)
tryout = last_block - currently_testing; tryout = last_block - currently_testing;
/* Add the block number at a fixed (random) offset during each pass to /* Add the block number at a fixed (random) offset during each pass to
@ -503,7 +504,7 @@ static unsigned int test_rw(HANDLE hDrive, blk_t last_block, int block_size, blk
num_blocks = 0; num_blocks = 0;
if (s_flag | v_flag) if (s_flag | v_flag)
uprintf("Reading and comparing\n"); uprintf("%sReading and comparing\n", bb_prefix);
cur_op = OP_READ; cur_op = OP_READ;
num_blocks = last_block; num_blocks = last_block;
currently_testing = first_block; currently_testing = first_block;
@ -517,7 +518,8 @@ static unsigned int test_rw(HANDLE hDrive, blk_t last_block, int block_size, blk
fprintf(log_fd, abort_msg); fprintf(log_fd, abort_msg);
fflush(log_fd); fflush(log_fd);
} }
break; cancel_ops = -1;
goto out;
} }
if (currently_testing + tryout > last_block) if (currently_testing + tryout > last_block)
tryout = last_block - currently_testing; tryout = last_block - currently_testing;
@ -544,7 +546,7 @@ static unsigned int test_rw(HANDLE hDrive, blk_t last_block, int block_size, blk
if (memcmp(read_buffer + i * block_size, if (memcmp(read_buffer + i * block_size,
buffer + i * block_size, buffer + i * block_size,
block_size)) block_size))
bb_count += bb_output(currently_testing+i, CORRUPTION_ERROR); bb_count += bb_output(currently_testing+i-got, CORRUPTION_ERROR);
} }
if (v_flag > 1) if (v_flag > 1)
print_status(); print_status();
@ -557,11 +559,11 @@ out:
return bb_count; return bb_count;
} }
BOOL BadBlocks(HANDLE hPhysicalDrive, ULONGLONG disk_size, int block_size, BOOL BadBlocks(HANDLE hPhysicalDrive, ULONGLONG disk_size, size_t block_size,
int nb_passes, badblocks_report *report, FILE* fd) int nb_passes, badblocks_report *report, FILE* fd)
{ {
errcode_t error_code; errcode_t error_code;
blk_t first_block = 0, last_block = (blk_t)disk_size/block_size; blk_t first_block = 0, last_block = disk_size/block_size;
if (report == NULL) return FALSE; if (report == NULL) return FALSE;
report->bb_count = 0; report->bb_count = 0;
@ -571,16 +573,16 @@ BOOL BadBlocks(HANDLE hPhysicalDrive, ULONGLONG disk_size, int block_size,
log_fd = freopen(NULL, "w", stderr); log_fd = freopen(NULL, "w", stderr);
} }
error_code = ext2fs_badblocks_list_create(&bb_list, 0); error_code = bb_badblocks_list_create(&bb_list, 0);
if (error_code) { if (error_code) {
uprintf("Error %d while creating in-memory bad blocks list", error_code); uprintf("%sError %d while creating in-memory bad blocks list", bb_prefix, error_code);
return FALSE; return FALSE;
} }
cancel_ops = 0; cancel_ops = 0;
/* use a timer to update status every second */ /* use a timer to update status every second */
SetTimer(hMainDialog, TID_BADBLOCKS_UPDATE, 1000, alarm_intr); SetTimer(hMainDialog, TID_BADBLOCKS_UPDATE, 1000, alarm_intr);
report->bb_count = test_rw(hPhysicalDrive, last_block, block_size, first_block, EXT2_BLOCKS_AT_ONCE, nb_passes); report->bb_count = test_rw(hPhysicalDrive, last_block, block_size, first_block, BB_BLOCKS_AT_ONCE, nb_passes);
KillTimer(hMainDialog, TID_BADBLOCKS_UPDATE); KillTimer(hMainDialog, TID_BADBLOCKS_UPDATE);
free(bb_list->list); free(bb_list->list);
free(bb_list); free(bb_list);

View file

@ -19,27 +19,25 @@
*/ */
#include <windows.h> #include <windows.h>
#include <stdint.h>
#ifndef __u32 typedef uint64_t blk_t;
#define __u32 UINT32
#endif
typedef UINT32 blk_t;
typedef DWORD errcode_t; typedef DWORD errcode_t;
typedef struct ext2_struct_u32_list *ext2_badblocks_list; typedef struct bb_struct_u64_list *bb_badblocks_list;
typedef struct ext2_struct_u32_iterate *ext2_badblocks_iterate; typedef struct bb_struct_u64_iterate *bb_badblocks_iterate;
typedef struct ext2_struct_u32_list *ext2_u32_list; typedef struct bb_struct_u64_list *bb_u64_list;
typedef struct ext2_struct_u32_iterate *ext2_u32_iterate; typedef struct bb_struct_u64_iterate *bb_u64_iterate;
#define EXT2_ET_NO_MEMORY (ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_NOT_ENOUGH_MEMORY) #define BB_ET_NO_MEMORY (ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_NOT_ENOUGH_MEMORY)
#define EXT2_ET_MAGIC_BADBLOCKS_LIST (ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_OBJECT_IN_LIST) #define BB_ET_MAGIC_BADBLOCKS_LIST (ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_OBJECT_IN_LIST)
#define EXT2_ET_MAGIC_BADBLOCKS_ITERATE (ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_INVALID_BLOCK) #define BB_ET_MAGIC_BADBLOCKS_ITERATE (ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_INVALID_BLOCK)
#define EXT2_CHECK_MAGIC(struct, code) \ #define BB_CHECK_MAGIC(struct, code) \
if ((struct)->magic != (code)) return (code) if ((struct)->magic != (code)) return (code)
#define EXT2_BAD_BLOCKS_THRESHOLD 256 #define BB_BAD_BLOCKS_THRESHOLD 256
#define EXT2_BLOCKS_AT_ONCE 64 #define BB_BLOCKS_AT_ONCE 64
#define EXT2_SYS_PAGE_SIZE 4096 #define BB_SYS_PAGE_SIZE 4096
enum error_types { READ_ERROR, WRITE_ERROR, CORRUPTION_ERROR }; enum error_types { READ_ERROR, WRITE_ERROR, CORRUPTION_ERROR };
enum op_type { OP_READ, OP_WRITE }; enum op_type { OP_READ, OP_WRITE };
@ -48,14 +46,14 @@ enum op_type { OP_READ, OP_WRITE };
* Badblocks report * Badblocks report
*/ */
typedef struct { typedef struct {
blk_t bb_count; uint32_t bb_count;
blk_t num_read_errors; uint32_t num_read_errors;
blk_t num_write_errors; uint32_t num_write_errors;
blk_t num_corruption_errors; uint32_t num_corruption_errors;
} badblocks_report; } badblocks_report;
/* /*
* Shared prototypes * Shared prototypes
*/ */
BOOL BadBlocks(HANDLE hPhysicalDrive, ULONGLONG disk_size, int block_size, BOOL BadBlocks(HANDLE hPhysicalDrive, ULONGLONG disk_size, size_t block_size,
int test_type, badblocks_report *report, FILE* fd); int test_type, badblocks_report *report, FILE* fd);

View file

@ -529,14 +529,16 @@ DWORD WINAPI FormatThread(LPVOID param)
if (!BadBlocks(hPhysicalDrive, SelectedDrive.DiskSize, if (!BadBlocks(hPhysicalDrive, SelectedDrive.DiskSize,
SelectedDrive.Geometry.BytesPerSector, ComboBox_GetCurSel(hNBPasses)+1, &report, log_fd)) { SelectedDrive.Geometry.BytesPerSector, ComboBox_GetCurSel(hNBPasses)+1, &report, log_fd)) {
uprintf("Bad blocks check failed.\n"); uprintf("Bad blocks: Check failed.\n");
if (!FormatStatus) if (!FormatStatus)
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)| FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|
APPERR(ERROR_BADBLOCKS_FAILURE); APPERR(ERROR_BADBLOCKS_FAILURE);
ClearMBR(hPhysicalDrive); ClearMBR(hPhysicalDrive);
fclose(log_fd);
_unlink(logfile);
goto out; goto out;
} }
uprintf("Check completed, %u bad block%s found. (%d/%d/%d errors)\n", uprintf("Bad Blocks: Check completed, %u bad block%s found. (%d/%d/%d errors)\n",
report.bb_count, (report.bb_count==1)?"":"s", report.bb_count, (report.bb_count==1)?"":"s",
report.num_read_errors, report.num_write_errors, report.num_corruption_errors); report.num_read_errors, report.num_write_errors, report.num_corruption_errors);
r = IDOK; r = IDOK;
@ -547,13 +549,15 @@ DWORD WINAPI FormatThread(LPVOID param)
report.num_read_errors, report.num_write_errors, report.num_read_errors, report.num_write_errors,
report.num_corruption_errors); report.num_corruption_errors);
fprintf(log_fd, "%s", bb_msg); fprintf(log_fd, "%s", bb_msg);
GetLocalTime(&lt);
fprintf(log_fd, "Rufus bad blocks check ended on: %04d.%02d.%02d %02d:%02d:%02d\n",
lt.wYear, lt.wMonth, lt.wDay, lt.wHour, lt.wMinute, lt.wSecond);
fclose(log_fd); fclose(log_fd);
safe_sprintf(&bb_msg[strlen(bb_msg)], sizeof(bb_msg)-strlen(bb_msg)-1, safe_sprintf(&bb_msg[strlen(bb_msg)], sizeof(bb_msg)-strlen(bb_msg)-1,
"\nA more detailed report can be found in:\n%s\n", logfile); "\nA more detailed report can be found in:\n%s\n", logfile);
r = MessageBoxU(hMainDialog, bb_msg, "Bad blocks found", MB_ABORTRETRYIGNORE|MB_ICONWARNING); r = MessageBoxU(hMainDialog, bb_msg, "Bad blocks found", MB_ABORTRETRYIGNORE|MB_ICONWARNING);
} else { } else {
// We didn't get any errors => delete the log file // We didn't get any errors => delete the log file
// NB: the log doesn't get deleted on abort
fclose(log_fd); fclose(log_fd);
_unlink(logfile); _unlink(logfile);
} }

View file

@ -18,17 +18,25 @@
******************************************************************/ ******************************************************************/
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <stdint.h>
#include "../rufus.h" #include "../rufus.h"
#include "file.h" #include "file.h"
/* Returns the number of bytes written or -1 on error */ /* Returns the number of bytes written or -1 on error */
int write_sectors(HANDLE hDrive, size_t SectorSize, int64_t write_sectors(HANDLE hDrive, uint64_t SectorSize,
size_t StartSector, size_t nSectors, uint64_t StartSector, uint64_t nSectors,
const void *pBuf) const void *pBuf)
{ {
LARGE_INTEGER ptr; LARGE_INTEGER ptr;
DWORD Size = (DWORD)(nSectors*SectorSize); DWORD Size;
if((nSectors*SectorSize) > 0xFFFFFFFFUL)
{
uprintf("write_sectors: nSectors x SectorSize is too big\n");
return -1;
}
Size = (DWORD)(nSectors*SectorSize);
ptr.QuadPart = StartSector*SectorSize; ptr.QuadPart = StartSector*SectorSize;
if(!SetFilePointerEx(hDrive, ptr, NULL, FILE_BEGIN)) if(!SetFilePointerEx(hDrive, ptr, NULL, FILE_BEGIN))
@ -44,16 +52,23 @@ int write_sectors(HANDLE hDrive, size_t SectorSize,
return Size; return Size;
} }
return Size; return (int64_t)Size;
} }
/* Returns the number of bytes read or -1 on error */ /* Returns the number of bytes read or -1 on error */
int read_sectors(HANDLE hDrive, size_t SectorSize, int64_t read_sectors(HANDLE hDrive, uint64_t SectorSize,
size_t StartSector, size_t nSectors, uint64_t StartSector, uint64_t nSectors,
void *pBuf) void *pBuf)
{ {
LARGE_INTEGER ptr; LARGE_INTEGER ptr;
DWORD Size = (DWORD)(nSectors*SectorSize); DWORD Size;
if((nSectors*SectorSize) > 0xFFFFFFFFUL)
{
uprintf("read_sectors: nSectors x SectorSize is too big\n");
return -1;
}
Size = (DWORD)(nSectors*SectorSize);
ptr.QuadPart = StartSector*SectorSize; ptr.QuadPart = StartSector*SectorSize;
if(!SetFilePointerEx(hDrive, ptr, NULL, FILE_BEGIN)) if(!SetFilePointerEx(hDrive, ptr, NULL, FILE_BEGIN))
@ -68,7 +83,7 @@ int read_sectors(HANDLE hDrive, size_t SectorSize,
uprintf(" StartSector:%0X, nSectors:%0X, SectorSize:%0X\n", StartSector, nSectors, SectorSize); uprintf(" StartSector:%0X, nSectors:%0X, SectorSize:%0X\n", StartSector, nSectors, SectorSize);
} }
return Size; return (int64_t)Size;
} }
/* /*
@ -77,14 +92,49 @@ int read_sectors(HANDLE hDrive, size_t SectorSize,
* fp->_bufsiz: the sector size * fp->_bufsiz: the sector size
* fp->_cnt: a file offset * fp->_cnt: a file offset
*/ */
int contains_data(FILE *fp, size_t Position, int contains_data(FILE *fp, uint64_t Position,
const void *pData, size_t Len) const void *pData, uint64_t Len)
{ {
unsigned char aucBuf[MAX_DATA_LEN]; unsigned char aucBuf[MAX_DATA_LEN];
HANDLE hDrive = (HANDLE)fp->_ptr; HANDLE hDrive = (HANDLE)fp->_ptr;
size_t SectorSize = (size_t)fp->_bufsiz; uint64_t SectorSize = (uint64_t)fp->_bufsiz;
size_t StartSector, EndSector, NumSectors; uint64_t StartSector, EndSector, NumSectors;
Position += (size_t)fp->_cnt; Position += (uint64_t)fp->_cnt;
StartSector = Position/SectorSize;
EndSector = (Position+Len+SectorSize-1)/SectorSize;
NumSectors = (size_t)(EndSector - StartSector);
if((NumSectors*SectorSize) > MAX_DATA_LEN)
{
uprintf("contains_data: please increase MAX_DATA_LEN in file.h\n");
return 0;
}
if(Len > 0xFFFFFFFFUL)
{
uprintf("contains_data: Len is too big\n");
return 0;
}
if(read_sectors(hDrive, SectorSize, StartSector,
NumSectors, aucBuf) <= 0)
return 0;
if(memcmp(pData, &aucBuf[Position - StartSector*SectorSize], (size_t)Len))
return 0;
return 1;
} /* contains_data */
/* May read/write the same sector many times, but compatible with existing ms-sys */
int write_data(FILE *fp, uint64_t Position,
const void *pData, uint64_t Len)
{
unsigned char aucBuf[MAX_DATA_LEN];
HANDLE hDrive = (HANDLE)fp->_ptr;
uint64_t SectorSize = (uint64_t)fp->_bufsiz;
uint64_t StartSector, EndSector, NumSectors;
Position += (uint64_t)fp->_cnt;
StartSector = Position/SectorSize; StartSector = Position/SectorSize;
EndSector = (Position+Len+SectorSize-1)/SectorSize; EndSector = (Position+Len+SectorSize-1)/SectorSize;
@ -96,32 +146,9 @@ int contains_data(FILE *fp, size_t Position,
return 0; return 0;
} }
if(read_sectors(hDrive, SectorSize, StartSector, if(Len > 0xFFFFFFFFUL)
NumSectors, aucBuf) <= 0)
return 0;
if(memcmp(pData, &aucBuf[Position - StartSector*SectorSize], Len))
return 0;
return 1;
} /* contains_data */
/* May read/write the same sector many times, but compatible with existing ms-sys */
int write_data(FILE *fp, size_t Position,
const void *pData, size_t Len)
{
unsigned char aucBuf[MAX_DATA_LEN];
HANDLE hDrive = (HANDLE)fp->_ptr;
size_t SectorSize = (size_t)fp->_bufsiz;
size_t StartSector, EndSector, NumSectors;
Position += (size_t)fp->_cnt;
StartSector = Position/SectorSize;
EndSector = (Position+Len+SectorSize-1)/SectorSize;
NumSectors = EndSector - StartSector;
if((NumSectors*SectorSize) > MAX_DATA_LEN)
{ {
uprintf("Please increase MAX_DATA_LEN in file.h\n"); uprintf("write_data: Len is too big\n");
return 0; return 0;
} }
@ -130,7 +157,7 @@ int write_data(FILE *fp, size_t Position,
NumSectors, aucBuf) <= 0) NumSectors, aucBuf) <= 0)
return 0; return 0;
if(!memcpy(&aucBuf[Position - StartSector*SectorSize], pData, Len)) if(!memcpy(&aucBuf[Position - StartSector*SectorSize], pData, (size_t)Len))
return 0; return 0;
if(write_sectors(hDrive, SectorSize, StartSector, if(write_sectors(hDrive, SectorSize, StartSector,

View file

@ -1,27 +1,29 @@
#ifndef FILE_H #ifndef FILE_H
#define FILE_H #define FILE_H
#include <stdint.h>
/* Max valid value of uiLen for contains_data */ /* Max valid value of uiLen for contains_data */
#define MAX_DATA_LEN 8192 #define MAX_DATA_LEN 8192
/* Checks if a file contains a data pattern of length uiLen at position /* Checks if a file contains a data pattern of length Len at position
ulPositoin. The file pointer will change when calling this function! */ Position. The file pointer will change when calling this function! */
int contains_data(FILE *fp, size_t ulPosition, int contains_data(FILE *fp, uint64_t Position,
const void *pData, size_t uiLen); const void *pData, uint64_t Len);
/* Writes a data pattern of length uiLen at position ulPositoin. /* Writes a data pattern of length Len at position Position.
The file pointer will change when calling this function! */ The file pointer will change when calling this function! */
int write_data(FILE *fp, size_t ulPosition, int write_data(FILE *fp, uint64_t Position,
const void *pData, size_t uiLen); const void *pData, uint64_t Len);
/* Writes nSectors of size SectorSize starting at sector StartSector */ /* Writes nSectors of size SectorSize starting at sector StartSector */
int write_sectors(void *hDrive, size_t SectorSize, int64_t write_sectors(void *hDrive, uint64_t SectorSize,
size_t StartSector, size_t nSectors, uint64_t StartSector, uint64_t nSectors,
const void *pBuf); const void *pBuf);
/* Reads nSectors of size SectorSize starting at sector StartSector */ /* Reads nSectors of size SectorSize starting at sector StartSector */
int read_sectors(void *hDrive, size_t SectorSize, int64_t read_sectors(void *hDrive, uint64_t SectorSize,
size_t StartSector, size_t nSectors, uint64_t StartSector, uint64_t nSectors,
void *pBuf); void *pBuf);
#endif #endif

View file

@ -33,7 +33,7 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL
IDD_DIALOG DIALOGEX 12, 12, 206, 289 IDD_DIALOG DIALOGEX 12, 12, 206, 289
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_APPWINDOW EXSTYLE WS_EX_APPWINDOW
CAPTION "Rufus v1.1.4.148" CAPTION "Rufus v1.1.4.149"
FONT 8, "MS Shell Dlg", 400, 0, 0x1 FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN BEGIN
DEFPUSHBUTTON "Start",IDC_START,94,248,50,14 DEFPUSHBUTTON "Start",IDC_START,94,248,50,14
@ -73,7 +73,7 @@ BEGIN
DEFPUSHBUTTON "OK",IDOK,231,175,50,14,WS_GROUP DEFPUSHBUTTON "OK",IDOK,231,175,50,14,WS_GROUP
CONTROL "<a href=""http://rufus.akeo.ie"">http://rufus.akeo.ie</a>",IDC_ABOUT_RUFUS_URL, CONTROL "<a href=""http://rufus.akeo.ie"">http://rufus.akeo.ie</a>",IDC_ABOUT_RUFUS_URL,
"SysLink",WS_TABSTOP,46,47,114,9 "SysLink",WS_TABSTOP,46,47,114,9
LTEXT "Version 1.1.4 (Build 148)",IDC_STATIC,46,19,78,8 LTEXT "Version 1.1.4 (Build 149)",IDC_STATIC,46,19,78,8
PUSHBUTTON "License...",IDC_ABOUT_LICENSE,46,175,50,14,WS_GROUP PUSHBUTTON "License...",IDC_ABOUT_LICENSE,46,175,50,14,WS_GROUP
EDITTEXT IDC_ABOUT_COPYRIGHTS,46,107,235,63,ES_MULTILINE | ES_READONLY | WS_VSCROLL EDITTEXT IDC_ABOUT_COPYRIGHTS,46,107,235,63,ES_MULTILINE | ES_READONLY | WS_VSCROLL
LTEXT "Report bugs or request enhancements at:",IDC_STATIC,46,66,187,8 LTEXT "Report bugs or request enhancements at:",IDC_STATIC,46,66,187,8
@ -223,8 +223,8 @@ END
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,1,4,148 FILEVERSION 1,1,4,149
PRODUCTVERSION 1,1,4,148 PRODUCTVERSION 1,1,4,149
FILEFLAGSMASK 0x3fL FILEFLAGSMASK 0x3fL
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
@ -241,13 +241,13 @@ BEGIN
BEGIN BEGIN
VALUE "CompanyName", "akeo.ie" VALUE "CompanyName", "akeo.ie"
VALUE "FileDescription", "Rufus" VALUE "FileDescription", "Rufus"
VALUE "FileVersion", "1.1.4.148" VALUE "FileVersion", "1.1.4.149"
VALUE "InternalName", "Rufus" VALUE "InternalName", "Rufus"
VALUE "LegalCopyright", "© 2011 Pete Batard (GPL v3)" VALUE "LegalCopyright", "© 2011 Pete Batard (GPL v3)"
VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html" VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html"
VALUE "OriginalFilename", "rufus.exe" VALUE "OriginalFilename", "rufus.exe"
VALUE "ProductName", "Rufus" VALUE "ProductName", "Rufus"
VALUE "ProductVersion", "1.1.4.148" VALUE "ProductVersion", "1.1.4.149"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"