badblocks.c revision 8820c79f75c37a3bc85cea7f56e7277025e157ef
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 * 8dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o * Copyright 1995, 1996, 1997, 1998, 1999 by Theodore Ts'o 9879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o * Copyright 1999 by David Beattie 1019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * 113839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * This file is based on the minix file system programs fsck and mkfs 123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * written and copyrighted by Linus Torvalds <Linus.Torvalds@cs.helsinki.fi> 1319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * 1419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * %Begin-Header% 1519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * This file may be redistributed under the terms of the GNU Public 1619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * License. 1719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * %End-Header% 183839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 193839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 203839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 213839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * History: 223839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * 93/05/26 - Creation from e2fsck 233839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * 94/02/27 - Made a separate bad blocks checker 24879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o * 99/06/30...99/07/26 - Added non-destructive write-testing, 25dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o * configurable blocks-at-once parameter, 26dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o * loading of badblocks list to avoid testing 27dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o * blocks known to be bad, multiple passes to 28dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o * make sure that no new blocks are added to the 29dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o * list. (Work done by David Beattie) 303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 313839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 323839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <errno.h> 333839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <fcntl.h> 34a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o#ifdef HAVE_GETOPT_H 353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <getopt.h> 36373b8337c7b6c6243810be250083fa4773891e92Theodore Ts'o#else 37373b8337c7b6c6243810be250083fa4773891e92Theodore Ts'oextern char *optarg; 38373b8337c7b6c6243810be250083fa4773891e92Theodore Ts'oextern int optind; 39a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o#endif 403839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <signal.h> 413839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <stdio.h> 423839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <stdlib.h> 433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <string.h> 443839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <unistd.h> 45879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o#include <setjmp.h> 463839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 473839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <sys/ioctl.h> 48f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#include <sys/types.h> 493839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 50a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o#if HAVE_LINUX_FS_H 513839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <linux/fd.h> 52a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o#endif 533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 543839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include "et/com_err.h" 55d40259fd552d942903f2fd0b426c75a5c2516017Theodore Ts'o#include "ext2fs/ext2_io.h" 56879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o#include <linux/ext2_fs.h> 57879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o#include "ext2fs/ext2fs.h" 58d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o#include "nls-enable.h" 593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'oconst char * program_name = "badblocks"; 618f5c0f66ca343ec4689470e5941aa3066ed062bbTheodore Ts'oconst char * done_string = N_("done \n"); 623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 634d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'ostatic int v_flag = 0; /* verbose */ 644d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'ostatic int w_flag = 0; /* do r/w test: 0=no, 1=yes, 654d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o * 2=non-destructive */ 664d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'ostatic int s_flag = 0; /* show progress of test */ 67981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'ostatic int force = 0; /* force check of mounted device */ 684d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 698820c79f75c37a3bc85cea7f56e7277025e157efTheodore Ts'ostatic void usage(void) 703839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 71a551b783479b47d05ec996da5c87009a092cf491Theodore Ts'o fprintf(stderr, _("Usage: %s [-b block_size] [-i input_file] [-o output_file] [-svwnf]\n [-c blocks_at_once] [-p num_passes] device [blocks_count [start_count]]\n"), 723839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o program_name); 733839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o exit (1); 743839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 753839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 7619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'ostatic unsigned long currently_testing = 0; 7719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'ostatic unsigned long num_blocks = 0; 78879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'ostatic ext2_badblocks_list bb_list = NULL; 79879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'ostatic FILE *out; 80879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'ostatic blk_t next_bad = 0; 81879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'ostatic ext2_badblocks_iterate bb_iter = NULL; 8219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 83dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o/* 84dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o * This routine reports a new bad block. If the bad block has already 85dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o * been seen before, then it returns 0; otherwise it returns 1. 86dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o */ 87dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'ostatic int bb_output (unsigned long bad) 88879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o{ 89879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o errcode_t errcode; 90879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 91dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o if (ext2fs_badblocks_list_test(bb_list, bad)) 92dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o return 0; 93dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o 94879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o fprintf (out, "%lu\n", bad); 95879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 96879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o errcode = ext2fs_badblocks_list_add (bb_list, bad); 97879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (errcode) { 98879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o com_err (program_name, errcode, "adding to in-memory bad block list"); 99879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 100879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 101879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 102879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o /* kludge: 103879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o increment the iteration through the bb_list if 104879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o an element was just added before the current iteration 105879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o position. This should not cause next_bad to change. */ 106879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (bb_iter && bad < next_bad) 107879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o ext2fs_badblocks_list_iterate (bb_iter, &next_bad); 108dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o return 1; 109879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o} 110879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 1118820c79f75c37a3bc85cea7f56e7277025e157efTheodore Ts'ostatic void print_status(void) 11219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o{ 11319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o fprintf(stderr, "%9ld/%9ld", currently_testing, num_blocks); 11419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o fprintf(stderr, "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"); 11519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o fflush (stderr); 11619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o} 11719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 118981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'ostatic void alarm_intr(int alnum) 11919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o{ 12019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o signal (SIGALRM, alarm_intr); 12119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o alarm(1); 12219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (!num_blocks) 12319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o return; 12419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o fprintf(stderr, "%9ld/%9ld", currently_testing, num_blocks); 12519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o fprintf(stderr, "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"); 12619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o fflush (stderr); 12719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o} 12819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 129879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'ostatic void *terminate_addr = NULL; 130879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 131981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'ostatic void terminate_intr(int signo) 132879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o{ 133879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (terminate_addr) 134879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o longjmp(terminate_addr,1); 135879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit(1); 136879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o} 137879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 138981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'ostatic void capture_terminate(jmp_buf term_addr) 139879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o{ 140879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o terminate_addr = term_addr; 141879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o signal (SIGHUP, terminate_intr); 142879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o signal (SIGINT, terminate_intr); 143879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o signal (SIGPIPE, terminate_intr); 144879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o signal (SIGTERM, terminate_intr); 145879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o signal (SIGUSR1, terminate_intr); 146879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o signal (SIGUSR2, terminate_intr); 147879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o} 148879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 1498820c79f75c37a3bc85cea7f56e7277025e157efTheodore Ts'ostatic void uncapture_terminate(void) 1504d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o{ 1514d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o terminate_addr = NULL; 1524d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o signal (SIGHUP, SIG_DFL); 1534d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o signal (SIGINT, SIG_DFL); 1544d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o signal (SIGPIPE, SIG_DFL); 1554d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o signal (SIGTERM, SIG_DFL); 1564d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o signal (SIGUSR1, SIG_DFL); 1574d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o signal (SIGUSR2, SIG_DFL); 1584d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o} 1594d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 1603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 161879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o * Perform a read of a sequence of blocks; return the number of blocks 162879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o * successfully sequentially read. 1633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 164dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'ostatic long do_read (int dev, char * buffer, int try, int block_size, 1653839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o unsigned long current_block) 1663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 1673839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o long got; 1683839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 16919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (v_flag > 1) 17019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o print_status(); 17119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o 1723839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* Seek to the correct loc. */ 17319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (ext2fs_llseek (dev, (ext2_loff_t) current_block * block_size, 174f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o SEEK_SET) != (ext2_loff_t) current_block * block_size) 175d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o com_err (program_name, errno, _("during seek")); 1763839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1773839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* Try the read */ 1783839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o got = read (dev, buffer, try * block_size); 1793839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (got < 0) 1803839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o got = 0; 1819f10a7b31e57288093930fc9565102409eeac6e9Theodore Ts'o if (got & 511) 182d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o fprintf(stderr, _("Weird value (%ld) in do_read\n"), got); 183879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o got /= block_size; 184879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o return got; 185879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o} 186879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 187879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o/* 188879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o * Perform a write of a sequence of blocks; return the number of blocks 189879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o * successfully sequentially written. 190879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o */ 191dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'ostatic long do_write (int dev, char * buffer, int try, int block_size, 192879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o unsigned long current_block) 193879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o{ 194879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o long got; 195879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 196879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (v_flag > 1) 197879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o print_status(); 198879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 199879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o /* Seek to the correct loc. */ 200879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (ext2fs_llseek (dev, (ext2_loff_t) current_block * block_size, 201879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o SEEK_SET) != (ext2_loff_t) current_block * block_size) 202d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o com_err (program_name, errno, _("during seek")); 203879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 204879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o /* Try the write */ 205879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o got = write (dev, buffer, try * block_size); 206879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (got < 0) 207879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o got = 0; 208879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (got & 511) 209879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o fprintf (stderr, 210879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o "Weird value (%ld) in do_write\n", got); 2113839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o got /= block_size; 2123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return got; 2133839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 2143839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 215879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'ostatic int host_dev; 216879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 217d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'ostatic void flush_bufs (int dev) 218a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o{ 219e2207ce595f05e4db5945326f9b2d553ff7a4d57Theodore Ts'o#ifdef HAVE_FDATASYNC 2208820c79f75c37a3bc85cea7f56e7277025e157efTheodore Ts'o if (fdatasync (dev) == -1) 221e2207ce595f05e4db5945326f9b2d553ff7a4d57Theodore Ts'o com_err (program_name, errno, _("during fdatasync")); 222e2207ce595f05e4db5945326f9b2d553ff7a4d57Theodore Ts'o#else 2238820c79f75c37a3bc85cea7f56e7277025e157efTheodore Ts'o if (fsync (dev) == -1) 224d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o com_err (program_name, errno, _("during fsync")); 225e2207ce595f05e4db5945326f9b2d553ff7a4d57Theodore Ts'o#endif 226a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o 227879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o#ifdef BLKFLSBUF 228879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o ioctl (host_dev, BLKFLSBUF, 0); /* In case this is a HD */ 229a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o#endif 230a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o#ifdef FDFLUSH 231879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o ioctl (host_dev, FDFLUSH, 0); /* In case this is floppy */ 232a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o#endif 233a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o} 234a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o 235879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'ostatic unsigned int test_ro (int dev, unsigned long blocks_count, 236dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o int block_size, unsigned long from_count, 237dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o unsigned long blocks_at_once) 2383839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 2393839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o char * blkbuf; 2403839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int try; 2413839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o long got; 242879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o unsigned int bb_count = 0; 243879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o errcode_t errcode; 2443839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 245879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o errcode = ext2fs_badblocks_list_iterate_begin(bb_list,&bb_iter); 246879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (errcode) { 247d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o com_err (program_name, errcode, 248d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o _("while beginning bad block list iteration")); 249879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 250879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 251879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o do { 252879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o ext2fs_badblocks_list_iterate (bb_iter, &next_bad); 253879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } while (next_bad && next_bad < from_count); 254879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 255879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o blkbuf = malloc (blocks_at_once * block_size); 2563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (!blkbuf) 2573839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o { 258d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o com_err (program_name, ENOMEM, _("while allocating buffers")); 2593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o exit (1); 2603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 261d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o flush_bufs(dev); 262f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (v_flag) { 263d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o fprintf(stderr, _("Checking for bad blocks in read-only mode\n")); 264d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o fprintf (stderr, _("From block %lu to %lu\n"), from_count, 265d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o blocks_count); 266f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o } 267879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o try = blocks_at_once; 268f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o currently_testing = from_count; 2693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o num_blocks = blocks_count; 27019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (s_flag || v_flag > 1) { 271d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o fprintf(stderr, 272d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o _("Checking for bad blocks (read-only test): ")); 27319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (v_flag <= 1) 27419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o alarm_intr(SIGALRM); 2753839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 2763839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o while (currently_testing < blocks_count) 2773839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o { 278879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (next_bad) { 279879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (currently_testing == next_bad) { 280879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o /* fprintf (out, "%lu\n", nextbad); */ 281879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o ext2fs_badblocks_list_iterate (bb_iter, &next_bad); 282879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o currently_testing++; 283879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o continue; 284879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 285879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o else if (currently_testing + try > next_bad) 286879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o try = next_bad - currently_testing; 287879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 2883839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (currently_testing + try > blocks_count) 2893839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o try = blocks_count - currently_testing; 290879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o got = do_read (dev, blkbuf, try, block_size, currently_testing); 2913839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o currently_testing += got; 2923839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (got == try) { 293879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o try = blocks_at_once; 2943839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o continue; 2953839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 2963839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o else 2973839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o try = 1; 298879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (got == 0) { 299dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o bb_count += bb_output(currently_testing++); 300879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 3013839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 3023839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o num_blocks = 0; 3033839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o alarm(0); 30419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (s_flag || v_flag > 1) 3058f5c0f66ca343ec4689470e5941aa3066ed062bbTheodore Ts'o fprintf(stderr, _(done_string)); 306879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 307f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o fflush (stderr); 3083839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o free (blkbuf); 309879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 310879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o ext2fs_badblocks_list_iterate_end(bb_iter); 311879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 312879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o return bb_count; 3133839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 3143839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 315879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'ostatic unsigned int test_rw (int dev, unsigned long blocks_count, 316dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o int block_size, unsigned long from_count, 317dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o unsigned long blocks_at_once) 3183839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 3193839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int i; 3203839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o char * buffer; 3218820c79f75c37a3bc85cea7f56e7277025e157efTheodore Ts'o static unsigned char pattern[] = {0xaa, 0x55, 0xff, 0x00}; 322879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o unsigned int bb_count = 0; 3233839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 3243839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o buffer = malloc (2 * block_size); 3253839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (!buffer) 3263839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o { 327d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o com_err (program_name, ENOMEM, _("while allocating buffers")); 3283839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o exit (1); 3293839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 3303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 331d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o flush_bufs(dev); 332a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o 33319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (v_flag) { 33419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o fprintf(stderr, 335d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o _("Checking for bad blocks in read-write mode\n")); 336d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o fprintf(stderr, _("From block %lu to %lu\n"), 33719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o from_count, blocks_count); 33819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o } 33919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o for (i = 0; i < sizeof (pattern); i++) { 3403839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o memset (buffer, pattern[i], block_size); 341f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (s_flag | v_flag) 342d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o fprintf (stderr, _("Writing pattern 0x%08x: "), 3433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o *((int *) buffer)); 344f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o num_blocks = blocks_count; 345f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o currently_testing = from_count; 34619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (s_flag && v_flag <= 1) 347f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o alarm_intr(SIGALRM); 348f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o for (; 349f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o currently_testing < blocks_count; 350f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o currently_testing++) 3513839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o { 35219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (ext2fs_llseek (dev, (ext2_loff_t) currently_testing * 353f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o block_size, SEEK_SET) != 354f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o (ext2_loff_t) currently_testing * block_size) 3553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o com_err (program_name, errno, 356d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o _("during seek on block %d"), 357f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o currently_testing); 35819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (v_flag > 1) 35919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o print_status(); 3603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o write (dev, buffer, block_size); 3613839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 362f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o num_blocks = 0; 363f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o alarm (0); 364f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (s_flag | v_flag) 3658f5c0f66ca343ec4689470e5941aa3066ed062bbTheodore Ts'o fprintf(stderr, _(done_string)); 366d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o flush_bufs(dev); 367f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (s_flag | v_flag) 368d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o fprintf (stderr, _("Reading and comparing: ")); 369f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o num_blocks = blocks_count; 370f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o currently_testing = from_count; 37119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (s_flag && v_flag <= 1) 372f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o alarm_intr(SIGALRM); 373f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o for (; 374f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o currently_testing < blocks_count; 375f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o currently_testing++) 3763839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o { 37719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (ext2fs_llseek (dev, (ext2_loff_t) currently_testing * 378f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o block_size, SEEK_SET) != 379f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o (ext2_loff_t) currently_testing * block_size) 3803839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o com_err (program_name, errno, 381d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o _("during seek on block %d"), 382f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o currently_testing); 38319c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (v_flag > 1) 38419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o print_status(); 385dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o if ((read (dev, buffer + block_size, block_size) 3864d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o != block_size) || 387dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o memcmp(buffer, buffer + block_size, block_size)) 3884d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o bb_count += bb_output(currently_testing); 3893839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 390f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o num_blocks = 0; 391f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o alarm (0); 392f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (s_flag | v_flag) 3938f5c0f66ca343ec4689470e5941aa3066ed062bbTheodore Ts'o fprintf(stderr, _(done_string)); 394d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o flush_bufs(dev); 3953839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 396879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 397879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o return bb_count; 398879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o} 399879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 400d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'ostruct saved_blk_record { 401d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o blk_t block; 402d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o int num; 403d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o}; 404d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o 405879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'ostatic unsigned int test_nd (int dev, unsigned long blocks_count, 406dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o int block_size, unsigned long from_count, 407dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o unsigned long blocks_at_once) 408879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o{ 409dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o char *blkbuf, *save_ptr, *test_ptr, *read_ptr; 410879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o char * ptr; 411dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o int try, i; 412a551b783479b47d05ec996da5c87009a092cf491Theodore Ts'o long got, used2, written, save_currently_testing; 413d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o struct saved_blk_record *test_record; 414a551b783479b47d05ec996da5c87009a092cf491Theodore Ts'o /* This is static to prevent being clobbered by the longjmp */ 415a551b783479b47d05ec996da5c87009a092cf491Theodore Ts'o static int num_saved; 416879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o jmp_buf terminate_env; 417879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o errcode_t errcode; 418a551b783479b47d05ec996da5c87009a092cf491Theodore Ts'o long buf_used; 419a551b783479b47d05ec996da5c87009a092cf491Theodore Ts'o unsigned int bb_count; 420879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 421879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o errcode = ext2fs_badblocks_list_iterate_begin(bb_list,&bb_iter); 422879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (errcode) { 423dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o com_err (program_name, errcode, 424d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o _("while beginning bad block list iteration")); 425879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 426879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 427879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o do { 428879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o ext2fs_badblocks_list_iterate (bb_iter, &next_bad); 429879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } while (next_bad && next_bad < from_count); 430879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 431879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o blkbuf = malloc (3 * blocks_at_once * block_size); 432d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o test_record = malloc (blocks_at_once*sizeof(struct saved_blk_record)); 433d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o if (!blkbuf || !test_record) { 434d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o com_err(program_name, ENOMEM, _("while allocating buffers")); 435879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 436879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 437d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o num_saved = 0; 438879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 439879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o /* inititalize the test data randomly: */ 440879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (v_flag) { 441d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o fprintf (stderr, _("Initializing random test data\n")); 442879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 443879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o for(ptr = blkbuf + blocks_at_once * block_size; 444dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o ptr < blkbuf + 2 * blocks_at_once * block_size; 445dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o ++ptr) { 446879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o (*ptr) = random() % (1 << sizeof(char)); 447879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 448879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 449d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o flush_bufs(dev); 450879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (v_flag) { 451879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o fprintf (stderr, 452d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o _("Checking for bad blocks in non-destructive read-write mode\n")); 453d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o fprintf (stderr, _("From block %lu to %lu\n"), from_count, blocks_count); 454879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 455879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (s_flag || v_flag > 1) { 456d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o fprintf(stderr, _("Checking for bad blocks (non-destructive read-write test): ")); 457879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (v_flag <= 1) 458879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o alarm_intr(SIGALRM); 459879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 4604d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o if (setjmp(terminate_env)) { 4614d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o /* 4624d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o * Abnormal termination by a signal is handled here. 4634d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o */ 464a551b783479b47d05ec996da5c87009a092cf491Theodore Ts'o signal (SIGALRM, SIG_IGN); 465a551b783479b47d05ec996da5c87009a092cf491Theodore Ts'o fprintf(stderr, _("\nInterrupt caught, cleaning up\n")); 466879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 467d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o save_ptr = blkbuf; 468d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o for (i=0; i < num_saved; i++) { 469d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o do_write(dev, save_ptr, test_record[i].num, 470d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o block_size, test_record[i].block); 471d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o save_ptr += test_record[i].num * block_size; 472d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o } 473879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o fflush (out); 474dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o exit(1); 475879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 4764d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 4774d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o /* set up abend handler */ 4784d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o capture_terminate(terminate_env); 4794d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 480d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o buf_used = 0; 481a551b783479b47d05ec996da5c87009a092cf491Theodore Ts'o bb_count = 0; 482d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o save_ptr = blkbuf; 4834d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o test_ptr = blkbuf + (blocks_at_once * block_size); 4844d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o currently_testing = from_count; 4854d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o num_blocks = blocks_count; 4864d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 4874d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o while (currently_testing < blocks_count) { 4884d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o try = blocks_at_once - buf_used; 4894d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o if (next_bad) { 4904d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o if (currently_testing == next_bad) { 4914d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o /* fprintf (out, "%lu\n", nextbad); */ 4924d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o ext2fs_badblocks_list_iterate (bb_iter, &next_bad); 493d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o currently_testing++; 494d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o goto check_for_more; 4954d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o } 4964d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o else if (currently_testing + try > next_bad) 4974d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o try = next_bad - currently_testing; 4984d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o } 4994d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o if (currently_testing + try > blocks_count) 5004d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o try = blocks_count - currently_testing; 5014d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o got = do_read (dev, save_ptr, try, block_size, 5024d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o currently_testing); 503d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o if (got == 0) { 504d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o /* First block must have been bad. */ 505d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o bb_count += bb_output(currently_testing++); 506d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o goto check_for_more; 507d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o } 5084d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 509d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o /* 510d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o * Note the fact that we've saved this much data 511d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o * *before* we overwrite it with test data 512d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o */ 513d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o test_record[num_saved].block = currently_testing; 514d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o test_record[num_saved].num = got; 515d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o num_saved++; 516d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o 517d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o /* Write the test data */ 518d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o written = do_write (dev, test_ptr, got, block_size, 519d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o currently_testing); 520d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o if (written != got) 521d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o com_err (program_name, errno, 5224d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o _("during test data write, block %lu"), 523d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o currently_testing + written); 5244d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 5254d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o buf_used += got; 5264d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o save_ptr += got * block_size; 5274d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o test_ptr += got * block_size; 5284d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o currently_testing += got; 5294d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o if (got != try) 5304d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o bb_count += bb_output(currently_testing++); 5314d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 532d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o check_for_more: 5334d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o /* 5344d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o * If there's room for more blocks to be tested this 5354d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o * around, and we're not done yet testing the disk, go 5364d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o * back and get some more blocks. 5374d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o */ 5384d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o if ((buf_used != blocks_at_once) && 539d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o (currently_testing < blocks_count)) 5404d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o continue; 5414d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 542d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o flush_bufs(dev); 543a551b783479b47d05ec996da5c87009a092cf491Theodore Ts'o save_currently_testing = currently_testing; 5444d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 5454d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o /* 5464d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o * for each contiguous block that we read into the 5474d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o * buffer (and wrote test data into afterwards), read 5484d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o * it back (looping if necessary, to get past newly 5494d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o * discovered unreadable blocks, of which there should 5504d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o * be none, but with a hard drive which is unreliable, 5514d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o * it has happened), and compare with the test data 5524d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o * that was written; output to the bad block list if 5534d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o * it doesn't match. 5544d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o */ 5554d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o used2 = 0; 5564d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o save_ptr = blkbuf; 5574d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o test_ptr = blkbuf + (blocks_at_once * block_size); 5584d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o read_ptr = blkbuf + (2 * blocks_at_once * block_size); 559d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o try = 0; 5604d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 561d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o while (1) { 562d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o if (try == 0) { 563d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o if (used2 >= num_saved) 564d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o break; 565d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o currently_testing = test_record[used2].block; 566d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o try = test_record[used2].num; 567d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o used2++; 568d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o } 569d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o 5704d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o got = do_read (dev, read_ptr, try, 5714d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o block_size, currently_testing); 5724d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 5734d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o /* test the comparison between all the 5744d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o blocks successfully read */ 5754d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o for (i = 0; i < got; ++i) 5764d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o if (memcmp (test_ptr+i*block_size, 5774d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o read_ptr+i*block_size, block_size)) 5784d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o bb_count += bb_output(currently_testing + i); 5794d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o if (got < try) { 5804d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o bb_count += bb_output(currently_testing + got); 5814d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o got++; 5824d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o } 5834d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 5844d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o /* when done, write back original data */ 5854d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o do_write (dev, save_ptr, got, block_size, 5864d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o currently_testing); 5874d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 5884d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o currently_testing += got; 5894d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o save_ptr += got * block_size; 5904d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o test_ptr += got * block_size; 5914d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o read_ptr += got * block_size; 5924d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o try -= got; 5934d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o } 5944d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 5954d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o /* empty the buffer so it can be reused */ 596d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o num_saved = 0; 5974d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o buf_used = 0; 598d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o save_ptr = blkbuf; 599d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o test_ptr = blkbuf + (blocks_at_once * block_size); 600a551b783479b47d05ec996da5c87009a092cf491Theodore Ts'o currently_testing = save_currently_testing; 6014d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o } 6024d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o num_blocks = 0; 6034d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o alarm(0); 6044d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o uncapture_terminate(); 6054d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o if (s_flag || v_flag > 1) 6064d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o fprintf(stderr, _(done_string)); 607879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 608dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o fflush(stderr); 609dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o free(blkbuf); 610d49a22b734299e4b433a19b8f5f60d689c92a78eTheodore Ts'o free(test_record); 611879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 612879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o ext2fs_badblocks_list_iterate_end(bb_iter); 613879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 614879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o return bb_count; 6153839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 6163839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 617981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'ostatic void check_mount(char *device_name) 618981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o{ 619981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o errcode_t retval; 620981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o int mount_flags; 621981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o 622981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o retval = ext2fs_check_if_mounted(device_name, &mount_flags); 623981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o if (retval) { 624981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o com_err("ext2fs_check_if_mount", retval, 625981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o _("while determining whether %s is mounted."), 626981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o device_name); 627981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o return; 628981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o } 629981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o if (!(mount_flags & EXT2_MF_MOUNTED)) 630981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o return; 631981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o 632981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o fprintf(stderr, _("%s is mounted; "), device_name); 633981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o if (force) { 634981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o fprintf(stderr, _("badblocks forced anyway. " 635981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o "Hope /etc/mtab is incorrect.\n")); 636981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o return; 637981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o } 638981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o fprintf(stderr, _("it's not safe to run badblocks!\n")); 639981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o exit(1); 640981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o} 641981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o 642981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o 64300e5433eb5e9f70f485968b809fdcf297d7fe7b9Theodore Ts'oint main (int argc, char ** argv) 6443839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 645519149fb458b0fa69c10fecd83fae42e838cf01dTheodore Ts'o int c; 6463839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o char * tmp; 6473839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o char * device_name; 648879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o char * host_device_name = NULL; 649879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o char * input_file = NULL; 6503839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o char * output_file = NULL; 651879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o FILE * in = NULL; 652dd018f5aa41cc21d22f01c45a3eee6ce492eb228Theodore Ts'o int block_size = 1024; 653879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o unsigned long blocks_at_once = 16; 65435964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o blk_t blocks_count, from_count; 655879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o int num_passes = 0; 656879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o int passes_clean = 0; 6573839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int dev; 658879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o errcode_t errcode; 6598820c79f75c37a3bc85cea7f56e7277025e157efTheodore Ts'o unsigned int (*test_func)(int, unsigned long, 6608820c79f75c37a3bc85cea7f56e7277025e157efTheodore Ts'o int, unsigned long, 6618820c79f75c37a3bc85cea7f56e7277025e157efTheodore Ts'o unsigned long); 6623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 6633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o setbuf(stdout, NULL); 6643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o setbuf(stderr, NULL); 665d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o#ifdef ENABLE_NLS 666d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o setlocale(LC_MESSAGES, ""); 667d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o bindtextdomain(NLS_CAT_NAME, LOCALEDIR); 668d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o textdomain(NLS_CAT_NAME); 669d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o#endif 6704d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o test_func = test_ro; 6714d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 6723839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (argc && *argv) 6733839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o program_name = *argv; 674a551b783479b47d05ec996da5c87009a092cf491Theodore Ts'o while ((c = getopt (argc, argv, "b:fi:o:svwnc:p:h:")) != EOF) { 6753839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o switch (c) { 6763839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o case 'b': 6773839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o block_size = strtoul (optarg, &tmp, 0); 6783839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (*tmp || block_size > 4096) { 6793839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o com_err (program_name, 0, 680d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o _("bad block size - %s"), optarg); 6813839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o exit (1); 6823839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 6833839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o break; 684981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o case 'f': 685981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o force++; 686981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o break; 687879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o case 'i': 688879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o input_file = optarg; 689879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o break; 6903839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o case 'o': 6913839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o output_file = optarg; 6923839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o break; 6933839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o case 's': 6943839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o s_flag = 1; 6953839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o break; 6963839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o case 'v': 69719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o v_flag++; 6983839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o break; 6993839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o case 'w': 7004d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o if (w_flag) 7014d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o usage(); 7024d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o test_func = test_rw; 7034d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o w_flag = 1; 704879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o break; 705879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o case 'n': 7064d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o if (w_flag) 7074d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o usage(); 7084d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o test_func = test_nd; 709879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o w_flag = 2; 710879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o break; 711879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o case 'c': 712879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o blocks_at_once = strtoul (optarg, &tmp, 0); 713879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (*tmp) { 714879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o com_err (program_name, 0, 715879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o "bad simultaneous block count - %s", optarg); 716879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 717879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 718879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o break; 719879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o case 'p': 720879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o num_passes = strtoul (optarg, &tmp, 0); 721879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (*tmp) { 722879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o com_err (program_name, 0, 723879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o "bad number of clean passes - %s", optarg); 724879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 725879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 726879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o break; 727879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o case 'h': 728879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o host_device_name = optarg; 7293839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o break; 7303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o default: 731818180cdfcff84b9048ecdc5dc86323f0fefba24Theodore Ts'o usage(); 7323839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 7333839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 7343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (optind > argc - 1) 735818180cdfcff84b9048ecdc5dc86323f0fefba24Theodore Ts'o usage(); 7363839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o device_name = argv[optind++]; 73735964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o if (optind > argc - 1) { 73835964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o errcode = ext2fs_get_device_size(device_name, 73935964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o block_size, 74035964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o &blocks_count); 74135964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o if (errcode == EXT2_ET_UNIMPLEMENTED) { 74235964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o com_err(program_name, 0, 74335964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o _("Couldn't determine device size; you " 74435964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o "must specify\nthe size manually\n")); 74535964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o exit(1); 74635964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o } 74735964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o if (errcode) { 74835964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o com_err(program_name, errcode, 74935964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o _("while trying to determine device size")); 75035964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o exit(1); 75135964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o } 75235964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o } else { 75335964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o blocks_count = strtoul (argv[optind], &tmp, 0); 75435964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o if (*tmp) { 75535964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o com_err (program_name, 0, _("bad blocks count - %s"), 75635964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o argv[optind]); 75735964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o exit (1); 75835964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o } 75935964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o optind++; 7603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 76135964b5c4a85ab73c1ac02caed98584b6527f7c2Theodore Ts'o if (optind <= argc-1) { 762f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o from_count = strtoul (argv[optind], &tmp, 0); 763a551b783479b47d05ec996da5c87009a092cf491Theodore Ts'o if (*tmp) { 764a551b783479b47d05ec996da5c87009a092cf491Theodore Ts'o com_err (program_name, 0, _("bad starting block - %s"), 765a551b783479b47d05ec996da5c87009a092cf491Theodore Ts'o argv[optind]); 766a551b783479b47d05ec996da5c87009a092cf491Theodore Ts'o exit (1); 767a551b783479b47d05ec996da5c87009a092cf491Theodore Ts'o } 768f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o } else from_count = 0; 769f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (from_count >= blocks_count) { 770d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o com_err (program_name, 0, _("bad blocks range: %lu-%lu"), 771f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o from_count, blocks_count); 772f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o exit (1); 773f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o } 774981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o if (w_flag) 775981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o check_mount(device_name); 776981dc56ae312ef6f13ab5fca57ef51616890e13fTheodore Ts'o 7773839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dev = open (device_name, w_flag ? O_RDWR : O_RDONLY); 7783839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (dev == -1) 7793839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o { 780d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o com_err (program_name, errno, _("while trying to open %s"), 7813839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o device_name); 7823839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o exit (1); 7833839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 784879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (host_device_name) { 785879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o host_dev = open (host_device_name, O_RDONLY); 786879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (host_dev == -1) 787879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o { 788d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o com_err (program_name, errno, 789d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o _("while trying to open %s"), 790d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o host_device_name); 791879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 792879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 793879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } else 794879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o host_dev = dev; 795879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (input_file) 796879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (strcmp (input_file, "-") == 0) 797879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o in = stdin; 798879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o else { 799879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o in = fopen (input_file, "r"); 800879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (in == NULL) 801879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o { 802d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o com_err (program_name, errno, 803d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o _("while trying to open %s"), 804879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o input_file); 805879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 806879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 807879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 8083839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (output_file && strcmp (output_file, "-") != 0) 8093839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o { 8103839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o out = fopen (output_file, "w"); 8113839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (out == NULL) 8123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o { 813d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o com_err (program_name, errno, 814d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o _("while trying to open %s"), 815879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o output_file); 8163839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o exit (1); 8173839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 8183839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 8193839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o else 8203839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o out = stdout; 821879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 822879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o errcode = ext2fs_badblocks_list_create(&bb_list,0); 823879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (errcode) { 824d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o com_err (program_name, errcode, 825d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o _("creating in-memory bad blocks list")); 826879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 827879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 828879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 829879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (in) { 830879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o for(;;) { 831a551b783479b47d05ec996da5c87009a092cf491Theodore Ts'o switch(fscanf (in, "%u\n", &next_bad)) { 832879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o case 0: 833879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o com_err (program_name, 0, "input file - bad format"); 834879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 835879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o case EOF: 836879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o break; 837879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o default: 838879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o errcode = ext2fs_badblocks_list_add(bb_list,next_bad); 839879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (errcode) { 840d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o com_err (program_name, errcode, _("adding to in-memory bad block list")); 841879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o exit (1); 842879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 843879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o continue; 844879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 845879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o break; 846879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 847879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 848879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (in != stdin) 849879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o fclose (in); 850879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } 851879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 852879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o do { 853879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o unsigned int bb_count; 854879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 8554d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o bb_count = test_func(dev, blocks_count, block_size, 8564d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o from_count, blocks_at_once); 8574d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o if (bb_count) 8584d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o passes_clean = 0; 8594d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o else 8604d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o ++passes_clean; 8614d003982f95ea4151b964f5f986e8af76707bde0Theodore Ts'o 862879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o if (v_flag) 863d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o fprintf(stderr, 864d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o _("Pass completed, %u bad blocks found.\n"), 865d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o bb_count); 866879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 867879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o } while (passes_clean < num_passes); 868879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o 8693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o close (dev); 8703839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (out != stdout) 8713839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o fclose (out); 872879ac920e347267d4461ba76b349fbef67b42b9bTheodore Ts'o return 0; 8733839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 874d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o 875