From e419cf90156ffa539efeb969e9acd7d4e5043a4b Mon Sep 17 00:00:00 2001 From: Pete Batard Date: Tue, 6 Dec 2011 02:23:28 +0000 Subject: [PATCH] [core] added badblock checks (ALPHA) * also fixed some issues with read_sectors/write_sectors and dropped bufsize parameters --- Makefile.in | 2 +- TODO | 3 +- configure | 2 +- configure.ac | 4 +- src/.msvc/rufus_2010.vcxproj | 2 + src/.msvc/rufus_2010.vcxproj.filters | 6 + src/.msvc/rufus_sources | 23 +- src/Makefile.am | 2 +- src/Makefile.in | 15 +- src/badblocks.c | 1051 ++++++++++++++++++++++++++ src/badblocks.h | 60 ++ src/file.c | 49 +- src/format.c | 27 +- src/inc/file.h | 8 +- src/msdos.c | 9 +- src/resource.h | 3 +- src/rufus.c | 5 +- src/rufus.rc | 28 +- 18 files changed, 1219 insertions(+), 80 deletions(-) create mode 100644 src/badblocks.c create mode 100644 src/badblocks.h diff --git a/Makefile.in b/Makefile.in index 1e08adf7..02e3b298 100644 --- a/Makefile.in +++ b/Makefile.in @@ -32,7 +32,7 @@ NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : subdir = . -DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ +DIST_COMMON = README $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/configure $(am__configure_deps) ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.ac diff --git a/TODO b/TODO index 46609588..3642192f 100644 --- a/TODO +++ b/TODO @@ -6,6 +6,7 @@ o set keyboard according to locale in DOS o allow selection of one of the existing compatible volume (keep existing MBR) / full repartitioning (overwrite MBR) o FreeDOS integration o Enable compression for NTFS -o Bootable NTFS/exFAT +o Bootable NTFS/exFAT? + http://sourceforge.net/projects/grub4dos/ o GPT support? o disable indexing support on NTFS? diff --git a/configure b/configure index f2a60a98..81c7c2db 100644 --- a/configure +++ b/configure @@ -3360,7 +3360,7 @@ $as_echo "#define _GNU_SOURCE /**/" >>confdefs.h # AC_MSG_ERROR([unsupported development environment]) #esac -AM_CFLAGS="${AM_CFLAGS} -DWINVER=0x501 -D_WIN32_IE=0x501" +AM_CFLAGS="${AM_CFLAGS} -D__MSVCRT_VERSION__=0x700 -DWINVER=0x501 -D_WIN32_IE=0x501" AM_LDFLAGS="${AM_LDFLAGS} -Wl,-no-undefined" # Debug logging diff --git a/configure.ac b/configure.ac index f54a00ac..6320e096 100644 --- a/configure.ac +++ b/configure.ac @@ -1,4 +1,4 @@ -AC_INIT([rufus], [1.0.1], [https://github.com/pbatard/rufus/issues], [rufus], [https://github.com/pbatard/rufus]) +AC_INIT([rufus], [1.0.2], [https://github.com/pbatard/rufus/issues], [rufus], [https://github.com/pbatard/rufus]) AM_INIT_AUTOMAKE([-Wno-portability foreign no-dist no-dependencies]) AC_CONFIG_SRCDIR([src/rufus.c]) AC_CONFIG_MACRO_DIR([m4]) @@ -31,7 +31,7 @@ AC_DEFINE([_GNU_SOURCE], [], [Use GNU extensions]) # AC_MSG_ERROR([unsupported development environment]) #esac -AM_CFLAGS="${AM_CFLAGS} -DWINVER=0x501 -D_WIN32_IE=0x501" +AM_CFLAGS="${AM_CFLAGS} -D__MSVCRT_VERSION__=0x700 -DWINVER=0x501 -D_WIN32_IE=0x501" AM_LDFLAGS="${AM_LDFLAGS} -Wl,-no-undefined" # Debug logging diff --git a/src/.msvc/rufus_2010.vcxproj b/src/.msvc/rufus_2010.vcxproj index 5438044c..12a1a896 100644 --- a/src/.msvc/rufus_2010.vcxproj +++ b/src/.msvc/rufus_2010.vcxproj @@ -146,6 +146,7 @@ + @@ -159,6 +160,7 @@ + diff --git a/src/.msvc/rufus_2010.vcxproj.filters b/src/.msvc/rufus_2010.vcxproj.filters index 3d76b7ae..d6b4d3e0 100644 --- a/src/.msvc/rufus_2010.vcxproj.filters +++ b/src/.msvc/rufus_2010.vcxproj.filters @@ -51,6 +51,9 @@ Source Files + + Source Files + @@ -155,6 +158,9 @@ Header Files + + Header Files + diff --git a/src/.msvc/rufus_sources b/src/.msvc/rufus_sources index 1932a2ef..9982e36e 100644 --- a/src/.msvc/rufus_sources +++ b/src/.msvc/rufus_sources @@ -23,15 +23,16 @@ TARGETLIBS=$(SDK_LIB_PATH)\kernel32.lib \ # http://jpassing.com/2008/02/01/how-to-use-manifests-with-buildexe/ SXS_APPLICATION_MANIFEST=common_controls_and_elevation.manifest -SOURCES=rufus.c \ - format.c \ - stdio.c \ - stdlg.c \ - msdos.c \ - drive.c \ - file.c \ - br.c \ - fat12.c \ - fat16.c \ - fat32.c \ +SOURCES=rufus.c \ + format.c \ + stdio.c \ + stdlg.c \ + msdos.c \ + badblocks.c \ + drive.c \ + file.c \ + br.c \ + fat12.c \ + fat16.c \ + fat32.c \ rufus.rc diff --git a/src/Makefile.am b/src/Makefile.am index 513eaeb8..e57b3725 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -9,7 +9,7 @@ pkg_v_rc_0 = @echo " RC $@"; %_rc.o: %.rc $(pkg_v_rc)$(WINDRES) -i $< -o $@ -rufus_SOURCES = fat12.c fat16.c fat32.c br.c file.c drive.c msdos.c format.c stdio.c stdlg.c rufus.c +rufus_SOURCES = fat12.c fat16.c fat32.c br.c file.c drive.c msdos.c badblocks.c format.c stdio.c stdlg.c rufus.c rufus_CFLAGS = -I./inc $(ARCH_CFLAGS) $(AM_CFLAGS) rufus_LDFLAGS = $(AM_LDFLAGS) -mwindows rufus_LDADD = rufus_rc.o -lsetupapi -lole32 -lgdi32 diff --git a/src/Makefile.in b/src/Makefile.in index 83566384..a423f1e2 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -48,8 +48,9 @@ PROGRAMS = $(noinst_PROGRAMS) am_rufus_OBJECTS = rufus-fat12.$(OBJEXT) rufus-fat16.$(OBJEXT) \ rufus-fat32.$(OBJEXT) rufus-br.$(OBJEXT) rufus-file.$(OBJEXT) \ rufus-drive.$(OBJEXT) rufus-msdos.$(OBJEXT) \ - rufus-format.$(OBJEXT) rufus-stdio.$(OBJEXT) \ - rufus-stdlg.$(OBJEXT) rufus-rufus.$(OBJEXT) + rufus-badblocks.$(OBJEXT) rufus-format.$(OBJEXT) \ + rufus-stdio.$(OBJEXT) rufus-stdlg.$(OBJEXT) \ + rufus-rufus.$(OBJEXT) rufus_OBJECTS = $(am_rufus_OBJECTS) rufus_DEPENDENCIES = rufus_rc.o rufus_LINK = $(CCLD) $(rufus_CFLAGS) $(CFLAGS) $(rufus_LDFLAGS) \ @@ -167,7 +168,7 @@ top_srcdir = @top_srcdir@ pkg_v_rc = $(pkg_v_rc_$(V)) pkg_v_rc_ = $(pkg_v_rc_$(AM_DEFAULT_VERBOSITY)) pkg_v_rc_0 = @echo " RC $@"; -rufus_SOURCES = fat12.c fat16.c fat32.c br.c file.c drive.c msdos.c format.c stdio.c stdlg.c rufus.c +rufus_SOURCES = fat12.c fat16.c fat32.c br.c file.c drive.c msdos.c badblocks.c format.c stdio.c stdlg.c rufus.c rufus_CFLAGS = -I./inc $(ARCH_CFLAGS) $(AM_CFLAGS) rufus_LDFLAGS = $(AM_LDFLAGS) -mwindows rufus_LDADD = rufus_rc.o -lsetupapi -lole32 -lgdi32 @@ -282,6 +283,14 @@ rufus-msdos.obj: msdos.c $(AM_V_CC) @AM_BACKSLASH@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rufus_CFLAGS) $(CFLAGS) -c -o rufus-msdos.obj `if test -f 'msdos.c'; then $(CYGPATH_W) 'msdos.c'; else $(CYGPATH_W) '$(srcdir)/msdos.c'; fi` +rufus-badblocks.o: badblocks.c + $(AM_V_CC) @AM_BACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rufus_CFLAGS) $(CFLAGS) -c -o rufus-badblocks.o `test -f 'badblocks.c' || echo '$(srcdir)/'`badblocks.c + +rufus-badblocks.obj: badblocks.c + $(AM_V_CC) @AM_BACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rufus_CFLAGS) $(CFLAGS) -c -o rufus-badblocks.obj `if test -f 'badblocks.c'; then $(CYGPATH_W) 'badblocks.c'; else $(CYGPATH_W) '$(srcdir)/badblocks.c'; fi` + rufus-format.o: format.c $(AM_V_CC) @AM_BACKSLASH@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rufus_CFLAGS) $(CFLAGS) -c -o rufus-format.o `test -f 'format.c' || echo '$(srcdir)/'`format.c diff --git a/src/badblocks.c b/src/badblocks.c new file mode 100644 index 00000000..8e9e13dd --- /dev/null +++ b/src/badblocks.c @@ -0,0 +1,1051 @@ +/* + * badblocks.c - Bad blocks checker + * + * Copyright (C) 1992, 1993, 1994 Remy Card + * Laboratoire MASI, Institut Blaise Pascal + * Universite Pierre et Marie Curie (Paris VI) + * + * Copyright 1995, 1996, 1997, 1998, 1999 by Theodore Ts'o + * Copyright 1999 by David Beattie + * Copyright 2011 by Pete Batard + * + * This file is based on the minix file system programs fsck and mkfs + * written and copyrighted by Linus Torvalds + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +/* + * History: + * 93/05/26 - Creation from e2fsck + * 94/02/27 - Made a separate bad blocks checker + * 99/06/30...99/07/26 - Added non-destructive write-testing, + * configurable blocks-at-once parameter, + * loading of badblocks list to avoid testing + * blocks known to be bad, multiple passes to + * make sure that no new blocks are added to the + * list. (Work done by David Beattie) + * 11/12/04 - Windows/Rufus integration (Pete Batard) + */ + +#include +#include +#include +//#include +#include +#include +#include +#include +#include + +#include "rufus.h" +#include "badblocks.h" +#include "file.h" + +/* + *From e2fsprogs/e2fsck/badblocks.c + */ +static errcode_t make_u32_list(int size, int num, __u32 *list, + ext2_u32_list *ret) +{ + ext2_u32_list bb; + + bb = calloc(1, sizeof(struct ext2_struct_u32_list)); + if (bb == NULL) + return EXT2_ET_NO_MEMORY; + bb->magic = EXT2_ET_MAGIC_BADBLOCKS_LIST; + bb->size = size ? size : 10; + bb->num = num; + bb->list = malloc(sizeof(blk_t) * bb->size); + if (bb->list == NULL) { + free(bb); + bb = NULL; + return EXT2_ET_NO_MEMORY; + } + if (list) + memcpy(bb->list, list, bb->size * sizeof(blk_t)); + else + memset(bb->list, 0, bb->size * sizeof(blk_t)); + *ret = bb; + return 0; +} + +/* + * This procedure creates an empty badblocks list. + */ +static errcode_t ext2fs_badblocks_list_create(ext2_badblocks_list *ret, int size) +{ + return make_u32_list(size, 0, 0, (ext2_badblocks_list *) ret); +} + +/* + * This procedure adds a block to a badblocks list. + */ +static errcode_t ext2fs_u32_list_add(ext2_u32_list bb, __u32 blk) +{ + int i, j; + unsigned long old_size; + __u32* old_bb_list = bb->list; + + EXT2_CHECK_MAGIC(bb, EXT2_ET_MAGIC_BADBLOCKS_LIST); + + if (bb->num >= bb->size) { + old_size = bb->size * sizeof(__u32); + bb->size += 100; + bb->list = realloc(bb->list, bb->size * sizeof(__u32)); + if (bb->list == NULL) { + bb->list = old_bb_list; + bb->size -= 100; + return EXT2_ET_NO_MEMORY; + } + } + + /* + * Add special case code for appending to the end of the list + */ + i = bb->num-1; + if ((bb->num != 0) && (bb->list[i] == blk)) + return 0; + if ((bb->num == 0) || (bb->list[i] < blk)) { + bb->list[bb->num++] = blk; + return 0; + } + + j = bb->num; + for (i=0; i < bb->num; i++) { + if (bb->list[i] == blk) + return 0; + if (bb->list[i] > blk) { + j = i; + break; + } + } + for (i=bb->num; i > j; i--) + bb->list[i] = bb->list[i-1]; + bb->list[j] = blk; + bb->num++; + return 0; +} + +static errcode_t ext2fs_badblocks_list_add(ext2_badblocks_list bb, blk_t blk) +{ + return ext2fs_u32_list_add((ext2_u32_list) bb, (__u32) blk); +} + +/* + * This procedure finds a particular block is on a badblocks + * list. + */ +static int ext2fs_u32_list_find(ext2_u32_list bb, __u32 blk) +{ + int low, high, mid; + + if (bb->magic != EXT2_ET_MAGIC_BADBLOCKS_LIST) + return -1; + + if (bb->num == 0) + return -1; + + low = 0; + high = bb->num-1; + if (blk == bb->list[low]) + return low; + if (blk == bb->list[high]) + return high; + + while (low < high) { + mid = ((unsigned)low + (unsigned)high)/2; + if (mid == low || mid == high) + break; + if (blk == bb->list[mid]) + return mid; + if (blk < bb->list[mid]) + high = mid; + else + low = mid; + } + return -1; +} + +/* + * This procedure tests to see if a particular block is on a badblocks + * list. + */ +static int ext2fs_u32_list_test(ext2_u32_list bb, __u32 blk) +{ + if (ext2fs_u32_list_find(bb, blk) < 0) + return 0; + else + return 1; +} + +static int ext2fs_badblocks_list_test(ext2_badblocks_list bb, blk_t blk) +{ + return ext2fs_u32_list_test((ext2_u32_list) bb, (__u32) blk); +} + +/* + * Remove a block from the badblock list + */ +int ext2fs_u32_list_del(ext2_u32_list bb, __u32 blk) +{ + int remloc, i; + + if (bb->num == 0) + return -1; + + remloc = ext2fs_u32_list_find(bb, blk); + if (remloc < 0) + return -1; + + for (i = remloc ; i < bb->num-1; i++) + bb->list[i] = bb->list[i+1]; + bb->num--; + return 0; +} + +static void ext2fs_badblocks_list_del(ext2_u32_list bb, __u32 blk) +{ + ext2fs_u32_list_del(bb, blk); +} + +static errcode_t ext2fs_u32_list_iterate_begin(ext2_u32_list bb, + ext2_u32_iterate *ret) +{ + ext2_u32_iterate iter; + + EXT2_CHECK_MAGIC(bb, EXT2_ET_MAGIC_BADBLOCKS_LIST); + + iter = malloc(sizeof(struct ext2_struct_u32_iterate)); + if (iter == NULL) + return EXT2_ET_NO_MEMORY; + + iter->magic = EXT2_ET_MAGIC_BADBLOCKS_ITERATE; + iter->bb = bb; + iter->ptr = 0; + *ret = iter; + return 0; +} + +static errcode_t ext2fs_badblocks_list_iterate_begin(ext2_badblocks_list bb, + ext2_badblocks_iterate *ret) +{ + return ext2fs_u32_list_iterate_begin((ext2_u32_list) bb, + (ext2_u32_iterate *) ret); +} + + +static int ext2fs_u32_list_iterate(ext2_u32_iterate iter, __u32 *blk) +{ + ext2_u32_list bb; + + if (iter->magic != EXT2_ET_MAGIC_BADBLOCKS_ITERATE) + return 0; + + bb = iter->bb; + + if (bb->magic != EXT2_ET_MAGIC_BADBLOCKS_LIST) + return 0; + + if (iter->ptr < bb->num) { + *blk = bb->list[iter->ptr++]; + return 1; + } + *blk = 0; + return 0; +} + +static int ext2fs_badblocks_list_iterate(ext2_badblocks_iterate iter, blk_t *blk) +{ + return ext2fs_u32_list_iterate((ext2_u32_iterate) iter, + (__u32 *) blk); +} + + +static void ext2fs_u32_list_iterate_end(ext2_u32_iterate iter) +{ + if (!iter || (iter->magic != EXT2_ET_MAGIC_BADBLOCKS_ITERATE)) + return; + + iter->bb = 0; + free(iter); +} + +static void ext2fs_badblocks_list_iterate_end(ext2_badblocks_iterate iter) +{ + ext2fs_u32_list_iterate_end((ext2_u32_iterate) iter); +} + + +static int ext2fs_u32_list_equal(ext2_u32_list bb1, ext2_u32_list bb2) +{ + EXT2_CHECK_MAGIC(bb1, EXT2_ET_MAGIC_BADBLOCKS_LIST); + EXT2_CHECK_MAGIC(bb2, EXT2_ET_MAGIC_BADBLOCKS_LIST); + + if (bb1->num != bb2->num) + return 0; + + if (memcmp(bb1->list, bb2->list, bb1->num * sizeof(blk_t)) != 0) + return 0; + return 1; +} + +static int ext2fs_badblocks_equal(ext2_badblocks_list bb1, ext2_badblocks_list bb2) +{ + return ext2fs_u32_list_equal((ext2_u32_list) bb1, + (ext2_u32_list) bb2); +} + +static int ext2fs_u32_list_count(ext2_u32_list bb) +{ + return bb->num; +} + +/* + * from e2fsprogs\misc\badblocks.c + */ +static int v_flag = 2; /* verbose */ +static int w_flag = 0; /* do r/w test: 0=no, 1=yes, + * 2=non-destructive */ +static int s_flag = 1; /* show progress of test */ +static int t_flag = 0; /* number of test patterns */ +static int t_max = 0; /* allocated test patterns */ +static unsigned int *t_patts = NULL; /* test patterns */ +// TODO: set this from parameter +static unsigned int max_bb = 32; /* Abort test if more than this number of bad blocks has been encountered */ +static unsigned int d_flag = 0; /* delay factor between reads */ +static DWORD time_start; + +#define T_INC 32 + +unsigned int sys_page_size = 4096; + +static blk_t currently_testing = 0; +static blk_t num_blocks = 0; +static blk_t num_read_errors = 0; +static blk_t num_write_errors = 0; +static blk_t num_corruption_errors = 0; +static ext2_badblocks_list bb_list = NULL; +static FILE *out; +static blk_t next_bad = 0; +static ext2_badblocks_iterate bb_iter = NULL; + +enum error_types { READ_ERROR, WRITE_ERROR, CORRUPTION_ERROR }; + +static __inline void *allocate_buffer(size_t size) { + // TODO: requires -D__MSVCRT_VERSION__=0x700 for MinGW + // find out if older XP platforms might miss it + return _aligned_malloc(size, sys_page_size); +} + +static __inline void free_buffer(void* p) { + _aligned_free(p); +} + +/* + * This routine reports a new bad block. If the bad block has already + * been seen before, then it returns 0; otherwise it returns 1. + */ +static int bb_output (blk_t bad, enum error_types error_type) +{ + errcode_t errcode; + + if (ext2fs_badblocks_list_test(bb_list, bad)) + return 0; + + uprintf("%lu\n", (unsigned long) bad); + + errcode = ext2fs_badblocks_list_add(bb_list, bad); + if (errcode) { + uprintf("Error %d adding to in-memory bad block list", errcode); + exit (1); + } + + /* kludge: + increment the iteration through the bb_list if + an element was just added before the current iteration + position. This should not cause next_bad to change. */ + if (bb_iter && bad < next_bad) + ext2fs_badblocks_list_iterate (bb_iter, &next_bad); + + if (error_type == READ_ERROR) { + num_read_errors++; + } else if (error_type == WRITE_ERROR) { + num_write_errors++; + } else if (error_type == CORRUPTION_ERROR) { + num_corruption_errors++; + } + return 1; +} + +static float calc_percent(unsigned long current, unsigned long total) { + float percent = 0.0; + if (total <= 0) + return percent; + if (current >= total) { + percent = 100.0f; + } else { + percent=(100.0f*(float)current/(float)total); + } + return percent; +} + +static void print_status(void) +{ + static DWORD msecs = 0; + DWORD time_end; + + // TODO: use GetTickCount64 on Vista and later + time_end = GetTickCount(); + /* update status every second */ + if (time_end - time_start >= msecs) { + uprintf("%6.2f%% done, %0.2f elapsed. " + "(%d/%d/%d errors)", + calc_percent((unsigned long) currently_testing, + (unsigned long) num_blocks), + (time_end - time_start)/1000.0, + num_read_errors, + num_write_errors, + num_corruption_errors); + msecs += 1000; + } +} + +static void pattern_fill(unsigned char *buffer, unsigned int pattern, + size_t n) +{ + unsigned int i, nb; + unsigned char bpattern[sizeof(pattern)], *ptr; + + if (pattern == (unsigned int) ~0) { + for (ptr = buffer; ptr < buffer + n; ptr++) { + (*ptr) = rand() % (1 << (8 * sizeof(char))); + } + PrintStatus("Testing with random pattern: "); + } else { + bpattern[0] = 0; + for (i = 0; i < sizeof(bpattern); i++) { + if (pattern == 0) + break; + bpattern[i] = pattern & 0xFF; + pattern = pattern >> 8; + } + nb = i ? (i-1) : 0; + for (ptr = buffer, i = nb; ptr < buffer + n; ptr++) { + *ptr = bpattern[i]; + if (i == 0) + i = nb; + else + i--; + } + PrintStatus("Testing with pattern 0x%02X", bpattern[i]); + } +} + +/* + * Perform a read of a sequence of blocks; return the number of blocks + * successfully sequentially read. + */ +static int do_read (HANDLE hDrive, unsigned char * buffer, int tryout, int block_size, + blk_t current_block) +{ + long got; + DWORD tv1, tv2; +#define NANOSEC (1000000000L) +#define MILISEC (1000L) + +#if 0 + printf("do_read: block %d, try %d\n", current_block, tryout); +#endif + + if (v_flag > 1) + print_status(); + + /* Try the read */ + if (d_flag) + tv1 = GetTickCount(); + got = read_sectors(hDrive, block_size, current_block, tryout, buffer); + // read (dev, buffer, tryout * block_size); + if (d_flag) + tv2 = GetTickCount(); + if (got < 0) + got = 0; + if (got & 511) + uprintf("Weird value (%ld) in do_read\n", got); + got /= block_size; + if (d_flag && got == tryout) { +// TODO: either remove or update for Windows +#ifdef HAVE_NANOSLEEP + struct timespec ts; + ts.tv_sec = tv2.tv_sec - tv1.tv_sec; + ts.tv_nsec = (tv2.tv_usec - tv1.tv_usec) * MILISEC; + if (ts.tv_nsec < 0) { + ts.tv_nsec += NANOSEC; + ts.tv_sec -= 1; + } + /* increase/decrease the sleep time based on d_flag value */ + ts.tv_sec = ts.tv_sec * d_flag / 100; + ts.tv_nsec = ts.tv_nsec * d_flag / 100; + if (ts.tv_nsec > NANOSEC) { + ts.tv_sec += ts.tv_nsec / NANOSEC; + ts.tv_nsec %= NANOSEC; + } + if (ts.tv_sec || ts.tv_nsec) + nanosleep(&ts, NULL); +#else +#ifdef HAVE_USLEEP + struct timeval tv; + tv.tv_sec = tv2.tv_sec - tv1.tv_sec; + tv.tv_usec = tv2.tv_usec - tv1.tv_usec; + tv.tv_sec = tv.tv_sec * d_flag / 100; + tv.tv_usec = tv.tv_usec * d_flag / 100; + if (tv.tv_usec > 1000000) { + tv.tv_sec += tv.tv_usec / 1000000; + tv.tv_usec %= 1000000; + } + if (tv.tv_sec) + sleep(tv.tv_sec); + if (tv.tv_usec) + usleep(tv.tv_usec); +#endif +#endif + } + return got; +} + +/* + * Perform a write of a sequence of blocks; return the number of blocks + * successfully sequentially written. + */ +static int do_write(HANDLE hDrive, unsigned char * buffer, int tryout, int block_size, + unsigned long current_block) +{ + long got; + +#if 0 + printf("do_write: block %lu, try %d\n", current_block, tryout); +#endif + if (v_flag > 1) + print_status(); + + /* Try the write */ + got = write_sectors(hDrive, block_size, current_block, tryout, buffer); + if (got < 0) + got = 0; + if (got & 511) + uprintf("Weird value (%ld) in do_write\n", got); + got /= block_size; + 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 errcode; + blk_t recover_block = ~0; + + errcode = ext2fs_badblocks_list_iterate_begin(bb_list,&bb_iter); + if (errcode) { + // TODO: set FormatStatus + uprintf("errcode %d while beginning bad block list iteration\n", errcode); + return 0; + } + do { + ext2fs_badblocks_list_iterate (bb_iter, &next_bad); + } while (next_bad && next_bad < first_block); + + if (t_flag) { + blkbuf = allocate_buffer((blocks_at_once + 1) * block_size); + } else { + blkbuf = allocate_buffer(blocks_at_once * block_size); + } + if (!blkbuf) + { + // TODO: err + uprintf("could not allocate buffers\n"); + return 0; + } + if (t_flag) { + uprintf("Checking for bad blocks in read-only mode\n"); + pattern_fill(blkbuf + blocks_at_once * block_size, + t_patts[0], block_size); + } + tryout = blocks_at_once; + currently_testing = first_block; + num_blocks = last_block - 1; + if (!t_flag && (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("Too many bad blocks, aborting test\n"); + } + 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 (t_flag) { + /* test the comparison between all the + blocks successfully read */ + int i; + for (i = 0; i < got; ++i) + if (memcmp (blkbuf+i*block_size, + blkbuf+blocks_at_once*block_size, + block_size)) + bb_count += bb_output(currently_testing + i, CORRUPTION_ERROR); + } + 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) +{ + unsigned char *buffer, *read_buffer; + const unsigned int patterns[] = {0xaa}; // {0xaa, 0x55, 0xff, 0x00}; + const unsigned int *pattern; + int i, tryout, got, nr_pattern, pat_idx; + unsigned int bb_count = 0; + blk_t recover_block = ~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"); + 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); + if (t_flag) { + pattern = t_patts; + nr_pattern = t_flag; + } else { + pattern = patterns; + nr_pattern = ARRAYSIZE(patterns); + } + // TODO: allow cancellation + for (pat_idx = 0; pat_idx < nr_pattern; pat_idx++) { + pattern_fill(buffer, pattern[pat_idx], blocks_at_once * block_size); + num_blocks = last_block - 1; + currently_testing = first_block; +// if (s_flag && v_flag <= 1) +// alarm_intr(SIGALRM); + if (s_flag | v_flag) + uprintf("Writing\n"); + tryout = blocks_at_once; + while (currently_testing < last_block) { + if (max_bb && bb_count >= max_bb) { + if (s_flag || v_flag) { + // TODO: this abort blows + uprintf("Too many bad blocks, aborting test\n"); + } + break; + } + if (currently_testing + tryout > last_block) + tryout = last_block - currently_testing; + got = do_write(hDrive, buffer, tryout, block_size, currently_testing); + if (v_flag > 1) + print_status(); + + if (got == 0 && tryout == 1) + bb_count += bb_output(currently_testing++, WRITE_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); + if (s_flag | v_flag) + // TODO: status + uprintf("Reading and comparing\n"); + num_blocks = last_block; + currently_testing = first_block; +// if (s_flag && v_flag <= 1) +// alarm_intr(SIGALRM); + + tryout = blocks_at_once; + while (currently_testing < last_block) { + if (max_bb && bb_count >= max_bb) { + if (s_flag || v_flag) { + uprintf("Too many bad blocks, aborting test\n"); + } + break; + } + if (currently_testing + tryout > last_block) + tryout = last_block - currently_testing; + got = do_read(hDrive, read_buffer, 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; + } + for (i=0; i < got; i++) { + if (memcmp(read_buffer + i * block_size, + buffer + i * block_size, + block_size)) + bb_count += bb_output(currently_testing+i, CORRUPTION_ERROR); + } + if (v_flag > 1) + print_status(); + } + + num_blocks = 0; +// alarm (0); +// if (s_flag | v_flag) +// fputs(_(done_string), stderr); + } + free_buffer(buffer); + return bb_count; +} + +struct saved_blk_record { + blk_t block; + int num; +}; + +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 patterns[] = { ~0 }; + const unsigned int *pattern; + int nr_pattern, 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 errcode; + unsigned long buf_used; + static unsigned int bb_count; + int granularity = blocks_at_once; + blk_t recover_block = ~0; + + bb_count = 0; + errcode = ext2fs_badblocks_list_iterate_begin(bb_list,&bb_iter); + if (errcode) { + uprintf("Error %d while beginning bad block list iteration", errcode); + 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"); + exit (1); + } + + 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; + } + fflush (out); + exit(1); + } + + if (t_flag) { + pattern = t_patts; + nr_pattern = t_flag; + } else { + pattern = patterns; + nr_pattern = sizeof(patterns) / sizeof(patterns[0]); + } + for (pat_idx = 0; pat_idx < nr_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("Too many bad blocks, aborting test\n"); + } + break; + } + got = 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) { + tryout = 1; + 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; +} + +int BadBlocks(HANDLE hPhysicalDrive, ULONGLONG disk_size, int block_size) +{ + errcode_t errcode; + unsigned int blocks_at_once = 64; + unsigned int (*test_func)(HANDLE, blk_t, + int, blk_t, + unsigned int); + int num_passes = 0; + int passes_clean = 0; + int bb_count; + blk_t first_block = 0, last_block = (blk_t)disk_size/block_size; + + errcode = ext2fs_badblocks_list_create(&bb_list, 0); + if (errcode) { + uprintf("Error %d while creating in-memory bad blocks list", errcode); + return -1; + } + + test_func = test_rw; + time_start = GetTickCount(); + do { + bb_count = test_func(hPhysicalDrive, last_block, block_size, first_block, blocks_at_once); + if (bb_count) + passes_clean = 0; + else + ++passes_clean; + + if (v_flag) + uprintf("Pass completed, %u bad blocks found. (%d/%d/%d errors)\n", + bb_count, num_read_errors, num_write_errors, num_corruption_errors); + + } while (passes_clean < num_passes); + free(t_patts); + free(bb_list->list); + free(bb_list); + + return bb_count; +} diff --git a/src/badblocks.h b/src/badblocks.h new file mode 100644 index 00000000..20e23963 --- /dev/null +++ b/src/badblocks.h @@ -0,0 +1,60 @@ +/* + * badblocks.c - Bad blocks checker + * + * Copyright (C) 1992, 1993, 1994 Remy Card + * Laboratoire MASI, Institut Blaise Pascal + * Universite Pierre et Marie Curie (Paris VI) + * + * Copyright 1995, 1996, 1997, 1998, 1999 by Theodore Ts'o + * Copyright 1999 by David Beattie + * Copyright 2011 by Pete Batard + * + * This file is based on the minix file system programs fsck and mkfs + * written and copyrighted by Linus Torvalds + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include + +#ifndef __u32 +#define __u32 UINT32 +#endif +typedef UINT32 blk_t; +typedef struct ext2_struct_u32_list *ext2_badblocks_list; +typedef struct ext2_struct_u32_iterate *ext2_badblocks_iterate; +typedef struct ext2_struct_u32_list *ext2_u32_list; +typedef struct ext2_struct_u32_iterate *ext2_u32_iterate; +typedef long errcode_t; + +#define EXT2_ET_NO_MEMORY (2133571398L) +#define EXT2_ET_MAGIC_BADBLOCKS_LIST (2133571330L) +#define EXT2_ET_MAGIC_BADBLOCKS_ITERATE (2133571331L) + +#define EXT2_CHECK_MAGIC(struct, code) \ + if ((struct)->magic != (code)) return (code) + +/* + * Badblocks list + */ +struct ext2_struct_u32_list { + int magic; + int num; + int size; + __u32 *list; + int badblocks_flags; +}; + +struct ext2_struct_u32_iterate { + int magic; + ext2_u32_list bb; + int ptr; +}; + +/* + * Shared prototypes + */ +BOOL BadBlocks(HANDLE hPhysicalDrive, ULONGLONG disk_size, int block_size); diff --git a/src/file.c b/src/file.c index 9b01b87a..31c2e319 100644 --- a/src/file.c +++ b/src/file.c @@ -22,64 +22,53 @@ #include "rufus.h" #include "file.h" +/* Returns the number of bytes written or -1 on error */ int write_sectors(HANDLE hDrive, size_t SectorSize, size_t StartSector, size_t nSectors, - const void *pBuf, size_t BufSize) + const void *pBuf) { LARGE_INTEGER ptr; - DWORD Size; - - if(SectorSize * nSectors > BufSize) - { - uprintf("write_sectors: Buffer is too small\n"); - return 0; - } + DWORD Size = 0; ptr.QuadPart = StartSector*SectorSize; if(!SetFilePointerEx(hDrive, ptr, NULL, FILE_BEGIN)) { uprintf("write_sectors: Could not access sector %d - %s\n", StartSector, WindowsErrorString()); - return 0; + return -1; } - if((!WriteFile(hDrive, pBuf, (DWORD)BufSize, &Size, NULL)) || (Size != BufSize)) + if((!WriteFile(hDrive, pBuf, (DWORD)nSectors*SectorSize, &Size, NULL)) || (Size != nSectors*SectorSize)) { uprintf("write_sectors: Write error - %s\n", WindowsErrorString()); uprintf(" StartSector:%0X, nSectors:%0X, SectorSize:%0X\n", StartSector, nSectors, SectorSize); - return 0; + return Size; } - return 1; + return Size; } +/* Returns the number of bytes read or -1 on error */ int read_sectors(HANDLE hDrive, size_t SectorSize, size_t StartSector, size_t nSectors, - void *pBuf, size_t BufSize) + void *pBuf) { LARGE_INTEGER ptr; - DWORD Size; - - if(SectorSize * nSectors > BufSize) - { - uprintf("read_sectors: Buffer is too small\n"); - return 0; - } + DWORD Size = 0; ptr.QuadPart = StartSector*SectorSize; if(!SetFilePointerEx(hDrive, ptr, NULL, FILE_BEGIN)) { uprintf("read_sectors: Could not access sector %d - %s\n", StartSector, WindowsErrorString()); - return 0; + return -1; } - if((!ReadFile(hDrive, pBuf, (DWORD)BufSize, &Size, NULL)) || (Size != BufSize)) + if((!ReadFile(hDrive, pBuf, (DWORD)nSectors*SectorSize, &Size, NULL)) || (Size != nSectors*SectorSize)) { uprintf("read_sectors: Read error - %s\n", WindowsErrorString()); uprintf(" StartSector:%0X, nSectors:%0X, SectorSize:%0X\n", StartSector, nSectors, SectorSize); - return 0; } - return 1; + return Size; } /* Use a bastardized fp that contains a Windows handle and the sector size */ @@ -101,8 +90,8 @@ int contains_data(FILE *fp, size_t Position, return 0; } - if(!read_sectors(hDrive, SectorSize, StartSector, - NumSectors, aucBuf, sizeof(aucBuf))) + if(read_sectors(hDrive, SectorSize, StartSector, + NumSectors, aucBuf) <= 0) return 0; if(memcmp(pData, &aucBuf[Position - StartSector*SectorSize], Len)) @@ -130,15 +119,15 @@ int write_data(FILE *fp, size_t Position, } /* Data to write may not be aligned on a sector boundary => read into a sector buffer first */ - if(!read_sectors(hDrive, SectorSize, StartSector, - NumSectors, aucBuf, sizeof(aucBuf))) + if(read_sectors(hDrive, SectorSize, StartSector, + NumSectors, aucBuf) <= 0) return 0; if(!memcpy(&aucBuf[Position - StartSector*SectorSize], pData, Len)) return 0; - if(!write_sectors(hDrive, SectorSize, StartSector, - NumSectors, aucBuf, sizeof(aucBuf))) + if(write_sectors(hDrive, SectorSize, StartSector, + NumSectors, aucBuf) <= 0) return 0; return 1; } /* write_data */ diff --git a/src/format.c b/src/format.c index e8eaa769..7afdf6be 100644 --- a/src/format.c +++ b/src/format.c @@ -37,6 +37,7 @@ #include "fat32.h" #include "file.h" #include "format.h" +#include "badblocks.h" /* * Globals @@ -234,7 +235,7 @@ static BOOL WriteMBR(HANDLE hPhysicalDrive) goto out; } - if (!read_sectors(hPhysicalDrive, SelectedDrive.Geometry.BytesPerSector, 0, nSecs, buf, SecSize)) { + if (!read_sectors(hPhysicalDrive, SelectedDrive.Geometry.BytesPerSector, 0, nSecs, buf)) { uprintf("Could not read MBR\n"); FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_READ_FAULT; goto out; @@ -262,7 +263,7 @@ static BOOL WriteMBR(HANDLE hPhysicalDrive) buf[0x1be] = 0x80; // Set first partition bootable } - if (!write_sectors(hPhysicalDrive, SelectedDrive.Geometry.BytesPerSector, 0, nSecs, buf, SecSize*nSecs)) { + if (!write_sectors(hPhysicalDrive, SecSize, 0, nSecs, buf)) { uprintf("Could not write MBR\n"); FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_WRITE_FAULT; goto out; @@ -318,7 +319,25 @@ void __cdecl FormatThread(void* param) FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_OPEN_FAILED; goto out; } - // At this stage with have both a handle and a lock to the physical drive + // At this stage with have both a handle and a lock to the physical drive... + + if (IsChecked(IDC_BADBLOCKS)) { + // ... but we can't write sectors that are part of a volume, even if we have + // access to physical, unless we have a lock (which doesn't have to be write) + hLogicalVolume = GetDriveHandle(num, drive_name, FALSE, TRUE); + if (hLogicalVolume == INVALID_HANDLE_VALUE) { + uprintf("Could not lock volume for badblock checks\n"); + FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_OPEN_FAILED; + goto out; + } + + if (BadBlocks(hPhysicalDrive, SelectedDrive.DiskSize, SelectedDrive.Geometry.BytesPerSector)) { + // TODO: report block failure number, etc + uprintf("Bad blocks check failed.\n"); + goto out; + } + safe_unlockclose(hLogicalVolume); + } if (!CreatePartition(hPhysicalDrive)) { FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_PARTITION_FAILURE; @@ -359,7 +378,7 @@ void __cdecl FormatThread(void* param) } if (IsChecked(IDC_DOS)) { - // We must have a lock to modify the FS boot record... + // We must have a lock to modify the volume boot record... hLogicalVolume = GetDriveHandle(num, drive_name, TRUE, TRUE); if (hLogicalVolume == INVALID_HANDLE_VALUE) { uprintf("Could not re-mount volume for partition boot record access\n"); diff --git a/src/inc/file.h b/src/inc/file.h index 7bff2107..16f1b2c3 100644 --- a/src/inc/file.h +++ b/src/inc/file.h @@ -14,14 +14,14 @@ int contains_data(FILE *fp, size_t ulPosition, int write_data(FILE *fp, size_t ulPosition, const void *pData, size_t uiLen); -/* Checks if a file contains a data pattern of length uiLen at position - ulPositoin. The file pointer will change when calling this function! */ +/* Writes nSectors of size SectorSize starting at sector StartSector */ int write_sectors(void *hDrive, size_t SectorSize, size_t StartSector, size_t nSectors, - const void *pBuf, size_t BufSize); + const void *pBuf); +/* Reads nSectors of size SectorSize starting at sector StartSector */ int read_sectors(void *hDrive, size_t SectorSize, size_t StartSector, size_t nSectors, - void *pBuf, size_t BufSize); + void *pBuf); #endif diff --git a/src/msdos.c b/src/msdos.c index d75101e9..ed9e43bb 100644 --- a/src/msdos.c +++ b/src/msdos.c @@ -288,6 +288,7 @@ BOOL ExtractMSDOS(const char* path) { char dllname[MAX_PATH] = "C:\\Windows\\System32"; int i, j; + BOOL r = TRUE; HMODULE hDLL; HRSRC hDiskImage; @@ -321,17 +322,17 @@ BOOL ExtractMSDOS(const char* path) return FALSE; } - for (i=0; i #include -// http://git.kernel.org/?p=fs/ext2/e2fsprogs.git;a=blob;f=misc/badblocks.c -// http://thestarman.pcministry.com/asm/mbr/MSWIN41.htm -// http://sourceforge.net/projects/grub4dos/ (bootable NTFS?) - #include "msapi_utf8.h" #include "resource.h" #include "rufus.h" @@ -571,6 +567,7 @@ static void EnableControls(BOOL bEnable) } else { EnableWindow(GetDlgItem(hMainDialog, IDC_DOS), FALSE); } + EnableWindow(GetDlgItem(hMainDialog, IDC_BADBLOCKS), bEnable); EnableWindow(GetDlgItem(hMainDialog, IDC_ABOUT), bEnable); EnableWindow(GetDlgItem(hMainDialog, IDC_START), bEnable); SetDlgItemTextA(hMainDialog, IDCANCEL, bEnable?"Close":"Cancel"); diff --git a/src/rufus.rc b/src/rufus.rc index 2fc58af5..255809c5 100644 --- a/src/rufus.rc +++ b/src/rufus.rc @@ -27,14 +27,14 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL // Dialog // -IDD_DIALOG DIALOGEX 12, 12, 206, 263 +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.1.76" +CAPTION "Rufus v1.0.2.77" FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN - DEFPUSHBUTTON "Start",IDC_START,94,223,50,14 - PUSHBUTTON "Close",IDCANCEL,148,223,50,14 + DEFPUSHBUTTON "Start",IDC_START,94,236,50,14 + PUSHBUTTON "Close",IDCANCEL,148,236,50,14 COMBOBOX IDC_DEVICE,8,17,190,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP CONTROL "&Device",IDC_STATIC,"Static",SS_LEFTNOWORDWRAP | WS_GROUP,9,6,22,8 COMBOBOX IDC_FILESYSTEM,8,75,190,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP @@ -43,13 +43,15 @@ BEGIN LTEXT "Ca&pacity",IDC_STATIC,9,35,29,8 COMBOBOX IDC_CLUSTERSIZE,8,104,190,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP LTEXT "&Cluster size",IDC_STATIC,9,93,105,10 - PUSHBUTTON "About...",IDC_ABOUT,8,223,50,14 - GROUPBOX "Format Options",IDC_STATIC,7,149,189,40 + PUSHBUTTON "About...",IDC_ABOUT,8,236,50,14 + GROUPBOX "Format Options",IDC_STATIC,7,149,189,52 EDITTEXT IDC_LABEL,7,131,190,13,ES_AUTOHSCROLL CONTROL "&Quick Format",IDC_QUICKFORMAT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,161,58,10 CONTROL "Create an &MS-DOS startup disk",IDC_DOS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,173,115,10 LTEXT "New volume &label",IDC_STATIC,9,121,105,10 - CONTROL "",IDC_PROGRESS,"msctls_progress32",PBS_SMOOTH | WS_BORDER,7,197,189,9 + CONTROL "",IDC_PROGRESS,"msctls_progress32",PBS_SMOOTH | WS_BORDER,7,210,189,9 + CONTROL "Check device for bad blocks (*ALPHA*)",IDC_BADBLOCKS, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,185,171,10 END IDD_ABOUTBOX DIALOGEX 0, 0, 287, 195 @@ -63,7 +65,7 @@ BEGIN DEFPUSHBUTTON "OK",IDOK,231,175,50,14,WS_GROUP CONTROL "https://github.com/pbatard/rufus",IDC_ABOUT_RUFUS_URL, "SysLink",WS_TABSTOP,46,47,114,9 - LTEXT "Version 1.0.1 (Build 76)",IDC_STATIC,46,19,78,8 + LTEXT "Version 1.0.2 (Build 77)",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 @@ -138,7 +140,7 @@ GUIDELINES DESIGNINFO BEGIN IDD_DIALOG, DIALOG BEGIN - BOTTOMMARGIN, 249 + BOTTOMMARGIN, 264 END IDD_ABOUTBOX, DIALOG @@ -162,8 +164,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,0,1,76 - PRODUCTVERSION 1,0,1,76 + FILEVERSION 1,0,2,77 + PRODUCTVERSION 1,0,2,77 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -180,13 +182,13 @@ BEGIN BEGIN VALUE "CompanyName", "akeo.ie" VALUE "FileDescription", "Rufus" - VALUE "FileVersion", "1.0.1.76" + VALUE "FileVersion", "1.0.2.77" 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.1.76" + VALUE "ProductVersion", "1.0.2.77" END END BLOCK "VarFileInfo"