X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=misc%2Fbadblocks.c;h=abf315cdd6010adbd9c5d45b09307a3ac2ac5ba3;hb=e08226c708a0d1ba0fa5f7ba4f6e240b94cd9fb3;hp=8da66f8c5041e1e5298ae7083eafbb69cb86ec5c;hpb=214580a339a18b0539b5998d3b47934956a30a1c;p=tools%2Fe2fsprogs.git diff --git a/misc/badblocks.c b/misc/badblocks.c index 8da66f8..abf315c 100644 --- a/misc/badblocks.c +++ b/misc/badblocks.c @@ -29,12 +29,11 @@ * list. (Work done by David Beattie) */ +#ifndef _GNU_SOURCE #define _GNU_SOURCE /* for O_DIRECT */ - -#ifndef O_LARGEFILE -#define O_LARGEFILE 0 #endif +#include "config.h" #include #include #ifdef HAVE_GETOPT_H @@ -51,6 +50,9 @@ extern int optind; #include #include #include +#ifdef HAVE_MBSTOWCS +#include +#endif #include #include @@ -60,34 +62,42 @@ extern int optind; #include "ext2fs/ext2_io.h" #include "ext2fs/ext2_fs.h" #include "ext2fs/ext2fs.h" -#include "nls-enable.h" +#include "support/nls-enable.h" -const char * program_name = "badblocks"; -const char * done_string = N_("done \n"); +#ifndef O_LARGEFILE +#define O_LARGEFILE 0 +#endif + +/* Maximum number of bad blocks we support */ +#define MAX_BAD_BLOCKS (INT_MAX/2) -static int v_flag = 0; /* verbose */ -static int w_flag = 0; /* do r/w test: 0=no, 1=yes, +static const char * program_name = "badblocks"; +static const char * done_string = N_("done \n"); + +static int v_flag; /* verbose */ +static int w_flag; /* do r/w test: 0=no, 1=yes, * 2=non-destructive */ -static int s_flag = 0; /* show progress of test */ -static int force = 0; /* force check of mounted device */ -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 */ -static int current_O_DIRECT = 0; /* Current status of O_DIRECT flag */ -static int use_buffered_io = 0; -static int exclusive_ok = 0; -static unsigned int max_bb = 0; /* Abort test if more than this number of bad blocks has been encountered */ -static unsigned int d_flag = 0; /* delay factor between reads */ +static int s_flag; /* show progress of test */ +static int force; /* force check of mounted device */ +static int t_flag; /* number of test patterns */ +static int t_max; /* allocated test patterns */ +static unsigned int *t_patts; /* test patterns */ +static int use_buffered_io; +static int exclusive_ok; +static unsigned int max_bb = MAX_BAD_BLOCKS; /* Abort test if more than this + * number of bad blocks has been + * encountered */ +static unsigned int d_flag; /* delay factor between reads */ static struct timeval time_start; #define T_INC 32 -unsigned int sys_page_size = 4096; +static unsigned int sys_page_size = 4096; static void usage(void) { fprintf(stderr, _( -"Usage: %s [-b block_size] [-i input_file] [-o output_file] [-svwnf]\n" +"Usage: %s [-b block_size] [-i input_file] [-o output_file] [-svwnfBX]\n" " [-c blocks_at_once] [-d delay_factor_between_reads] [-e max_bad_blocks]\n" " [-p num_passes] [-t test_pattern [-t test_pattern [...]]]\n" " device [last_block [first_block]]\n"), @@ -120,7 +130,7 @@ static void *allocate_buffer(size_t size) void *ret = 0; #ifdef HAVE_POSIX_MEMALIGN - if (posix_memalign(&ret, sys_page_size, size) < 0) + if (posix_memalign(&ret, sys_page_size, size) != 0) ret = 0; #else #ifdef HAVE_MEMALIGN @@ -209,6 +219,9 @@ static void print_status(void) { struct timeval time_end; char diff_buf[32], line_buf[128]; +#ifdef HAVE_MBSTOWCS + wchar_t wline_buf[128]; +#endif int len; gettimeofday(&time_end, 0); @@ -222,7 +235,10 @@ static void print_status(void) num_write_errors, num_corruption_errors); #ifdef HAVE_MBSTOWCS - len = mbstowcs(NULL, line_buf, sizeof(line_buf)); + mbstowcs(wline_buf, line_buf, sizeof(line_buf)); + len = wcswidth(wline_buf, sizeof(line_buf)); + if (len < 0) + len = strlen(line_buf); /* Should never happen... */ #endif fputs(line_buf, stderr); memset(line_buf, '\b', len); @@ -283,6 +299,7 @@ static void set_o_direct(int dev, unsigned char *buffer, size_t size, ext2_loff_t offset) { #ifdef O_DIRECT + static int current_O_DIRECT; /* Current status of O_DIRECT flag */ int new_flag = O_DIRECT; int flag; @@ -297,7 +314,8 @@ static void set_o_direct(int dev, unsigned char *buffer, size_t size, flag = fcntl(dev, F_GETFL); if (flag > 0) { flag = (flag & ~O_DIRECT) | new_flag; - fcntl(dev, F_SETFL, flag); + if (fcntl(dev, F_SETFL, flag) < 0) + perror("set_o_direct"); } current_O_DIRECT = new_flag; } @@ -366,7 +384,7 @@ static int do_read (int dev, unsigned char * buffer, int try, int block_size, /* Seek to the correct loc. */ if (ext2fs_llseek (dev, (ext2_loff_t) current_block * block_size, SEEK_SET) != (ext2_loff_t) current_block * block_size) - com_err (program_name, errno, _("during seek")); + com_err (program_name, errno, "%s", _("during seek")); /* Try the read */ if (d_flag) @@ -439,7 +457,7 @@ static int do_write(int dev, unsigned char * buffer, int try, int block_size, /* Seek to the correct loc. */ if (ext2fs_llseek (dev, (ext2_loff_t) current_block * block_size, SEEK_SET) != (ext2_loff_t) current_block * block_size) - com_err (program_name, errno, _("during seek")); + com_err (program_name, errno, "%s", _("during seek")); /* Try the write */ got = write (dev, buffer, try * block_size); @@ -463,7 +481,8 @@ static void flush_bufs(void) #endif retval = ext2fs_sync_device(host_dev, 1); if (retval) - com_err(program_name, retval, _("during ext2fs_sync_device")); + com_err(program_name, retval, "%s", + _("during ext2fs_sync_device")); } static unsigned int test_ro (int dev, blk_t last_block, @@ -482,8 +501,8 @@ static unsigned int test_ro (int dev, blk_t last_block, errcode = ext2fs_badblocks_list_iterate_begin(bb_list,&bb_iter); if (errcode) { - com_err (program_name, errcode, - _("while beginning bad block list iteration")); + com_err(program_name, errcode, "%s", + _("while beginning bad block list iteration")); exit (1); } do { @@ -497,13 +516,14 @@ static unsigned int test_ro (int dev, blk_t last_block, } if (!blkbuf) { - com_err (program_name, ENOMEM, _("while allocating buffers")); + com_err(program_name, ENOMEM, "%s", + _("while allocating buffers")); exit (1); } if (v_flag) { - fprintf (stderr, _("Checking blocks %lu to %lu\n"), - (unsigned long) first_block, - (unsigned long) last_block - 1); + fprintf(stderr, _("Checking blocks %lu to %lu\n"), + (unsigned long)first_block, + (unsigned long)last_block - 1); } if (t_flag) { fputs(_("Checking for bad blocks in read-only mode\n"), stderr); @@ -514,14 +534,13 @@ static unsigned int test_ro (int dev, blk_t last_block, try = blocks_at_once; currently_testing = first_block; num_blocks = last_block - 1; - if (!t_flag && (s_flag || v_flag)) { + if (!t_flag && (s_flag || v_flag)) fputs(_("Checking for bad blocks (read-only test): "), stderr); - if (v_flag <= 1) - alarm_intr(SIGALRM); - } + if (s_flag && v_flag <= 1) + alarm_intr(SIGALRM); while (currently_testing < last_block) { - if (max_bb && bb_count >= max_bb) { + if (bb_count >= max_bb) { if (s_flag || v_flag) { fputs(_("Too many bad blocks, aborting test\n"), stderr); } @@ -555,7 +574,7 @@ static unsigned int test_ro (int dev, blk_t last_block, currently_testing += got; if (got != try) { try = 1; - if (recover_block == ~0) + if (recover_block == ~0U) recover_block = currently_testing - got + blocks_at_once; continue; @@ -597,7 +616,8 @@ static unsigned int test_rw (int dev, blk_t last_block, read_buffer = buffer + blocks_at_once * block_size; if (!buffer) { - com_err (program_name, ENOMEM, _("while allocating buffers")); + com_err(program_name, ENOMEM, "%s", + _("while allocating buffers")); exit (1); } @@ -627,7 +647,7 @@ static unsigned int test_rw (int dev, blk_t last_block, try = blocks_at_once; while (currently_testing < last_block) { - if (max_bb && bb_count >= max_bb) { + if (bb_count >= max_bb) { if (s_flag || v_flag) { fputs(_("Too many bad blocks, aborting test\n"), stderr); } @@ -645,7 +665,7 @@ static unsigned int test_rw (int dev, blk_t last_block, currently_testing += got; if (got != try) { try = 1; - if (recover_block == ~0) + if (recover_block == ~0U) recover_block = currently_testing - got + blocks_at_once; continue; @@ -669,7 +689,7 @@ static unsigned int test_rw (int dev, blk_t last_block, try = blocks_at_once; while (currently_testing < last_block) { - if (max_bb && bb_count >= max_bb) { + if (bb_count >= max_bb) { if (s_flag || v_flag) { fputs(_("Too many bad blocks, aborting test\n"), stderr); } @@ -684,13 +704,13 @@ static unsigned int test_rw (int dev, blk_t last_block, currently_testing += got; if (got != try) { try = 1; - if (recover_block == ~0) + if (recover_block == ~0U) recover_block = currently_testing - got + blocks_at_once; continue; } else if (currently_testing == recover_block) { try = blocks_at_once; - recover_block = ~0; + recover_block = ~0U; } for (i=0; i < got; i++) { if (memcmp(read_buffer + i * block_size, @@ -737,14 +757,14 @@ static unsigned int test_nd (int dev, blk_t last_block, errcode_t errcode; unsigned long buf_used; static unsigned int bb_count; - int granularity = blocks_at_once; - blk_t recover_block = ~0; + unsigned int granularity = blocks_at_once; + blk_t recover_block = ~0U; bb_count = 0; errcode = ext2fs_badblocks_list_iterate_begin(bb_list,&bb_iter); if (errcode) { - com_err (program_name, errcode, - _("while beginning bad block list iteration")); + com_err(program_name, errcode, "%s", + _("while beginning bad block list iteration")); exit (1); } do { @@ -752,9 +772,10 @@ static unsigned int test_nd (int dev, blk_t last_block, } 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)); + test_record = malloc(blocks_at_once * sizeof(struct saved_blk_record)); if (!blkbuf || !test_record) { - com_err(program_name, ENOMEM, _("while allocating buffers")); + com_err(program_name, ENOMEM, "%s", + _("while allocating buffers")); exit (1); } @@ -815,7 +836,7 @@ static unsigned int test_nd (int dev, blk_t last_block, alarm_intr(SIGALRM); while (currently_testing < last_block) { - if (max_bb && bb_count >= max_bb) { + if (bb_count >= max_bb) { if (s_flag || v_flag) { fputs(_("Too many bad blocks, aborting test\n"), stderr); } @@ -837,7 +858,7 @@ static unsigned int test_nd (int dev, blk_t last_block, got = do_read (dev, save_ptr, try, block_size, currently_testing); if (got == 0) { - if (recover_block == ~0) + if (recover_block == ~0U) recover_block = currently_testing + blocks_at_once; if (granularity != 1) { @@ -872,7 +893,7 @@ static unsigned int test_nd (int dev, blk_t last_block, currently_testing += got; if (got != try) { try = 1; - if (recover_block == ~0) + if (recover_block == ~0U) recover_block = currently_testing - got + blocks_at_once; continue; @@ -1045,6 +1066,7 @@ int main (int argc, char ** argv) unsigned int); int open_flag; long sysval; + blk64_t inblk; setbuf(stdout, NULL); setbuf(stderr, NULL); @@ -1053,6 +1075,7 @@ int main (int argc, char ** argv) setlocale(LC_CTYPE, ""); bindtextdomain(NLS_CAT_NAME, LOCALEDIR); textdomain(NLS_CAT_NAME); + set_com_err_gettext(gettext); #endif srandom((unsigned int)time(NULL)); /* simple randomness is enough */ test_func = test_ro; @@ -1108,6 +1131,16 @@ int main (int argc, char ** argv) break; case 'e': max_bb = parse_uint(optarg, "max bad block count"); + if (max_bb > MAX_BAD_BLOCKS) { + com_err (program_name, 0, + _("Too big max bad blocks count %u - " + "maximum is %u"), max_bb, + MAX_BAD_BLOCKS); + exit (1); + } + /* 0 really means unlimited but we cannot do that much... */ + if (max_bb == 0) + max_bb = MAX_BAD_BLOCKS; break; case 'd': d_flag = parse_uint(optarg, "read delay factor"); @@ -1156,15 +1189,15 @@ int main (int argc, char ** argv) } if (!w_flag) { if (t_flag > 1) { - com_err(program_name, 0, - _("Maximum of one test_pattern may be specified " - "in read-only mode")); + com_err(program_name, 0, "%s", + _("Maximum of one test_pattern may be " + "specified in read-only mode")); exit(1); } if (t_patts && (t_patts[0] == (unsigned int) ~0)) { - com_err(program_name, 0, - _("Random test_pattern is not allowed " - "in read-only mode")); + com_err(program_name, 0, "%s", + _("Random test_pattern is not allowed " + "in read-only mode")); exit(1); } } @@ -1176,13 +1209,13 @@ int main (int argc, char ** argv) block_size, &last_block); if (errcode == EXT2_ET_UNIMPLEMENTED) { - com_err(program_name, 0, + com_err(program_name, 0, "%s", _("Couldn't determine device size; you " "must specify\nthe size manually\n")); exit(1); } if (errcode) { - com_err(program_name, errcode, + com_err(program_name, errcode, "%s", _("while trying to determine device size")); exit(1); } @@ -1197,10 +1230,17 @@ int main (int argc, char ** argv) first_block = parse_uint(argv[optind], _("first block")); } else first_block = 0; if (first_block >= last_block) { - com_err (program_name, 0, _("invalid starting block (%lu): must be less than %lu"), - (unsigned long) first_block, (unsigned long) last_block); + com_err (program_name, 0, _("invalid starting block (%llu): must be less than %llu"), + first_block, last_block); exit (1); } + /* ext2 badblocks file can't handle large values */ + if (last_block >> 32) { + com_err(program_name, EOVERFLOW, + _("invalid end block (%llu): must be 32-bit value"), + last_block); + exit(1); + } if (w_flag) check_mount(device_name); @@ -1252,23 +1292,35 @@ int main (int argc, char ** argv) errcode = ext2fs_badblocks_list_create(&bb_list,0); if (errcode) { - com_err (program_name, errcode, - _("while creating in-memory bad blocks list")); + com_err(program_name, errcode, "%s", + _("while creating in-memory bad blocks list")); exit (1); } if (in) { for(;;) { - switch(fscanf (in, "%u\n", &next_bad)) { + switch (fscanf(in, "%llu\n", &inblk)) { case 0: - com_err (program_name, 0, "input file - bad format"); + com_err(program_name, 0, "%s", + _("input file - bad format")); exit (1); case EOF: break; default: + if (inblk >> 32) { + com_err(program_name, + EOVERFLOW, "%s", + _("while adding to in-memory " + "bad block list")); + exit(1); + } + next_bad = inblk; errcode = ext2fs_badblocks_list_add(bb_list,next_bad); if (errcode) { - com_err (program_name, errcode, _("while adding to in-memory bad block list")); + com_err(program_name, errcode, + "%s", + _("while adding to in-memory " + "bad block list")); exit (1); } continue;