badblocks.c revision 54c637d4d29af3e6365779f8b12976abe95a4753
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 503839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include "et/com_err.h" 51d40259fd552d942903f2fd0b426c75a5c2516017Theodore Ts'o#include "ext2fs/ext2_io.h" 5254c637d4d29af3e6365779f8b12976abe95a4753Theodore Ts'o#include "ext2fs/ext2_fs.h" 53879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o#include "ext2fs/ext2fs.h" 54d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o#include "nls-enable.h" 553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'oconst char * program_name = "badblocks"; 578f5c0f66ca343ec4689470e5941aa3066ed062bbTheodore Ts'oconst char * done_string = N_("done \n"); 583839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 594d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'ostatic int v_flag = 0; /* verbose */ 604d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'ostatic int w_flag = 0; /* do r/w test: 0=no, 1=yes, 614d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o * 2=non-destructive */ 624d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'ostatic int s_flag = 0; /* show progress of test */ 63981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'ostatic int force = 0; /* force check of mounted device */ 644d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 658820c79f75c37a3bc85cea7f56e7277025e157efTheodore Ts'ostatic void usage(void) 663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 67cd130a0887b5e5e9436533bbcda4c17ec5202788Theodore Ts'o fprintf(stderr, _("Usage: %s [-b block_size] [-i input_file] [-o output_file] [-svwnf]\n [-c blocks_at_once] [-p num_passes] device [last_block [start_count]]\n"), 683839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o program_name); 693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o exit (1); 703839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 713839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 7219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'ostatic unsigned long currently_testing = 0; 7319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'ostatic unsigned long num_blocks = 0; 74879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'ostatic ext2_badblocks_list bb_list = NULL; 75879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'ostatic FILE *out; 76879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'ostatic blk_t next_bad = 0; 77879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'ostatic ext2_badblocks_iterate bb_iter = NULL; 7819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 79dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o/* 80dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o * This routine reports a new bad block. If the bad block has already 81dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o * been seen before, then it returns 0; otherwise it returns 1. 82dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o */ 83dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'ostatic int bb_output (unsigned long bad) 84879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o{ 85879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o errcode_t errcode; 86879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 87dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o if (ext2fs_badblocks_list_test(bb_list, bad)) 88dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o return 0; 89dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o 90879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o fprintf (out, "%lu\n", bad); 91879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 92879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o errcode = ext2fs_badblocks_list_add (bb_list, bad); 93879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (errcode) { 94879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o com_err (program_name, errcode, "adding to in-memory bad block list"); 95879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 96879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 97879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 98879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o /* kludge: 99879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o increment the iteration through the bb_list if 100879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o an element was just added before the current iteration 101879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o position. This should not cause next_bad to change. */ 102879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (bb_iter && bad < next_bad) 103879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o ext2fs_badblocks_list_iterate (bb_iter, &next_bad); 104dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o return 1; 105879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o} 106879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 1078820c79f75c37a3bc85cea7f56e7277025e157efTheodore Ts'ostatic void print_status(void) 10819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o{ 10919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o fprintf(stderr, "%9ld/%9ld", currently_testing, num_blocks); 11019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o fprintf(stderr, "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"); 11119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o fflush (stderr); 11219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o} 11319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 114981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'ostatic void alarm_intr(int alnum) 11519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o{ 11619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o signal (SIGALRM, alarm_intr); 11719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o alarm(1); 11819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (!num_blocks) 11919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o return; 12019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o fprintf(stderr, "%9ld/%9ld", currently_testing, num_blocks); 12119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o fprintf(stderr, "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"); 12219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o fflush (stderr); 12319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o} 12419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 125879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'ostatic void *terminate_addr = NULL; 126879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 127981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'ostatic void terminate_intr(int signo) 128879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o{ 129879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (terminate_addr) 130879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o longjmp(terminate_addr,1); 131879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit(1); 132879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o} 133879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 134981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'ostatic void capture_terminate(jmp_buf term_addr) 135879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o{ 136879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o terminate_addr = term_addr; 137879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o signal (SIGHUP, terminate_intr); 138879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o signal (SIGINT, terminate_intr); 139879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o signal (SIGPIPE, terminate_intr); 140879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o signal (SIGTERM, terminate_intr); 141879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o signal (SIGUSR1, terminate_intr); 142879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o signal (SIGUSR2, terminate_intr); 143879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o} 144879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 1458820c79f75c37a3bc85cea7f56e7277025e157efTheodore Ts'ostatic void uncapture_terminate(void) 1464d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o{ 1474d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o terminate_addr = NULL; 1484d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o signal (SIGHUP, SIG_DFL); 1494d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o signal (SIGINT, SIG_DFL); 1504d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o signal (SIGPIPE, SIG_DFL); 1514d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o signal (SIGTERM, SIG_DFL); 1524d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o signal (SIGUSR1, SIG_DFL); 1534d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o signal (SIGUSR2, SIG_DFL); 1544d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o} 1554d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 1563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 157879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o * Perform a read of a sequence of blocks; return the number of blocks 158879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o * successfully sequentially read. 1593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 160dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'ostatic long do_read (int dev, char * buffer, int try, int block_size, 1613839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o unsigned long current_block) 1623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 1633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o long got; 1643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 16519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (v_flag > 1) 16619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o print_status(); 16719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 1683839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* Seek to the correct loc. */ 16919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (ext2fs_llseek (dev, (ext2_loff_t) current_block * block_size, 170f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o SEEK_SET) != (ext2_loff_t) current_block * block_size) 171d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o com_err (program_name, errno, _("during seek")); 1723839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1733839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* Try the read */ 1743839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o got = read (dev, buffer, try * block_size); 1753839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (got < 0) 1763839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o got = 0; 1779f10a7b31e57288093930fc9565102409eeac6e9Theodore Ts'o if (got & 511) 178d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o fprintf(stderr, _("Weird value (%ld) in do_read\n"), got); 179879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o got /= block_size; 180879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o return got; 181879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o} 182879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 183879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o/* 184879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o * Perform a write of a sequence of blocks; return the number of blocks 185879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o * successfully sequentially written. 186879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o */ 187dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'ostatic long do_write (int dev, char * buffer, int try, int block_size, 188879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o unsigned long current_block) 189879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o{ 190879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o long got; 191879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 192879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (v_flag > 1) 193879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o print_status(); 194879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 195879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o /* Seek to the correct loc. */ 196879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (ext2fs_llseek (dev, (ext2_loff_t) current_block * block_size, 197879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o SEEK_SET) != (ext2_loff_t) current_block * block_size) 198d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o com_err (program_name, errno, _("during seek")); 199879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 200879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o /* Try the write */ 201879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o got = write (dev, buffer, try * block_size); 202879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (got < 0) 203879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o got = 0; 204879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (got & 511) 205879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o fprintf (stderr, 206879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o "Weird value (%ld) in do_write\n", got); 2073839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o got /= block_size; 2083839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return got; 2093839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 2103839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 211879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'ostatic int host_dev; 212879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 2134d4045475f80ad2901c468815976d2beffd0cb59Theodore Ts'ostatic void flush_bufs(void) 214a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o{ 2154d4045475f80ad2901c468815976d2beffd0cb59Theodore Ts'o errcode_t retval; 216a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o 2174d4045475f80ad2901c468815976d2beffd0cb59Theodore Ts'o retval = ext2fs_sync_device(host_dev, 1); 2184d4045475f80ad2901c468815976d2beffd0cb59Theodore Ts'o if (retval) 2194d4045475f80ad2901c468815976d2beffd0cb59Theodore Ts'o com_err(program_name, retval, _("during ext2fs_sync_device")); 220a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o} 221a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o 222cd130a0887b5e5e9436533bbcda4c17ec5202788Theodore Ts'ostatic unsigned int test_ro (int dev, unsigned long last_block, 223dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o int block_size, unsigned long from_count, 224dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o unsigned long blocks_at_once) 2253839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 2263839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o char * blkbuf; 2273839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int try; 2283839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o long got; 229879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o unsigned int bb_count = 0; 230879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o errcode_t errcode; 2313839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 232879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o errcode = ext2fs_badblocks_list_iterate_begin(bb_list,&bb_iter); 233879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (errcode) { 234d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o com_err (program_name, errcode, 235d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o _("while beginning bad block list iteration")); 236879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 237879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 238879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o do { 239879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o ext2fs_badblocks_list_iterate (bb_iter, &next_bad); 240879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } while (next_bad && next_bad < from_count); 241879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 242879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o blkbuf = malloc (blocks_at_once * block_size); 2433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (!blkbuf) 2443839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o { 245d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o com_err (program_name, ENOMEM, _("while allocating buffers")); 2463839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o exit (1); 2473839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 2484d4045475f80ad2901c468815976d2beffd0cb59Theodore Ts'o flush_bufs(); 249f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (v_flag) { 250d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o fprintf(stderr, _("Checking for bad blocks in read-only mode\n")); 251d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o fprintf (stderr, _("From block %lu to %lu\n"), from_count, 252cd130a0887b5e5e9436533bbcda4c17ec5202788Theodore Ts'o last_block); 253f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o } 254879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o try = blocks_at_once; 255f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o currently_testing = from_count; 256cd130a0887b5e5e9436533bbcda4c17ec5202788Theodore Ts'o num_blocks = last_block; 25719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (s_flag || v_flag > 1) { 258d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o fprintf(stderr, 259d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o _("Checking for bad blocks (read-only test): ")); 26019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (v_flag <= 1) 26119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o alarm_intr(SIGALRM); 2623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 263cd130a0887b5e5e9436533bbcda4c17ec5202788Theodore Ts'o while (currently_testing < last_block) 2643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o { 265879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (next_bad) { 266879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (currently_testing == next_bad) { 267879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o /* fprintf (out, "%lu\n", nextbad); */ 268879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o ext2fs_badblocks_list_iterate (bb_iter, &next_bad); 269879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o currently_testing++; 270879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o continue; 271879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 272879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o else if (currently_testing + try > next_bad) 273879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o try = next_bad - currently_testing; 274879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 275cd130a0887b5e5e9436533bbcda4c17ec5202788Theodore Ts'o if (currently_testing + try > last_block) 276cd130a0887b5e5e9436533bbcda4c17ec5202788Theodore Ts'o try = last_block - currently_testing; 277879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o got = do_read (dev, blkbuf, try, block_size, currently_testing); 2783839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o currently_testing += got; 2793839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (got == try) { 280879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o try = blocks_at_once; 2813839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o continue; 2823839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 2833839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o else 2843839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o try = 1; 285879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (got == 0) { 286dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o bb_count += bb_output(currently_testing++); 287879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 2883839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 2893839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o num_blocks = 0; 2903839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o alarm(0); 29119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (s_flag || v_flag > 1) 2928f5c0f66ca343ec4689470e5941aa3066ed062bbTheodore Ts'o fprintf(stderr, _(done_string)); 293879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 294f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o fflush (stderr); 2953839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o free (blkbuf); 296879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 297879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o ext2fs_badblocks_list_iterate_end(bb_iter); 298879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 299879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o return bb_count; 3003839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 3013839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 302cd130a0887b5e5e9436533bbcda4c17ec5202788Theodore Ts'ostatic unsigned int test_rw (int dev, unsigned long last_block, 303dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o int block_size, unsigned long from_count, 304dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o unsigned long blocks_at_once) 3053839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 3063839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int i; 3073839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o char * buffer; 3088820c79f75c37a3bc85cea7f56e7277025e157efTheodore Ts'o static unsigned char pattern[] = {0xaa, 0x55, 0xff, 0x00}; 309879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o unsigned int bb_count = 0; 3103839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 3113839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o buffer = malloc (2 * block_size); 3123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (!buffer) 3133839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o { 314d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o com_err (program_name, ENOMEM, _("while allocating buffers")); 3153839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o exit (1); 3163839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 3173839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 3184d4045475f80ad2901c468815976d2beffd0cb59Theodore Ts'o flush_bufs(); 319a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o 32019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (v_flag) { 32119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o fprintf(stderr, 322d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o _("Checking for bad blocks in read-write mode\n")); 323d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o fprintf(stderr, _("From block %lu to %lu\n"), 324cd130a0887b5e5e9436533bbcda4c17ec5202788Theodore Ts'o from_count, last_block); 32519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o } 32619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o for (i = 0; i < sizeof (pattern); i++) { 3273839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o memset (buffer, pattern[i], block_size); 328f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (s_flag | v_flag) 329d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o fprintf (stderr, _("Writing pattern 0x%08x: "), 3303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o *((int *) buffer)); 331cd130a0887b5e5e9436533bbcda4c17ec5202788Theodore Ts'o num_blocks = last_block; 332f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o currently_testing = from_count; 33319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (s_flag && v_flag <= 1) 334f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o alarm_intr(SIGALRM); 335f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o for (; 336cd130a0887b5e5e9436533bbcda4c17ec5202788Theodore Ts'o currently_testing < last_block; 337f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o currently_testing++) 3383839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o { 33919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (ext2fs_llseek (dev, (ext2_loff_t) currently_testing * 340f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o block_size, SEEK_SET) != 341f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o (ext2_loff_t) currently_testing * block_size) 3423839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o com_err (program_name, errno, 343d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o _("during seek on block %d"), 344f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o currently_testing); 34519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (v_flag > 1) 34619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o print_status(); 3473839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o write (dev, buffer, block_size); 3483839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 349f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o num_blocks = 0; 350f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o alarm (0); 351f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (s_flag | v_flag) 3528f5c0f66ca343ec4689470e5941aa3066ed062bbTheodore Ts'o fprintf(stderr, _(done_string)); 3534d4045475f80ad2901c468815976d2beffd0cb59Theodore Ts'o flush_bufs(); 354f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (s_flag | v_flag) 355d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o fprintf (stderr, _("Reading and comparing: ")); 356cd130a0887b5e5e9436533bbcda4c17ec5202788Theodore Ts'o num_blocks = last_block; 357f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o currently_testing = from_count; 35819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (s_flag && v_flag <= 1) 359f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o alarm_intr(SIGALRM); 360f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o for (; 361cd130a0887b5e5e9436533bbcda4c17ec5202788Theodore Ts'o currently_testing < last_block; 362f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o currently_testing++) 3633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o { 36419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (ext2fs_llseek (dev, (ext2_loff_t) currently_testing * 365f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o block_size, SEEK_SET) != 366f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o (ext2_loff_t) currently_testing * block_size) 3673839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o com_err (program_name, errno, 368d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o _("during seek on block %d"), 369f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o currently_testing); 37019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (v_flag > 1) 37119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o print_status(); 372dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o if ((read (dev, buffer + block_size, block_size) 3734d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o != block_size) || 374dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o memcmp(buffer, buffer + block_size, block_size)) 3754d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o bb_count += bb_output(currently_testing); 3763839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 377f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o num_blocks = 0; 378f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o alarm (0); 379f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (s_flag | v_flag) 3808f5c0f66ca343ec4689470e5941aa3066ed062bbTheodore Ts'o fprintf(stderr, _(done_string)); 3814d4045475f80ad2901c468815976d2beffd0cb59Theodore Ts'o flush_bufs(); 3823839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 383879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 384879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o return bb_count; 385879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o} 386879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 387d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'ostruct saved_blk_record { 388d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o blk_t block; 389d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o int num; 390d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o}; 391d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o 392cd130a0887b5e5e9436533bbcda4c17ec5202788Theodore Ts'ostatic unsigned int test_nd (int dev, unsigned long last_block, 393dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o int block_size, unsigned long from_count, 394dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o unsigned long blocks_at_once) 395879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o{ 396dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o char *blkbuf, *save_ptr, *test_ptr, *read_ptr; 397879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o char * ptr; 398dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o int try, i; 399a551b783479b47d05ec996da5c87009a092cf491Theodore Ts'o long got, used2, written, save_currently_testing; 400d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o struct saved_blk_record *test_record; 401a551b783479b47d05ec996da5c87009a092cf491Theodore Ts'o /* This is static to prevent being clobbered by the longjmp */ 402a551b783479b47d05ec996da5c87009a092cf491Theodore Ts'o static int num_saved; 403879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o jmp_buf terminate_env; 404879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o errcode_t errcode; 405a551b783479b47d05ec996da5c87009a092cf491Theodore Ts'o long buf_used; 406a551b783479b47d05ec996da5c87009a092cf491Theodore Ts'o unsigned int bb_count; 407879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 408879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o errcode = ext2fs_badblocks_list_iterate_begin(bb_list,&bb_iter); 409879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (errcode) { 410dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o com_err (program_name, errcode, 411d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o _("while beginning bad block list iteration")); 412879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 413879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 414879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o do { 415879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o ext2fs_badblocks_list_iterate (bb_iter, &next_bad); 416879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } while (next_bad && next_bad < from_count); 417879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 418879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o blkbuf = malloc (3 * blocks_at_once * block_size); 419d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o test_record = malloc (blocks_at_once*sizeof(struct saved_blk_record)); 420d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o if (!blkbuf || !test_record) { 421d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o com_err(program_name, ENOMEM, _("while allocating buffers")); 422879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 423879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 424d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o num_saved = 0; 425879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 426879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o /* inititalize the test data randomly: */ 427879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (v_flag) { 428d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o fprintf (stderr, _("Initializing random test data\n")); 429879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 430879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o for(ptr = blkbuf + blocks_at_once * block_size; 431dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o ptr < blkbuf + 2 * blocks_at_once * block_size; 432dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o ++ptr) { 433879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o (*ptr) = random() % (1 << sizeof(char)); 434879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 435879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 4364d4045475f80ad2901c468815976d2beffd0cb59Theodore Ts'o flush_bufs(); 437879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (v_flag) { 438879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o fprintf (stderr, 439d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o _("Checking for bad blocks in non-destructive read-write mode\n")); 440cd130a0887b5e5e9436533bbcda4c17ec5202788Theodore Ts'o fprintf (stderr, _("From block %lu to %lu\n"), from_count, last_block); 441879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 442879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (s_flag || v_flag > 1) { 443d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o fprintf(stderr, _("Checking for bad blocks (non-destructive read-write test): ")); 444879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (v_flag <= 1) 445879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o alarm_intr(SIGALRM); 446879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 4474d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o if (setjmp(terminate_env)) { 4484d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o /* 4494d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o * Abnormal termination by a signal is handled here. 4504d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o */ 451a551b783479b47d05ec996da5c87009a092cf491Theodore Ts'o signal (SIGALRM, SIG_IGN); 452a551b783479b47d05ec996da5c87009a092cf491Theodore Ts'o fprintf(stderr, _("\nInterrupt caught, cleaning up\n")); 453879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 454d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o save_ptr = blkbuf; 455d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o for (i=0; i < num_saved; i++) { 456d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o do_write(dev, save_ptr, test_record[i].num, 457d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o block_size, test_record[i].block); 458d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o save_ptr += test_record[i].num * block_size; 459d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o } 460879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o fflush (out); 461dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o exit(1); 462879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 4634d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 4644d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o /* set up abend handler */ 4654d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o capture_terminate(terminate_env); 4664d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 467d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o buf_used = 0; 468a551b783479b47d05ec996da5c87009a092cf491Theodore Ts'o bb_count = 0; 469d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o save_ptr = blkbuf; 4704d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o test_ptr = blkbuf + (blocks_at_once * block_size); 4714d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o currently_testing = from_count; 472cd130a0887b5e5e9436533bbcda4c17ec5202788Theodore Ts'o num_blocks = last_block; 4734d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 474cd130a0887b5e5e9436533bbcda4c17ec5202788Theodore Ts'o while (currently_testing < last_block) { 4754d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o try = blocks_at_once - buf_used; 4764d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o if (next_bad) { 4774d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o if (currently_testing == next_bad) { 4784d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o /* fprintf (out, "%lu\n", nextbad); */ 4794d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o ext2fs_badblocks_list_iterate (bb_iter, &next_bad); 480d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o currently_testing++; 481d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o goto check_for_more; 4824d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o } 4834d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o else if (currently_testing + try > next_bad) 4844d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o try = next_bad - currently_testing; 4854d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o } 486cd130a0887b5e5e9436533bbcda4c17ec5202788Theodore Ts'o if (currently_testing + try > last_block) 487cd130a0887b5e5e9436533bbcda4c17ec5202788Theodore Ts'o try = last_block - currently_testing; 4884d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o got = do_read (dev, save_ptr, try, block_size, 4894d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o currently_testing); 490d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o if (got == 0) { 491d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o /* First block must have been bad. */ 492d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o bb_count += bb_output(currently_testing++); 493d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o goto check_for_more; 494d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o } 4954d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 496d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o /* 497d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o * Note the fact that we've saved this much data 498d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o * *before* we overwrite it with test data 499d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o */ 500d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o test_record[num_saved].block = currently_testing; 501d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o test_record[num_saved].num = got; 502d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o num_saved++; 503d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o 504d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o /* Write the test data */ 505d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o written = do_write (dev, test_ptr, got, block_size, 506d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o currently_testing); 507d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o if (written != got) 508d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o com_err (program_name, errno, 5094d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o _("during test data write, block %lu"), 510d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o currently_testing + written); 5114d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 5124d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o buf_used += got; 5134d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o save_ptr += got * block_size; 5144d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o test_ptr += got * block_size; 5154d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o currently_testing += got; 5164d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o if (got != try) 5174d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o bb_count += bb_output(currently_testing++); 5184d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 519d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o check_for_more: 5204d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o /* 5214d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o * If there's room for more blocks to be tested this 5224d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o * around, and we're not done yet testing the disk, go 5234d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o * back and get some more blocks. 5244d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o */ 5254d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o if ((buf_used != blocks_at_once) && 526cd130a0887b5e5e9436533bbcda4c17ec5202788Theodore Ts'o (currently_testing < last_block)) 5274d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o continue; 5284d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 5294d4045475f80ad2901c468815976d2beffd0cb59Theodore Ts'o flush_bufs(); 530a551b783479b47d05ec996da5c87009a092cf491Theodore Ts'o save_currently_testing = currently_testing; 5314d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 5324d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o /* 5334d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o * for each contiguous block that we read into the 5344d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o * buffer (and wrote test data into afterwards), read 5354d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o * it back (looping if necessary, to get past newly 5364d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o * discovered unreadable blocks, of which there should 5374d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o * be none, but with a hard drive which is unreliable, 5384d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o * it has happened), and compare with the test data 5394d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o * that was written; output to the bad block list if 5404d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o * it doesn't match. 5414d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o */ 5424d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o used2 = 0; 5434d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o save_ptr = blkbuf; 5444d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o test_ptr = blkbuf + (blocks_at_once * block_size); 5454d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o read_ptr = blkbuf + (2 * blocks_at_once * block_size); 546d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o try = 0; 5474d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 548d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o while (1) { 549d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o if (try == 0) { 550d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o if (used2 >= num_saved) 551d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o break; 552d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o currently_testing = test_record[used2].block; 553d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o try = test_record[used2].num; 554d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o used2++; 555d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o } 556d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o 5574d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o got = do_read (dev, read_ptr, try, 5584d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o block_size, currently_testing); 5594d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 5604d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o /* test the comparison between all the 5614d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o blocks successfully read */ 5624d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o for (i = 0; i < got; ++i) 5634d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o if (memcmp (test_ptr+i*block_size, 5644d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o read_ptr+i*block_size, block_size)) 5654d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o bb_count += bb_output(currently_testing + i); 5664d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o if (got < try) { 5674d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o bb_count += bb_output(currently_testing + got); 5684d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o got++; 5694d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o } 5704d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 5714d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o /* when done, write back original data */ 5724d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o do_write (dev, save_ptr, got, block_size, 5734d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o currently_testing); 5744d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 5754d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o currently_testing += got; 5764d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o save_ptr += got * block_size; 5774d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o test_ptr += got * block_size; 5784d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o read_ptr += got * block_size; 5794d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o try -= got; 5804d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o } 5814d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 5824d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o /* empty the buffer so it can be reused */ 583d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o num_saved = 0; 5844d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o buf_used = 0; 585d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o save_ptr = blkbuf; 586d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o test_ptr = blkbuf + (blocks_at_once * block_size); 587a551b783479b47d05ec996da5c87009a092cf491Theodore Ts'o currently_testing = save_currently_testing; 5884d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o } 5894d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o num_blocks = 0; 5904d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o alarm(0); 5914d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o uncapture_terminate(); 5924d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o if (s_flag || v_flag > 1) 5934d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o fprintf(stderr, _(done_string)); 594879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 595dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o fflush(stderr); 596dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o free(blkbuf); 597d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o free(test_record); 598879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 599879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o ext2fs_badblocks_list_iterate_end(bb_iter); 600879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 601879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o return bb_count; 6023839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 6033839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 604981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'ostatic void check_mount(char *device_name) 605981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o{ 606981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o errcode_t retval; 607981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o int mount_flags; 608981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o 609981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o retval = ext2fs_check_if_mounted(device_name, &mount_flags); 610981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o if (retval) { 611981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o com_err("ext2fs_check_if_mount", retval, 612981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o _("while determining whether %s is mounted."), 613981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o device_name); 614981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o return; 615981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o } 616981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o if (!(mount_flags & EXT2_MF_MOUNTED)) 617981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o return; 618981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o 619981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o fprintf(stderr, _("%s is mounted; "), device_name); 620981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o if (force) { 621981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o fprintf(stderr, _("badblocks forced anyway. " 622981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o "Hope /etc/mtab is incorrect.\n")); 623981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o return; 624981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o } 625981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o fprintf(stderr, _("it's not safe to run badblocks!\n")); 626981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o exit(1); 627981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o} 628981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o 629981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o 63000e5433eb5e9f70f485968b809fdcf297d7fe7b9Theodore Ts'oint main (int argc, char ** argv) 6313839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 632519149fb458b0fa69c10fecd83fae42e838cf01dTheodore Ts'o int c; 6333839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o char * tmp; 6343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o char * device_name; 635879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o char * host_device_name = NULL; 636879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o char * input_file = NULL; 6373839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o char * output_file = NULL; 638879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o FILE * in = NULL; 639dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o int block_size = 1024; 640879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o unsigned long blocks_at_once = 16; 641cd130a0887b5e5e9436533bbcda4c17ec5202788Theodore Ts'o blk_t last_block, from_count; 642879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o int num_passes = 0; 643879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o int passes_clean = 0; 6443839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int dev; 645879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o errcode_t errcode; 6468820c79f75c37a3bc85cea7f56e7277025e157efTheodore Ts'o unsigned int (*test_func)(int, unsigned long, 6478820c79f75c37a3bc85cea7f56e7277025e157efTheodore Ts'o int, unsigned long, 6488820c79f75c37a3bc85cea7f56e7277025e157efTheodore Ts'o unsigned long); 6493839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 6503839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o setbuf(stdout, NULL); 6513839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o setbuf(stderr, NULL); 652d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o#ifdef ENABLE_NLS 653d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o setlocale(LC_MESSAGES, ""); 654d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o bindtextdomain(NLS_CAT_NAME, LOCALEDIR); 655d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o textdomain(NLS_CAT_NAME); 656d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o#endif 6574d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o test_func = test_ro; 6584d4045475f80ad2901c468815976d2beffd0cb59Theodore Ts'o 6593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (argc && *argv) 6603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o program_name = *argv; 661a551b783479b47d05ec996da5c87009a092cf491Theodore Ts'o while ((c = getopt (argc, argv, "b:fi:o:svwnc:p:h:")) != EOF) { 6623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o switch (c) { 6633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o case 'b': 6643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o block_size = strtoul (optarg, &tmp, 0); 6653839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (*tmp || block_size > 4096) { 6663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o com_err (program_name, 0, 667d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o _("bad block size - %s"), optarg); 6683839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o exit (1); 6693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 6703839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o break; 671981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o case 'f': 672981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o force++; 673981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o break; 674879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o case 'i': 675879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o input_file = optarg; 676879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o break; 6773839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o case 'o': 6783839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o output_file = optarg; 6793839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o break; 6803839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o case 's': 6813839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o s_flag = 1; 6823839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o break; 6833839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o case 'v': 68419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o v_flag++; 6853839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o break; 6863839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o case 'w': 6874d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o if (w_flag) 6884d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o usage(); 6894d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o test_func = test_rw; 6904d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o w_flag = 1; 691879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o break; 692879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o case 'n': 6934d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o if (w_flag) 6944d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o usage(); 6954d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o test_func = test_nd; 696879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o w_flag = 2; 697879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o break; 698879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o case 'c': 699879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o blocks_at_once = strtoul (optarg, &tmp, 0); 700879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (*tmp) { 701879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o com_err (program_name, 0, 702879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o "bad simultaneous block count - %s", optarg); 703879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 704879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 705879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o break; 706879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o case 'p': 707879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o num_passes = strtoul (optarg, &tmp, 0); 708879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (*tmp) { 709879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o com_err (program_name, 0, 710879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o "bad number of clean passes - %s", optarg); 711879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 712879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 713879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o break; 714879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o case 'h': 715879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o host_device_name = optarg; 7163839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o break; 7173839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o default: 718818180cdfcff84b9048ecdc5dc86323f0fefba24Theodore Ts'o usage(); 7193839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 7203839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 7213839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (optind > argc - 1) 722818180cdfcff84b9048ecdc5dc86323f0fefba24Theodore Ts'o usage(); 7233839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o device_name = argv[optind++]; 72435964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o if (optind > argc - 1) { 72535964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o errcode = ext2fs_get_device_size(device_name, 72635964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o block_size, 727cd130a0887b5e5e9436533bbcda4c17ec5202788Theodore Ts'o &last_block); 72835964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o if (errcode == EXT2_ET_UNIMPLEMENTED) { 72935964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o com_err(program_name, 0, 73035964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o _("Couldn't determine device size; you " 73135964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o "must specify\nthe size manually\n")); 73235964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o exit(1); 73335964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o } 73435964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o if (errcode) { 73535964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o com_err(program_name, errcode, 73635964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o _("while trying to determine device size")); 73735964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o exit(1); 73835964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o } 73935964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o } else { 740cd130a0887b5e5e9436533bbcda4c17ec5202788Theodore Ts'o last_block = strtoul (argv[optind], &tmp, 0); 74135964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o if (*tmp) { 74235964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o com_err (program_name, 0, _("bad blocks count - %s"), 74335964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o argv[optind]); 74435964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o exit (1); 74535964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o } 74635964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o optind++; 7473839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 74835964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o if (optind <= argc-1) { 749f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o from_count = strtoul (argv[optind], &tmp, 0); 750a551b783479b47d05ec996da5c87009a092cf491Theodore Ts'o if (*tmp) { 751a551b783479b47d05ec996da5c87009a092cf491Theodore Ts'o com_err (program_name, 0, _("bad starting block - %s"), 752a551b783479b47d05ec996da5c87009a092cf491Theodore Ts'o argv[optind]); 753a551b783479b47d05ec996da5c87009a092cf491Theodore Ts'o exit (1); 754a551b783479b47d05ec996da5c87009a092cf491Theodore Ts'o } 755f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o } else from_count = 0; 756cd130a0887b5e5e9436533bbcda4c17ec5202788Theodore Ts'o if (from_count >= last_block) { 757d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o com_err (program_name, 0, _("bad blocks range: %lu-%lu"), 758cd130a0887b5e5e9436533bbcda4c17ec5202788Theodore Ts'o from_count, last_block); 759f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o exit (1); 760f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o } 761981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o if (w_flag) 762981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o check_mount(device_name); 763981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o 7643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dev = open (device_name, w_flag ? O_RDWR : O_RDONLY); 7653839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (dev == -1) 7663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o { 767d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o com_err (program_name, errno, _("while trying to open %s"), 7683839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o device_name); 7693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o exit (1); 7703839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 771879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (host_device_name) { 772879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o host_dev = open (host_device_name, O_RDONLY); 773879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (host_dev == -1) 774879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o { 775d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o com_err (program_name, errno, 776d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o _("while trying to open %s"), 777d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o host_device_name); 778879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 779879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 780879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } else 781879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o host_dev = dev; 782879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (input_file) 783879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (strcmp (input_file, "-") == 0) 784879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o in = stdin; 785879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o else { 786879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o in = fopen (input_file, "r"); 787879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (in == NULL) 788879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o { 789d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o com_err (program_name, errno, 790d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o _("while trying to open %s"), 791879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o input_file); 792879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 793879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 794879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 7953839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (output_file && strcmp (output_file, "-") != 0) 7963839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o { 7973839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o out = fopen (output_file, "w"); 7983839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (out == NULL) 7993839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o { 800d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o com_err (program_name, errno, 801d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o _("while trying to open %s"), 802879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o output_file); 8033839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o exit (1); 8043839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 8053839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 8063839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o else 8073839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o out = stdout; 808879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 809879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o errcode = ext2fs_badblocks_list_create(&bb_list,0); 810879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (errcode) { 811d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o com_err (program_name, errcode, 812d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o _("creating in-memory bad blocks list")); 813879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 814879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 815879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 816879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (in) { 817879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o for(;;) { 818a551b783479b47d05ec996da5c87009a092cf491Theodore Ts'o switch(fscanf (in, "%u\n", &next_bad)) { 819879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o case 0: 820879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o com_err (program_name, 0, "input file - bad format"); 821879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 822879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o case EOF: 823879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o break; 824879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o default: 825879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o errcode = ext2fs_badblocks_list_add(bb_list,next_bad); 826879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (errcode) { 827d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o com_err (program_name, errcode, _("adding to in-memory bad block list")); 828879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 829879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 830879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o continue; 831879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 832879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o break; 833879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 834879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 835879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (in != stdin) 836879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o fclose (in); 837879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 838879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 839879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o do { 840879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o unsigned int bb_count; 841879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 842cd130a0887b5e5e9436533bbcda4c17ec5202788Theodore Ts'o bb_count = test_func(dev, last_block, block_size, 8434d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o from_count, blocks_at_once); 8444d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o if (bb_count) 8454d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o passes_clean = 0; 8464d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o else 8474d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o ++passes_clean; 8484d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 849879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (v_flag) 850d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o fprintf(stderr, 851d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o _("Pass completed, %u bad blocks found.\n"), 852d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o bb_count); 853879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 854879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } while (passes_clean < num_passes); 855879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 8563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o close (dev); 8573839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (out != stdout) 8583839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o fclose (out); 859879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o return 0; 8603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 861d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o 862