badblocks.c revision d49a22b734299e4b433a19b8f5f60d689c92a78e
13839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 23839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * badblocks.c - Bad blocks checker 33839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * 43839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Copyright (C) 1992, 1993, 1994 Remy Card <card@masi.ibp.fr> 53839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Laboratoire MASI, Institut Blaise Pascal 63839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Universite Pierre et Marie Curie (Paris VI) 73839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * 8dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o * Copyright 1995, 1996, 1997, 1998, 1999 by Theodore Ts'o 9879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o * Copyright 1999 by David Beattie 1019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * 113839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * This file is based on the minix file system programs fsck and mkfs 123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * written and copyrighted by Linus Torvalds <Linus.Torvalds@cs.helsinki.fi> 1319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * 1419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * %Begin-Header% 1519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * This file may be redistributed under the terms of the GNU Public 1619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * License. 1719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * %End-Header% 183839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 193839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 203839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 213839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * History: 223839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * 93/05/26 - Creation from e2fsck 233839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * 94/02/27 - Made a separate bad blocks checker 24879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o * 99/06/30...99/07/26 - Added non-destructive write-testing, 25dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o * configurable blocks-at-once parameter, 26dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o * loading of badblocks list to avoid testing 27dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o * blocks known to be bad, multiple passes to 28dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o * make sure that no new blocks are added to the 29dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o * list. (Work done by David Beattie) 303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 313839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 323839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <errno.h> 333839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <fcntl.h> 34a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o#ifdef HAVE_GETOPT_H 353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <getopt.h> 36373b8337c7b6c6243810be250083fa4773891e92Theodore Ts'o#else 37373b8337c7b6c6243810be250083fa4773891e92Theodore Ts'oextern char *optarg; 38373b8337c7b6c6243810be250083fa4773891e92Theodore Ts'oextern int optind; 39a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o#endif 403839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <signal.h> 413839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <stdio.h> 423839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <stdlib.h> 433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <string.h> 443839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <unistd.h> 45879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o#include <setjmp.h> 463839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 473839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <sys/ioctl.h> 48f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#include <sys/types.h> 493839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 50a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o#if HAVE_LINUX_FS_H 513839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <linux/fd.h> 52a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o#endif 533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 543839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include "et/com_err.h" 55d40259fd552d942903f2fd0b426c75a5c2516017Theodore Ts'o#include "ext2fs/ext2_io.h" 56879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o#include <linux/ext2_fs.h> 57879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o#include "ext2fs/ext2fs.h" 58d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o#include "nls-enable.h" 593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'oconst char * program_name = "badblocks"; 618f5c0f66ca343ec4689470e5941aa3066ed062bbTheodore Ts'oconst char * done_string = N_("done \n"); 623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 634d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'ostatic int v_flag = 0; /* verbose */ 644d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'ostatic int w_flag = 0; /* do r/w test: 0=no, 1=yes, 654d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o * 2=non-destructive */ 664d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'ostatic int s_flag = 0; /* show progress of test */ 674d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 684d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'ostatic char *blkbuf; /* Allocation array for bad block testing */ 694d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 703839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 71818180cdfcff84b9048ecdc5dc86323f0fefba24Theodore Ts'ostatic void usage(void) 723839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 73d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o fprintf(stderr, _("Usage: %s [-b block_size] [-i input_file] [-o output_file] [-svwn]\n [-c blocks_at_once] [-p num_passes] device blocks_count [start_count]\n"), 743839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o program_name); 753839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o exit (1); 763839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 773839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 7819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'ostatic unsigned long currently_testing = 0; 7919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'ostatic unsigned long num_blocks = 0; 80879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'ostatic ext2_badblocks_list bb_list = NULL; 81879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'ostatic FILE *out; 82879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'ostatic blk_t next_bad = 0; 83879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'ostatic ext2_badblocks_iterate bb_iter = NULL; 8419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 85dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o/* 86dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o * This routine reports a new bad block. If the bad block has already 87dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o * been seen before, then it returns 0; otherwise it returns 1. 88dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o */ 89dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'ostatic int bb_output (unsigned long bad) 90879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o{ 91879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o errcode_t errcode; 92879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 93dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o if (ext2fs_badblocks_list_test(bb_list, bad)) 94dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o return 0; 95dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o 96879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o fprintf (out, "%lu\n", bad); 97879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 98879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o errcode = ext2fs_badblocks_list_add (bb_list, bad); 99879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (errcode) { 100879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o com_err (program_name, errcode, "adding to in-memory bad block list"); 101879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 102879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 103879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 104879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o /* kludge: 105879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o increment the iteration through the bb_list if 106879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o an element was just added before the current iteration 107879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o position. This should not cause next_bad to change. */ 108879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (bb_iter && bad < next_bad) 109879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o ext2fs_badblocks_list_iterate (bb_iter, &next_bad); 110dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o return 1; 111879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o} 112879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 113879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'ostatic void print_status (void) 11419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o{ 11519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o fprintf(stderr, "%9ld/%9ld", currently_testing, num_blocks); 11619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o fprintf(stderr, "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"); 11719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o fflush (stderr); 11819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o} 11919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 12019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'ostatic void alarm_intr (int alnum) 12119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o{ 12219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o signal (SIGALRM, alarm_intr); 12319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o alarm(1); 12419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (!num_blocks) 12519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o return; 12619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o fprintf(stderr, "%9ld/%9ld", currently_testing, num_blocks); 12719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o fprintf(stderr, "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"); 12819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o fflush (stderr); 12919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o} 13019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 131879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'ostatic void *terminate_addr = NULL; 132879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 133879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'ostatic void terminate_intr (int signo) 134879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o{ 135879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (terminate_addr) 136879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o longjmp(terminate_addr,1); 137879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit(1); 138879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o} 139879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 140879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'ostatic void capture_terminate (jmp_buf term_addr) 141879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o{ 142879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o terminate_addr = term_addr; 143879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o signal (SIGHUP, terminate_intr); 144879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o signal (SIGINT, terminate_intr); 145879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o signal (SIGPIPE, terminate_intr); 146879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o signal (SIGTERM, terminate_intr); 147879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o signal (SIGUSR1, terminate_intr); 148879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o signal (SIGUSR2, terminate_intr); 149879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o} 150879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 1514d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'ostatic void uncapture_terminate() 1524d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o{ 1534d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o terminate_addr = NULL; 1544d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o signal (SIGHUP, SIG_DFL); 1554d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o signal (SIGINT, SIG_DFL); 1564d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o signal (SIGPIPE, SIG_DFL); 1574d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o signal (SIGTERM, SIG_DFL); 1584d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o signal (SIGUSR1, SIG_DFL); 1594d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o signal (SIGUSR2, SIG_DFL); 1604d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o} 1614d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 1623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 163879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o * Perform a read of a sequence of blocks; return the number of blocks 164879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o * successfully sequentially read. 1653839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 166dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'ostatic long do_read (int dev, char * buffer, int try, int block_size, 1673839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o unsigned long current_block) 1683839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 1693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o long got; 1703839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 17119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (v_flag > 1) 17219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o print_status(); 17319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 1743839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* Seek to the correct loc. */ 17519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (ext2fs_llseek (dev, (ext2_loff_t) current_block * block_size, 176f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o SEEK_SET) != (ext2_loff_t) current_block * block_size) 177d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o com_err (program_name, errno, _("during seek")); 1783839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1793839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* Try the read */ 1803839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o got = read (dev, buffer, try * block_size); 1813839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (got < 0) 1823839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o got = 0; 1839f10a7b31e57288093930fc9565102409eeac6e9Theodore Ts'o if (got & 511) 184d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o fprintf(stderr, _("Weird value (%ld) in do_read\n"), got); 185879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o got /= block_size; 186879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o return got; 187879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o} 188879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 189879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o/* 190879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o * Perform a write of a sequence of blocks; return the number of blocks 191879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o * successfully sequentially written. 192879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o */ 193dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'ostatic long do_write (int dev, char * buffer, int try, int block_size, 194879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o unsigned long current_block) 195879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o{ 196879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o long got; 197879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 198879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (v_flag > 1) 199879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o print_status(); 200879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 201879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o /* Seek to the correct loc. */ 202879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (ext2fs_llseek (dev, (ext2_loff_t) current_block * block_size, 203879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o SEEK_SET) != (ext2_loff_t) current_block * block_size) 204d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o com_err (program_name, errno, _("during seek")); 205879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 206879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o /* Try the write */ 207879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o got = write (dev, buffer, try * block_size); 208879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (got < 0) 209879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o got = 0; 210879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (got & 511) 211879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o fprintf (stderr, 212879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o "Weird value (%ld) in do_write\n", got); 2133839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o got /= block_size; 2143839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return got; 2153839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 2163839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 217879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'ostatic int host_dev; 218879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 219d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'ostatic void flush_bufs (int dev) 220a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o{ 221e2207ce595f05e4db5945326f9b2d553ff7a4d57Theodore Ts'o#ifdef HAVE_FDATASYNC 222879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (sync && fdatasync (dev) == -1) 223e2207ce595f05e4db5945326f9b2d553ff7a4d57Theodore Ts'o com_err (program_name, errno, _("during fdatasync")); 224e2207ce595f05e4db5945326f9b2d553ff7a4d57Theodore Ts'o#else 225e2207ce595f05e4db5945326f9b2d553ff7a4d57Theodore Ts'o if (sync && fsync (dev) == -1) 226d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o com_err (program_name, errno, _("during fsync")); 227e2207ce595f05e4db5945326f9b2d553ff7a4d57Theodore Ts'o#endif 228a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o 229879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o#ifdef BLKFLSBUF 230879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o ioctl (host_dev, BLKFLSBUF, 0); /* In case this is a HD */ 231a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o#endif 232a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o#ifdef FDFLUSH 233879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o ioctl (host_dev, FDFLUSH, 0); /* In case this is floppy */ 234a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o#endif 235a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o} 236a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o 237879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'ostatic unsigned int test_ro (int dev, unsigned long blocks_count, 238dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o int block_size, unsigned long from_count, 239dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o unsigned long blocks_at_once) 2403839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 2413839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o char * blkbuf; 2423839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int try; 2433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o long got; 244879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o unsigned int bb_count = 0; 245879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o errcode_t errcode; 2463839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 247879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o errcode = ext2fs_badblocks_list_iterate_begin(bb_list,&bb_iter); 248879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (errcode) { 249d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o com_err (program_name, errcode, 250d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o _("while beginning bad block list iteration")); 251879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 252879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 253879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o do { 254879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o ext2fs_badblocks_list_iterate (bb_iter, &next_bad); 255879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } while (next_bad && next_bad < from_count); 256879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 257879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o blkbuf = malloc (blocks_at_once * block_size); 2583839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (!blkbuf) 2593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o { 260d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o com_err (program_name, ENOMEM, _("while allocating buffers")); 2613839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o exit (1); 2623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 263d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o flush_bufs(dev); 264f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (v_flag) { 265d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o fprintf(stderr, _("Checking for bad blocks in read-only mode\n")); 266d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o fprintf (stderr, _("From block %lu to %lu\n"), from_count, 267d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o blocks_count); 268f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o } 269879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o try = blocks_at_once; 270f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o currently_testing = from_count; 2713839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o num_blocks = blocks_count; 27219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (s_flag || v_flag > 1) { 273d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o fprintf(stderr, 274d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o _("Checking for bad blocks (read-only test): ")); 27519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (v_flag <= 1) 27619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o alarm_intr(SIGALRM); 2773839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 2783839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o while (currently_testing < blocks_count) 2793839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o { 280879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (next_bad) { 281879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (currently_testing == next_bad) { 282879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o /* fprintf (out, "%lu\n", nextbad); */ 283879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o ext2fs_badblocks_list_iterate (bb_iter, &next_bad); 284879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o currently_testing++; 285879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o continue; 286879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 287879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o else if (currently_testing + try > next_bad) 288879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o try = next_bad - currently_testing; 289879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 2903839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (currently_testing + try > blocks_count) 2913839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o try = blocks_count - currently_testing; 292879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o got = do_read (dev, blkbuf, try, block_size, currently_testing); 2933839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o currently_testing += got; 2943839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (got == try) { 295879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o try = blocks_at_once; 2963839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o continue; 2973839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 2983839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o else 2993839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o try = 1; 300879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (got == 0) { 301dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o bb_count += bb_output(currently_testing++); 302879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 3033839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 3043839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o num_blocks = 0; 3053839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o alarm(0); 30619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (s_flag || v_flag > 1) 3078f5c0f66ca343ec4689470e5941aa3066ed062bbTheodore Ts'o fprintf(stderr, _(done_string)); 308879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 309f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o fflush (stderr); 3103839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o free (blkbuf); 311879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 312879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o ext2fs_badblocks_list_iterate_end(bb_iter); 313879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 314879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o return bb_count; 3153839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 3163839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 317879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'ostatic unsigned int test_rw (int dev, unsigned long blocks_count, 318dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o int block_size, unsigned long from_count, 319dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o unsigned long blocks_at_once) 3203839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 3213839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int i; 3223839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o char * buffer; 3233839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o unsigned char pattern[] = {0xaa, 0x55, 0xff, 0x00}; 324879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o unsigned int bb_count = 0; 3253839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 3263839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o buffer = malloc (2 * block_size); 3273839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (!buffer) 3283839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o { 329d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o com_err (program_name, ENOMEM, _("while allocating buffers")); 3303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o exit (1); 3313839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 3323839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 333d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o flush_bufs(dev); 334a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o 33519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (v_flag) { 33619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o fprintf(stderr, 337d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o _("Checking for bad blocks in read-write mode\n")); 338d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o fprintf(stderr, _("From block %lu to %lu\n"), 33919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o from_count, blocks_count); 34019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o } 34119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o for (i = 0; i < sizeof (pattern); i++) { 3423839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o memset (buffer, pattern[i], block_size); 343f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (s_flag | v_flag) 344d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o fprintf (stderr, _("Writing pattern 0x%08x: "), 3453839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o *((int *) buffer)); 346f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o num_blocks = blocks_count; 347f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o currently_testing = from_count; 34819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (s_flag && v_flag <= 1) 349f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o alarm_intr(SIGALRM); 350f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o for (; 351f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o currently_testing < blocks_count; 352f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o currently_testing++) 3533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o { 35419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (ext2fs_llseek (dev, (ext2_loff_t) currently_testing * 355f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o block_size, SEEK_SET) != 356f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o (ext2_loff_t) currently_testing * block_size) 3573839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o com_err (program_name, errno, 358d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o _("during seek on block %d"), 359f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o currently_testing); 36019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (v_flag > 1) 36119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o print_status(); 3623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o write (dev, buffer, block_size); 3633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 364f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o num_blocks = 0; 365f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o alarm (0); 366f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (s_flag | v_flag) 3678f5c0f66ca343ec4689470e5941aa3066ed062bbTheodore Ts'o fprintf(stderr, _(done_string)); 368d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o flush_bufs(dev); 369f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (s_flag | v_flag) 370d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o fprintf (stderr, _("Reading and comparing: ")); 371f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o num_blocks = blocks_count; 372f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o currently_testing = from_count; 37319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (s_flag && v_flag <= 1) 374f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o alarm_intr(SIGALRM); 375f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o for (; 376f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o currently_testing < blocks_count; 377f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o currently_testing++) 3783839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o { 37919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (ext2fs_llseek (dev, (ext2_loff_t) currently_testing * 380f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o block_size, SEEK_SET) != 381f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o (ext2_loff_t) currently_testing * block_size) 3823839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o com_err (program_name, errno, 383d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o _("during seek on block %d"), 384f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o currently_testing); 38519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (v_flag > 1) 38619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o print_status(); 387dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o if ((read (dev, buffer + block_size, block_size) 3884d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o != block_size) || 389dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o memcmp(buffer, buffer + block_size, block_size)) 3904d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o bb_count += bb_output(currently_testing); 3913839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 392f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o num_blocks = 0; 393f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o alarm (0); 394f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (s_flag | v_flag) 3958f5c0f66ca343ec4689470e5941aa3066ed062bbTheodore Ts'o fprintf(stderr, _(done_string)); 396d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o flush_bufs(dev); 3973839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 398879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 399879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o return bb_count; 400879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o} 401879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 402d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'ostruct saved_blk_record { 403d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o blk_t block; 404d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o int num; 405d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o}; 406d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o 407879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'ostatic unsigned int test_nd (int dev, unsigned long blocks_count, 408dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o int block_size, unsigned long from_count, 409dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o unsigned long blocks_at_once) 410879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o{ 411dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o char *blkbuf, *save_ptr, *test_ptr, *read_ptr; 412879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o char * ptr; 413dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o int try, i; 414d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o long got, used2, written; 415d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o struct saved_blk_record *test_record; 416d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o int num_saved; 417879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o jmp_buf terminate_env; 418879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o errcode_t errcode; 419dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o /* These are static to prevent being clobbered by the longjmp */ 4204d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o static long buf_used = 0; 4214d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o static unsigned int bb_count = 0; 422879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 423879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o errcode = ext2fs_badblocks_list_iterate_begin(bb_list,&bb_iter); 424879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (errcode) { 425dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o com_err (program_name, errcode, 426d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o _("while beginning bad block list iteration")); 427879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 428879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 429879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o do { 430879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o ext2fs_badblocks_list_iterate (bb_iter, &next_bad); 431879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } while (next_bad && next_bad < from_count); 432879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 433879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o blkbuf = malloc (3 * blocks_at_once * block_size); 434d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o test_record = malloc (blocks_at_once*sizeof(struct saved_blk_record)); 435d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o if (!blkbuf || !test_record) { 436d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o com_err(program_name, ENOMEM, _("while allocating buffers")); 437879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 438879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 439d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o num_saved = 0; 440879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 441879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o /* inititalize the test data randomly: */ 442879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (v_flag) { 443d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o fprintf (stderr, _("Initializing random test data\n")); 444879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 445879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o for(ptr = blkbuf + blocks_at_once * block_size; 446dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o ptr < blkbuf + 2 * blocks_at_once * block_size; 447dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o ++ptr) { 448879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o (*ptr) = random() % (1 << sizeof(char)); 449879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 450879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 451d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o flush_bufs(dev); 452879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (v_flag) { 453879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o fprintf (stderr, 454d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o _("Checking for bad blocks in non-destructive read-write mode\n")); 455d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o fprintf (stderr, _("From block %lu to %lu\n"), from_count, blocks_count); 456879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 457879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (s_flag || v_flag > 1) { 458d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o fprintf(stderr, _("Checking for bad blocks (non-destructive read-write test): ")); 459879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (v_flag <= 1) 460879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o alarm_intr(SIGALRM); 461879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 4624d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o if (setjmp(terminate_env)) { 4634d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o /* 4644d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o * Abnormal termination by a signal is handled here. 4654d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o */ 466879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 467d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o fprintf(stderr, _("Interrupt caught, cleaning up\n")); 468879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 469d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o save_ptr = blkbuf; 470d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o for (i=0; i < num_saved; i++) { 471d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o do_write(dev, save_ptr, test_record[i].num, 472d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o block_size, test_record[i].block); 473d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o save_ptr += test_record[i].num * block_size; 474d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o } 475879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o fflush (out); 476dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o exit(1); 477879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 4784d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 4794d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o /* set up abend handler */ 4804d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o capture_terminate(terminate_env); 4814d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 482d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o buf_used = 0; 483d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o save_ptr = blkbuf; 4844d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o test_ptr = blkbuf + (blocks_at_once * block_size); 4854d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o currently_testing = from_count; 4864d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o num_blocks = blocks_count; 4874d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 4884d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o while (currently_testing < blocks_count) { 4894d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o try = blocks_at_once - buf_used; 4904d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o if (next_bad) { 4914d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o if (currently_testing == next_bad) { 4924d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o /* fprintf (out, "%lu\n", nextbad); */ 4934d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o ext2fs_badblocks_list_iterate (bb_iter, &next_bad); 494d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o currently_testing++; 495d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o goto check_for_more; 4964d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o } 4974d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o else if (currently_testing + try > next_bad) 4984d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o try = next_bad - currently_testing; 4994d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o } 5004d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o if (currently_testing + try > blocks_count) 5014d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o try = blocks_count - currently_testing; 5024d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o got = do_read (dev, save_ptr, try, block_size, 5034d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o currently_testing); 504d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o if (got == 0) { 505d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o /* First block must have been bad. */ 506d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o bb_count += bb_output(currently_testing++); 507d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o goto check_for_more; 508d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o } 5094d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 510d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o /* 511d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o * Note the fact that we've saved this much data 512d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o * *before* we overwrite it with test data 513d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o */ 514d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o test_record[num_saved].block = currently_testing; 515d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o test_record[num_saved].num = got; 516d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o num_saved++; 517d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o 518d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o /* Write the test data */ 519d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o written = do_write (dev, test_ptr, got, block_size, 520d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o currently_testing); 521d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o if (written != got) 522d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o com_err (program_name, errno, 5234d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o _("during test data write, block %lu"), 524d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o currently_testing + written); 5254d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 5264d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o buf_used += got; 5274d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o save_ptr += got * block_size; 5284d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o test_ptr += got * block_size; 5294d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o currently_testing += got; 5304d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o if (got != try) 5314d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o bb_count += bb_output(currently_testing++); 5324d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 533d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o check_for_more: 5344d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o /* 5354d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o * If there's room for more blocks to be tested this 5364d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o * around, and we're not done yet testing the disk, go 5374d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o * back and get some more blocks. 5384d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o */ 5394d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o if ((buf_used != blocks_at_once) && 540d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o (currently_testing < blocks_count)) 5414d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o continue; 5424d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 543d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o flush_bufs(dev); 5444d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 5454d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o /* 5464d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o * for each contiguous block that we read into the 5474d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o * buffer (and wrote test data into afterwards), read 5484d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o * it back (looping if necessary, to get past newly 5494d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o * discovered unreadable blocks, of which there should 5504d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o * be none, but with a hard drive which is unreliable, 5514d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o * it has happened), and compare with the test data 5524d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o * that was written; output to the bad block list if 5534d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o * it doesn't match. 5544d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o */ 5554d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o used2 = 0; 5564d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o save_ptr = blkbuf; 5574d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o test_ptr = blkbuf + (blocks_at_once * block_size); 5584d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o read_ptr = blkbuf + (2 * blocks_at_once * block_size); 559d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o try = 0; 5604d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 561d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o while (1) { 562d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o if (try == 0) { 563d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o if (used2 >= num_saved) 564d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o break; 565d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o currently_testing = test_record[used2].block; 566d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o try = test_record[used2].num; 567d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o used2++; 568d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o } 569d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o 5704d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o got = do_read (dev, read_ptr, try, 5714d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o block_size, currently_testing); 5724d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 5734d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o /* test the comparison between all the 5744d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o blocks successfully read */ 5754d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o for (i = 0; i < got; ++i) 5764d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o if (memcmp (test_ptr+i*block_size, 5774d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o read_ptr+i*block_size, block_size)) 5784d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o bb_count += bb_output(currently_testing + i); 5794d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o if (got < try) { 5804d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o bb_count += bb_output(currently_testing + got); 5814d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o got++; 5824d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o } 5834d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 5844d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o /* when done, write back original data */ 5854d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o do_write (dev, save_ptr, got, block_size, 5864d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o currently_testing); 5874d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 5884d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o currently_testing += got; 5894d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o save_ptr += got * block_size; 5904d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o test_ptr += got * block_size; 5914d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o read_ptr += got * block_size; 5924d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o try -= got; 5934d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o } 5944d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 5954d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o /* empty the buffer so it can be reused */ 596d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o num_saved = 0; 5974d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o buf_used = 0; 598d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o save_ptr = blkbuf; 599d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o test_ptr = blkbuf + (blocks_at_once * block_size); 6004d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o } 6014d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o num_blocks = 0; 6024d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o alarm(0); 6034d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o uncapture_terminate(); 6044d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o if (s_flag || v_flag > 1) 6054d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o fprintf(stderr, _(done_string)); 606879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 607dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o fflush(stderr); 608dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o free(blkbuf); 609d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o free(test_record); 610879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 611879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o ext2fs_badblocks_list_iterate_end(bb_iter); 612879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 613879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o return bb_count; 6143839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 6153839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 61600e5433eb5e9f70f485968b809fdcf297d7fe7b9Theodore Ts'oint main (int argc, char ** argv) 6173839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 618519149fb458b0fa69c10fecd83fae42e838cf01dTheodore Ts'o int c; 6193839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o char * tmp; 6203839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o char * device_name; 621879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o char * host_device_name = NULL; 622879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o char * input_file = NULL; 6233839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o char * output_file = NULL; 624879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o FILE * in = NULL; 625dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o int block_size = 1024; 626879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o unsigned long blocks_at_once = 16; 627f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o unsigned long blocks_count, from_count; 628879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o int num_passes = 0; 629879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o int passes_clean = 0; 6303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int dev; 631879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o errcode_t errcode; 6324d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o unsigned int (*test_func)(int dev, unsigned long blocks_count, 6334d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o int block_size, unsigned long from_count, 6344d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o unsigned long blocks_at_once); 6354d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o size_t buf_size; 6363839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 6373839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o setbuf(stdout, NULL); 6383839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o setbuf(stderr, NULL); 639d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o#ifdef ENABLE_NLS 640d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o setlocale(LC_MESSAGES, ""); 641d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o bindtextdomain(NLS_CAT_NAME, LOCALEDIR); 642d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o textdomain(NLS_CAT_NAME); 643d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o#endif 6444d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o test_func = test_ro; 6454d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 6463839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (argc && *argv) 6473839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o program_name = *argv; 648879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o while ((c = getopt (argc, argv, "b:i:o:svwnc:p:h:")) != EOF) { 6493839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o switch (c) { 6503839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o case 'b': 6513839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o block_size = strtoul (optarg, &tmp, 0); 6523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (*tmp || block_size > 4096) { 6533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o com_err (program_name, 0, 654d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o _("bad block size - %s"), optarg); 6553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o exit (1); 6563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 6573839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o break; 658879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o case 'i': 659879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o input_file = optarg; 660879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o break; 6613839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o case 'o': 6623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o output_file = optarg; 6633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o break; 6643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o case 's': 6653839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o s_flag = 1; 6663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o break; 6673839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o case 'v': 66819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o v_flag++; 6693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o break; 6703839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o case 'w': 6714d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o if (w_flag) 6724d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o usage(); 6734d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o test_func = test_rw; 6744d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o w_flag = 1; 675879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o break; 676879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o case 'n': 6774d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o if (w_flag) 6784d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o usage(); 6794d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o test_func = test_nd; 680879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o w_flag = 2; 681879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o break; 682879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o case 'c': 683879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o blocks_at_once = strtoul (optarg, &tmp, 0); 684879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (*tmp) { 685879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o com_err (program_name, 0, 686879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o "bad simultaneous block count - %s", optarg); 687879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 688879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 689879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o break; 690879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o case 'p': 691879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o num_passes = strtoul (optarg, &tmp, 0); 692879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (*tmp) { 693879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o com_err (program_name, 0, 694879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o "bad number of clean passes - %s", optarg); 695879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 696879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 697879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o break; 698879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o case 'h': 699879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o host_device_name = optarg; 7003839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o break; 7013839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o default: 702818180cdfcff84b9048ecdc5dc86323f0fefba24Theodore Ts'o usage(); 7033839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 7043839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 7053839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (optind > argc - 1) 706818180cdfcff84b9048ecdc5dc86323f0fefba24Theodore Ts'o usage(); 7073839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o device_name = argv[optind++]; 7083839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (optind > argc - 1) 709818180cdfcff84b9048ecdc5dc86323f0fefba24Theodore Ts'o usage(); 7103839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o blocks_count = strtoul (argv[optind], &tmp, 0); 7113839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (*tmp) 7123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o { 713d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o com_err (program_name, 0, _("bad blocks count - %s"), 714d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o argv[optind]); 7153839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o exit (1); 7163839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 717f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (++optind <= argc-1) { 718f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o from_count = strtoul (argv[optind], &tmp, 0); 719f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o } else from_count = 0; 720f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (from_count >= blocks_count) { 721d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o com_err (program_name, 0, _("bad blocks range: %lu-%lu"), 722f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o from_count, blocks_count); 723f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o exit (1); 724f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o } 7253839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dev = open (device_name, w_flag ? O_RDWR : O_RDONLY); 7263839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (dev == -1) 7273839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o { 728d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o com_err (program_name, errno, _("while trying to open %s"), 7293839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o device_name); 7303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o exit (1); 7313839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 732879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (host_device_name) { 733879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o host_dev = open (host_device_name, O_RDONLY); 734879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (host_dev == -1) 735879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o { 736d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o com_err (program_name, errno, 737d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o _("while trying to open %s"), 738d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o host_device_name); 739879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 740879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 741879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } else 742879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o host_dev = dev; 743879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (input_file) 744879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (strcmp (input_file, "-") == 0) 745879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o in = stdin; 746879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o else { 747879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o in = fopen (input_file, "r"); 748879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (in == NULL) 749879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o { 750d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o com_err (program_name, errno, 751d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o _("while trying to open %s"), 752879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o input_file); 753879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 754879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 755879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 7563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (output_file && strcmp (output_file, "-") != 0) 7573839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o { 7583839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o out = fopen (output_file, "w"); 7593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (out == NULL) 7603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o { 761d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o com_err (program_name, errno, 762d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o _("while trying to open %s"), 763879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o output_file); 7643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o exit (1); 7653839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 7663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 7673839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o else 7683839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o out = stdout; 769879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 770879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o errcode = ext2fs_badblocks_list_create(&bb_list,0); 771879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (errcode) { 772d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o com_err (program_name, errcode, 773d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o _("creating in-memory bad blocks list")); 774879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 775879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 776879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 777879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (in) { 778879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o for(;;) { 779879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o switch(fscanf (in, "%lu\n", &next_bad)) { 780879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o case 0: 781879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o com_err (program_name, 0, "input file - bad format"); 782879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 783879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o case EOF: 784879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o break; 785879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o default: 786879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o errcode = ext2fs_badblocks_list_add(bb_list,next_bad); 787879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (errcode) { 788d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o com_err (program_name, errcode, _("adding to in-memory bad block list")); 789879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 790879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 791879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o continue; 792879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 793879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o break; 794879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 795879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 796879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (in != stdin) 797879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o fclose (in); 798879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 799879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 800879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o do { 801879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o unsigned int bb_count; 802879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 8034d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o bb_count = test_func(dev, blocks_count, block_size, 8044d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o from_count, blocks_at_once); 8054d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o if (bb_count) 8064d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o passes_clean = 0; 8074d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o else 8084d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o ++passes_clean; 8094d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 810879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (v_flag) 811d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o fprintf(stderr, 812d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o _("Pass completed, %u bad blocks found.\n"), 813d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o bb_count); 814879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 815879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } while (passes_clean < num_passes); 816879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 8173839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o close (dev); 8183839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (out != stdout) 8193839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o fclose (out); 820879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o return 0; 8213839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 822d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o 823