119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/*
219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * badblocks.c		- Bad blocks checker
319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project *
419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Copyright (C) 1992, 1993, 1994  Remy Card <card@masi.ibp.fr>
519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project *                                 Laboratoire MASI, Institut Blaise Pascal
619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project *                                 Universite Pierre et Marie Curie (Paris VI)
719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project *
819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Copyright 1995, 1996, 1997, 1998, 1999 by Theodore Ts'o
919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Copyright 1999 by David Beattie
1019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project *
1119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * This file is based on the minix file system programs fsck and mkfs
1219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * written and copyrighted by Linus Torvalds <Linus.Torvalds@cs.helsinki.fi>
133984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt *
1419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * %Begin-Header%
1519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * This file may be redistributed under the terms of the GNU Public
1619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * License.
1719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * %End-Header%
1819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */
1919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
2019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/*
2119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * History:
2219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * 93/05/26	- Creation from e2fsck
2319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * 94/02/27	- Made a separate bad blocks checker
2419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * 99/06/30...99/07/26 - Added non-destructive write-testing,
2519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project *                       configurable blocks-at-once parameter,
2619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * 			 loading of badblocks list to avoid testing
273984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * 			 blocks known to be bad, multiple passes to
2819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * 			 make sure that no new blocks are added to the
2919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * 			 list.  (Work done by David Beattie)
3019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */
3119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
3219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#define _GNU_SOURCE /* for O_DIRECT */
3319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
343984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#ifndef O_LARGEFILE
353984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#define O_LARGEFILE 0
363984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#endif
373984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
3819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <errno.h>
3919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <fcntl.h>
4019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#ifdef HAVE_GETOPT_H
4119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <getopt.h>
4219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#else
4319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectextern char *optarg;
4419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectextern int optind;
4519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif
4619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <signal.h>
4719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <stdio.h>
4819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <stdlib.h>
4919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <string.h>
5019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <unistd.h>
5119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <setjmp.h>
5219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <time.h>
5319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <limits.h>
5419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
553984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#include <sys/time.h>
5619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <sys/ioctl.h>
5719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <sys/types.h>
5819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
5919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include "et/com_err.h"
6019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include "ext2fs/ext2_io.h"
6119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include "ext2fs/ext2_fs.h"
6219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include "ext2fs/ext2fs.h"
6319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include "nls-enable.h"
6419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
6519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectconst char * program_name = "badblocks";
6619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectconst char * done_string = N_("done                                \n");
6719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
6819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic int v_flag = 0;			/* verbose */
6919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic int w_flag = 0;			/* do r/w test: 0=no, 1=yes,
7019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					 * 2=non-destructive */
7119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic int s_flag = 0;			/* show progress of test */
7219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic int force = 0;			/* force check of mounted device */
7319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic int t_flag = 0;			/* number of test patterns */
7419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic int t_max = 0;			/* allocated test patterns */
753984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtstatic unsigned int *t_patts = NULL;	/* test patterns */
7619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic int current_O_DIRECT = 0;	/* Current status of O_DIRECT flag */
7719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic int exclusive_ok = 0;
783984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtstatic unsigned int max_bb = 0;		/* Abort test if more than this number of bad blocks has been encountered */
793984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtstatic unsigned int d_flag = 0;		/* delay factor between reads */
803984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtstatic struct timeval time_start;
8119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
8219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#define T_INC 32
8319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
843984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtunsigned int sys_page_size = 4096;
8519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
8619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic void usage(void)
8719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
883984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	fprintf(stderr, _(
893984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt"Usage: %s [-b block_size] [-i input_file] [-o output_file] [-svwnf]\n"
903984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt"       [-c blocks_at_once] [-d delay_factor_between_reads] [-e max_bad_blocks]\n"
913984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt"       [-p num_passes] [-t test_pattern [-t test_pattern [...]]]\n"
923984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt"       device [last_block [first_block]]\n"),
9319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		 program_name);
9419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	exit (1);
9519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
9619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
9719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic void exclusive_usage(void)
9819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
993984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	fprintf(stderr,
1003984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		_("%s: The -n and -w options are mutually exclusive.\n\n"),
10119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		program_name);
10219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	exit(1);
10319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
10419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
1053984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtstatic blk_t currently_testing = 0;
1063984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtstatic blk_t num_blocks = 0;
10719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic ext2_badblocks_list bb_list = NULL;
10819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic FILE *out;
10919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic blk_t next_bad = 0;
11019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic ext2_badblocks_iterate bb_iter = NULL;
11119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
11219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic void *allocate_buffer(size_t size)
11319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
11419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	void	*ret = 0;
1153984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
11619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#ifdef HAVE_POSIX_MEMALIGN
11719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (posix_memalign(&ret, sys_page_size, size) < 0)
11819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		ret = 0;
11919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#else
12019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#ifdef HAVE_MEMALIGN
12119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ret = memalign(sys_page_size, size);
12219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#else
12319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#ifdef HAVE_VALLOC
12419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ret = valloc(size);
12519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif /* HAVE_VALLOC */
1263984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#endif /* HAVE_MEMALIGN */
12719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif /* HAVE_POSIX_MEMALIGN */
12819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
12919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (!ret)
13019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		ret = malloc(size);
13119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
13219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	return ret;
13319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
13419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
13519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/*
13619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * This routine reports a new bad block.  If the bad block has already
13719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * been seen before, then it returns 0; otherwise it returns 1.
13819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */
1393984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtstatic int bb_output (blk_t bad)
14019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
14119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	errcode_t errcode;
14219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
14319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (ext2fs_badblocks_list_test(bb_list, bad))
14419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return 0;
14519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
1463984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	fprintf(out, "%lu\n", (unsigned long) bad);
14719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	fflush(out);
14819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
14919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	errcode = ext2fs_badblocks_list_add (bb_list, bad);
15019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (errcode) {
15119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		com_err (program_name, errcode, "adding to in-memory bad block list");
15219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		exit (1);
15319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
15419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
15519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	/* kludge:
1563984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	   increment the iteration through the bb_list if
15719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	   an element was just added before the current iteration
15819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	   position.  This should not cause next_bad to change. */
15919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (bb_iter && bad < next_bad)
16019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		ext2fs_badblocks_list_iterate (bb_iter, &next_bad);
16119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	return 1;
16219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
16319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
1643984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtstatic char *time_diff_format(struct timeval *tv1,
1653984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			      struct timeval *tv2, char *buf)
1663984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{
1673984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt        time_t	diff = (tv1->tv_sec - tv2->tv_sec);
1683984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	int	hr,min,sec;
1693984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
1703984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	sec = diff % 60;
1713984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	diff /= 60;
1723984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	min = diff % 60;
1733984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	hr = diff / 60;
1743984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
1753984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (hr)
1763984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		sprintf(buf, "%d:%02d:%02d", hr, min, sec);
1773984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	else
1783984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		sprintf(buf, "%d:%02d", min, sec);
1793984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	return buf;
1803984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt}
1813984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
1823984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtstatic float calc_percent(unsigned long current, unsigned long total) {
1833984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	float percent = 0.0;
1843984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (total <= 0)
1853984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		return percent;
1863984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (current >= total) {
1873984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		percent = 100.0;
1883984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	} else {
1893984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		percent=(100.0*(float)current/(float)total);
1903984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
1913984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	return percent;
1923984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt}
1933984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
19419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic void print_status(void)
19519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
1963984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	struct timeval time_end;
1973984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	char diff_buf[32], line_buf[128];
1983984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	int len;
1993984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
2003984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	gettimeofday(&time_end, 0);
2013984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	len = snprintf(line_buf, sizeof(line_buf),
2023984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		       _("%6.2f%% done, %s elapsed"),
2033984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		       calc_percent((unsigned long) currently_testing,
2043984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				    (unsigned long) num_blocks),
2053984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		       time_diff_format(&time_end, &time_start, diff_buf));
2063984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	fputs(line_buf, stderr);
2073984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	memset(line_buf, '\b', len);
2083984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	line_buf[len] = 0;
2093984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	fputs(line_buf, stderr);
21019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	fflush (stderr);
21119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
21219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
21319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic void alarm_intr(int alnum EXT2FS_ATTR((unused)))
21419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
21519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	signal (SIGALRM, alarm_intr);
21619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	alarm(1);
21719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (!num_blocks)
21819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return;
21919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	print_status();
22019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
22119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
22219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic void *terminate_addr = NULL;
22319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
22419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic void terminate_intr(int signo EXT2FS_ATTR((unused)))
22519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
2263984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	fflush(out);
2273984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	fprintf(stderr, "\n\nInterrupted at block %llu\n",
2283984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		(unsigned long long) currently_testing);
2293984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	fflush(stderr);
23019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (terminate_addr)
23119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		longjmp(terminate_addr,1);
23219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	exit(1);
23319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
23419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
23519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic void capture_terminate(jmp_buf term_addr)
23619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
23719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	terminate_addr = term_addr;
23819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	signal (SIGHUP, terminate_intr);
23919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	signal (SIGINT, terminate_intr);
24019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	signal (SIGPIPE, terminate_intr);
24119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	signal (SIGTERM, terminate_intr);
24219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	signal (SIGUSR1, terminate_intr);
24319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	signal (SIGUSR2, terminate_intr);
24419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
24519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
24619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic void uncapture_terminate(void)
24719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
24819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	terminate_addr = NULL;
24919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	signal (SIGHUP, SIG_DFL);
25019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	signal (SIGINT, SIG_DFL);
25119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	signal (SIGPIPE, SIG_DFL);
25219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	signal (SIGTERM, SIG_DFL);
25319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	signal (SIGUSR1, SIG_DFL);
25419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	signal (SIGUSR2, SIG_DFL);
25519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
25619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
25719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic void set_o_direct(int dev, unsigned char *buffer, size_t size,
2583984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			 blk_t current_block)
25919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
26019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#ifdef O_DIRECT
26119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	int new_flag = O_DIRECT;
26219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	int flag;
2633984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
26419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if ((((unsigned long) buffer & (sys_page_size - 1)) != 0) ||
26519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	    ((size & (sys_page_size - 1)) != 0) ||
26619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	    ((current_block & ((sys_page_size >> 9)-1)) != 0))
26719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		new_flag = 0;
26819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
26919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (new_flag != current_O_DIRECT) {
27019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	     /* printf("%s O_DIRECT\n", new_flag ? "Setting" : "Clearing"); */
27119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		flag = fcntl(dev, F_GETFL);
27219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (flag > 0) {
27319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			flag = (flag & ~O_DIRECT) | new_flag;
27419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			fcntl(dev, F_SETFL, flag);
27519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
27619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		current_O_DIRECT = new_flag;
27719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
27819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif
27919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
28019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
28119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
2823984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtstatic void pattern_fill(unsigned char *buffer, unsigned int pattern,
28319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			 size_t n)
28419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
28519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	unsigned int	i, nb;
28619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	unsigned char	bpattern[sizeof(pattern)], *ptr;
2873984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
2883984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (pattern == (unsigned int) ~0) {
28919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		for (ptr = buffer; ptr < buffer + n; ptr++) {
29019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			(*ptr) = random() % (1 << (8 * sizeof(char)));
29119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
29219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (s_flag | v_flag)
29319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			fputs(_("Testing with random pattern: "), stderr);
29419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	} else {
29519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		bpattern[0] = 0;
29619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		for (i = 0; i < sizeof(bpattern); i++) {
29719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			if (pattern == 0)
29819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				break;
29919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			bpattern[i] = pattern & 0xFF;
30019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			pattern = pattern >> 8;
30119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
30219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		nb = i ? (i-1) : 0;
30319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		for (ptr = buffer, i = nb; ptr < buffer + n; ptr++) {
30419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			*ptr = bpattern[i];
30519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			if (i == 0)
30619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				i = nb;
30719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			else
30819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				i--;
30919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
31019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (s_flag | v_flag) {
31119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			fputs(_("Testing with pattern 0x"), stderr);
31219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			for (i = 0; i <= nb; i++)
31319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				fprintf(stderr, "%02x", buffer[i]);
31419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			fputs(": ", stderr);
31519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
31619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
31719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
31819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
31919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/*
32019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Perform a read of a sequence of blocks; return the number of blocks
32119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project *    successfully sequentially read.
32219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */
3233984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtstatic int do_read (int dev, unsigned char * buffer, int try, int block_size,
3243984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		    blk_t current_block)
32519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
32619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	long got;
3273984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	struct timeval tv1, tv2;
3283984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#define NANOSEC (1000000000L)
3293984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#define MILISEC (1000L)
33019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
33119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	set_o_direct(dev, buffer, try * block_size, current_block);
33219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
33319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (v_flag > 1)
33419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		print_status();
33519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
33619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	/* Seek to the correct loc. */
33719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (ext2fs_llseek (dev, (ext2_loff_t) current_block * block_size,
33819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			 SEEK_SET) != (ext2_loff_t) current_block * block_size)
33919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		com_err (program_name, errno, _("during seek"));
34019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
34119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	/* Try the read */
3423984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (d_flag)
3433984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		gettimeofday(&tv1, NULL);
34419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	got = read (dev, buffer, try * block_size);
3453984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (d_flag)
3463984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		gettimeofday(&tv2, NULL);
34719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (got < 0)
3483984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		got = 0;
34919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (got & 511)
35019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		fprintf(stderr, _("Weird value (%ld) in do_read\n"), got);
35119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	got /= block_size;
3523984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (d_flag && got == try) {
3533984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#ifdef HAVE_NANOSLEEP
3543984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		struct timespec ts;
3553984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		ts.tv_sec = tv2.tv_sec - tv1.tv_sec;
3563984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		ts.tv_nsec = (tv2.tv_usec - tv1.tv_usec) * MILISEC;
3573984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (ts.tv_nsec < 0) {
3583984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			ts.tv_nsec += NANOSEC;
3593984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			ts.tv_sec -= 1;
3603984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		}
3613984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		/* increase/decrease the sleep time based on d_flag value */
3623984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		ts.tv_sec = ts.tv_sec * d_flag / 100;
3633984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		ts.tv_nsec = ts.tv_nsec * d_flag / 100;
3643984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (ts.tv_nsec > NANOSEC) {
3653984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			ts.tv_sec += ts.tv_nsec / NANOSEC;
3663984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			ts.tv_nsec %= NANOSEC;
3673984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		}
3683984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (ts.tv_sec || ts.tv_nsec)
3693984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			nanosleep(&ts, NULL);
3703984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#else
3713984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#ifdef HAVE_USLEEP
3723984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		struct timeval tv;
3733984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		tv.tv_sec = tv2.tv_sec - tv1.tv_sec;
3743984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		tv.tv_usec = tv2.tv_usec - tv1.tv_usec;
3753984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		tv.tv_sec = tv.tv_sec * d_flag / 100;
3763984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		tv.tv_usec = tv.tv_usec * d_flag / 100;
3773984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (tv.tv_usec > 1000000) {
3783984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			tv.tv_sec += tv.tv_usec / 1000000;
3793984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			tv.tv_usec %= 1000000;
3803984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		}
3813984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (tv.tv_sec)
3823984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			sleep(tv.tv_sec);
3833984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (tv.tv_usec)
3843984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			usleep(tv.tv_usec);
3853984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#endif
3863984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#endif
3873984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
38819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	return got;
38919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
39019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
39119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/*
39219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Perform a write of a sequence of blocks; return the number of blocks
39319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project *    successfully sequentially written.
39419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */
3953984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtstatic int do_write(int dev, unsigned char * buffer, int try, int block_size,
3963984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		    unsigned long current_block)
39719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
39819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	long got;
39919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
40019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	set_o_direct(dev, buffer, try * block_size, current_block);
40119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
40219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (v_flag > 1)
40319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		print_status();
40419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
40519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	/* Seek to the correct loc. */
40619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (ext2fs_llseek (dev, (ext2_loff_t) current_block * block_size,
40719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			 SEEK_SET) != (ext2_loff_t) current_block * block_size)
40819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		com_err (program_name, errno, _("during seek"));
40919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
41019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	/* Try the write */
41119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	got = write (dev, buffer, try * block_size);
41219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (got < 0)
4133984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		got = 0;
41419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (got & 511)
41519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		fprintf(stderr, "Weird value (%ld) in do_write\n", got);
41619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	got /= block_size;
41719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	return got;
41819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
41919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
42019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic int host_dev;
42119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
42219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic void flush_bufs(void)
42319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
42419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	errcode_t	retval;
42519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
42619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	retval = ext2fs_sync_device(host_dev, 1);
42719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (retval)
42819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		com_err(program_name, retval, _("during ext2fs_sync_device"));
42919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
43019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
4313984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtstatic unsigned int test_ro (int dev, blk_t last_block,
4323984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			     int block_size, blk_t first_block,
4333984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			     unsigned int blocks_at_once)
43419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
43519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	unsigned char * blkbuf;
43619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	int try;
4373984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	int got;
43819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	unsigned int bb_count = 0;
43919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	errcode_t errcode;
44019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
4413984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	/* set up abend handler */
4423984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	capture_terminate(NULL);
4433984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
44419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	errcode = ext2fs_badblocks_list_iterate_begin(bb_list,&bb_iter);
44519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (errcode) {
44619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		com_err (program_name, errcode,
44719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			 _("while beginning bad block list iteration"));
44819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		exit (1);
44919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
45019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	do {
45119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		ext2fs_badblocks_list_iterate (bb_iter, &next_bad);
4523984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	} while (next_bad && next_bad < first_block);
45319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
45419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (t_flag) {
45519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		blkbuf = allocate_buffer((blocks_at_once + 1) * block_size);
45619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	} else {
45719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		blkbuf = allocate_buffer(blocks_at_once * block_size);
45819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
45919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (!blkbuf)
46019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	{
46119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		com_err (program_name, ENOMEM, _("while allocating buffers"));
46219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		exit (1);
46319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
46419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (v_flag) {
4653984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		fprintf (stderr, _("Checking blocks %lu to %lu\n"),
4663984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			 (unsigned long) first_block,
4673984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			 (unsigned long) last_block - 1);
46819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
46919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (t_flag) {
47019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		fputs(_("Checking for bad blocks in read-only mode\n"), stderr);
47119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		pattern_fill(blkbuf + blocks_at_once * block_size,
47219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			     t_patts[0], block_size);
47319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
47419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	flush_bufs();
47519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	try = blocks_at_once;
4763984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	currently_testing = first_block;
47719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	num_blocks = last_block - 1;
47819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (!t_flag && (s_flag || v_flag)) {
47919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		fputs(_("Checking for bad blocks (read-only test): "), stderr);
48019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (v_flag <= 1)
48119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			alarm_intr(SIGALRM);
48219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
48319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	while (currently_testing < last_block)
48419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	{
4853984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (max_bb && bb_count >= max_bb) {
4863984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			if (s_flag || v_flag) {
4873984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				fputs(_("Too many bad blocks, aborting test\n"), stderr);
4883984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			}
4893984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			break;
4903984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		}
49119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (next_bad) {
49219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			if (currently_testing == next_bad) {
49319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				/* fprintf (out, "%lu\n", nextbad); */
49419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				ext2fs_badblocks_list_iterate (bb_iter, &next_bad);
49519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				currently_testing++;
49619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				continue;
49719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			}
49819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			else if (currently_testing + try > next_bad)
49919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				try = next_bad - currently_testing;
50019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
50119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (currently_testing + try > last_block)
50219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			try = last_block - currently_testing;
50319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		got = do_read (dev, blkbuf, try, block_size, currently_testing);
50419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (t_flag) {
50519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			/* test the comparison between all the
50619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			   blocks successfully read  */
50719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			int i;
50819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			for (i = 0; i < got; ++i)
50919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				if (memcmp (blkbuf+i*block_size,
51019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					    blkbuf+blocks_at_once*block_size,
51119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					    block_size))
51219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					bb_count += bb_output(currently_testing + i);
51319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
51419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		currently_testing += got;
51519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (got == try) {
51619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			try = blocks_at_once;
51719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			/* recover page-aligned offset for O_DIRECT */
5183984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			if ( (blocks_at_once >= sys_page_size >> 9)
51919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			     && (currently_testing % (sys_page_size >> 9)!= 0))
52019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				try -= (sys_page_size >> 9)
5213984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt					- (currently_testing
52219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					   % (sys_page_size >> 9));
52319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			continue;
52419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
52519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		else
52619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			try = 1;
52719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (got == 0) {
52819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			bb_count += bb_output(currently_testing++);
52919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
53019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
53119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	num_blocks = 0;
53219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	alarm(0);
53319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (s_flag || v_flag)
53419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		fputs(_(done_string), stderr);
53519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
53619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	fflush (stderr);
53719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	free (blkbuf);
53819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
53919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ext2fs_badblocks_list_iterate_end(bb_iter);
54019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
5413984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	uncapture_terminate();
5423984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
54319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	return bb_count;
54419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
54519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
5463984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtstatic unsigned int test_rw (int dev, blk_t last_block,
5473984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			     int block_size, blk_t first_block,
5483984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			     unsigned int blocks_at_once)
54919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
55019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	unsigned char *buffer, *read_buffer;
5513984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	const unsigned int patterns[] = {0xaa, 0x55, 0xff, 0x00};
5523984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	const unsigned int *pattern;
55319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	int i, try, got, nr_pattern, pat_idx;
55419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	unsigned int bb_count = 0;
55519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
5563984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	/* set up abend handler */
5573984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	capture_terminate(NULL);
5583984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
55919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	buffer = allocate_buffer(2 * blocks_at_once * block_size);
56019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	read_buffer = buffer + blocks_at_once * block_size;
5613984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
56219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (!buffer) {
56319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		com_err (program_name, ENOMEM, _("while allocating buffers"));
56419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		exit (1);
56519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
56619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
56719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	flush_bufs();
56819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
56919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (v_flag) {
5703984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		fputs(_("Checking for bad blocks in read-write mode\n"),
57119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		      stderr);
57219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		fprintf(stderr, _("From block %lu to %lu\n"),
5733984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			(unsigned long) first_block,
5743984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			(unsigned long) last_block - 1);
57519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
57619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (t_flag) {
57719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		pattern = t_patts;
57819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		nr_pattern = t_flag;
57919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	} else {
58019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		pattern = patterns;
58119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		nr_pattern = sizeof(patterns) / sizeof(patterns[0]);
58219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
58319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	for (pat_idx = 0; pat_idx < nr_pattern; pat_idx++) {
58419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		pattern_fill(buffer, pattern[pat_idx],
58519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			     blocks_at_once * block_size);
58619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		num_blocks = last_block - 1;
5873984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		currently_testing = first_block;
58819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (s_flag && v_flag <= 1)
58919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			alarm_intr(SIGALRM);
59019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
59119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		try = blocks_at_once;
59219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		while (currently_testing < last_block) {
5933984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			if (max_bb && bb_count >= max_bb) {
5943984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				if (s_flag || v_flag) {
5953984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt					fputs(_("Too many bad blocks, aborting test\n"), stderr);
5963984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				}
5973984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				break;
5983984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			}
59919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			if (currently_testing + try > last_block)
60019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				try = last_block - currently_testing;
60119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			got = do_write(dev, buffer, try, block_size,
60219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					currently_testing);
60319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			if (v_flag > 1)
60419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				print_status();
60519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
60619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			currently_testing += got;
60719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			if (got == try) {
60819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				try = blocks_at_once;
60919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				/* recover page-aligned offset for O_DIRECT */
6103984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				if ( (blocks_at_once >= sys_page_size >> 9)
6113984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				     && (currently_testing %
61219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					 (sys_page_size >> 9)!= 0))
61319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					try -= (sys_page_size >> 9)
6143984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt						- (currently_testing
61519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project						   % (sys_page_size >> 9));
61619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				continue;
61719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			} else
61819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				try = 1;
61919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			if (got == 0) {
62019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				bb_count += bb_output(currently_testing++);
62119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			}
62219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
6233984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
62419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		num_blocks = 0;
62519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		alarm (0);
62619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (s_flag | v_flag)
62719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			fputs(_(done_string), stderr);
62819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		flush_bufs();
62919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (s_flag | v_flag)
63019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			fputs(_("Reading and comparing: "), stderr);
63119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		num_blocks = last_block;
6323984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		currently_testing = first_block;
63319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (s_flag && v_flag <= 1)
63419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			alarm_intr(SIGALRM);
63519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
63619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		try = blocks_at_once;
63719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		while (currently_testing < last_block) {
6383984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			if (max_bb && bb_count >= max_bb) {
6393984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				if (s_flag || v_flag) {
6403984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt					fputs(_("Too many bad blocks, aborting test\n"), stderr);
6413984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				}
6423984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				break;
6433984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			}
64419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			if (currently_testing + try > last_block)
64519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				try = last_block - currently_testing;
64619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			got = do_read (dev, read_buffer, try, block_size,
64719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				       currently_testing);
64819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			if (got == 0) {
64919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				bb_count += bb_output(currently_testing++);
65019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				continue;
65119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			}
65219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			for (i=0; i < got; i++) {
65319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				if (memcmp(read_buffer + i * block_size,
65419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					   buffer + i * block_size,
65519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					   block_size))
65619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					bb_count += bb_output(currently_testing+i);
65719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			}
65819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			currently_testing += got;
65919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			/* recover page-aligned offset for O_DIRECT */
6603984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			if ( (blocks_at_once >= sys_page_size >> 9)
66119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			     && (currently_testing % (sys_page_size >> 9)!= 0))
66219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				try = blocks_at_once - (sys_page_size >> 9)
6633984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt					- (currently_testing
66419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					   % (sys_page_size >> 9));
66519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			else
66619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				try = blocks_at_once;
66719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			if (v_flag > 1)
66819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				print_status();
66919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
6703984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
67119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		num_blocks = 0;
67219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		alarm (0);
67319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (s_flag | v_flag)
67419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			fputs(_(done_string), stderr);
67519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		flush_bufs();
67619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
67719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	uncapture_terminate();
67819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	free(buffer);
67919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	return bb_count;
68019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
68119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
68219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstruct saved_blk_record {
68319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	blk_t	block;
68419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	int	num;
68519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project};
68619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
6873984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtstatic unsigned int test_nd (int dev, blk_t last_block,
6883984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			     int block_size, blk_t first_block,
6893984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			     unsigned int blocks_at_once)
69019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
69119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	unsigned char *blkbuf, *save_ptr, *test_ptr, *read_ptr;
69219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	unsigned char *test_base, *save_base, *read_base;
69319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	int try, i;
6943984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	const unsigned int patterns[] = { ~0 };
6953984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	const unsigned int *pattern;
69619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	int nr_pattern, pat_idx;
6973984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	int got, used2, written;
6983984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	blk_t save_currently_testing;
69919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	struct saved_blk_record *test_record;
70019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	/* This is static to prevent being clobbered by the longjmp */
70119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	static int num_saved;
70219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	jmp_buf terminate_env;
70319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	errcode_t errcode;
70419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	unsigned long buf_used;
70519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	static unsigned int bb_count;
70619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
70719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	bb_count = 0;
70819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	errcode = ext2fs_badblocks_list_iterate_begin(bb_list,&bb_iter);
70919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (errcode) {
71019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		com_err (program_name, errcode,
71119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			 _("while beginning bad block list iteration"));
71219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		exit (1);
71319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
71419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	do {
71519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		ext2fs_badblocks_list_iterate (bb_iter, &next_bad);
7163984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	} while (next_bad && next_bad < first_block);
71719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
71819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	blkbuf = allocate_buffer(3 * blocks_at_once * block_size);
71919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	test_record = malloc (blocks_at_once*sizeof(struct saved_blk_record));
72019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (!blkbuf || !test_record) {
72119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		com_err(program_name, ENOMEM, _("while allocating buffers"));
72219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		exit (1);
72319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
72419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
72519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	save_base = blkbuf;
72619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	test_base = blkbuf + (blocks_at_once * block_size);
72719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	read_base = blkbuf + (2 * blocks_at_once * block_size);
7283984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
72919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	num_saved = 0;
73019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
73119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	flush_bufs();
73219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (v_flag) {
73319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	    fputs(_("Checking for bad blocks in non-destructive read-write mode\n"), stderr);
7343984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	    fprintf (stderr, _("From block %lu to %lu\n"),
7353984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		     (unsigned long) first_block,
7363984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		     (unsigned long) last_block - 1);
73719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
73819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (s_flag || v_flag > 1) {
73919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		fputs(_("Checking for bad blocks (non-destructive read-write test)\n"), stderr);
74019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
74119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (setjmp(terminate_env)) {
74219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		/*
74319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		 * Abnormal termination by a signal is handled here.
74419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		 */
74519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		signal (SIGALRM, SIG_IGN);
74619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		fputs(_("\nInterrupt caught, cleaning up\n"), stderr);
74719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
74819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		save_ptr = save_base;
74919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		for (i=0; i < num_saved; i++) {
75019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			do_write(dev, save_ptr, test_record[i].num,
75119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				 block_size, test_record[i].block);
75219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			save_ptr += test_record[i].num * block_size;
75319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
75419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		fflush (out);
75519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		exit(1);
75619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
7573984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
75819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	/* set up abend handler */
75919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	capture_terminate(terminate_env);
76019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
76119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (t_flag) {
76219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		pattern = t_patts;
76319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		nr_pattern = t_flag;
76419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	} else {
76519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		pattern = patterns;
76619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		nr_pattern = sizeof(patterns) / sizeof(patterns[0]);
76719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
76819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	for (pat_idx = 0; pat_idx < nr_pattern; pat_idx++) {
76919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		pattern_fill(test_base, pattern[pat_idx],
77019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			     blocks_at_once * block_size);
77119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
77219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		buf_used = 0;
77319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		bb_count = 0;
77419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		save_ptr = save_base;
77519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		test_ptr = test_base;
7763984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		currently_testing = first_block;
77719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		num_blocks = last_block - 1;
77819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (s_flag && v_flag <= 1)
77919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			alarm_intr(SIGALRM);
78019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
78119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		while (currently_testing < last_block) {
7823984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			if (max_bb && bb_count >= max_bb) {
7833984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				if (s_flag || v_flag) {
7843984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt					fputs(_("Too many bad blocks, aborting test\n"), stderr);
7853984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				}
7863984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				break;
7873984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			}
78819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			got = try = blocks_at_once - buf_used;
78919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			if (next_bad) {
79019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				if (currently_testing == next_bad) {
79119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					/* fprintf (out, "%lu\n", nextbad); */
79219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					ext2fs_badblocks_list_iterate (bb_iter, &next_bad);
79319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					currently_testing++;
79419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					goto check_for_more;
79519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				}
79619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				else if (currently_testing + try > next_bad)
79719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					try = next_bad - currently_testing;
79819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			}
79919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			if (currently_testing + try > last_block)
80019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				try = last_block - currently_testing;
80119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			got = do_read (dev, save_ptr, try, block_size,
80219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				       currently_testing);
80319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			if (got == 0) {
80419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				/* First block must have been bad. */
80519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				bb_count += bb_output(currently_testing++);
80619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				goto check_for_more;
80719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			}
80819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
80919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			/*
81019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			 * Note the fact that we've saved this much data
81119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			 * *before* we overwrite it with test data
81219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			 */
81319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			test_record[num_saved].block = currently_testing;
81419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			test_record[num_saved].num = got;
81519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			num_saved++;
81619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
81719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			/* Write the test data */
81819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			written = do_write (dev, test_ptr, got, block_size,
81919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					    currently_testing);
82019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			if (written != got)
82119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				com_err (program_name, errno,
82219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					 _("during test data write, block %lu"),
8233984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt					 (unsigned long) currently_testing +
8243984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt					 written);
82519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
82619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			buf_used += got;
82719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			save_ptr += got * block_size;
82819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			test_ptr += got * block_size;
82919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			currently_testing += got;
83019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			if (got != try)
83119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				bb_count += bb_output(currently_testing++);
83219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
83319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		check_for_more:
83419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			/*
83519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			 * If there's room for more blocks to be tested this
83619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			 * around, and we're not done yet testing the disk, go
83719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			 * back and get some more blocks.
83819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			 */
83919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			if ((buf_used != blocks_at_once) &&
84019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			    (currently_testing < last_block))
84119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				continue;
84219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
84319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			flush_bufs();
84419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			save_currently_testing = currently_testing;
84519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
84619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			/*
84719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			 * for each contiguous block that we read into the
84819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			 * buffer (and wrote test data into afterwards), read
84919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			 * it back (looping if necessary, to get past newly
85019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			 * discovered unreadable blocks, of which there should
85119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			 * be none, but with a hard drive which is unreliable,
85219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			 * it has happened), and compare with the test data
85319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			 * that was written; output to the bad block list if
85419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			 * it doesn't match.
85519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			 */
85619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			used2 = 0;
85719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			save_ptr = save_base;
85819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			test_ptr = test_base;
85919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			read_ptr = read_base;
86019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			try = 0;
86119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
86219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			while (1) {
86319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				if (try == 0) {
86419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					if (used2 >= num_saved)
86519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project						break;
86619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					currently_testing = test_record[used2].block;
86719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					try = test_record[used2].num;
86819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					used2++;
86919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				}
8703984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
87119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				got = do_read (dev, read_ptr, try,
87219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					       block_size, currently_testing);
87319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
87419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				/* test the comparison between all the
87519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				   blocks successfully read  */
87619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				for (i = 0; i < got; ++i)
87719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					if (memcmp (test_ptr+i*block_size,
87819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project						    read_ptr+i*block_size, block_size))
87919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project						bb_count += bb_output(currently_testing + i);
88019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				if (got < try) {
88119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					bb_count += bb_output(currently_testing + got);
88219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					got++;
88319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				}
8843984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
88519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				/* write back original data */
88619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				do_write (dev, save_ptr, got,
88719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					  block_size, currently_testing);
88819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				save_ptr += got * block_size;
88919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
89019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				currently_testing += got;
89119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				test_ptr += got * block_size;
89219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				read_ptr += got * block_size;
89319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				try -= got;
89419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			}
89519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
89619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			/* empty the buffer so it can be reused */
89719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			num_saved = 0;
89819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			buf_used = 0;
89919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			save_ptr = save_base;
90019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			test_ptr = test_base;
90119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			currently_testing = save_currently_testing;
90219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
90319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		num_blocks = 0;
90419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		alarm(0);
90519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (s_flag || v_flag > 1)
90619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			fputs(_(done_string), stderr);
90719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
90819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		flush_bufs();
90919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
91019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	uncapture_terminate();
91119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	fflush(stderr);
91219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	free(blkbuf);
91319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	free(test_record);
91419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
91519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	ext2fs_badblocks_list_iterate_end(bb_iter);
91619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
91719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	return bb_count;
91819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
91919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
92019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic void check_mount(char *device_name)
92119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
92219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	errcode_t	retval;
92319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	int		mount_flags;
92419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
92519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	retval = ext2fs_check_if_mounted(device_name, &mount_flags);
92619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (retval) {
92719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		com_err("ext2fs_check_if_mount", retval,
92819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			_("while determining whether %s is mounted."),
92919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			device_name);
93019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		return;
93119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
93219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (mount_flags & EXT2_MF_MOUNTED) {
93319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		fprintf(stderr, _("%s is mounted; "), device_name);
93419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (force) {
93519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			fputs(_("badblocks forced anyway.  "
93619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				"Hope /etc/mtab is incorrect.\n"), stderr);
93719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			return;
93819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
93919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	abort_badblocks:
94019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		fputs(_("it's not safe to run badblocks!\n"), stderr);
94119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		exit(1);
94219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
94319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
94419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if ((mount_flags & EXT2_MF_BUSY) && !exclusive_ok) {
94519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		fprintf(stderr, _("%s is apparently in use by the system; "),
94619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			device_name);
94719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (force)
94819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			fputs(_("badblocks forced anyway.\n"), stderr);
94919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		else
95019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			goto abort_badblocks;
95119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
95219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
95319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
95419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
9553984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt/*
9563984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * This function will convert a string to an unsigned long, printing
9573984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * an error message if it fails, and returning success or failure in err.
9583984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt */
9593984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidtstatic unsigned int parse_uint(const char *str, const char *descr)
9603984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt{
9613984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	char		*tmp;
9623984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	unsigned long	ret;
9633984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
9643984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	errno = 0;
9653984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	ret = strtoul(str, &tmp, 0);
9663984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (*tmp || errno || (ret > UINT_MAX) ||
9673984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	    (ret == ULONG_MAX && errno == ERANGE)) {
9683984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		com_err (program_name, 0, _("invalid %s - %s"), descr, str);
9693984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		exit (1);
9703984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	}
9713984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	return ret;
9723984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt}
97319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
97419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectint main (int argc, char ** argv)
97519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{
97619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	int c;
97719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	char * device_name;
97819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	char * host_device_name = NULL;
97919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	char * input_file = NULL;
98019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	char * output_file = NULL;
98119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	FILE * in = NULL;
98219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	int block_size = 1024;
9833984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	unsigned int blocks_at_once = 64;
9843984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	blk_t last_block, first_block;
98519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	int num_passes = 0;
98619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	int passes_clean = 0;
98719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	int dev;
98819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	errcode_t errcode;
9893984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	unsigned int pattern;
9903984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	unsigned int (*test_func)(int, blk_t,
9913984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				  int, blk_t,
9923984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				  unsigned int);
9933984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	int open_flag;
99419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	long sysval;
99519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
99619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	setbuf(stdout, NULL);
99719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	setbuf(stderr, NULL);
99819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#ifdef ENABLE_NLS
99919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	setlocale(LC_MESSAGES, "");
100019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	setlocale(LC_CTYPE, "");
100119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
100219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	textdomain(NLS_CAT_NAME);
100319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif
100419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	srandom((unsigned int)time(NULL));  /* simple randomness is enough */
100519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	test_func = test_ro;
100619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
100719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	/* Determine the system page size if possible */
100819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#ifdef HAVE_SYSCONF
100919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#if (!defined(_SC_PAGESIZE) && defined(_SC_PAGE_SIZE))
101019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#define _SC_PAGESIZE _SC_PAGE_SIZE
101119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif
101219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#ifdef _SC_PAGESIZE
101319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	sysval = sysconf(_SC_PAGESIZE);
101419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (sysval > 0)
101519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		sys_page_size = sysval;
101619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif /* _SC_PAGESIZE */
101719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif /* HAVE_SYSCONF */
10183984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
101919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (argc && *argv)
102019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		program_name = *argv;
10213984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	while ((c = getopt (argc, argv, "b:d:e:fi:o:svwnc:p:h:t:X")) != EOF) {
102219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		switch (c) {
102319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		case 'b':
10243984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			block_size = parse_uint(optarg, "block size");
102519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			break;
102619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		case 'f':
102719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			force++;
102819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			break;
102919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		case 'i':
103019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			input_file = optarg;
103119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			break;
103219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		case 'o':
103319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			output_file = optarg;
103419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			break;
103519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		case 's':
103619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			s_flag = 1;
103719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			break;
103819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		case 'v':
103919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			v_flag++;
104019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			break;
104119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		case 'w':
104219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			if (w_flag)
104319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				exclusive_usage();
104419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			test_func = test_rw;
104519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			w_flag = 1;
104619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			break;
104719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		case 'n':
104819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			if (w_flag)
104919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				exclusive_usage();
105019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			test_func = test_nd;
105119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			w_flag = 2;
105219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			break;
105319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		case 'c':
10543984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			blocks_at_once = parse_uint(optarg, "blocks at once");
10553984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			break;
10563984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		case 'e':
10573984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			max_bb = parse_uint(optarg, "max bad block count");
10583984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			break;
10593984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		case 'd':
10603984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			d_flag = parse_uint(optarg, "read delay factor");
106119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			break;
106219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		case 'p':
10633984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt			num_passes = parse_uint(optarg,
10643984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt						"number of clean passes");
106519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			break;
106619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		case 'h':
106719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			host_device_name = optarg;
106819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			break;
106919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		case 't':
107019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			if (t_flag + 1 > t_max) {
10713984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				unsigned int *t_patts_new;
107219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
10733984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				t_patts_new = realloc(t_patts, sizeof(int) *
10743984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt						      (t_max + T_INC));
107519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				if (!t_patts_new) {
107619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					com_err(program_name, ENOMEM,
107719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project						_("can't allocate memory for "
107819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project						  "test_pattern - %s"),
107919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project						optarg);
108019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					exit(1);
108119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				}
108219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				t_patts = t_patts_new;
108319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				t_max += T_INC;
108419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			}
108519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			if (!strcmp(optarg, "r") || !strcmp(optarg,"random")) {
108619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				t_patts[t_flag++] = ~0;
108719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			} else {
10883984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				pattern = parse_uint(optarg, "test pattern");
10893984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				if (pattern == (unsigned int) ~0)
109019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					pattern = 0xffff;
109119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				t_patts[t_flag++] = pattern;
109219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			}
109319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			break;
109419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		case 'X':
109519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			exclusive_ok++;
109619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			break;
109719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		default:
109819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			usage();
109919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
110019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
110119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (!w_flag) {
110219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (t_flag > 1) {
110319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			com_err(program_name, 0,
110419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			_("Maximum of one test_pattern may be specified "
110519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			  "in read-only mode"));
110619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			exit(1);
110719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
11083984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		if (t_patts && (t_patts[0] == (unsigned int) ~0)) {
110919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			com_err(program_name, 0,
111019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			_("Random test_pattern is not allowed "
111119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			  "in read-only mode"));
111219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			exit(1);
111319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
111419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
111519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (optind > argc - 1)
111619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		usage();
111719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	device_name = argv[optind++];
111819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (optind > argc - 1) {
111919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		errcode = ext2fs_get_device_size(device_name,
112019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project						 block_size,
112119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project						 &last_block);
112219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (errcode == EXT2_ET_UNIMPLEMENTED) {
112319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			com_err(program_name, 0,
112419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				_("Couldn't determine device size; you "
112519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				  "must specify\nthe size manually\n"));
112619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			exit(1);
112719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
112819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (errcode) {
112919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			com_err(program_name, errcode,
113019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				_("while trying to determine device size"));
113119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			exit(1);
113219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
113319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	} else {
113419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		errno = 0;
11353984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		last_block = parse_uint(argv[optind], _("last block"));
113619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		last_block++;
113719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		optind++;
113819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
113919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (optind <= argc-1) {
114019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		errno = 0;
11413984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		first_block = parse_uint(argv[optind], _("first block"));
11423984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	} else first_block = 0;
11433984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	if (first_block >= last_block) {
11443984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	    com_err (program_name, 0, _("invalid starting block (%lu): must be less than %lu"),
11453984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt		     (unsigned long) first_block, (unsigned long) last_block);
114619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	    exit (1);
114719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
114819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (w_flag)
114919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		check_mount(device_name);
11503984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
11513984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	gettimeofday(&time_start, 0);
11523984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	open_flag = O_LARGEFILE | (w_flag ? O_RDWR : O_RDONLY);
115319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	dev = open (device_name, open_flag);
115419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (dev == -1) {
115519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		com_err (program_name, errno, _("while trying to open %s"),
115619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			 device_name);
115719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		exit (1);
115819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
115919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (host_device_name) {
116019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		host_dev = open (host_device_name, open_flag);
116119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (host_dev == -1) {
116219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			com_err (program_name, errno,
116319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				 _("while trying to open %s"),
116419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				 host_device_name);
116519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			exit (1);
116619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
116719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	} else
116819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		host_dev = dev;
116919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (input_file) {
117019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (strcmp (input_file, "-") == 0)
117119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			in = stdin;
117219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		else {
117319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			in = fopen (input_file, "r");
117419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			if (in == NULL)
117519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			{
117619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				com_err (program_name, errno,
117719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					 _("while trying to open %s"),
117819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					 input_file);
117919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				exit (1);
118019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			}
118119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
118219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
118319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (output_file && strcmp (output_file, "-") != 0)
118419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	{
118519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		out = fopen (output_file, "w");
118619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (out == NULL)
118719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		{
118819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			com_err (program_name, errno,
118919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				 _("while trying to open %s"),
119019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				 output_file);
119119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			exit (1);
119219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
119319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
119419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	else
119519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		out = stdout;
119619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
119719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	errcode = ext2fs_badblocks_list_create(&bb_list,0);
119819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (errcode) {
119919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		com_err (program_name, errcode,
120019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			 _("while creating in-memory bad blocks list"));
120119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		exit (1);
120219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
120319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
120419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (in) {
120519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		for(;;) {
120619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			switch(fscanf (in, "%u\n", &next_bad)) {
120719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				case 0:
120819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					com_err (program_name, 0, "input file - bad format");
120919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					exit (1);
121019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				case EOF:
121119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					break;
121219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				default:
121319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					errcode = ext2fs_badblocks_list_add(bb_list,next_bad);
121419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					if (errcode) {
121519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project						com_err (program_name, errcode, _("while adding to in-memory bad block list"));
121619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project						exit (1);
121719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					}
121819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project					continue;
121919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			}
122019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			break;
122119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		}
122219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
122319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (in != stdin)
122419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			fclose (in);
122519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	}
122619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
122719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	do {
122819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		unsigned int bb_count;
122919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
123019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		bb_count = test_func(dev, last_block, block_size,
12313984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				     first_block, blocks_at_once);
123219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (bb_count)
123319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			passes_clean = 0;
123419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		else
123519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			++passes_clean;
12363984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt
123719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		if (v_flag)
123819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project			fprintf(stderr,
12393984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt				_("Pass completed, %u bad blocks found.\n"),
124019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project				bb_count);
124119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
124219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	} while (passes_clean < num_passes);
124319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
124419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	close (dev);
124519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	if (out != stdout)
124619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project		fclose (out);
12473984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt	free(t_patts);
124819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project	return 0;
124919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}
125019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project
1251