From 01d1d74f0442750eb91b7c2095d3b3d3cfd06896 Mon Sep 17 00:00:00 2001 From: Pete Batard Date: Sun, 8 Jan 2012 23:41:20 +0000 Subject: [PATCH] [bb] allow selection of nb passes/patterns * also removed nd/ro tests as unlikely to be used --- src/badblocks.c | 362 ++---------------------------------------------- src/badblocks.h | 7 - src/format.c | 2 +- src/resource.h | 5 +- src/rufus.c | 11 +- src/rufus.h | 2 +- src/rufus.rc | 12 +- 7 files changed, 33 insertions(+), 368 deletions(-) diff --git a/src/badblocks.c b/src/badblocks.c index 79a718a9..0b47ac17 100644 --- a/src/badblocks.c +++ b/src/badblocks.c @@ -465,115 +465,36 @@ static int do_write(HANDLE hDrive, unsigned char * buffer, int tryout, int block return got; } -static unsigned int test_ro (HANDLE hDrive, blk_t last_block, - int block_size, blk_t first_block, - unsigned int blocks_at_once) -{ - unsigned char * blkbuf; - int tryout; - int got; - unsigned int bb_count = 0; - errcode_t error_code; - blk_t recover_block = ~0; - - error_code = ext2fs_badblocks_list_iterate_begin(bb_list,&bb_iter); - if (error_code) { - // TODO: set FormatStatus - uprintf("errcode %d while beginning bad block list iteration\n", error_code); - return 0; - } - do { - ext2fs_badblocks_list_iterate (bb_iter, &next_bad); - } while (next_bad && next_bad < first_block); - - blkbuf = allocate_buffer(blocks_at_once * block_size); - if (!blkbuf) - { - uprintf("could not allocate buffers\n"); - cancel_ops = -1; - return 0; - } - tryout = blocks_at_once; - currently_testing = first_block; - num_blocks = last_block - 1; - if (s_flag || v_flag) { - // Printstatus - uprintf("Checking for bad blocks (read-only test): \n"); - } - while (currently_testing < last_block) - { - if (max_bb && bb_count >= max_bb) { - if (s_flag || v_flag) { - uprintf(abort_msg); - fprintf(log_fd, abort_msg); - fflush(log_fd); - } - cancel_ops = -1; - break; - } - if (next_bad) { - if (currently_testing == next_bad) { - /* fprintf (out, "%lu\n", nextbad); */ - ext2fs_badblocks_list_iterate (bb_iter, &next_bad); - currently_testing++; - continue; - } - else if (currently_testing + tryout > next_bad) - tryout = next_bad - currently_testing; - } - if (currently_testing + tryout > last_block) - tryout = last_block - currently_testing; - got = do_read(hDrive, blkbuf, tryout, block_size, currently_testing); - if (got == 0 && tryout == 1) - bb_count += bb_output(currently_testing++, READ_ERROR); - currently_testing += got; - if (got != tryout) { - tryout = 1; - if (recover_block == ~0) - recover_block = currently_testing - got + - blocks_at_once; - continue; - } else if (currently_testing == recover_block) { - tryout = blocks_at_once; - recover_block = ~0; - } - } - num_blocks = 0; -// alarm(0); -// if (s_flag || v_flag) -// fputs(_(done_string), stderr); - - fflush (stderr); - free_buffer(blkbuf); - - ext2fs_badblocks_list_iterate_end(bb_iter); - - return bb_count; -} - -static unsigned int test_rw(HANDLE hDrive, blk_t last_block, int block_size, blk_t first_block, unsigned int blocks_at_once) +static unsigned int test_rw(HANDLE hDrive, blk_t last_block, int block_size, blk_t first_block, + unsigned int blocks_at_once, int nb_passes) { unsigned char *buffer = NULL, *read_buffer; - const unsigned int pattern[] = EXT2_RW_PATTERNS; + const unsigned int pattern[] = {0xaa, 0x55, 0xff, 0x00}; int i, tryout, got, pat_idx; unsigned int bb_count = 0; blk_t recover_block = ~0; + if ((nb_passes < 1) || (nb_passes > 4)) { + uprintf("Invalid number of passes\n"); + cancel_ops = -1; + return 0; + } + buffer = allocate_buffer(2 * blocks_at_once * block_size); read_buffer = buffer + blocks_at_once * block_size; if (!buffer) { - uprintf("Error while allocating buffers"); + uprintf("Error while allocating buffers\n"); cancel_ops = -1; return 0; } uprintf("Checking for bad blocks in read-write mode\n"); uprintf("From block %lu to %lu\n", (unsigned long) first_block, (unsigned long) last_block - 1); - nr_pattern = ARRAYSIZE(pattern); + nr_pattern = nb_passes; cur_pattern = 0; - for (pat_idx = 0; pat_idx < ARRAYSIZE(pattern); pat_idx++) { + for (pat_idx = 0; pat_idx < nb_passes; pat_idx++) { if (cancel_ops) goto out; pattern_fill(buffer, pattern[pat_idx], blocks_at_once * block_size); num_blocks = last_block - 1; @@ -666,254 +587,10 @@ out: return bb_count; } -struct saved_blk_record { - blk_t block; - int num; -}; - -// TODO: this is untested! -static unsigned int test_nd(HANDLE hDrive, blk_t last_block, - int block_size, blk_t first_block, - unsigned int blocks_at_once) -{ - unsigned char *blkbuf, *save_ptr, *test_ptr, *read_ptr; - unsigned char *test_base, *save_base, *read_base; - int tryout, i; - const unsigned int pattern[] = { ~0 }; - int pat_idx; - int got, used2, written; - blk_t save_currently_testing; - struct saved_blk_record *test_record; - /* This is static to prevent being clobbered by the longjmp */ - static int num_saved; - jmp_buf terminate_env; - errcode_t error_code; - unsigned long buf_used; - static unsigned int bb_count; - int granularity = blocks_at_once; - blk_t recover_block = ~0; - - bb_count = 0; - error_code = ext2fs_badblocks_list_iterate_begin(bb_list,&bb_iter); - if (error_code) { - uprintf("Error %d while beginning bad block list iteration", error_code); - // TODO - exit (1); - } - do { - ext2fs_badblocks_list_iterate (bb_iter, &next_bad); - } while (next_bad && next_bad < first_block); - - blkbuf = allocate_buffer(3 * blocks_at_once * block_size); - test_record = malloc (blocks_at_once*sizeof(struct saved_blk_record)); - if (!blkbuf || !test_record) { - uprintf("Error while allocating buffers"); - cancel_ops = -1; - return 0; - } - - save_base = blkbuf; - test_base = blkbuf + (blocks_at_once * block_size); - read_base = blkbuf + (2 * blocks_at_once * block_size); - - num_saved = 0; - - if (v_flag) { - uprintf("Checking for bad blocks in non-destructive read-write mode\n"); - uprintf("From block %lu to %lu\n", - (unsigned long) first_block, - (unsigned long) last_block - 1); - } - if (s_flag || v_flag > 1) { - uprintf("Checking for bad blocks (non-destructive read-write test)\n"); - } - if (setjmp(terminate_env)) { - /* - * Abnormal termination by a signal is handled here. - */ -// signal (SIGALRM, SIG_IGN); - uprintf("Interrupt caught, cleaning up\n"); - - save_ptr = save_base; - for (i=0; i < num_saved; i++) { - do_write(hDrive, save_ptr, test_record[i].num, - block_size, test_record[i].block); - save_ptr += test_record[i].num * block_size; - } - // TODO - exit(1); - } - - nr_pattern = ARRAYSIZE(pattern); - for (pat_idx = 0; pat_idx < ARRAYSIZE(pattern); pat_idx++) { - pattern_fill(test_base, pattern[pat_idx], blocks_at_once * block_size); - buf_used = 0; - bb_count = 0; - save_ptr = save_base; - test_ptr = test_base; - currently_testing = first_block; - num_blocks = last_block - 1; -// if (s_flag && v_flag <= 1) -// alarm_intr(SIGALRM); - - while (currently_testing < last_block) { - if (max_bb && bb_count >= max_bb) { - if (s_flag || v_flag) { - uprintf(abort_msg); - fprintf(log_fd, abort_msg); - fflush(log_fd); - } - cancel_ops = -1; - break; - } - tryout = granularity - buf_used; - if (next_bad) { - if (currently_testing == next_bad) { - /* fprintf (out, "%lu\n", nextbad); */ - ext2fs_badblocks_list_iterate (bb_iter, &next_bad); - currently_testing++; - goto check_for_more; - } - else if (currently_testing + tryout > next_bad) - tryout = next_bad - currently_testing; - } - if (currently_testing + tryout > last_block) - tryout = last_block - currently_testing; - got = do_read(hDrive, save_ptr, tryout, block_size, - currently_testing); - if (got == 0) { - if (recover_block == ~0) - recover_block = currently_testing + - blocks_at_once; - if (granularity != 1) { - granularity = 1; - continue; - } - /* First block must have been bad. */ - bb_count += bb_output(currently_testing++, READ_ERROR); - goto check_for_more; - } - - /* - * Note the fact that we've saved this much data - * *before* we overwrite it with test data - */ - test_record[num_saved].block = currently_testing; - test_record[num_saved].num = got; - num_saved++; - - /* Write the test data */ - written = do_write(hDrive, test_ptr, got, block_size, - currently_testing); - if (written != got) - uprintf("Error %d during test data write, block %lu", errno, - (unsigned long) currently_testing + - written); - - buf_used += got; - save_ptr += got * block_size; - test_ptr += got * block_size; - currently_testing += got; - if (got != tryout) { - if (recover_block == ~0) - recover_block = currently_testing - - got + blocks_at_once; - continue; - } - - check_for_more: - /* - * If there's room for more blocks to be tested this - * around, and we're not done yet testing the disk, go - * back and get some more blocks. - */ - if ((buf_used != granularity) && - (currently_testing < last_block)) - continue; - - if (currently_testing >= recover_block) { - granularity = blocks_at_once; - recover_block = ~0; - } - - save_currently_testing = currently_testing; - - /* - * for each contiguous block that we read into the - * buffer (and wrote test data into afterwards), read - * it back (looping if necessary, to get past newly - * discovered unreadable blocks, of which there should - * be none, but with a hard drive which is unreliable, - * it has happened), and compare with the test data - * that was written; output to the bad block list if - * it doesn't match. - */ - used2 = 0; - save_ptr = save_base; - test_ptr = test_base; - read_ptr = read_base; - tryout = 0; - - while (1) { - if (tryout == 0) { - if (used2 >= num_saved) - break; - currently_testing = test_record[used2].block; - tryout = test_record[used2].num; - used2++; - } - - got = do_read(hDrive, read_ptr, tryout, - block_size, currently_testing); - - /* test the comparison between all the - blocks successfully read */ - for (i = 0; i < got; ++i) - if (memcmp (test_ptr+i*block_size, - read_ptr+i*block_size, block_size)) - bb_count += bb_output(currently_testing + i, CORRUPTION_ERROR); - if (got < tryout) { - bb_count += bb_output(currently_testing + got, READ_ERROR); - got++; - } - - /* write back original data */ - do_write(hDrive, save_ptr, got, - block_size, currently_testing); - save_ptr += got * block_size; - - currently_testing += got; - test_ptr += got * block_size; - read_ptr += got * block_size; - tryout -= got; - } - - /* empty the buffer so it can be reused */ - num_saved = 0; - buf_used = 0; - save_ptr = save_base; - test_ptr = test_base; - currently_testing = save_currently_testing; - } - num_blocks = 0; -// alarm(0); -// if (s_flag || v_flag > 1) -// fputs(_(done_string), stderr); - - } - free_buffer(blkbuf); - free(test_record); - - ext2fs_badblocks_list_iterate_end(bb_iter); - - return bb_count; -} - BOOL BadBlocks(HANDLE hPhysicalDrive, ULONGLONG disk_size, int block_size, - int test_type, badblocks_report *report, FILE* fd) + int nb_passes, badblocks_report *report, FILE* fd) { errcode_t error_code; - unsigned int (*test_func)(HANDLE, blk_t, int, blk_t, unsigned int); blk_t first_block = 0, last_block = (blk_t)disk_size/block_size; if (report == NULL) return FALSE; @@ -930,21 +607,10 @@ BOOL BadBlocks(HANDLE hPhysicalDrive, ULONGLONG disk_size, int block_size, return FALSE; } - switch(test_type) { - case BADBLOCKS_RW: - test_func = test_rw; - break; - case BADBLOCKS_ND: - test_func = test_nd; - break; - default: - test_func = test_ro; - break; - } cancel_ops = 0; /* use a timer to update status every second */ SetTimer(hMainDialog, TID_BADBLOCKS_UPDATE, 1000, alarm_intr); - report->bb_count = test_func(hPhysicalDrive, last_block, block_size, first_block, EXT2_BLOCKS_AT_ONCE); + report->bb_count = test_rw(hPhysicalDrive, last_block, block_size, first_block, EXT2_BLOCKS_AT_ONCE, nb_passes); KillTimer(hMainDialog, TID_BADBLOCKS_UPDATE); free(bb_list->list); free(bb_list); diff --git a/src/badblocks.h b/src/badblocks.h index b836e6d4..07e3898f 100644 --- a/src/badblocks.h +++ b/src/badblocks.h @@ -35,19 +35,12 @@ typedef struct ext2_struct_u32_iterate *ext2_u32_iterate; #define EXT2_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 EXT2_CHECK_MAGIC(struct, code) \ if ((struct)->magic != (code)) return (code) #define EXT2_BAD_BLOCKS_THRESHOLD 256 #define EXT2_BLOCKS_AT_ONCE 64 #define EXT2_SYS_PAGE_SIZE 4096 -#define EXT2_RW_PATTERNS {0xaa, 0x55} -enum test_types { - BADBLOCKS_RO, /* Read-only */ - BADBLOCKS_RW, /* DESTRUCTIVE read-write */ - BADBLOCKS_ND /* non-destructive read-write */ -}; enum error_types { READ_ERROR, WRITE_ERROR, CORRUPTION_ERROR }; enum op_type { OP_READ, OP_WRITE }; diff --git a/src/format.c b/src/format.c index 40ddac0a..1e6eea1d 100644 --- a/src/format.c +++ b/src/format.c @@ -423,7 +423,7 @@ void __cdecl FormatThread(void* param) } if (!BadBlocks(hPhysicalDrive, SelectedDrive.DiskSize, - SelectedDrive.Geometry.BytesPerSector, BADBLOCKS_RW, &report, log_fd)) { + SelectedDrive.Geometry.BytesPerSector, ComboBox_GetCurSel(hNBPasses)+1, &report, log_fd)) { uprintf("Bad blocks check failed.\n"); if (!FormatStatus) FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)| diff --git a/src/resource.h b/src/resource.h index 742c1b48..7bf5aa43 100644 --- a/src/resource.h +++ b/src/resource.h @@ -47,6 +47,8 @@ #define IDC_DOS 1010 #define IDC_BADBLOCKS 1011 #define IDC_PROGRESS 1012 +#define IDC_DOSTYPE 1013 +#define IDC_NBPASSES 1014 #define IDC_ABOUT_LICENSE 1030 #define IDC_ABOUT_ICON 1031 #define IDC_RUFUS_BOLD 1032 @@ -57,7 +59,6 @@ #define IDC_NOTIFICATION_ICON 1040 #define IDC_NOTIFICATION_TEXT 1041 #define IDC_NOTIFICATION_LINE 1042 -#define IDC_DOSTYPE 1043 // Next default values for new objects // @@ -66,7 +67,7 @@ #define _APS_NO_MFC 1 #define _APS_NEXT_RESOURCE_VALUE 107 #define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1044 +#define _APS_NEXT_CONTROL_VALUE 1043 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif diff --git a/src/rufus.c b/src/rufus.c index 36aef5f8..abf43a33 100644 --- a/src/rufus.c +++ b/src/rufus.c @@ -55,7 +55,7 @@ HWND hMainDialog; char szFolderPath[MAX_PATH]; float fScale = 1.0f; int default_fs; -HWND hDeviceList, hCapacity, hFileSystem, hClusterSize, hLabel, hDOSType; +HWND hDeviceList, hCapacity, hFileSystem, hClusterSize, hLabel, hDOSType, hNBPasses; BOOL bWithFreeDOS; static HWND hDeviceTooltip = NULL, hFSTooltip = NULL, hProgress = NULL; @@ -904,6 +904,7 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA hProgress = GetDlgItem(hDlg, IDC_PROGRESS); hDOS = GetDlgItem(hDlg, IDC_DOS); hDOSType = GetDlgItem(hDlg, IDC_DOSTYPE); + hNBPasses = GetDlgItem(hDlg, IDC_NBPASSES); // High DPI scaling hDC = GetDC(hDlg); fScale = GetDeviceCaps(hDC, LOGPIXELSX) / 96.0f; @@ -924,11 +925,15 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA CreateStatusBar(); // Use maximum granularity for the progress bar SendMessage(hProgress, PBM_SETRANGE, 0, MAX_PROGRESS<<16); + // Fill up the passes + IGNORE_RETVAL(ComboBox_AddStringU(hNBPasses, "1 Pass")); + IGNORE_RETVAL(ComboBox_AddStringU(hNBPasses, "2 Passes")); + IGNORE_RETVAL(ComboBox_AddStringU(hNBPasses, "3 Passes")); + IGNORE_RETVAL(ComboBox_AddStringU(hNBPasses, "4 Passes")); + IGNORE_RETVAL(ComboBox_SetCurSel(hNBPasses, 1)); // Fill up the DOS type dropdown IGNORE_RETVAL(ComboBox_AddStringU(hDOSType, "FreeDOS")); IGNORE_RETVAL(ComboBox_AddStringU(hDOSType, "WinMe")); - // TODO: enable folder selection - // IGNORE_RETVAL(ComboBox_AddStringU(hDOSType, "Custom")); IGNORE_RETVAL(ComboBox_SetCurSel(hDOSType, bWithFreeDOS?DT_FREEDOS:DT_WINME)); if (bWithFreeDOS) { SetDlgItemTextA(hDlg, IDC_DOS, "Create a DOS bootable disk:"); diff --git a/src/rufus.h b/src/rufus.h index 906c1615..21bc832a 100644 --- a/src/rufus.h +++ b/src/rufus.h @@ -140,7 +140,7 @@ typedef struct { */ extern HINSTANCE hMainInstance; extern HWND hMainDialog, hStatus, hDeviceList, hCapacity; -extern HWND hFileSystem, hClusterSize, hLabel, hDOSType; +extern HWND hFileSystem, hClusterSize, hLabel, hDOSType, hNBPasses; extern float fScale; extern char szFolderPath[MAX_PATH]; extern DWORD FormatStatus; diff --git a/src/rufus.rc b/src/rufus.rc index de9d3e27..f3a2eabf 100644 --- a/src/rufus.rc +++ b/src/rufus.rc @@ -30,7 +30,7 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL IDD_DIALOG DIALOGEX 12, 12, 206, 278 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU EXSTYLE WS_EX_APPWINDOW -CAPTION "Rufus v1.0.7.111" +CAPTION "Rufus v1.0.7.112" FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN DEFPUSHBUTTON "Start",IDC_START,94,236,50,14 @@ -66,7 +66,7 @@ BEGIN DEFPUSHBUTTON "OK",IDOK,231,175,50,14,WS_GROUP CONTROL "http://rufus.akeo.ie",IDC_ABOUT_RUFUS_URL, "SysLink",WS_TABSTOP,46,47,114,9 - LTEXT "Version 1.0.7 (Build 111)",IDC_STATIC,46,19,78,8 + LTEXT "Version 1.0.7 (Build 112)",IDC_STATIC,46,19,78,8 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 LTEXT "Report bugs or request enhancements at:",IDC_STATIC,46,66,187,8 @@ -196,8 +196,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,0,7,111 - PRODUCTVERSION 1,0,7,111 + FILEVERSION 1,0,7,112 + PRODUCTVERSION 1,0,7,112 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -214,13 +214,13 @@ BEGIN BEGIN VALUE "CompanyName", "akeo.ie" VALUE "FileDescription", "Rufus" - VALUE "FileVersion", "1.0.7.111" + VALUE "FileVersion", "1.0.7.112" VALUE "InternalName", "Rufus" VALUE "LegalCopyright", "© 2011 Pete Batard (GPL v3)" VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html" VALUE "OriginalFilename", "rufus.exe" VALUE "ProductName", "Rufus" - VALUE "ProductVersion", "1.0.7.111" + VALUE "ProductVersion", "1.0.7.112" END END BLOCK "VarFileInfo"