badblocks.c revision 45ff69ffeb700012a7c052f5e45882557a40be7e
153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)/*
253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * badblocks.c		- Bad blocks checker
353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) *
453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * Copyright (C) 1992, 1993, 1994  Remy Card <card@masi.ibp.fr>
553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) *                                 Laboratoire MASI, Institut Blaise Pascal
653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) *                                 Universite Pierre et Marie Curie (Paris VI)
753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) *
853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * Copyright 1995, 1996, 1997, 1998, 1999 by Theodore Ts'o
953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * Copyright 1999 by David Beattie
1053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) *
1153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * This file is based on the minix file system programs fsck and mkfs
1253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * written and copyrighted by Linus Torvalds <Linus.Torvalds@cs.helsinki.fi>
1353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) *
1453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * %Begin-Header%
1553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * This file may be redistributed under the terms of the GNU Public
1653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * License.
1753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * %End-Header%
1853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) */
1953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
2053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)/*
2153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * History:
2253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * 93/05/26	- Creation from e2fsck
2353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * 94/02/27	- Made a separate bad blocks checker
2453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * 99/06/30...99/07/26 - Added non-destructive write-testing,
2553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) *                       configurable blocks-at-once parameter,
2653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * 			 loading of badblocks list to avoid testing
2753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * 			 blocks known to be bad, multiple passes to
28a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) * 			 make sure that no new blocks are added to the
2953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * 			 list.  (Work done by David Beattie)
301e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) */
311e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)
32a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#ifndef _GNU_SOURCE
3319cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)#define _GNU_SOURCE /* for O_DIRECT */
34a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#endif
35a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)
361e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#ifndef O_LARGEFILE
37a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#define O_LARGEFILE 0
3851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)#endif
3953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
4053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "config.h"
4153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include <errno.h>
4209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#include <fcntl.h>
4319cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)#ifdef HAVE_GETOPT_H
44591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#include <getopt.h>
4593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)#else
46d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)extern char *optarg;
4753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)extern int optind;
48591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#endif
491e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include <signal.h>
50a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include <stdio.h>
51a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include <stdlib.h>
52521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)#include <string.h>
53521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)#include <unistd.h>
5453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include <setjmp.h>
558abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)#include <time.h>
5653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include <limits.h>
5753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
5853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include <sys/time.h>
5953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include <sys/ioctl.h>
60a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include <sys/types.h>
6153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
6253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "et/com_err.h"
6353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "ext2fs/ext2_io.h"
64a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "ext2fs/ext2_fs.h"
65a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "ext2fs/ext2fs.h"
66a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "nls-enable.h"
67a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)
68a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)const char * program_name = "badblocks";
69d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)const char * done_string = N_("done                                                 \n");
70a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)
71d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)static int v_flag;			/* verbose */
72a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)static int w_flag;			/* do r/w test: 0=no, 1=yes,
73a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)					 * 2=non-destructive */
74a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)static int s_flag;			/* show progress of test */
75a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)static int force;			/* force check of mounted device */
76d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)static int t_flag;			/* number of test patterns */
77d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)static int t_max;			/* allocated test patterns */
78d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)static unsigned int *t_patts;		/* test patterns */
79a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)static int use_buffered_io;
80a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)static int exclusive_ok;
81a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)static unsigned int max_bb;		/* Abort test if more than this number of bad blocks has been encountered */
82d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)static unsigned int d_flag;		/* delay factor between reads */
83a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)static struct timeval time_start;
84a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)
85a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#define T_INC 32
86a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)
87a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)unsigned int sys_page_size = 4096;
88a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)
89a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)static void usage(void)
90d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
91a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)	fprintf(stderr, _(
92a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)"Usage: %s [-b block_size] [-i input_file] [-o output_file] [-svwnf]\n"
93a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)"       [-c blocks_at_once] [-d delay_factor_between_reads] [-e max_bad_blocks]\n"
94a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)"       [-p num_passes] [-t test_pattern [-t test_pattern [...]]]\n"
9509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)"       device [last_block [first_block]]\n"),
9607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch		 program_name);
9707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch	exit (1);
9881a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)}
9907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
10081a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)static void exclusive_usage(void)
10181a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles){
10281a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)	fprintf(stderr,
10319cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)		_("%s: The -n and -w options are mutually exclusive.\n\n"),
10451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)		program_name);
10551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)	exit(1);
10619cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)}
10751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
10819cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)static blk_t currently_testing = 0;
10919cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)static blk_t num_blocks = 0;
11019cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)static blk_t num_read_errors = 0;
11119cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)static blk_t num_write_errors = 0;
11219cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)static blk_t num_corruption_errors = 0;
11351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)static ext2_badblocks_list bb_list = NULL;
11419cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)static FILE *out;
11519cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)static blk_t next_bad = 0;
11653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)static ext2_badblocks_iterate bb_iter = NULL;
11781a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)
11809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)enum error_types { READ_ERROR, WRITE_ERROR, CORRUPTION_ERROR };
11909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
12007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdochstatic void *allocate_buffer(size_t size)
1215267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles){
12281a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)	void	*ret = 0;
1235267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
124c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)#ifdef HAVE_POSIX_MEMALIGN
12581a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)	if (posix_memalign(&ret, sys_page_size, size) < 0)
12653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		ret = 0;
12793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)#else
12853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#ifdef HAVE_MEMALIGN
12953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	ret = memalign(sys_page_size, size);
13053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#else
13153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#ifdef HAVE_VALLOC
13253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	ret = valloc(size);
133aafa69cb17c9d6606c07663ade5f81388a2c5986Ben Murdoch#endif /* HAVE_VALLOC */
13453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#endif /* HAVE_MEMALIGN */
13509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#endif /* HAVE_POSIX_MEMALIGN */
13609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
13709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)	if (!ret)
13809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)		ret = malloc(size);
13953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
14053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	return ret;
14153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
14253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
14309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)/*
144d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) * This routine reports a new bad block.  If the bad block has already
1455267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) * been seen before, then it returns 0; otherwise it returns 1.
146c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles) */
14719cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)static int bb_output (blk_t bad, enum error_types error_type)
14853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
14953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	errcode_t errcode;
15053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
15153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	if (ext2fs_badblocks_list_test(bb_list, bad))
15253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		return 0;
15353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
15453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	fprintf(out, "%lu\n", (unsigned long) bad);
155d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)	fflush(out);
15681a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)
15707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch	errcode = ext2fs_badblocks_list_add (bb_list, bad);
15807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch	if (errcode) {
15953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		com_err (program_name, errcode, "adding to in-memory bad block list");
16053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		exit (1);
16153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	}
16253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
16353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	/* kludge:
16453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	   increment the iteration through the bb_list if
16553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	   an element was just added before the current iteration
166d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)	   position.  This should not cause next_bad to change. */
167a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)	if (bb_iter && bad < next_bad)
16853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		ext2fs_badblocks_list_iterate (bb_iter, &next_bad);
16953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
17053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	if (error_type == READ_ERROR) {
171d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)	  num_read_errors++;
172d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)	} else if (error_type == WRITE_ERROR) {
17309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)	  num_write_errors++;
17409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)	} else if (error_type == CORRUPTION_ERROR) {
17509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)	  num_corruption_errors++;
17609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)	}
17781a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)	return 1;
17809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
17909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
18007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdochstatic char *time_diff_format(struct timeval *tv1,
18181a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)			      struct timeval *tv2, char *buf)
18253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
18353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        time_t	diff = (tv1->tv_sec - tv2->tv_sec);
18407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch	int	hr,min,sec;
18553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
186e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)	sec = diff % 60;
187e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)	diff /= 60;
188e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)	min = diff % 60;
18907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch	hr = diff / 60;
19053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
19107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch	if (hr)
19253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		sprintf(buf, "%d:%02d:%02d", hr, min, sec);
19353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	else
19453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		sprintf(buf, "%d:%02d", min, sec);
19553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	return buf;
19653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
19753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
198e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)static float calc_percent(unsigned long current, unsigned long total) {
199e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)	float percent = 0.0;
200e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)	if (total <= 0)
20181a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)		return percent;
20253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	if (current >= total) {
20353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		percent = 100.0;
20453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	} else {
20553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		percent=(100.0*(float)current/(float)total);
206a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)	}
207a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)	return percent;
2085267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)}
2095267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
2105267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)static void print_status(void)
2115267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles){
2125267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)	struct timeval time_end;
2135267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)	char diff_buf[32], line_buf[128];
214a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)	int len;
2155267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
2165267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)	gettimeofday(&time_end, 0);
2175267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)	len = snprintf(line_buf, sizeof(line_buf),
2185267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)		       _("%6.2f%% done, %s elapsed. "
2195267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)		         "(%d/%d/%d errors)"),
2205267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)		       calc_percent((unsigned long) currently_testing,
2215267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)				    (unsigned long) num_blocks),
2225267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)		       time_diff_format(&time_end, &time_start, diff_buf),
2235267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)		       num_read_errors,
2245267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)		       num_write_errors,
2255267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)		       num_corruption_errors);
2265267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)#ifdef HAVE_MBSTOWCS
2275267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)	len = mbstowcs(NULL, line_buf, sizeof(line_buf));
2285267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)#endif
2295267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)	fputs(line_buf, stderr);
2305267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)	memset(line_buf, '\b', len);
2315267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)	line_buf[len] = 0;
2325267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)	fputs(line_buf, stderr);
2335267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)	fflush (stderr);
2345267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)}
2355267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
2365267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)static void alarm_intr(int alnum EXT2FS_ATTR((unused)))
2375267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles){
2385267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)	signal (SIGALRM, alarm_intr);
2395267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)	alarm(1);
24093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)	if (!num_blocks)
24153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		return;
24253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	print_status();
24353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
24453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
24593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)static void *terminate_addr = NULL;
24693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
2475267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)static void terminate_intr(int signo EXT2FS_ATTR((unused)))
24853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
24953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	fflush(out);
250d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)	fprintf(stderr, "\n\nInterrupted at block %llu\n",
25153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		(unsigned long long) currently_testing);
25253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	fflush(stderr);
25393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)	if (terminate_addr)
25453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		longjmp(terminate_addr,1);
25553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	exit(1);
25653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
257e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)
25893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)static void capture_terminate(jmp_buf term_addr)
25993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles){
2605267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)	terminate_addr = term_addr;
26193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)	signal (SIGHUP, terminate_intr);
26293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)	signal (SIGINT, terminate_intr);
263d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)	signal (SIGPIPE, terminate_intr);
26453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	signal (SIGTERM, terminate_intr);
26553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	signal (SIGUSR1, terminate_intr);
26653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	signal (SIGUSR2, terminate_intr);
26753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
268e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)
269e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)static void uncapture_terminate(void)
270e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles){
27153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	terminate_addr = NULL;
27253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	signal (SIGHUP, SIG_DFL);
2735267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)	signal (SIGINT, SIG_DFL);
27453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	signal (SIGPIPE, SIG_DFL);
27553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	signal (SIGTERM, SIG_DFL);
27609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)	signal (SIGUSR1, SIG_DFL);
277d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)	signal (SIGUSR2, SIG_DFL);
27853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
27953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
28053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)/* Linux requires that O_DIRECT I/Os be 512-byte sector aligned */
28153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
282e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)#define O_DIRECT_SIZE 512
283e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)
284e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)static void set_o_direct(int dev, unsigned char *buffer, size_t size,
28553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			 ext2_loff_t offset)
28653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
2875267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)#ifdef O_DIRECT
28853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	static int current_O_DIRECT;	/* Current status of O_DIRECT flag */
28953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	int new_flag = O_DIRECT;
29009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)	int flag;
291d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
29253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	if ((use_buffered_io != 0) ||
29353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	    (((unsigned long) buffer & (sys_page_size - 1)) != 0) ||
294591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch	    ((size & (sys_page_size - 1)) != 0) ||
295d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)	    ((offset & (O_DIRECT_SIZE - 1)) != 0))
296d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)		new_flag = 0;
29753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
29853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	if (new_flag != current_O_DIRECT) {
29953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	     /* printf("%s O_DIRECT\n", new_flag ? "Setting" : "Clearing"); */
300e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)		flag = fcntl(dev, F_GETFL);
30109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)		if (flag > 0) {
30293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)			flag = (flag & ~O_DIRECT) | new_flag;
30353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			fcntl(dev, F_SETFL, flag);
30453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		}
30553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		current_O_DIRECT = new_flag;
306d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)	}
307d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)#endif
308d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
309d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
31053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
31153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)static void pattern_fill(unsigned char *buffer, unsigned int pattern,
312d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)			 size_t n)
31353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
31453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	unsigned int	i, nb;
31553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	unsigned char	bpattern[sizeof(pattern)], *ptr;
316e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)
317d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)	if (pattern == (unsigned int) ~0) {
31853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		for (ptr = buffer; ptr < buffer + n; ptr++) {
31953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			(*ptr) = random() % (1 << (8 * sizeof(char)));
32093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)		}
32153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		if (s_flag | v_flag)
32253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			fputs(_("Testing with random pattern: "), stderr);
32353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	} else {
324e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)		bpattern[0] = 0;
325d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)		for (i = 0; i < sizeof(bpattern); i++) {
32653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			if (pattern == 0)
32753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)				break;
32893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)			bpattern[i] = pattern & 0xFF;
32953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			pattern = pattern >> 8;
330d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)		}
331e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)		nb = i ? (i-1) : 0;
332e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)		for (ptr = buffer, i = nb; ptr < buffer + n; ptr++) {
33309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)			*ptr = bpattern[i];
334e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)			if (i == 0)
335e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)				i = nb;
33609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)			else
33709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)				i--;
33809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)		}
33909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)		if (s_flag | v_flag) {
34009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)			fputs(_("Testing with pattern 0x"), stderr);
341e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)			for (i = 0; i <= nb; i++)
342e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)				fprintf(stderr, "%02x", buffer[i]);
34306f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)			fputs(": ", stderr);
34406f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)		}
34506f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)	}
34606f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)}
34706f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)
34806f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)/*
34906f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) * Perform a read of a sequence of blocks; return the number of blocks
35006f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) *    successfully sequentially read.
35106f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) */
35206f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)static int do_read (int dev, unsigned char * buffer, int try, int block_size,
35306f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)		    blk_t current_block)
35406f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles){
35551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)	long got;
356e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)	struct timeval tv1, tv2;
35793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)#define NANOSEC (1000000000L)
35893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)#define MILISEC (1000L)
35951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
36051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)#if 0
36151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)	printf("do_read: block %d, try %d\n", current_block, try);
36251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)#endif
36351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)	set_o_direct(dev, buffer, try * block_size,
36451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)		     ((ext2_loff_t) current_block) * block_size);
36551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
36651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)	if (v_flag > 1)
36751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)		print_status();
368e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)
369e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)	/* Seek to the correct loc. */
37093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)	if (ext2fs_llseek (dev, (ext2_loff_t) current_block * block_size,
371e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)			 SEEK_SET) != (ext2_loff_t) current_block * block_size)
372e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)		com_err (program_name, errno, "%s", _("during seek"));
373e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)
374e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)	/* Try the read */
37593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)	if (d_flag)
37693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)		gettimeofday(&tv1, NULL);
37793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)	got = read (dev, buffer, try * block_size);
37893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)	if (d_flag)
379e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)		gettimeofday(&tv2, NULL);
380e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)	if (got < 0)
38193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)		got = 0;
382e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)	if (got & 511)
38393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)		fprintf(stderr, _("Weird value (%ld) in do_read\n"), got);
38493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)	got /= block_size;
38593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)	if (d_flag && got == try) {
38693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)#ifdef HAVE_NANOSLEEP
387591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch		struct timespec ts;
38893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)		ts.tv_sec = tv2.tv_sec - tv1.tv_sec;
389e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)		ts.tv_nsec = (tv2.tv_usec - tv1.tv_usec) * MILISEC;
39093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)		if (ts.tv_nsec < 0) {
391e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)			ts.tv_nsec += NANOSEC;
392e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)			ts.tv_sec -= 1;
393a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)		}
394e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)		/* increase/decrease the sleep time based on d_flag value */
39507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch		ts.tv_sec = ts.tv_sec * d_flag / 100;
39607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch		ts.tv_nsec = ts.tv_nsec * d_flag / 100;
397d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)		if (ts.tv_nsec > NANOSEC) {
398e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)			ts.tv_sec += ts.tv_nsec / NANOSEC;
399e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)			ts.tv_nsec %= NANOSEC;
4001e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)		}
401c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)		if (ts.tv_sec || ts.tv_nsec)
402d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)			nanosleep(&ts, NULL);
4031e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#else
4041e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#ifdef HAVE_USLEEP
4051e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)		struct timeval tv;
4061e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)		tv.tv_sec = tv2.tv_sec - tv1.tv_sec;
40709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)		tv.tv_usec = tv2.tv_usec - tv1.tv_usec;
40809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)		tv.tv_sec = tv.tv_sec * d_flag / 100;
4091e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)		tv.tv_usec = tv.tv_usec * d_flag / 100;
4101e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)		if (tv.tv_usec > 1000000) {
411d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)			tv.tv_sec += tv.tv_usec / 1000000;
412d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)			tv.tv_usec %= 1000000;
413c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)		}
414c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)		if (tv.tv_sec)
41507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch			sleep(tv.tv_sec);
416e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)		if (tv.tv_usec)
41793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)			usleep(tv.tv_usec);
41893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)#endif
41993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)#endif
42007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch	}
421e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)	return got;
422e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)}
42393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
424e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)/*
42593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) * Perform a write of a sequence of blocks; return the number of blocks
42693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) *    successfully sequentially written.
42793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) */
42807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdochstatic int do_write(int dev, unsigned char * buffer, int try, int block_size,
42993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)		    unsigned long current_block)
43093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles){
431e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)	long got;
432e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)
433d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)#if 0
434e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)	printf("do_write: block %lu, try %d\n", current_block, try);
43593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)#endif
436d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)	set_o_direct(dev, buffer, try * block_size,
43709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)		     ((ext2_loff_t) current_block) * block_size);
43809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
439d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)	if (v_flag > 1)
44009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)		print_status();
44107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
44293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)	/* Seek to the correct loc. */
443d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)	if (ext2fs_llseek (dev, (ext2_loff_t) current_block * block_size,
44453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			 SEEK_SET) != (ext2_loff_t) current_block * block_size)
44553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		com_err (program_name, errno, "%s", _("during seek"));
446c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)
44753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	/* Try the write */
448d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)	got = write (dev, buffer, try * block_size);
4498abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)	if (got < 0)
4508abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)		got = 0;
45109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)	if (got & 511)
4528abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)		fprintf(stderr, "Weird value (%ld) in do_write\n", got);
45353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	got /= block_size;
45453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	return got;
45553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
45653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
45753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)static int host_dev;
458d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
4591e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)static void flush_bufs(void)
46009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
46153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	errcode_t	retval;
462c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)
463c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)#ifdef O_DIRECT
46407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch	if (!use_buffered_io)
465c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)		return;
46607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch#endif
467c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)	retval = ext2fs_sync_device(host_dev, 1);
468c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)	if (retval)
46981a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)		com_err(program_name, retval, "%s",
470c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)			_("during ext2fs_sync_device"));
47181a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)}
47253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
47353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)static unsigned int test_ro (int dev, blk_t last_block,
474c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)			     int block_size, blk_t first_block,
47553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			     unsigned int blocks_at_once)
476e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles){
477e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)	unsigned char * blkbuf;
478e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)	int try;
479c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)	int got;
48053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	unsigned int bb_count = 0;
481c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)	errcode_t errcode;
482c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)	blk_t recover_block = ~0;
483c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)
484c0e19a689c8ac22cdc96b291a8d33a5d3b0b34a4Torne (Richard Coles)	/* set up abend handler */
48553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	capture_terminate(NULL);
48653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
48719cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)	errcode = ext2fs_badblocks_list_iterate_begin(bb_list,&bb_iter);
48819cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)	if (errcode) {
48919cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)		com_err(program_name, errcode, "%s",
49019cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)			_("while beginning bad block list iteration"));
49151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)		exit (1);
49251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)	}
49351b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)	do {
49407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch		ext2fs_badblocks_list_iterate (bb_iter, &next_bad);
49507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch	} while (next_bad && next_bad < first_block);
49607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch
49707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch	if (t_flag) {
49807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch		blkbuf = allocate_buffer((blocks_at_once + 1) * block_size);
49907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch	} else {
50007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch		blkbuf = allocate_buffer(blocks_at_once * block_size);
50107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch	}
50207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch	if (!blkbuf)
50307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch	{
50407a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch		com_err(program_name, ENOMEM, "%s",
50507a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch			_("while allocating buffers"));
50651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)		exit (1);
50751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)	}
50851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)	if (v_flag) {
50919cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)		fprintf(stderr, _("Checking blocks %lu to %lu\n"),
51019cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)			(unsigned long)first_block,
51119cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)			(unsigned long)last_block - 1);
51219cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)	}
51319cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)	if (t_flag) {
51419cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)		fputs(_("Checking for bad blocks in read-only mode\n"), stderr);
51519cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)		pattern_fill(blkbuf + blocks_at_once * block_size,
51607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch			     t_patts[0], block_size);
51707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch	}
51807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch	flush_bufs();
51907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch	try = blocks_at_once;
52019cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)	currently_testing = first_block;
52119cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)	num_blocks = last_block - 1;
52219cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)	if (!t_flag && (s_flag || v_flag))
52319cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)		fputs(_("Checking for bad blocks (read-only test): "), stderr);
52419cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)	if (s_flag && v_flag <= 1)
52519cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)		alarm_intr(SIGALRM);
52619cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)	while (currently_testing < last_block)
52751b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)	{
52851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)		if (max_bb && bb_count >= max_bb) {
52951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)			if (s_flag || v_flag) {
53051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)				fputs(_("Too many bad blocks, aborting test\n"), stderr);
53151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)			}
53219cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)			break;
53319cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)		}
53409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)		if (next_bad) {
53519cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)			if (currently_testing == next_bad) {
53619cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)				/* fprintf (out, "%lu\n", nextbad); */
53709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)				ext2fs_badblocks_list_iterate (bb_iter, &next_bad);
53819cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)				currently_testing++;
53919cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)				continue;
54007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch			}
54119cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)			else if (currently_testing + try > next_bad)
54219cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)				try = next_bad - currently_testing;
54319cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)		}
54419cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)		if (currently_testing + try > last_block)
54519cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)			try = last_block - currently_testing;
54619cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)		got = do_read (dev, blkbuf, try, block_size, currently_testing);
54719cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)		if (t_flag) {
54819cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)			/* test the comparison between all the
54919cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)			   blocks successfully read  */
55019cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)			int i;
55119cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)			for (i = 0; i < got; ++i)
55281a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)				if (memcmp (blkbuf+i*block_size,
55381a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)					    blkbuf+blocks_at_once*block_size,
554e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)					    block_size))
555e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)					bb_count += bb_output(currently_testing + i, CORRUPTION_ERROR);
556e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)		}
557d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)		if (got == 0 && try == 1)
55881a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)			bb_count += bb_output(currently_testing++, READ_ERROR);
55981a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)		currently_testing += got;
560d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)		if (got != try) {
56181a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)			try = 1;
562e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)			if (recover_block == ~0U)
563d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)				recover_block = currently_testing - got +
56481a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)					blocks_at_once;
565d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)			continue;
56653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		} else if (currently_testing == recover_block) {
56753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			try = blocks_at_once;
56853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			recover_block = ~0;
56953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		}
57053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	}
57153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	num_blocks = 0;
57253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	alarm(0);
57353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	if (s_flag || v_flag)
57453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		fputs(_(done_string), stderr);
57553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
57653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	fflush (stderr);
57753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	free (blkbuf);
57853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
579d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)	ext2fs_badblocks_list_iterate_end(bb_iter);
58053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
58153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	uncapture_terminate();
58253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
583d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)	return bb_count;
584d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)}
58553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
58653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)static unsigned int test_rw (int dev, blk_t last_block,
58753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			     int block_size, blk_t first_block,
58853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			     unsigned int blocks_at_once)
58953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
59053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	unsigned char *buffer, *read_buffer;
59153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	const unsigned int patterns[] = {0xaa, 0x55, 0xff, 0x00};
59253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	const unsigned int *pattern;
59353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	int i, try, got, nr_pattern, pat_idx;
594d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)	unsigned int bb_count = 0;
59553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	blk_t recover_block = ~0;
596d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
597d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)	/* set up abend handler */
59853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	capture_terminate(NULL);
59953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
600591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch	buffer = allocate_buffer(2 * blocks_at_once * block_size);
60153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	read_buffer = buffer + blocks_at_once * block_size;
602591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
603591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch	if (!buffer) {
604591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch		com_err(program_name, ENOMEM, "%s",
605591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch			_("while allocating buffers"));
606591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch		exit (1);
607591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch	}
608591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
609591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch	flush_bufs();
610591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
611591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch	if (v_flag) {
612591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch		fputs(_("Checking for bad blocks in read-write mode\n"),
61353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		      stderr);
61453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		fprintf(stderr, _("From block %lu to %lu\n"),
61553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			(unsigned long) first_block,
61653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			(unsigned long) last_block - 1);
61753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	}
61853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	if (t_flag) {
61953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		pattern = t_patts;
62053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		nr_pattern = t_flag;
62153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	} else {
62253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		pattern = patterns;
62353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		nr_pattern = sizeof(patterns) / sizeof(patterns[0]);
62453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	}
62553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	for (pat_idx = 0; pat_idx < nr_pattern; pat_idx++) {
62653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		pattern_fill(buffer, pattern[pat_idx],
62753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			     blocks_at_once * block_size);
62853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		num_blocks = last_block - 1;
62953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		currently_testing = first_block;
63053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		if (s_flag && v_flag <= 1)
63153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			alarm_intr(SIGALRM);
63253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
63353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		try = blocks_at_once;
63453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		while (currently_testing < last_block) {
63553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			if (max_bb && bb_count >= max_bb) {
63653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)				if (s_flag || v_flag) {
63753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)					fputs(_("Too many bad blocks, aborting test\n"), stderr);
63853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)				}
63953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)				break;
64053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			}
64153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			if (currently_testing + try > last_block)
64253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)				try = last_block - currently_testing;
643591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch			got = do_write(dev, buffer, try, block_size,
644591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch					currently_testing);
645591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch			if (v_flag > 1)
646591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch				print_status();
647591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
648591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch			if (got == 0 && try == 1)
649591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch				bb_count += bb_output(currently_testing++, WRITE_ERROR);
650591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch			currently_testing += got;
651591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch			if (got != try) {
652591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch				try = 1;
653591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch				if (recover_block == ~0U)
654591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch					recover_block = currently_testing -
655591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch						got + blocks_at_once;
656591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch				continue;
657591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch			} else if (currently_testing == recover_block) {
658591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch				try = blocks_at_once;
65907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch				recover_block = ~0;
66007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch			}
66107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch		}
662591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
663591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch		num_blocks = 0;
664591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch		alarm (0);
665591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch		if (s_flag | v_flag)
666591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch			fputs(_(done_string), stderr);
667591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch		flush_bufs();
668591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch		if (s_flag | v_flag)
669591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch			fputs(_("Reading and comparing: "), stderr);
670591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch		num_blocks = last_block;
671591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch		currently_testing = first_block;
672591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch		if (s_flag && v_flag <= 1)
673591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch			alarm_intr(SIGALRM);
674591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
675591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch		try = blocks_at_once;
676591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch		while (currently_testing < last_block) {
677591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch			if (max_bb && bb_count >= max_bb) {
678591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch				if (s_flag || v_flag) {
679591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch					fputs(_("Too many bad blocks, aborting test\n"), stderr);
680591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch				}
681591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch				break;
682591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch			}
683591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch			if (currently_testing + try > last_block)
684591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch				try = last_block - currently_testing;
685591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch			got = do_read (dev, read_buffer, try, block_size,
686591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch				       currently_testing);
687591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch			if (got == 0 && try == 1)
688591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch				bb_count += bb_output(currently_testing++, READ_ERROR);
689591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch			currently_testing += got;
690591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch			if (got != try) {
691591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch				try = 1;
692591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch				if (recover_block == ~0U)
693591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch					recover_block = currently_testing -
694591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch						got + blocks_at_once;
695591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch				continue;
696591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch			} else if (currently_testing == recover_block) {
697591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch				try = blocks_at_once;
698591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch				recover_block = ~0U;
699591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch			}
700591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch			for (i=0; i < got; i++) {
701d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)				if (memcmp(read_buffer + i * block_size,
702d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)					   buffer + i * block_size,
703d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)					   block_size))
704d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)					bb_count += bb_output(currently_testing+i, CORRUPTION_ERROR);
705591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch			}
706591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch			if (v_flag > 1)
707591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch				print_status();
708591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch		}
709591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
71053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		num_blocks = 0;
71153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		alarm (0);
71253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		if (s_flag | v_flag)
71353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			fputs(_(done_string), stderr);
71453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		flush_bufs();
71553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	}
71653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	uncapture_terminate();
71753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	free(buffer);
71853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	return bb_count;
71953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
72053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
72153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)struct saved_blk_record {
72253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	blk_t	block;
72353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	int	num;
72453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)};
72553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
72653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)static unsigned int test_nd (int dev, blk_t last_block,
72753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			     int block_size, blk_t first_block,
72809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)			     unsigned int blocks_at_once)
729d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){
73053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	unsigned char *blkbuf, *save_ptr, *test_ptr, *read_ptr;
73153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	unsigned char *test_base, *save_base, *read_base;
73253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	int try, i;
73353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	const unsigned int patterns[] = { ~0 };
73453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	const unsigned int *pattern;
73553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	int nr_pattern, pat_idx;
73653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	int got, used2, written;
73753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	blk_t save_currently_testing;
73853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	struct saved_blk_record *test_record;
73953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	/* This is static to prevent being clobbered by the longjmp */
74053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	static int num_saved;
74153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	jmp_buf terminate_env;
74253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	errcode_t errcode;
74353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	unsigned long buf_used;
74453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	static unsigned int bb_count;
74553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	unsigned int granularity = blocks_at_once;
74653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	blk_t recover_block = ~0U;
74753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
74853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	bb_count = 0;
74953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	errcode = ext2fs_badblocks_list_iterate_begin(bb_list,&bb_iter);
75053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	if (errcode) {
75153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		com_err(program_name, errcode, "%s",
752a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch			_("while beginning bad block list iteration"));
75353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		exit (1);
75481a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)	}
75553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	do {
75653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		ext2fs_badblocks_list_iterate (bb_iter, &next_bad);
75753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	} while (next_bad && next_bad < first_block);
75853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
75953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	blkbuf = allocate_buffer(3 * blocks_at_once * block_size);
76053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	test_record = malloc(blocks_at_once * sizeof(struct saved_blk_record));
76153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	if (!blkbuf || !test_record) {
76253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		com_err(program_name, ENOMEM, "%s",
76353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			_("while allocating buffers"));
76453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		exit (1);
76553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	}
76653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
76753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	save_base = blkbuf;
76853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	test_base = blkbuf + (blocks_at_once * block_size);
76953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	read_base = blkbuf + (2 * blocks_at_once * block_size);
77053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
77153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	num_saved = 0;
77253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
7738abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)	flush_bufs();
77453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	if (v_flag) {
77553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	    fputs(_("Checking for bad blocks in non-destructive read-write mode\n"), stderr);
77653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	    fprintf (stderr, _("From block %lu to %lu\n"),
77743e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)		     (unsigned long) first_block,
77843e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)		     (unsigned long) last_block - 1);
77943e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)	}
78053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	if (s_flag || v_flag > 1) {
78143e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)		fputs(_("Checking for bad blocks (non-destructive read-write test)\n"), stderr);
78253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	}
78353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	if (setjmp(terminate_env)) {
78453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		/*
78553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		 * Abnormal termination by a signal is handled here.
786521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)		 */
787521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)		signal (SIGALRM, SIG_IGN);
78853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		fputs(_("\nInterrupt caught, cleaning up\n"), stderr);
78953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
79053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		save_ptr = save_base;
79153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		for (i=0; i < num_saved; i++) {
79253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			do_write(dev, save_ptr, test_record[i].num,
79353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)				 block_size, test_record[i].block);
79443e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)			save_ptr += test_record[i].num * block_size;
79553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		}
79653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		fflush (out);
79753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		exit(1);
79853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	}
79953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
80053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	/* set up abend handler */
80153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	capture_terminate(terminate_env);
80253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
80353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	if (t_flag) {
804521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)		pattern = t_patts;
805521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)		nr_pattern = t_flag;
80653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	} else {
80753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		pattern = patterns;
80853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		nr_pattern = sizeof(patterns) / sizeof(patterns[0]);
80953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	}
81053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	for (pat_idx = 0; pat_idx < nr_pattern; pat_idx++) {
81153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		pattern_fill(test_base, pattern[pat_idx],
81253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			     blocks_at_once * block_size);
81353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
81453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		buf_used = 0;
81543e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)		bb_count = 0;
81653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		save_ptr = save_base;
81753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		test_ptr = test_base;
81853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		currently_testing = first_block;
81953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		num_blocks = last_block - 1;
82053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		if (s_flag && v_flag <= 1)
82153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			alarm_intr(SIGALRM);
82253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
82353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		while (currently_testing < last_block) {
82453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			if (max_bb && bb_count >= max_bb) {
82553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)				if (s_flag || v_flag) {
82653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)					fputs(_("Too many bad blocks, aborting test\n"), stderr);
82743e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)				}
82843e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)				break;
82953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			}
83053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			got = try = granularity - buf_used;
83153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			if (next_bad) {
83253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)				if (currently_testing == next_bad) {
83353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)					/* fprintf (out, "%lu\n", nextbad); */
83453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)					ext2fs_badblocks_list_iterate (bb_iter, &next_bad);
83543e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)					currently_testing++;
83643e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)					goto check_for_more;
83743e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)				}
83853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)				else if (currently_testing + try > next_bad)
83943e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)					try = next_bad - currently_testing;
84053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			}
84143e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)			if (currently_testing + try > last_block)
84253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)				try = last_block - currently_testing;
84343e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)			got = do_read (dev, save_ptr, try, block_size,
84453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)				       currently_testing);
84553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			if (got == 0) {
84643e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)				if (recover_block == ~0U)
84743e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)					recover_block = currently_testing +
84853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)						blocks_at_once;
84953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)				if (granularity != 1) {
85053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)					granularity = 1;
8518abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)					continue;
85253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)				}
85353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)				/* First block must have been bad. */
85453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)				bb_count += bb_output(currently_testing++, READ_ERROR);
85553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)				goto check_for_more;
85653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			}
85753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
85853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			/*
85953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			 * Note the fact that we've saved this much data
86053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			 * *before* we overwrite it with test data
86153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			 */
86253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			test_record[num_saved].block = currently_testing;
86353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			test_record[num_saved].num = got;
86453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			num_saved++;
86553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
86653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			/* Write the test data */
86753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			written = do_write (dev, test_ptr, got, block_size,
86853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)					    currently_testing);
8697757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch			if (written != got)
8707757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch				com_err (program_name, errno,
87153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)					 _("during test data write, block %lu"),
87253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)					 (unsigned long) currently_testing +
87353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)					 written);
87453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
87553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			buf_used += got;
8767757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch			save_ptr += got * block_size;
87753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			test_ptr += got * block_size;
87853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			currently_testing += got;
87953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			if (got != try) {
88053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)				try = 1;
88153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)				if (recover_block == ~0U)
88281a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)					recover_block = currently_testing -
88381a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)						got + blocks_at_once;
88453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)				continue;
88553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			}
88653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
88781a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)		check_for_more:
88853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			/*
88953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			 * If there's room for more blocks to be tested this
89053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			 * around, and we're not done yet testing the disk, go
89153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			 * back and get some more blocks.
89253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			 */
89353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			if ((buf_used != granularity) &&
89453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			    (currently_testing < last_block))
89553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)				continue;
89653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
89753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			if (currently_testing >= recover_block) {
89853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)				granularity = blocks_at_once;
89993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)				recover_block = ~0;
90093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)			}
90193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
90293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)			flush_bufs();
903d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)			save_currently_testing = currently_testing;
904d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
905d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)			/*
906d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)			 * for each contiguous block that we read into the
907d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)			 * buffer (and wrote test data into afterwards), read
908d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)			 * it back (looping if necessary, to get past newly
909d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)			 * discovered unreadable blocks, of which there should
910d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)			 * be none, but with a hard drive which is unreliable,
911d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)			 * it has happened), and compare with the test data
912d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)			 * that was written; output to the bad block list if
913d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)			 * it doesn't match.
914d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)			 */
915d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)			used2 = 0;
916d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)			save_ptr = save_base;
917d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)			test_ptr = test_base;
91893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)			read_ptr = read_base;
919d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)			try = 0;
920d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
921d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)			while (1) {
922d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)				if (try == 0) {
923d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)					if (used2 >= num_saved)
92493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)						break;
92593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)					currently_testing = test_record[used2].block;
926d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)					try = test_record[used2].num;
92753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)					used2++;
92853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)				}
92953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
93053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)				got = do_read (dev, read_ptr, try,
93153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)					       block_size, currently_testing);
93253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
93353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)				/* test the comparison between all the
93453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)				   blocks successfully read  */
93553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)				for (i = 0; i < got; ++i)
93653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)					if (memcmp (test_ptr+i*block_size,
93753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)						    read_ptr+i*block_size, block_size))
93853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)						bb_count += bb_output(currently_testing + i, CORRUPTION_ERROR);
93981a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)				if (got < try) {
940d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)					bb_count += bb_output(currently_testing + got, READ_ERROR);
941d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)					got++;
942d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)				}
943d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
944d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)				/* write back original data */
945d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)				do_write (dev, save_ptr, got,
946d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)					  block_size, currently_testing);
947d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)				save_ptr += got * block_size;
948d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
949d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)				currently_testing += got;
950d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)				test_ptr += got * block_size;
951d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)				read_ptr += got * block_size;
952d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)				try -= got;
95381a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)			}
95481a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)
95553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			/* empty the buffer so it can be reused */
95653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			num_saved = 0;
95793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)			buf_used = 0;
95853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			save_ptr = save_base;
95953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			test_ptr = test_base;
96053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			currently_testing = save_currently_testing;
96153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		}
96293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)		num_blocks = 0;
96353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		alarm(0);
96453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		if (s_flag || v_flag > 1)
96593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)			fputs(_(done_string), stderr);
96653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
96753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		flush_bufs();
96853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	}
96953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	uncapture_terminate();
97093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)	fflush(stderr);
97153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	free(blkbuf);
97253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	free(test_record);
97393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
97453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	ext2fs_badblocks_list_iterate_end(bb_iter);
97553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
97653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	return bb_count;
97753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
97893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
97993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)static void check_mount(char *device_name)
98093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles){
98153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	errcode_t	retval;
98253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	int		mount_flags;
98353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
98453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	retval = ext2fs_check_if_mounted(device_name, &mount_flags);
98553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	if (retval) {
98653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		com_err("ext2fs_check_if_mount", retval,
98753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			_("while determining whether %s is mounted."),
98853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			device_name);
98953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		return;
99053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	}
99153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	if (mount_flags & EXT2_MF_MOUNTED) {
99253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		fprintf(stderr, _("%s is mounted; "), device_name);
99353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		if (force) {
99453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			fputs(_("badblocks forced anyway.  "
99553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)				"Hope /etc/mtab is incorrect.\n"), stderr);
99653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			return;
99753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		}
99853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	abort_badblocks:
99953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		fputs(_("it's not safe to run badblocks!\n"), stderr);
100093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)		exit(1);
100193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)	}
100293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
100353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	if ((mount_flags & EXT2_MF_BUSY) && !exclusive_ok) {
100453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		fprintf(stderr, _("%s is apparently in use by the system; "),
100553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			device_name);
100653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		if (force)
100753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			fputs(_("badblocks forced anyway.\n"), stderr);
100853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		else
100953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			goto abort_badblocks;
101053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	}
101153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
101253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
10135267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
101453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)/*
101553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * This function will convert a string to an unsigned long, printing
101653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * an error message if it fails, and returning success or failure in err.
101753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) */
10185267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)static unsigned int parse_uint(const char *str, const char *descr)
101953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
102053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	char		*tmp;
10215267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)	unsigned long	ret;
102253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
102353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	errno = 0;
102453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	ret = strtoul(str, &tmp, 0);
10255267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)	if (*tmp || errno || (ret > UINT_MAX) ||
102653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	    (ret == ULONG_MAX && errno == ERANGE)) {
102753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		com_err (program_name, 0, _("invalid %s - %s"), descr, str);
102843e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)		exit (1);
102953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	}
103053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	return ret;
103153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
103243e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)
103353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)int main (int argc, char ** argv)
103453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
103543e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)	int c;
103653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	char * device_name;
103743e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)	char * host_device_name = NULL;
103853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	char * input_file = NULL;
103953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	char * output_file = NULL;
10405267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)	FILE * in = NULL;
104153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	int block_size = 1024;
104253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	unsigned int blocks_at_once = 64;
104353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	blk64_t last_block, first_block;
10445267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)	int num_passes = 0;
104553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	int passes_clean = 0;
104653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	int dev;
104743e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)	errcode_t errcode;
104843e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)	unsigned int pattern;
104943e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)	unsigned int (*test_func)(int, blk_t,
105053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)				  int, blk_t,
10515267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)				  unsigned int);
105253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	int open_flag;
105353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	long sysval;
105443e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)	blk64_t inblk;
105553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
105653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	setbuf(stdout, NULL);
105753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	setbuf(stderr, NULL);
105843e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)#ifdef ENABLE_NLS
105953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	setlocale(LC_MESSAGES, "");
106053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	setlocale(LC_CTYPE, "");
10615267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)	bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
106243e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)	textdomain(NLS_CAT_NAME);
106353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	set_com_err_gettext(gettext);
106453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#endif
106553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	srandom((unsigned int)time(NULL));  /* simple randomness is enough */
106653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	test_func = test_ro;
106753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
106853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	/* Determine the system page size if possible */
10695267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)#ifdef HAVE_SYSCONF
107053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#if (!defined(_SC_PAGESIZE) && defined(_SC_PAGE_SIZE))
107153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#define _SC_PAGESIZE _SC_PAGE_SIZE
107253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#endif
107343e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)#ifdef _SC_PAGESIZE
107453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	sysval = sysconf(_SC_PAGESIZE);
107553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	if (sysval > 0)
1076a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)		sys_page_size = sysval;
107753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#endif /* _SC_PAGESIZE */
107853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#endif /* HAVE_SYSCONF */
107953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
1080a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)	if (argc && *argv)
108153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		program_name = *argv;
108253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	while ((c = getopt (argc, argv, "b:d:e:fi:o:svwnc:p:h:t:BX")) != EOF) {
108343e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)		switch (c) {
108453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		case 'b':
108553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			block_size = parse_uint(optarg, "block size");
108653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			break;
108743e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)		case 'f':
108853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			force++;
108953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			break;
1090a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)		case 'i':
109153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			input_file = optarg;
10925267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)			break;
109353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		case 'o':
109453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			output_file = optarg;
109543e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)			break;
109653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		case 's':
109743e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)			s_flag = 1;
109853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			break;
109953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		case 'v':
11005267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)			v_flag++;
110153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			break;
110253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		case 'w':
110353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			if (w_flag)
1104a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)				exclusive_usage();
110553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			test_func = test_rw;
110653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			w_flag = 1;
110743e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)			break;
110853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		case 'n':
110953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			if (w_flag)
111053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)				exclusive_usage();
111143e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)			test_func = test_nd;
111253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			w_flag = 2;
111353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			break;
1114d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)		case 'c':
111553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			blocks_at_once = parse_uint(optarg, "blocks at once");
1116e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)			break;
1117e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)		case 'e':
1118e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)			max_bb = parse_uint(optarg, "max bad block count");
1119d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)			break;
112053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		case 'd':
112153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			d_flag = parse_uint(optarg, "read delay factor");
1122d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)			break;
112353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		case 'p':
112453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			num_passes = parse_uint(optarg,
112553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)						"number of clean passes");
1126d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)			break;
1127d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)		case 'h':
1128d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)			host_device_name = optarg;
1129d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)			break;
1130d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)		case 't':
1131d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)			if (t_flag + 1 > t_max) {
1132d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)				unsigned int *t_patts_new;
1133d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
1134d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)				t_patts_new = realloc(t_patts, sizeof(int) *
1135d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)						      (t_max + T_INC));
1136d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)				if (!t_patts_new) {
113707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch					com_err(program_name, ENOMEM,
113807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch						_("can't allocate memory for "
113907a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch						  "test_pattern - %s"),
1140d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)						optarg);
1141d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)					exit(1);
1142d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)				}
1143d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)				t_patts = t_patts_new;
114453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)				t_max += T_INC;
114553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			}
114653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			if (!strcmp(optarg, "r") || !strcmp(optarg,"random")) {
1147e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)				t_patts[t_flag++] = ~0;
114853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			} else {
1149e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)				pattern = parse_uint(optarg, "test pattern");
1150e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)				if (pattern == (unsigned int) ~0)
1151e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)					pattern = 0xffff;
115281a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)				t_patts[t_flag++] = pattern;
115353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			}
115453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			break;
115553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		case 'B':
115653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			use_buffered_io = 1;
115753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			break;
115853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		case 'X':
115953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			exclusive_ok++;
11605267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)			break;
116153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		default:
116253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			usage();
1163e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)		}
1164e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)	}
1165e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)	if (!w_flag) {
1166d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)		if (t_flag > 1) {
1167d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)			com_err(program_name, 0, "%s",
11689bbd2f5e390b01907d97ecffde80aa1b06113aacTorne (Richard Coles)				_("Maximum of one test_pattern may be "
11699bbd2f5e390b01907d97ecffde80aa1b06113aacTorne (Richard Coles)				  "specified in read-only mode"));
117053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			exit(1);
117153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		}
117253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		if (t_patts && (t_patts[0] == (unsigned int) ~0)) {
117353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			com_err(program_name, 0, "%s",
117453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)				_("Random test_pattern is not allowed "
117553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)				  "in read-only mode"));
117653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			exit(1);
1177e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)		}
1178e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)	}
1179e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)	if (optind > argc - 1)
118081a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)		usage();
118153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	device_name = argv[optind++];
118253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	if (optind > argc - 1) {
118353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		errcode = ext2fs_get_device_size2(device_name,
118453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)						 block_size,
118553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)						 &last_block);
118653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		if (errcode == EXT2_ET_UNIMPLEMENTED) {
118753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			com_err(program_name, 0, "%s",
1188e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)				_("Couldn't determine device size; you "
1189e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)				  "must specify\nthe size manually\n"));
1190e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)			exit(1);
119181a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)		}
119253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		if (errcode) {
119353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			com_err(program_name, errcode, "%s",
119453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)				_("while trying to determine device size"));
119553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			exit(1);
119653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		}
119753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	} else {
119853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		errno = 0;
1199e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)		last_block = parse_uint(argv[optind], _("last block"));
1200e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)		last_block++;
1201e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)		optind++;
120281a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)	}
120353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	if (optind <= argc-1) {
120453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		errno = 0;
120553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		first_block = parse_uint(argv[optind], _("first block"));
120653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	} else first_block = 0;
120753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	if (first_block >= last_block) {
120853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	    com_err (program_name, 0, _("invalid starting block (%llu): must be less than %llu"),
120953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		     first_block, last_block);
121007a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch	    exit (1);
121107a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch	}
121207a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch	/* ext2 badblocks file can't handle large values */
121353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	if (last_block >> 32) {
121453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		com_err(program_name, EOVERFLOW,
121553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			_("invalid end block (%llu): must be 32-bit value"),
121653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			last_block);
121753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		exit(1);
121893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)	}
121953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	if (w_flag)
1220e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)		check_mount(device_name);
1221e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)
1222e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)	gettimeofday(&time_start, 0);
122381a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)	open_flag = O_LARGEFILE | (w_flag ? O_RDWR : O_RDONLY);
122493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)	dev = open (device_name, open_flag);
122553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	if (dev == -1) {
122653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		com_err (program_name, errno, _("while trying to open %s"),
122753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			 device_name);
122853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		exit (1);
122953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	}
123053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	if (host_device_name) {
123153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		host_dev = open (host_device_name, open_flag);
123253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		if (host_dev == -1) {
123353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			com_err (program_name, errno,
123453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)				 _("while trying to open %s"),
123553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)				 host_device_name);
123653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			exit (1);
123753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		}
123853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	} else
123953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		host_dev = dev;
1240d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)	if (input_file) {
1241d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)		if (strcmp (input_file, "-") == 0)
124253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			in = stdin;
124353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		else {
1244d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)			in = fopen (input_file, "r");
124553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			if (in == NULL)
124653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			{
124753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)				com_err (program_name, errno,
124853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)					 _("while trying to open %s"),
124953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)					 input_file);
125053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)				exit (1);
125153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			}
125253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		}
125353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	}
125453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	if (output_file && strcmp (output_file, "-") != 0)
125553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	{
1256d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)		out = fopen (output_file, "w");
125753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		if (out == NULL)
125853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		{
12595267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)			com_err (program_name, errno,
126053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)				 _("while trying to open %s"),
126153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)				 output_file);
126253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			exit (1);
126353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		}
126453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	}
1265d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)	else
126653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		out = stdout;
126753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
126853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	errcode = ext2fs_badblocks_list_create(&bb_list,0);
126953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	if (errcode) {
1270d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)		com_err(program_name, errcode, "%s",
1271d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)			_("while creating in-memory bad blocks list"));
1272d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)		exit (1);
1273d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)	}
1274d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)
1275d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)	if (in) {
1276d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)		for(;;) {
1277d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)			switch (fscanf(in, "%llu\n", &inblk)) {
1278d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)				case 0:
1279d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)					com_err(program_name, 0, "%s",
1280d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)						_("input file - bad format"));
1281d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)					exit (1);
1282d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)				case EOF:
1283d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)					break;
1284d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)				default:
1285d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)					if (inblk >> 32) {
1286d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)						com_err(program_name,
1287d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)							EOVERFLOW, "%s",
1288d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)						_("while adding to in-memory "
1289d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)						  "bad block list"));
1290d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)						exit(1);
1291d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)					}
1292d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)					next_bad = inblk;
1293d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)					errcode = ext2fs_badblocks_list_add(bb_list,next_bad);
1294d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)					if (errcode) {
1295d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)						com_err(program_name, errcode,
1296d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)							"%s",
1297d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)						_("while adding to in-memory "
1298d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)						  "bad block list"));
1299d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)						exit (1);
1300e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)					}
13015267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)					continue;
130253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			}
130353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			break;
130453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		}
130553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
130653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		if (in != stdin)
130753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			fclose (in);
130853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	}
130953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
131053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	do {
131153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		unsigned int bb_count;
131253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
13135267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)		bb_count = test_func(dev, last_block, block_size,
131453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)				     first_block, blocks_at_once);
131553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		if (bb_count)
131653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			passes_clean = 0;
131753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		else
131853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			++passes_clean;
131953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
132053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		if (v_flag)
132153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			fprintf(stderr,
132253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)				_("Pass completed, %u bad blocks found. (%d/%d/%d errors)\n"),
1323d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)				bb_count, num_read_errors, num_write_errors, num_corruption_errors);
132453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
132553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	} while (passes_clean < num_passes);
132681a5157921f1d2a7ff6aae115bfe3c139b38a5c8Torne (Richard Coles)
132753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	close (dev);
132853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	if (out != stdout)
132953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)		fclose (out);
133053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	free(t_patts);
133153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	return 0;
133253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
133353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)