badblocks.c revision 818180cdfcff84b9048ecdc5dc86323f0fefba24
13839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 23839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * badblocks.c - Bad blocks checker 33839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * 43839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Copyright (C) 1992, 1993, 1994 Remy Card <card@masi.ibp.fr> 53839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Laboratoire MASI, Institut Blaise Pascal 63839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Universite Pierre et Marie Curie (Paris VI) 73839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * 819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * Copyright 1995, 1996, 1997 by Theodore Ts'o 919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * 103839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * This file is based on the minix file system programs fsck and mkfs 113839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * written and copyrighted by Linus Torvalds <Linus.Torvalds@cs.helsinki.fi> 1219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * 1319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * %Begin-Header% 1419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * This file may be redistributed under the terms of the GNU Public 1519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * License. 1619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * %End-Header% 173839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 183839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 193839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 203839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * History: 213839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * 93/05/26 - Creation from e2fsck 223839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * 94/02/27 - Made a separate bad blocks checker 233839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 243839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 253839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <errno.h> 263839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <fcntl.h> 27a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o#ifdef HAVE_GETOPT_H 283839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <getopt.h> 29a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o#endif 303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <signal.h> 313839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <stdio.h> 323839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <stdlib.h> 333839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <string.h> 343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <unistd.h> 353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 363839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <sys/ioctl.h> 37f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#include <sys/types.h> 383839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 39a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o#if HAVE_LINUX_FS_H 403839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <linux/fd.h> 413839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <linux/fs.h> 42a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o#endif 433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 443839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include "et/com_err.h" 45d40259fd552d942903f2fd0b426c75a5c2516017Theodore Ts'o#include "ext2fs/ext2_io.h" 463839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 473839e65723771b85975f4263102dd3ceec4523cTheodore Ts'oconst char * program_name = "badblocks"; 483839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 493839e65723771b85975f4263102dd3ceec4523cTheodore Ts'oint v_flag = 0; /* verbose */ 503839e65723771b85975f4263102dd3ceec4523cTheodore Ts'oint w_flag = 0; /* do r/w test */ 513839e65723771b85975f4263102dd3ceec4523cTheodore Ts'oint s_flag = 0; /* show progress of test */ 523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 53818180cdfcff84b9048ecdc5dc86323f0fefba24Theodore Ts'ostatic void usage(void) 543839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 55f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o fprintf (stderr, "Usage: %s [-b block_size] [-o output_file] [-svw] device blocks_count\n [start_count]\n", 563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o program_name); 573839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o exit (1); 583839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 6019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'ostatic unsigned long currently_testing = 0; 6119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'ostatic unsigned long num_blocks = 0; 6219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 6319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'ostatic void print_status(void) 6419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o{ 6519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o fprintf(stderr, "%9ld/%9ld", currently_testing, num_blocks); 6619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o fprintf(stderr, "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"); 6719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o fflush (stderr); 6819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o} 6919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 7019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'ostatic void alarm_intr (int alnum) 7119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o{ 7219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o signal (SIGALRM, alarm_intr); 7319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o alarm(1); 7419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (!num_blocks) 7519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o return; 7619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o fprintf(stderr, "%9ld/%9ld", currently_testing, num_blocks); 7719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o fprintf(stderr, "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"); 7819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o fflush (stderr); 7919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o} 8019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 813839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 823839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Perform a test of a block; return the number of blocks readable/writeable. 833839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 843839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic long do_test (int dev, char * buffer, int try, unsigned long block_size, 853839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o unsigned long current_block) 863839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 873839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o long got; 883839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 8919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (v_flag > 1) 9019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o print_status(); 9119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 923839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* Seek to the correct loc. */ 9319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (ext2fs_llseek (dev, (ext2_loff_t) current_block * block_size, 94f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o SEEK_SET) != (ext2_loff_t) current_block * block_size) 95f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o com_err (program_name, errno, "during seek"); 963839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 973839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* Try the read */ 983839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o got = read (dev, buffer, try * block_size); 993839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (got < 0) 1003839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o got = 0; 1013839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (got & (block_size - 1)) 102f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o fprintf (stderr, 103f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o "Weird value (%ld) in do_test: probably bugs\n", 104f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o got); 1053839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o got /= block_size; 1063839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return got; 1073839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 1083839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 109a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'ostatic void flush_bufs (int dev, int sync) 110a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o{ 111a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o if (v_flag 112a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o#if !defined (BLKFLSBUF) && !defined (FDFLUSH) 113a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o && sync 114a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o#endif 115a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o ) 116a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o fprintf (stderr, "Flushing buffers\n"); 117a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o 118a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o if (sync && fsync (dev) == -1) 119a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o com_err (program_name, errno, "during fsync"); 120a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o 121a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o#ifdef BLKLSBUF 122a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o ioctl (dev, BLKFLSBUF, 0); /* In case this is a HD */ 123a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o#endif 124a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o#ifdef FDFLUSH 125a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o ioctl (dev, FDFLUSH, 0); /* In case this is floppy */ 126a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o#endif 127a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o} 128a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o 1293839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic void test_ro (int dev, unsigned long blocks_count, 130f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o unsigned long block_size, FILE * out, 131f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o unsigned long from_count) 1323839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 1333839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#define TEST_BUFFER_BLOCKS 16 1343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o char * blkbuf; 1353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int try; 1363839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o long got; 1373839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1383839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o blkbuf = malloc (TEST_BUFFER_BLOCKS * block_size); 1393839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (!blkbuf) 1403839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o { 1413839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o com_err (program_name, ENOMEM, "while allocating buffers"); 1423839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o exit (1); 1433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 144a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o flush_bufs (dev, 0); 145f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (v_flag) { 146f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o fprintf (stderr, 147f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o "Checking for bad blocks in read-only mode\n"); 148f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o fprintf (stderr, "From block %lu to %lu\n", from_count, blocks_count); 149f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o } 1503839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o try = TEST_BUFFER_BLOCKS; 151f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o currently_testing = from_count; 1523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o num_blocks = blocks_count; 15319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (s_flag || v_flag > 1) { 1543839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o fprintf(stderr, "Checking for bad blocks (read-only test): "); 15519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (v_flag <= 1) 15619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o alarm_intr(SIGALRM); 1573839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 1583839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o while (currently_testing < blocks_count) 1593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o { 1603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (currently_testing + try > blocks_count) 1613839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o try = blocks_count - currently_testing; 1623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o got = do_test (dev, blkbuf, try, block_size, currently_testing); 1633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o currently_testing += got; 1643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (got == try) { 1653839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o try = TEST_BUFFER_BLOCKS; 1663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o continue; 1673839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 1683839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o else 1693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o try = 1; 1703839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (got == 0) 1713839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o fprintf (out, "%lu\n", currently_testing++); 1723839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 1733839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o num_blocks = 0; 1743839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o alarm(0); 17519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (s_flag || v_flag > 1) 176f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o fprintf(stderr, "done \n"); 177f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o fflush (stderr); 1783839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o free (blkbuf); 1793839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 1803839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1813839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic void test_rw (int dev, unsigned long blocks_count, 182f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o unsigned long block_size, FILE * out, 183f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o unsigned long from_count) 1843839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 1853839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int i; 1863839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o char * buffer; 1873839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o unsigned char pattern[] = {0xaa, 0x55, 0xff, 0x00}; 1883839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1893839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o buffer = malloc (2 * block_size); 1903839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (!buffer) 1913839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o { 1923839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o com_err (program_name, ENOMEM, "while allocating buffers"); 1933839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o exit (1); 1943839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 1953839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 196a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o flush_bufs (dev, 0); 197a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o 19819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (v_flag) { 19919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o fprintf(stderr, 20019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o "Checking for bad blocks in read-write mode\n"); 20119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o fprintf(stderr, "From block %lu to %lu\n", 20219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o from_count, blocks_count); 20319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o } 20419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o for (i = 0; i < sizeof (pattern); i++) { 2053839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o memset (buffer, pattern[i], block_size); 206f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (s_flag | v_flag) 207f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o fprintf (stderr, "Writing pattern 0x%08x: ", 2083839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o *((int *) buffer)); 209f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o num_blocks = blocks_count; 210f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o currently_testing = from_count; 21119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (s_flag && v_flag <= 1) 212f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o alarm_intr(SIGALRM); 213f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o for (; 214f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o currently_testing < blocks_count; 215f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o currently_testing++) 2163839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o { 21719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (ext2fs_llseek (dev, (ext2_loff_t) currently_testing * 218f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o block_size, SEEK_SET) != 219f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o (ext2_loff_t) currently_testing * block_size) 2203839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o com_err (program_name, errno, 221f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o "during seek on block %d", 222f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o currently_testing); 22319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (v_flag > 1) 22419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o print_status(); 2253839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o write (dev, buffer, block_size); 2263839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 227f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o num_blocks = 0; 228f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o alarm (0); 229f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (s_flag | v_flag) 230f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o fprintf(stderr, "done \n"); 231a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o flush_bufs (dev, 1); 232f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (s_flag | v_flag) 233f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o fprintf (stderr, "Reading and comparing: "); 234f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o num_blocks = blocks_count; 235f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o currently_testing = from_count; 23619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (s_flag && v_flag <= 1) 237f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o alarm_intr(SIGALRM); 238f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o for (; 239f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o currently_testing < blocks_count; 240f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o currently_testing++) 2413839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o { 24219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (ext2fs_llseek (dev, (ext2_loff_t) currently_testing * 243f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o block_size, SEEK_SET) != 244f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o (ext2_loff_t) currently_testing * block_size) 2453839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o com_err (program_name, errno, 246f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o "during seek on block %d", 247f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o currently_testing); 24819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (v_flag > 1) 24919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o print_status(); 2503839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (read (dev, buffer + block_size, block_size) < block_size) 251f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o fprintf (out, "%ld\n", currently_testing); 2523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o else if (memcmp (buffer, buffer + block_size, block_size)) 253f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o fprintf (out, "%ld\n", currently_testing); 2543839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 255f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o num_blocks = 0; 256f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o alarm (0); 257f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (s_flag | v_flag) 258f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o fprintf(stderr, "done \n"); 259a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o flush_bufs (dev, 0); 2603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 2613839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 2623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 26300e5433eb5e9f70f485968b809fdcf297d7fe7b9Theodore Ts'oint main (int argc, char ** argv) 2643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 265519149fb458b0fa69c10fecd83fae42e838cf01dTheodore Ts'o int c; 2663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o char * tmp; 2673839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o char * device_name; 2683839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o char * output_file = NULL; 2693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o FILE * out; 2703839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o unsigned long block_size = 1024; 271f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o unsigned long blocks_count, from_count; 2723839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int dev; 2733839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 2743839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o setbuf(stdout, NULL); 2753839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o setbuf(stderr, NULL); 2763839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (argc && *argv) 2773839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o program_name = *argv; 2783839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o while ((c = getopt (argc, argv, "b:o:svw")) != EOF) { 2793839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o switch (c) { 2803839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o case 'b': 2813839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o block_size = strtoul (optarg, &tmp, 0); 2823839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (*tmp || block_size > 4096) { 2833839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o com_err (program_name, 0, 2843839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o "bad block size - %s", optarg); 2853839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o exit (1); 2863839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 2873839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o break; 2883839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o case 'o': 2893839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o output_file = optarg; 2903839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o break; 2913839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o case 's': 2923839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o s_flag = 1; 2933839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o break; 2943839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o case 'v': 29519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o v_flag++; 2963839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o break; 2973839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o case 'w': 2983839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o w_flag = 1; 2993839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o break; 3003839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o default: 301818180cdfcff84b9048ecdc5dc86323f0fefba24Theodore Ts'o usage(); 3023839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 3033839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 3043839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (optind > argc - 1) 305818180cdfcff84b9048ecdc5dc86323f0fefba24Theodore Ts'o usage(); 3063839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o device_name = argv[optind++]; 3073839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (optind > argc - 1) 308818180cdfcff84b9048ecdc5dc86323f0fefba24Theodore Ts'o usage(); 3093839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o blocks_count = strtoul (argv[optind], &tmp, 0); 3103839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (*tmp) 3113839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o { 3123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o com_err (program_name, 0, "bad blocks count - %s", argv[optind]); 3133839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o exit (1); 3143839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 315f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (++optind <= argc-1) { 316f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o from_count = strtoul (argv[optind], &tmp, 0); 317f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o } else from_count = 0; 318f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (from_count >= blocks_count) { 319f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o com_err (program_name, 0, "bad blocks range: %lu-%lu", 320f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o from_count, blocks_count); 321f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o exit (1); 322f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o } 3233839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dev = open (device_name, w_flag ? O_RDWR : O_RDONLY); 3243839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (dev == -1) 3253839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o { 3263839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o com_err (program_name, errno,"while trying to open %s", 3273839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o device_name); 3283839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o exit (1); 3293839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 3303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (output_file && strcmp (output_file, "-") != 0) 3313839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o { 3323839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o out = fopen (output_file, "w"); 3333839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (out == NULL) 3343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o { 3353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o com_err (program_name, errno,"while trying to open %s", 3363839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o device_name); 3373839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o exit (1); 3383839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 3393839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 3403839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o else 3413839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o out = stdout; 3423839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (w_flag) 343f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o test_rw (dev, blocks_count, block_size, out, from_count); 3443839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o else 345f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o test_ro (dev, blocks_count, block_size, out, from_count); 3463839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o close (dev); 3473839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (out != stdout) 3483839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o fclose (out); 34900e5433eb5e9f70f485968b809fdcf297d7fe7b9Theodore Ts'o exit(0); 3503839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 351