badblocks.c revision 879ac920e347267d4461ba76b349fbef67b42b9b
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 * 819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * Copyright 1995, 1996, 1997 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, 25879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o * and a whole host of other features. 263839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 273839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 283839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <errno.h> 293839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <fcntl.h> 30a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o#ifdef HAVE_GETOPT_H 313839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <getopt.h> 32a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o#endif 333839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <signal.h> 343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <stdio.h> 353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <stdlib.h> 363839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <string.h> 373839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <unistd.h> 38879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o#include <setjmp.h> 393839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 403839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <sys/ioctl.h> 41f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#include <sys/types.h> 423839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 43a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o#if HAVE_LINUX_FS_H 443839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <linux/fd.h> 453839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <linux/fs.h> 46a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o#endif 473839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 483839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include "et/com_err.h" 49d40259fd552d942903f2fd0b426c75a5c2516017Theodore Ts'o#include "ext2fs/ext2_io.h" 50879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o#include <linux/ext2_fs.h> 51879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o#include "ext2fs/ext2fs.h" 523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'oconst char * program_name = "badblocks"; 5400eedba1bd3a37812ee9403abca7ea4376ac9a08Theodore Ts'oconst char * done_string = "done \n"; 553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'oint v_flag = 0; /* verbose */ 57879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'oint w_flag = 0; /* do r/w test: 0=no, 1=yes, 2=non-destructive */ 583839e65723771b85975f4263102dd3ceec4523cTheodore Ts'oint s_flag = 0; /* show progress of test */ 593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 60818180cdfcff84b9048ecdc5dc86323f0fefba24Theodore Ts'ostatic void usage(void) 613839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 62879ac920e347267d4461ba76b349fbef67b42b9bTheodore 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", 633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o program_name); 643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o exit (1); 653839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 6719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'ostatic unsigned long currently_testing = 0; 6819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'ostatic unsigned long num_blocks = 0; 69879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'ostatic ext2_badblocks_list bb_list = NULL; 70879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'ostatic FILE *out; 71879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'ostatic blk_t next_bad = 0; 72879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'ostatic ext2_badblocks_iterate bb_iter = NULL; 7319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 74879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'ostatic void bb_output (unsigned long bad) 75879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o{ 76879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o errcode_t errcode; 77879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 78879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o fprintf (out, "%lu\n", bad); 79879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 80879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o errcode = ext2fs_badblocks_list_add (bb_list, bad); 81879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (errcode) { 82879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o com_err (program_name, errcode, "adding to in-memory bad block list"); 83879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 84879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 85879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 86879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o /* kludge: 87879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o increment the iteration through the bb_list if 88879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o an element was just added before the current iteration 89879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o position. This should not cause next_bad to change. */ 90879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (bb_iter && bad < next_bad) 91879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o ext2fs_badblocks_list_iterate (bb_iter, &next_bad); 92879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o} 93879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 94879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'ostatic void print_status (void) 9519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o{ 9619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o fprintf(stderr, "%9ld/%9ld", currently_testing, num_blocks); 9719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o fprintf(stderr, "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"); 9819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o fflush (stderr); 9919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o} 10019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 10119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'ostatic void alarm_intr (int alnum) 10219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o{ 10319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o signal (SIGALRM, alarm_intr); 10419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o alarm(1); 10519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (!num_blocks) 10619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o return; 10719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o fprintf(stderr, "%9ld/%9ld", currently_testing, num_blocks); 10819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o fprintf(stderr, "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"); 10919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o fflush (stderr); 11019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o} 11119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 112879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'ostatic void *terminate_addr = NULL; 113879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 114879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'ostatic void terminate_intr (int signo) 115879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o{ 116879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (terminate_addr) 117879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o longjmp(terminate_addr,1); 118879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit(1); 119879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o} 120879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 121879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'ostatic void capture_terminate (jmp_buf term_addr) 122879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o{ 123879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o terminate_addr = term_addr; 124879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o signal (SIGHUP, terminate_intr); 125879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o signal (SIGINT, terminate_intr); 126879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o signal (SIGPIPE, terminate_intr); 127879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o signal (SIGTERM, terminate_intr); 128879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o signal (SIGUSR1, terminate_intr); 129879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o signal (SIGUSR2, terminate_intr); 130879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o} 131879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 1323839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 133879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o * Perform a read of a sequence of blocks; return the number of blocks 134879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o * successfully sequentially read. 1353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 136879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'ostatic long do_read (int dev, char * buffer, int try, unsigned long block_size, 1373839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o unsigned long current_block) 1383839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 1393839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o long got; 1403839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 14119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (v_flag > 1) 14219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o print_status(); 14319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 1443839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* Seek to the correct loc. */ 14519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (ext2fs_llseek (dev, (ext2_loff_t) current_block * block_size, 146f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o SEEK_SET) != (ext2_loff_t) current_block * block_size) 147f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o com_err (program_name, errno, "during seek"); 1483839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1493839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* Try the read */ 1503839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o got = read (dev, buffer, try * block_size); 1513839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (got < 0) 1523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o got = 0; 1539f10a7b31e57288093930fc9565102409eeac6e9Theodore Ts'o if (got & 511) 154f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o fprintf (stderr, 155879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o "Weird value (%ld) in do_read\n", got); 156879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o got /= block_size; 157879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o return got; 158879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o} 159879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 160879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o/* 161879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o * Perform a write of a sequence of blocks; return the number of blocks 162879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o * successfully sequentially written. 163879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o */ 164879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'ostatic long do_write (int dev, char * buffer, int try, unsigned long block_size, 165879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o unsigned long current_block) 166879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o{ 167879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o long got; 168879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 169879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (v_flag > 1) 170879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o print_status(); 171879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 172879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o /* Seek to the correct loc. */ 173879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (ext2fs_llseek (dev, (ext2_loff_t) current_block * block_size, 174879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o SEEK_SET) != (ext2_loff_t) current_block * block_size) 175879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o com_err (program_name, errno, "during seek"); 176879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 177879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o /* Try the write */ 178879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o got = write (dev, buffer, try * block_size); 179879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (got < 0) 180879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o got = 0; 181879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (got & 511) 182879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o fprintf (stderr, 183879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o "Weird value (%ld) in do_write\n", got); 1843839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o got /= block_size; 1853839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return got; 1863839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 1873839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 188879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'ostatic int host_dev; 189879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 190a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'ostatic void flush_bufs (int dev, int sync) 191a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o{ 192a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o if (v_flag 193a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o#if !defined (BLKFLSBUF) && !defined (FDFLUSH) 194a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o && sync 195a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o#endif 196a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o ) 197a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o fprintf (stderr, "Flushing buffers\n"); 198a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o 199879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (sync && fdatasync (dev) == -1) 200a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o com_err (program_name, errno, "during fsync"); 201a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o 202879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o#ifdef BLKFLSBUF 203879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o ioctl (host_dev, BLKFLSBUF, 0); /* In case this is a HD */ 204a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o#endif 205a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o#ifdef FDFLUSH 206879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o ioctl (host_dev, FDFLUSH, 0); /* In case this is floppy */ 207a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o#endif 208a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o} 209a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o 210879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'ostatic unsigned int test_ro (int dev, unsigned long blocks_count, 211879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o unsigned long block_size, 212879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o unsigned long from_count, unsigned long blocks_at_once) 2133839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 2143839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o char * blkbuf; 2153839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int try; 2163839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o long got; 217879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o unsigned int bb_count = 0; 218879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o errcode_t errcode; 2193839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 220879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o errcode = ext2fs_badblocks_list_iterate_begin(bb_list,&bb_iter); 221879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (errcode) { 222879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o com_err (program_name, errcode, "while beginning bad block list iteration"); 223879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 224879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 225879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o do { 226879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o ext2fs_badblocks_list_iterate (bb_iter, &next_bad); 227879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } while (next_bad && next_bad < from_count); 228879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 229879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o blkbuf = malloc (blocks_at_once * block_size); 2303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (!blkbuf) 2313839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o { 2323839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o com_err (program_name, ENOMEM, "while allocating buffers"); 2333839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o exit (1); 2343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 235a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o flush_bufs (dev, 0); 236f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (v_flag) { 237f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o fprintf (stderr, 238f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o "Checking for bad blocks in read-only mode\n"); 239f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o fprintf (stderr, "From block %lu to %lu\n", from_count, blocks_count); 240f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o } 241879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o try = blocks_at_once; 242f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o currently_testing = from_count; 2433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o num_blocks = blocks_count; 24419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (s_flag || v_flag > 1) { 2453839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o fprintf(stderr, "Checking for bad blocks (read-only test): "); 24619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (v_flag <= 1) 24719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o alarm_intr(SIGALRM); 2483839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 2493839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o while (currently_testing < blocks_count) 2503839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o { 251879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (next_bad) { 252879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (currently_testing == next_bad) { 253879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o /* fprintf (out, "%lu\n", nextbad); */ 254879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o ext2fs_badblocks_list_iterate (bb_iter, &next_bad); 255879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o currently_testing++; 256879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o continue; 257879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 258879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o else if (currently_testing + try > next_bad) 259879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o try = next_bad - currently_testing; 260879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 2613839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (currently_testing + try > blocks_count) 2623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o try = blocks_count - currently_testing; 263879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o got = do_read (dev, blkbuf, try, block_size, currently_testing); 2643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o currently_testing += got; 2653839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (got == try) { 266879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o try = blocks_at_once; 2673839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o continue; 2683839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 2693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o else 2703839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o try = 1; 271879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (got == 0) { 272879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o bb_output (currently_testing++), ++bb_count; 273879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 2743839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 2753839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o num_blocks = 0; 2763839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o alarm(0); 27719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (s_flag || v_flag > 1) 27800eedba1bd3a37812ee9403abca7ea4376ac9a08Theodore Ts'o fprintf(stderr, done_string); 279879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 280f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o fflush (stderr); 2813839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o free (blkbuf); 282879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 283879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o ext2fs_badblocks_list_iterate_end(bb_iter); 284879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 285879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o return bb_count; 2863839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 2873839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 288879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'ostatic unsigned int test_rw (int dev, unsigned long blocks_count, 289879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o unsigned long block_size, 290879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o unsigned long from_count, unsigned long blocks_at_once) 2913839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 2923839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int i; 2933839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o char * buffer; 2943839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o unsigned char pattern[] = {0xaa, 0x55, 0xff, 0x00}; 295879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o unsigned int bb_count = 0; 2963839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 2973839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o buffer = malloc (2 * block_size); 2983839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (!buffer) 2993839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o { 3003839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o com_err (program_name, ENOMEM, "while allocating buffers"); 3013839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o exit (1); 3023839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 3033839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 304a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o flush_bufs (dev, 0); 305a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o 30619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (v_flag) { 30719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o fprintf(stderr, 30819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o "Checking for bad blocks in read-write mode\n"); 30919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o fprintf(stderr, "From block %lu to %lu\n", 31019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o from_count, blocks_count); 31119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o } 31219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o for (i = 0; i < sizeof (pattern); i++) { 3133839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o memset (buffer, pattern[i], block_size); 314f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (s_flag | v_flag) 315f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o fprintf (stderr, "Writing pattern 0x%08x: ", 3163839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o *((int *) buffer)); 317f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o num_blocks = blocks_count; 318f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o currently_testing = from_count; 31919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (s_flag && v_flag <= 1) 320f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o alarm_intr(SIGALRM); 321f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o for (; 322f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o currently_testing < blocks_count; 323f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o currently_testing++) 3243839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o { 32519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (ext2fs_llseek (dev, (ext2_loff_t) currently_testing * 326f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o block_size, SEEK_SET) != 327f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o (ext2_loff_t) currently_testing * block_size) 3283839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o com_err (program_name, errno, 329f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o "during seek on block %d", 330f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o currently_testing); 33119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (v_flag > 1) 33219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o print_status(); 3333839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o write (dev, buffer, block_size); 3343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 335f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o num_blocks = 0; 336f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o alarm (0); 337f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (s_flag | v_flag) 33800eedba1bd3a37812ee9403abca7ea4376ac9a08Theodore Ts'o fprintf(stderr, done_string); 339a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o flush_bufs (dev, 1); 340f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (s_flag | v_flag) 341f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o fprintf (stderr, "Reading and comparing: "); 342f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o num_blocks = blocks_count; 343f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o currently_testing = from_count; 34419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (s_flag && v_flag <= 1) 345f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o alarm_intr(SIGALRM); 346f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o for (; 347f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o currently_testing < blocks_count; 348f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o currently_testing++) 3493839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o { 35019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (ext2fs_llseek (dev, (ext2_loff_t) currently_testing * 351f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o block_size, SEEK_SET) != 352f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o (ext2_loff_t) currently_testing * block_size) 3533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o com_err (program_name, errno, 354f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o "during seek on block %d", 355f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o currently_testing); 35619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (v_flag > 1) 35719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o print_status(); 3583839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (read (dev, buffer + block_size, block_size) < block_size) 359879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 360879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o ext2fs_badblocks_list_test (bb_list, currently_testing) 361879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o || ( bb_output (currently_testing), ++bb_count ); 362879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 3633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o else if (memcmp (buffer, buffer + block_size, block_size)) 364879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 365879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o ext2fs_badblocks_list_test (bb_list, currently_testing) 366879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o || ( bb_output (currently_testing), ++bb_count ); 367879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 3683839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 369f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o num_blocks = 0; 370f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o alarm (0); 371f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (s_flag | v_flag) 37200eedba1bd3a37812ee9403abca7ea4376ac9a08Theodore Ts'o fprintf(stderr, done_string); 373a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o flush_bufs (dev, 0); 3743839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 375879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 376879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o return bb_count; 377879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o} 378879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 379879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'ostatic unsigned int test_nd (int dev, unsigned long blocks_count, 380879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o unsigned long block_size, 381879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o unsigned long from_count, unsigned long blocks_at_once) 382879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o{ 383879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o char * blkbuf; 384879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o char * ptr; 385879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o int try; 386879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o long got; 387879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o long buf_used; 388879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o unsigned long bufblk[blocks_at_once]; 389879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o unsigned long bufblks[blocks_at_once]; 390879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o jmp_buf terminate_env; 391879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o unsigned int bb_count = 0; 392879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o errcode_t errcode; 393879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 394879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o errcode = ext2fs_badblocks_list_iterate_begin(bb_list,&bb_iter); 395879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (errcode) { 396879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o com_err (program_name, errcode, "while beginning bad block list iteration"); 397879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 398879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 399879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o do { 400879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o ext2fs_badblocks_list_iterate (bb_iter, &next_bad); 401879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } while (next_bad && next_bad < from_count); 402879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 403879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o blkbuf = malloc (3 * blocks_at_once * block_size); 404879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (!blkbuf) 405879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o { 406879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o com_err (program_name, ENOMEM, "while allocating buffers"); 407879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 408879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 409879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 410879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o /* inititalize the test data randomly: */ 411879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (v_flag) { 412879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o fprintf (stderr, "Initializing random test data\n"); 413879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 414879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o for(ptr = blkbuf + blocks_at_once * block_size; 415879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o ptr < blkbuf + 2 * blocks_at_once * block_size; 416879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o ++ptr) { 417879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o (*ptr) = random() % (1 << sizeof(char)); 418879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 419879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 420879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o flush_bufs (dev, 0); 421879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (v_flag) { 422879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o fprintf (stderr, 423879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o "Checking for bad blocks in non-destructive read-write mode\n"); 424879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o fprintf (stderr, "From block %lu to %lu\n", from_count, blocks_count); 425879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 426879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o buf_used = 0; 427879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o currently_testing = from_count; 428879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o num_blocks = blocks_count; 429879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (s_flag || v_flag > 1) { 430879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o fprintf (stderr, "Checking for bad blocks (non-destructive read-write test): "); 431879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (v_flag <= 1) 432879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o alarm_intr(SIGALRM); 433879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 434879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (! setjmp(terminate_env)) { 435879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o /* set up abend handler */ 436879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o capture_terminate(terminate_env); 437879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 438879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o while (currently_testing < blocks_count) 439879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o { 440879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o try = blocks_at_once - buf_used; 441879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (next_bad) { 442879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (currently_testing == next_bad) { 443879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o /* fprintf (out, "%lu\n", nextbad); */ 444879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o ext2fs_badblocks_list_iterate (bb_iter, &next_bad); 445879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o bufblk[buf_used] = currently_testing++; 446879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o goto test_full_buf; 447879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 448879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o else if (currently_testing + try > next_bad) 449879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o try = next_bad - currently_testing; 450879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 451879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (currently_testing + try > blocks_count) 452879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o try = blocks_count - currently_testing; 453879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o got = do_read (dev, blkbuf + buf_used * block_size, try, 454879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o block_size, currently_testing); 455879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 456879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o /* if reading succeeded, write the test data */ 457879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (got) { 458879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o long written; 459879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 460879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o written = do_write (dev, blkbuf + (buf_used + blocks_at_once) * block_size, 461879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o got, block_size, currently_testing); 462879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (written != got) 463879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o com_err (program_name, errno, "during test data write, block %lu", 464879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o currently_testing + written); 465879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 466879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 467879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o bufblk[buf_used] = currently_testing; 468879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o bufblks[buf_used] = got; 469879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o buf_used += got; 470879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o currently_testing += got; 471879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (got != try) 472879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o bb_output (currently_testing++), ++bb_count; 473879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 474879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o test_full_buf: 475879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 476879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (buf_used == blocks_at_once || currently_testing == blocks_count) { 477879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (s_flag || v_flag > 1) 478879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o fprintf(stderr, "\n"); 479879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o flush_bufs (dev, 1); 480879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 481879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o for (buf_used = 0, currently_testing = bufblk[0]; 482879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o buf_used < blocks_at_once && 483879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o currently_testing < blocks_count && 484879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o (currently_testing = bufblk[buf_used]) < blocks_count; 485879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o buf_used += bufblks[buf_used]) 486879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o { 487879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o /* for each contiguous block that we read into the buffer 488879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o (and wrote test data into afterwards), read it back 489879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o (looping if necessary, to get past newly discovered 490879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o unreadable blocks, of which there should be none, but with 491879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o a hard drive which is unreliable, it has happened), and 492879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o compare with the test data that was written; output to 493879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o the bad block list if it doesn't match. */ 494879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 495879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o int offset; 496879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 497879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o while ((offset = currently_testing - bufblk[buf_used]) < 498879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o bufblks[buf_used]) { 499879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o int i; 500879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 501879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o try = bufblks[buf_used] - offset; 502879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o got = do_read (dev, blkbuf + (2 * blocks_at_once + buf_used + offset) * block_size, 503879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o try, block_size, currently_testing); 504879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 505879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o /* test the comparison between all the blocks successfully read */ 506879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o for (i = 0; i < got; ++i) 507879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (memcmp (blkbuf + (blocks_at_once + buf_used + offset + i) * block_size, 508879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o blkbuf + (2 * blocks_at_once + buf_used + offset + i) * block_size, 509879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o block_size)) 510879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o bb_output (currently_testing + i), ++bb_count; 511879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 512879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o currently_testing += got; 513879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (got != try) 514879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o bb_output (currently_testing++), ++bb_count; 515879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 516879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 517879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o /* when done, write back original data */ 518879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o do_write (dev, blkbuf + buf_used * block_size, 519879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o bufblks[buf_used], block_size, bufblk[buf_used]); 520879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 521879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 522879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o /* empty the buffer so it can be reused */ 523879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o buf_used = 0; 524879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 525879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 526879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o num_blocks = 0; 527879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o alarm(0); 528879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (s_flag || v_flag > 1) 529879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o fprintf(stderr, "done \n"); 530879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 531879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } else { 532879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o /* abnormal termination by a signal is handled here */ 533879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o /* logic is: write back the data that is in the buffer, 534879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o so that we can maintain data integrity on disk. Then 535879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o abort. */ 536879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o long buf_written; 537879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 538879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o fprintf(stderr, "Interrupt caught, cleaning up\n"); 539879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 540879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o for (buf_written = 0; 541879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o buf_written < buf_used; 542879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o buf_written += bufblks[buf_written]) 543879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o do_write (dev, blkbuf + buf_written * block_size, 544879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o bufblks[buf_written], block_size, bufblk[buf_written]); 545879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 546879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o fflush (out); 547879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 548879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o abort (); 549879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 550879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 551879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o fflush (stderr); 552879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o free (blkbuf); 553879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 554879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o ext2fs_badblocks_list_iterate_end(bb_iter); 555879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 556879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o return bb_count; 5573839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 5583839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 55900e5433eb5e9f70f485968b809fdcf297d7fe7b9Theodore Ts'oint main (int argc, char ** argv) 5603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 561519149fb458b0fa69c10fecd83fae42e838cf01dTheodore Ts'o int c; 5623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o char * tmp; 5633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o char * device_name; 564879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o char * host_device_name = NULL; 565879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o char * input_file = NULL; 5663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o char * output_file = NULL; 567879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o FILE * in = NULL; 5683839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o unsigned long block_size = 1024; 569879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o unsigned long blocks_at_once = 16; 570f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o unsigned long blocks_count, from_count; 571879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o int num_passes = 0; 572879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o int passes_clean = 0; 5733839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int dev; 574879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o errcode_t errcode; 5753839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 5763839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o setbuf(stdout, NULL); 5773839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o setbuf(stderr, NULL); 5783839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (argc && *argv) 5793839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o program_name = *argv; 580879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o while ((c = getopt (argc, argv, "b:i:o:svwnc:p:h:")) != EOF) { 5813839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o switch (c) { 5823839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o case 'b': 5833839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o block_size = strtoul (optarg, &tmp, 0); 5843839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (*tmp || block_size > 4096) { 5853839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o com_err (program_name, 0, 5863839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o "bad block size - %s", optarg); 5873839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o exit (1); 5883839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 5893839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o break; 590879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o case 'i': 591879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o input_file = optarg; 592879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o break; 5933839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o case 'o': 5943839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o output_file = optarg; 5953839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o break; 5963839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o case 's': 5973839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o s_flag = 1; 5983839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o break; 5993839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o case 'v': 60019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o v_flag++; 6013839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o break; 6023839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o case 'w': 603879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (! w_flag) 604879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o w_flag = 1; 605879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o break; 606879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o case 'n': 607879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o w_flag = 2; 608879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o break; 609879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o case 'c': 610879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o blocks_at_once = strtoul (optarg, &tmp, 0); 611879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (*tmp) { 612879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o com_err (program_name, 0, 613879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o "bad simultaneous block count - %s", optarg); 614879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 615879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 616879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o break; 617879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o case 'p': 618879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o num_passes = strtoul (optarg, &tmp, 0); 619879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (*tmp) { 620879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o com_err (program_name, 0, 621879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o "bad number of clean passes - %s", optarg); 622879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 623879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 624879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o break; 625879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o case 'h': 626879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o host_device_name = optarg; 6273839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o break; 6283839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o default: 629818180cdfcff84b9048ecdc5dc86323f0fefba24Theodore Ts'o usage(); 6303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 6313839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 6323839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (optind > argc - 1) 633818180cdfcff84b9048ecdc5dc86323f0fefba24Theodore Ts'o usage(); 6343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o device_name = argv[optind++]; 6353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (optind > argc - 1) 636818180cdfcff84b9048ecdc5dc86323f0fefba24Theodore Ts'o usage(); 6373839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o blocks_count = strtoul (argv[optind], &tmp, 0); 6383839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (*tmp) 6393839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o { 6403839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o com_err (program_name, 0, "bad blocks count - %s", argv[optind]); 6413839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o exit (1); 6423839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 643f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (++optind <= argc-1) { 644f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o from_count = strtoul (argv[optind], &tmp, 0); 645f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o } else from_count = 0; 646f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (from_count >= blocks_count) { 647f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o com_err (program_name, 0, "bad blocks range: %lu-%lu", 648f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o from_count, blocks_count); 649f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o exit (1); 650f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o } 6513839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dev = open (device_name, w_flag ? O_RDWR : O_RDONLY); 6523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (dev == -1) 6533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o { 654879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o com_err (program_name, errno, "while trying to open %s", 6553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o device_name); 6563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o exit (1); 6573839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 658879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (host_device_name) { 659879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o host_dev = open (host_device_name, O_RDONLY); 660879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (host_dev == -1) 661879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o { 662879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o com_err (program_name, errno, "while trying to open %s", 663879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o host_device_name); 664879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 665879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 666879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } else 667879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o host_dev = dev; 668879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (input_file) 669879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (strcmp (input_file, "-") == 0) 670879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o in = stdin; 671879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o else { 672879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o in = fopen (input_file, "r"); 673879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (in == NULL) 674879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o { 675879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o com_err (program_name, errno,"while trying to open %s", 676879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o input_file); 677879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 678879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 679879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 6803839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (output_file && strcmp (output_file, "-") != 0) 6813839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o { 6823839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o out = fopen (output_file, "w"); 6833839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (out == NULL) 6843839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o { 6853839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o com_err (program_name, errno,"while trying to open %s", 686879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o output_file); 6873839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o exit (1); 6883839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 6893839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 6903839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o else 6913839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o out = stdout; 692879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 693879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o errcode = ext2fs_badblocks_list_create(&bb_list,0); 694879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (errcode) { 695879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o com_err (program_name, errcode, "creating in-memory bad blocks list"); 696879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 697879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 698879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 699879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (in) { 700879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o for(;;) { 701879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o switch(fscanf (in, "%lu\n", &next_bad)) { 702879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o case 0: 703879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o com_err (program_name, 0, "input file - bad format"); 704879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 705879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o case EOF: 706879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o break; 707879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o default: 708879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o errcode = ext2fs_badblocks_list_add(bb_list,next_bad); 709879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (errcode) { 710879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o com_err (program_name, errcode, "adding to in-memory bad block list"); 711879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 712879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 713879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o continue; 714879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 715879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o break; 716879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 717879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 718879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (in != stdin) 719879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o fclose (in); 720879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 721879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 722879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o do { 723879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o unsigned int bb_count; 724879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 725879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o (bb_count = 726879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 727879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o (w_flag == 2 ? test_nd 728879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o : w_flag ? test_rw 729879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o : test_ro) 730879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o (dev, blocks_count, block_size, from_count, 731879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o blocks_at_once) 732879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o ) ? passes_clean = 0 : ++passes_clean; 733879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 734879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (v_flag) 735879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o fprintf(stderr,"Pass completed, %u bad blocks found.\n", bb_count); 736879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 737879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } while (passes_clean < num_passes); 738879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 7393839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o close (dev); 7403839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (out != stdout) 7413839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o fclose (out); 742879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o return 0; 7433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 744