badblocks.c revision a418d3ad819323f871005d253f7f9ac378e78ba5
13839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/*
23839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * badblocks.c		- Bad blocks checker
3efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o *
455f4cbd96e0029f0ff67c4913192d87bf52fd149Theodore Ts'o * Copyright (C) 1992, 1993, 1994  Remy Card <card@masi.ibp.fr>
555f4cbd96e0029f0ff67c4913192d87bf52fd149Theodore Ts'o *                                 Laboratoire MASI, Institut Blaise Pascal
619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o *                                 Universite Pierre et Marie Curie (Paris VI)
719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o *
819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * This file is based on the minix file system programs fsck and mkfs
919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * written and copyrighted by Linus Torvalds <Linus.Torvalds@cs.helsinki.fi>
1019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o *
113839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * This file can be redistributed under the terms of the GNU General
123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Public License
133839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */
14efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
153839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/*
16efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o * History:
173839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * 93/05/26	- Creation from e2fsck
183839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * 94/02/27	- Made a separate bad blocks checker
19ebabf2ad6d19af5c674b624bafe619dedbc94403Theodore Ts'o */
20ebabf2ad6d19af5c674b624bafe619dedbc94403Theodore Ts'o
21d1154eb460efe588eaed3d439c1caaca149fa362Theodore Ts'o#include <errno.h>
22a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o#include <fcntl.h>
233839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#ifdef HAVE_GETOPT_H
24d0c537748d5a9799dd0658b0a5cceaafc28084bbTheodore Ts'o#include <getopt.h>
253839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#endif
263839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <signal.h>
273839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <stdio.h>
28756df353e8ffd010fcca8cef8972cf27006edb6aTheodore Ts'o#include <stdlib.h>
292740156bd12747389eaf745529653b26a3a9d73dTheodore Ts'o#include <string.h>
302740156bd12747389eaf745529653b26a3a9d73dTheodore Ts'o#include <unistd.h>
31a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o
323839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <sys/ioctl.h>
33373b8337c7b6c6243810be250083fa4773891e92Theodore Ts'o#include <sys/types.h>
34373b8337c7b6c6243810be250083fa4773891e92Theodore Ts'o
35373b8337c7b6c6243810be250083fa4773891e92Theodore Ts'o#if HAVE_LINUX_FS_H
36a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o#include <linux/fd.h>
37a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o#include <linux/fs.h>
383839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#endif
39a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o
40a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o#include "et/com_err.h"
413839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include "ext2fs/io.h"
42a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o
43a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'oconst char * program_name = "badblocks";
44a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o
45a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'oint v_flag = 0;			/* verbose */
463839e65723771b85975f4263102dd3ceec4523cTheodore Ts'oint w_flag = 0;			/* do r/w test */
47f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'oint s_flag = 0;			/* show progress of test */
4813b0b1231ed28aac75ba336de7a8cb3b4611ce68Eric Sandeen
49b626b39a8c87dfb6d973b4ad7eca1eefa659d3d6Aneesh Kumar K.Vstatic volatile void usage (void)
50365857912e27914afa8857af5adf74ee19ca9e03Theodore Ts'o{
519ed8e5fec226aa53634ed95cbeac736d90a518e5Eric Sandeen	fprintf (stderr, "Usage: %s [-b block_size] [-o output_file] [-svw] device blocks_count\n [start_count]\n",
52f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o		 program_name);
5354c637d4d29af3e6365779f8b12976abe95a4753Theodore Ts'o	exit (1);
5495fd65bb7fcf84e8d1e207f84b9d5a9f99626a38Valerie Aurora Henson}
553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
561e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o/*
57896938d57e7091e7a032674dfeeb91f2a17fd78bTheodore Ts'o * Perform a test of a block; return the number of blocks readable/writeable.
583839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */
5963985320384bf143eaac9857af424800d9867a1aTheodore Ts'ostatic long do_test (int dev, char * buffer, int try, unsigned long block_size,
609dc6ad1ecb0ba3caf14e05279f1cc3cea52095a2Theodore Ts'o		     unsigned long current_block)
61a6d8302b4873527798a77c1ba3106a04b71dfeacTheodore Ts'o{
623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	long got;
63d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o
641f5d7a890e8b2ad03ee91fd891b0b5b4327da030Aditya Kali	/* Seek to the correct loc. */
653839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	if (ext2_llseek (dev, (ext2_loff_t) current_block * block_size,
663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			 SEEK_SET) != (ext2_loff_t) current_block * block_size)
673839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		com_err (program_name, errno, "during seek");
68493024ea1d74e4cb48aac3a24111f5c8da343e9fTheodore Ts'o
69493024ea1d74e4cb48aac3a24111f5c8da343e9fTheodore Ts'o	/* Try the read */
706733c2fd0046c525203034f58fc0a8c69fdf480bTheodore Ts'o	got = read (dev, buffer, try * block_size);
711e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o	if (got < 0)
721e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o		got = 0;
731e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o	if (got & (block_size - 1))
747d9e31655fca48e9d6c2647ad443124113508b73Lukas Czerner		fprintf (stderr,
757d9e31655fca48e9d6c2647ad443124113508b73Lukas Czerner			 "Weird value (%ld) in do_test: probably bugs\n",
763839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			 got);
77f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o	got /= block_size;
783839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	return got;
793839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}
80d48755e97f7d4cb06092921bff0d3681d30a8acaTheodore Ts'o
813839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic unsigned long currently_testing = 0;
823839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic unsigned long num_blocks = 0;
8316ed5b3af43c72f60991222b9d7ab65cf53f203dTheodore Ts'o
8416ed5b3af43c72f60991222b9d7ab65cf53f203dTheodore Ts'ostatic void alarm_intr (int alnum)
8516ed5b3af43c72f60991222b9d7ab65cf53f203dTheodore Ts'o{
8616ed5b3af43c72f60991222b9d7ab65cf53f203dTheodore Ts'o	signal (SIGALRM, alarm_intr);
877fe5ff3c1e06c4705a7a709a7ed34f02c5a02fd8Lukas Czerner	alarm(1);
8837c8db7b2078d0310e5676404e21cc143d8e4d56Theodore Ts'o	if (!num_blocks)
8916ed5b3af43c72f60991222b9d7ab65cf53f203dTheodore Ts'o		return;
9016ed5b3af43c72f60991222b9d7ab65cf53f203dTheodore Ts'o	fprintf(stderr, "%9ld/%9ld", currently_testing, num_blocks);
9116ed5b3af43c72f60991222b9d7ab65cf53f203dTheodore Ts'o	fprintf(stderr, "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b");
9216ed5b3af43c72f60991222b9d7ab65cf53f203dTheodore Ts'o	fflush (stderr);
937fe5ff3c1e06c4705a7a709a7ed34f02c5a02fd8Lukas Czerner}
9416ed5b3af43c72f60991222b9d7ab65cf53f203dTheodore Ts'o
9516ed5b3af43c72f60991222b9d7ab65cf53f203dTheodore Ts'ostatic void flush_bufs (int dev, int sync)
96d678fef0d78fb3c5546cd9398698ddc0106618f6Aditya Kali{
973839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o  if (v_flag
989b9a780f5a5823865f62f0c9fd194d262f63a06fTheodore Ts'o#if !defined (BLKFLSBUF) && !defined (FDFLUSH)
99b0afdda1bc044026336009576fbe6b72884140cbTheodore Ts'o      && sync
10016ed5b3af43c72f60991222b9d7ab65cf53f203dTheodore Ts'o#endif
10116ed5b3af43c72f60991222b9d7ab65cf53f203dTheodore Ts'o      )
10216ed5b3af43c72f60991222b9d7ab65cf53f203dTheodore Ts'o    fprintf (stderr, "Flushing buffers\n");
10316ed5b3af43c72f60991222b9d7ab65cf53f203dTheodore Ts'o
10416ed5b3af43c72f60991222b9d7ab65cf53f203dTheodore Ts'o  if (sync && fsync (dev) == -1)
105b626b39a8c87dfb6d973b4ad7eca1eefa659d3d6Aneesh Kumar K.V    com_err (program_name, errno, "during fsync");
1063839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
1079dc6ad1ecb0ba3caf14e05279f1cc3cea52095a2Theodore Ts'o#ifdef BLKLSBUF
1089dc6ad1ecb0ba3caf14e05279f1cc3cea52095a2Theodore Ts'o  ioctl (dev, BLKFLSBUF, 0);	/* In case this is a HD */
10931e29a12d1e22745c74afe47bf172a3c73280dd9Theodore Ts'o#endif
110d99225ecceb580d497c649daa4894fa2e10019adTheodore Ts'o#ifdef FDFLUSH
11131e29a12d1e22745c74afe47bf172a3c73280dd9Theodore Ts'o  ioctl (dev, FDFLUSH, 0);	/* In case this is floppy */
11263985320384bf143eaac9857af424800d9867a1aTheodore Ts'o#endif
1133839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}
114bdd80f28d759cda94bab13af689d4aee0328dd7fTheodore Ts'o
11528e2cb9e72cce9e97a4a6f738d28b0f3f31efe69Eric Sandeenstatic void test_ro (int dev, unsigned long blocks_count,
116bdd80f28d759cda94bab13af689d4aee0328dd7fTheodore Ts'o		     unsigned long block_size, FILE * out,
1178dbcbe1c4a4bdd30c6e9aa1a3df9b06f4f3cbee1Yongqiang Yang		     unsigned long from_count)
1189ba400027fb00ce43d14673346bbfb6f5719985aTheodore Ts'o{
1199ba400027fb00ce43d14673346bbfb6f5719985aTheodore Ts'o#define TEST_BUFFER_BLOCKS 16
120067911ae734bb5fef7c5780a639533847b5b578cAndreas Dilger	char * blkbuf;
121bdd80f28d759cda94bab13af689d4aee0328dd7fTheodore Ts'o	int try;
12265794cf159aa051ea3fe79db1950f562600b252eMike Frysinger	long got;
12337c8db7b2078d0310e5676404e21cc143d8e4d56Theodore Ts'o
1243839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	blkbuf = malloc (TEST_BUFFER_BLOCKS * block_size);
1253839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	if (!blkbuf)
1263839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	{
1273839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		com_err (program_name, ENOMEM, "while allocating buffers");
12802d6f47e9647d3155a38c8676c2da6ea773d9b68Jose R. Santos		exit (1);
1293839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
1303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	flush_bufs (dev, 0);
1313839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	if (v_flag) {
1323839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	    fprintf (stderr,
1333839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		     "Checking for bad blocks in read-only mode\n");
1343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	    fprintf (stderr, "From block %lu to %lu\n", from_count, blocks_count);
1353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
1363839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	try = TEST_BUFFER_BLOCKS;
1373839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	currently_testing = from_count;
1383839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	num_blocks = blocks_count;
1393839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	if (s_flag) {
14002d6f47e9647d3155a38c8676c2da6ea773d9b68Jose R. Santos		fprintf(stderr, "Checking for bad blocks (read-only test): ");
1411dde43f0c1176f61dd0bf91aff265ce8cd1c5fd6Theodore Ts'o		alarm_intr(SIGALRM);
1421dde43f0c1176f61dd0bf91aff265ce8cd1c5fd6Theodore Ts'o	}
1431dde43f0c1176f61dd0bf91aff265ce8cd1c5fd6Theodore Ts'o	while (currently_testing < blocks_count)
1441dde43f0c1176f61dd0bf91aff265ce8cd1c5fd6Theodore Ts'o	{
1451dde43f0c1176f61dd0bf91aff265ce8cd1c5fd6Theodore Ts'o		if (currently_testing + try > blocks_count)
1461dde43f0c1176f61dd0bf91aff265ce8cd1c5fd6Theodore Ts'o			try = blocks_count - currently_testing;
1471dde43f0c1176f61dd0bf91aff265ce8cd1c5fd6Theodore Ts'o		got = do_test (dev, blkbuf, try, block_size, currently_testing);
1481dde43f0c1176f61dd0bf91aff265ce8cd1c5fd6Theodore Ts'o		currently_testing += got;
1491d6fd6d0c3766a8165e69284c75812574a29c804Andreas Dilger		if (got == try) {
150d99225ecceb580d497c649daa4894fa2e10019adTheodore Ts'o			try = TEST_BUFFER_BLOCKS;
151d99225ecceb580d497c649daa4894fa2e10019adTheodore Ts'o			continue;
152d99225ecceb580d497c649daa4894fa2e10019adTheodore Ts'o		}
153d99225ecceb580d497c649daa4894fa2e10019adTheodore Ts'o		else
154d99225ecceb580d497c649daa4894fa2e10019adTheodore Ts'o			try = 1;
155d99225ecceb580d497c649daa4894fa2e10019adTheodore Ts'o		if (got == 0)
156d99225ecceb580d497c649daa4894fa2e10019adTheodore Ts'o			fprintf (out, "%lu\n", currently_testing++);
157d99225ecceb580d497c649daa4894fa2e10019adTheodore Ts'o	}
158d99225ecceb580d497c649daa4894fa2e10019adTheodore Ts'o	num_blocks = 0;
159d99225ecceb580d497c649daa4894fa2e10019adTheodore Ts'o	alarm(0);
160d99225ecceb580d497c649daa4894fa2e10019adTheodore Ts'o	if (s_flag)
161d99225ecceb580d497c649daa4894fa2e10019adTheodore Ts'o		fprintf(stderr, "done               \n");
162d99225ecceb580d497c649daa4894fa2e10019adTheodore Ts'o	fflush (stderr);
163d99225ecceb580d497c649daa4894fa2e10019adTheodore Ts'o	free (blkbuf);
164d99225ecceb580d497c649daa4894fa2e10019adTheodore Ts'o}
165d99225ecceb580d497c649daa4894fa2e10019adTheodore Ts'o
166d99225ecceb580d497c649daa4894fa2e10019adTheodore Ts'ostatic void test_rw (int dev, unsigned long blocks_count,
167d99225ecceb580d497c649daa4894fa2e10019adTheodore Ts'o		     unsigned long block_size, FILE * out,
168d99225ecceb580d497c649daa4894fa2e10019adTheodore Ts'o		     unsigned long from_count)
169d99225ecceb580d497c649daa4894fa2e10019adTheodore Ts'o{
170d99225ecceb580d497c649daa4894fa2e10019adTheodore Ts'o	int i;
1711d6fd6d0c3766a8165e69284c75812574a29c804Andreas Dilger	char * buffer;
172d99225ecceb580d497c649daa4894fa2e10019adTheodore Ts'o	unsigned char pattern[] = {0xaa, 0x55, 0xff, 0x00};
17350787ea22edd8b4662203daf3569411d9dcf4287Theodore Ts'o
1743839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	buffer = malloc (2 * block_size);
1753839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	if (!buffer)
176544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o	{
1773839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		com_err (program_name, ENOMEM, "while allocating buffers");
1786693837e59cc7b5397a0d46d2753c309382c76f9Theodore Ts'o		exit (1);
1793839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
1803839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
1813839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	flush_bufs (dev, 0);
1823839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
1833839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	if (v_flag)
1843839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		fprintf (stderr, "Checking for bad blocks in read-write mode\n");
1853839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	for (i = 0; i < sizeof (pattern); i++)
1863839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	{
1873839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		memset (buffer, pattern[i], block_size);
1883839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		if (s_flag | v_flag)
1893839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			fprintf (stderr, "Writing pattern 0x%08x: ",
1903839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				 *((int *) buffer));
1913839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		num_blocks = blocks_count;
1923839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		currently_testing = from_count;
1933839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		if (s_flag)
194d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o			alarm_intr(SIGALRM);
1953839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		for (;
1963839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		     currently_testing < blocks_count;
1973839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		     currently_testing++)
1983839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		{
1993839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			if (ext2_llseek (dev, (ext2_loff_t) currently_testing *
2003839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o					 block_size, SEEK_SET) !=
201d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o			    (ext2_loff_t) currently_testing * block_size)
2023839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				com_err (program_name, errno,
2033839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o					 "during seek on block %d",
2043839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o					 currently_testing);
2053839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			write (dev, buffer, block_size);
2063839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		}
2073839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		num_blocks = 0;
2083839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		alarm (0);
2093839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		if (s_flag | v_flag)
2103839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			fprintf(stderr, "done               \n");
2113839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		flush_bufs (dev, 1);
2123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		if (s_flag | v_flag)
2133839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			fprintf (stderr, "Reading and comparing: ");
2143839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		num_blocks = blocks_count;
2154efbac6fed75c29d3d5f1b676b932754653a2ac5Valerie Aurora Henson		currently_testing = from_count;
2163ed57c27df0ba0942a19c71bc065c8eec3036567Theodore Ts'o		if (s_flag)
2174efbac6fed75c29d3d5f1b676b932754653a2ac5Valerie Aurora Henson			alarm_intr(SIGALRM);
2183839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		for (;
219d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o		     currently_testing < blocks_count;
2203839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		     currently_testing++)
2213839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		{
2223839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			if (ext2_llseek (dev, (ext2_loff_t) currently_testing *
223f37ab68a26bacf4f5cc7643b8373e40292b7682aTheodore Ts'o					 block_size, SEEK_SET) !=
2243839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			    (ext2_loff_t) currently_testing * block_size)
2253839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				com_err (program_name, errno,
2263839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o					 "during seek on block %d",
227f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o					 currently_testing);
2283839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			if (read (dev, buffer + block_size, block_size) < block_size)
2293839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				fprintf (out, "%ld\n", currently_testing);
230d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o			else if (memcmp (buffer, buffer + block_size, block_size))
2313839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				fprintf (out, "%ld\n", currently_testing);
2323839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		}
2333839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		num_blocks = 0;
2343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		alarm (0);
2353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		if (s_flag | v_flag)
2363839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			fprintf(stderr, "done           \n");
237544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o		flush_bufs (dev, 0);
238544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o	}
239544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o}
2403839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
2413839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ovoid main (int argc, char ** argv)
2423839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{
243f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o	char c;
244f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o	char * tmp;
245f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o	char * device_name;
2463839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	char * output_file = NULL;
2473839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	FILE * out;
2483839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	unsigned long block_size = 1024;
249efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o	unsigned long blocks_count, from_count;
2503839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	int dev;
2513839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
2523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	setbuf(stdout, NULL);
2533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	setbuf(stderr, NULL);
2543839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	if (argc && *argv)
2553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		program_name = *argv;
256cbbf031b6edf9bdf5511af2193e44cff7fdaa66aTheodore Ts'o	while ((c = getopt (argc, argv, "b:o:svw")) != EOF) {
257d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o		switch (c) {
258d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o		case 'b':
259d0ff90d5202428583c78a60c3042e7b60d88bc45Eric Sandeen			block_size = strtoul (optarg, &tmp, 0);
260d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o			if (*tmp || block_size > 4096) {
2613839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				com_err (program_name, 0,
262544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o					 "bad block size - %s", optarg);
2633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				exit (1);
2643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			}
2653839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			break;
266f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o		case 'o':
267f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o			output_file = optarg;
268f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o			break;
269f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o		case 's':
270f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o			s_flag = 1;
271f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o			break;
272f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o		case 'v':
273f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o			v_flag = 1;
274efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o			break;
275f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o		case 'w':
27692bcc595dcb31ad15e12d8c72e6edfc70545c204Theodore Ts'o			w_flag = 1;
277f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o			break;
278cbbf031b6edf9bdf5511af2193e44cff7fdaa66aTheodore Ts'o		default:
279cbbf031b6edf9bdf5511af2193e44cff7fdaa66aTheodore Ts'o			usage ();
280efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o		}
281f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o	}
2828deb80a5d1078cbe43eaffcdeebf0a1a549d6a54Takashi Sato	if (optind > argc - 1)
283d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o		usage ();
284f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o	device_name = argv[optind++];
285f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o	if (optind > argc - 1)
2866493f8e85defc568a4ca8cdb4a53361f36fb94baTheodore Ts'o		usage ();
287d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson	blocks_count = strtoul (argv[optind], &tmp, 0);
2885711ed297b1a3d94086256b5b3b891d4f77b21caTheodore Ts'o	if (*tmp)
2894efbac6fed75c29d3d5f1b676b932754653a2ac5Valerie Aurora Henson	{
290f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o		com_err (program_name, 0, "bad blocks count - %s", argv[optind]);
291f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o		exit (1);
292f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o	}
293f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o	if (++optind <= argc-1) {
294efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o		from_count = strtoul (argv[optind], &tmp, 0);
2953839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	} else from_count = 0;
2963839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	if (from_count >= blocks_count) {
2973839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	    com_err (program_name, 0, "bad blocks range: %lu-%lu",
298cbbf031b6edf9bdf5511af2193e44cff7fdaa66aTheodore Ts'o		     from_count, blocks_count);
2993839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	    exit (1);
300cbbf031b6edf9bdf5511af2193e44cff7fdaa66aTheodore Ts'o	}
301d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o	dev = open (device_name, w_flag ? O_RDWR : O_RDONLY);
3023839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	if (dev == -1)
3033839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	{
304efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o		com_err (program_name, errno,"while trying to open %s",
305c6ed60cdeb1355a884f635ac8118c8f330e2ba68Theodore Ts'o			 device_name);
306cbbf031b6edf9bdf5511af2193e44cff7fdaa66aTheodore Ts'o		exit (1);
3073839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
3083839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	if (output_file && strcmp (output_file, "-") != 0)
3096fcd6f84c235f4bf2bd9770f172837da9982eb6eEric Sandeen	{
31016ed5b3af43c72f60991222b9d7ab65cf53f203dTheodore Ts'o		out = fopen (output_file, "w");
31116ed5b3af43c72f60991222b9d7ab65cf53f203dTheodore Ts'o		if (out == NULL)
31202d6f47e9647d3155a38c8676c2da6ea773d9b68Jose R. Santos		{
313544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o			com_err (program_name, errno,"while trying to open %s",
314e16324210286dc72a013e66d91bd3a59c3ab7538Theodore Ts'o				 device_name);
31595fd65bb7fcf84e8d1e207f84b9d5a9f99626a38Valerie Aurora Henson			exit (1);
31616ed5b3af43c72f60991222b9d7ab65cf53f203dTheodore Ts'o		}
31795fd65bb7fcf84e8d1e207f84b9d5a9f99626a38Valerie Aurora Henson	}
31895fd65bb7fcf84e8d1e207f84b9d5a9f99626a38Valerie Aurora Henson	else
31995fd65bb7fcf84e8d1e207f84b9d5a9f99626a38Valerie Aurora Henson		out = stdout;
3201dde43f0c1176f61dd0bf91aff265ce8cd1c5fd6Theodore Ts'o	if (w_flag)
3213839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		test_rw (dev, blocks_count, block_size, out, from_count);
322c498cb11d3e72e41af760bd882675f44db8b77e7Theodore Ts'o	else
323efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o		test_ro (dev, blocks_count, block_size, out, from_count);
324d7cca6b06f366f998ed43346f9b6fca9e163692fValerie Aurora Henson	close (dev);
32519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o	if (out != stdout)
32616ed5b3af43c72f60991222b9d7ab65cf53f203dTheodore Ts'o		fclose (out);
327e16324210286dc72a013e66d91bd3a59c3ab7538Theodore Ts'o}
328e16324210286dc72a013e66d91bd3a59c3ab7538Theodore Ts'o