1 /* 2 * badblocks.c --- replace/append bad blocks to the bad block inode 3 * 4 * Copyright (C) 1993, 1994 Theodore Ts'o. This file may be 5 * redistributed under the terms of the GNU Public License. 6 */ 7 8 #include <time.h> 9 #ifdef HAVE_ERRNO_H 10 #include <errno.h> 11 #endif 12 13 #include <et/com_err.h> 14 #include "e2fsck.h" 15 16 static int check_bb_inode_blocks(ext2_filsys fs, blk_t *block_nr, int blockcnt, 17 void *priv_data); 18 19 20 static void invalid_block(ext2_filsys fs EXT2FS_ATTR((unused)), blk_t blk) 21 { 22 printf(_("Bad block %u out of range; ignored.\n"), blk); 23 return; 24 } 25 26 void read_bad_blocks_file(e2fsck_t ctx, const char *bad_blocks_file, 27 int replace_bad_blocks) 28 { 29 ext2_filsys fs = ctx->fs; 30 errcode_t retval; 31 badblocks_list bb_list = 0; 32 FILE *f; 33 char buf[1024]; 34 35 e2fsck_read_bitmaps(ctx); 36 37 /* 38 * Make sure the bad block inode is sane. If there are any 39 * illegal blocks, clear them. 40 */ 41 retval = ext2fs_block_iterate(fs, EXT2_BAD_INO, 0, 0, 42 check_bb_inode_blocks, 0); 43 if (retval) { 44 com_err("ext2fs_block_iterate", retval, 45 _("while sanity checking the bad blocks inode")); 46 goto fatal; 47 } 48 49 /* 50 * If we're appending to the bad blocks inode, read in the 51 * current bad blocks. 52 */ 53 if (!replace_bad_blocks) { 54 retval = ext2fs_read_bb_inode(fs, &bb_list); 55 if (retval) { 56 com_err("ext2fs_read_bb_inode", retval, 57 _("while reading the bad blocks inode")); 58 goto fatal; 59 } 60 } 61 62 /* 63 * Now read in the bad blocks from the file; if 64 * bad_blocks_file is null, then try to run the badblocks 65 * command. 66 */ 67 if (bad_blocks_file) { 68 f = fopen(bad_blocks_file, "r"); 69 if (!f) { 70 com_err("read_bad_blocks_file", errno, 71 _("while trying to open %s"), bad_blocks_file); 72 goto fatal; 73 } 74 } else { 75 sprintf(buf, "badblocks -b %d -X %s%s%s %d", fs->blocksize, 76 (ctx->options & E2F_OPT_PREEN) ? "" : "-s ", 77 (ctx->options & E2F_OPT_WRITECHECK) ? "-n " : "", 78 fs->device_name, fs->super->s_blocks_count-1); 79 f = popen(buf, "r"); 80 if (!f) { 81 com_err("read_bad_blocks_file", errno, 82 _("while trying popen '%s'"), buf); 83 goto fatal; 84 } 85 } 86 retval = ext2fs_read_bb_FILE(fs, f, &bb_list, invalid_block); 87 if (bad_blocks_file) 88 fclose(f); 89 else 90 pclose(f); 91 if (retval) { 92 com_err("ext2fs_read_bb_FILE", retval, 93 _("while reading in list of bad blocks from file")); 94 goto fatal; 95 } 96 97 /* 98 * Finally, update the bad blocks from the bad_block_map 99 */ 100 printf("%s: Updating bad block inode.\n", ctx->device_name); 101 retval = ext2fs_update_bb_inode(fs, bb_list); 102 if (retval) { 103 com_err("ext2fs_update_bb_inode", retval, 104 _("while updating bad block inode")); 105 goto fatal; 106 } 107 108 ext2fs_badblocks_list_free(bb_list); 109 return; 110 111 fatal: 112 ctx->flags |= E2F_FLAG_ABORT; 113 return; 114 115 } 116 117 static int check_bb_inode_blocks(ext2_filsys fs, 118 blk_t *block_nr, 119 int blockcnt EXT2FS_ATTR((unused)), 120 void *priv_data EXT2FS_ATTR((unused))) 121 { 122 if (!*block_nr) 123 return 0; 124 125 /* 126 * If the block number is outrageous, clear it and ignore it. 127 */ 128 if (*block_nr >= fs->super->s_blocks_count || 129 *block_nr < fs->super->s_first_data_block) { 130 printf(_("Warning: illegal block %u found in bad block inode. " 131 "Cleared.\n"), *block_nr); 132 *block_nr = 0; 133 return BLOCK_CHANGED; 134 } 135 136 return 0; 137 } 138 139