13839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 23839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * badblocks.c --- replace/append bad blocks to the bad block inode 3efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o * 43839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Copyright (C) 1993, 1994 Theodore Ts'o. This file may be 53839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * redistributed under the terms of the GNU Public License. 63839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 73839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 83839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <time.h> 950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#ifdef HAVE_ERRNO_H 1050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#include <errno.h> 1150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#endif 123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 133839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <et/com_err.h> 143839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include "e2fsck.h" 153839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 16f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'ostatic int check_bb_inode_blocks(ext2_filsys fs, blk_t *block_nr, int blockcnt, 1754dc7ca2869897ae8cb81a9ab9880ebff11680bcTheodore Ts'o void *priv_data); 18f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 19f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 20544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'ostatic void invalid_block(ext2_filsys fs EXT2FS_ATTR((unused)), blk_t blk) 213839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 220c4a07264e55b42c6e30230e66b1dea7d4b94ea9Theodore Ts'o printf(_("Bad block %u out of range; ignored.\n"), blk); 233839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return; 243839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 253839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 261b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'ovoid read_bad_blocks_file(e2fsck_t ctx, const char *bad_blocks_file, 273839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int replace_bad_blocks) 283839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 291b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2_filsys fs = ctx->fs; 303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o errcode_t retval; 313839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o badblocks_list bb_list = 0; 323839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o FILE *f; 3374becf3c0a065f8d64e07ce4d31f9fe53be91d62Theodore Ts'o char buf[1024]; 343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 35f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o e2fsck_read_bitmaps(ctx); 36f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 37f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o /* 38f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o * Make sure the bad block inode is sane. If there are any 39f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o * illegal blocks, clear them. 40f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o */ 41f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o retval = ext2fs_block_iterate(fs, EXT2_BAD_INO, 0, 0, 42f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o check_bb_inode_blocks, 0); 43f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (retval) { 44e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall com_err("ext2fs_block_iterate", retval, "%s", 450c4a07264e55b42c6e30230e66b1dea7d4b94ea9Theodore Ts'o _("while sanity checking the bad blocks inode")); 46f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o goto fatal; 47f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o } 48efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 493839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 503839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * If we're appending to the bad blocks inode, read in the 513839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * current bad blocks. 523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (!replace_bad_blocks) { 543839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = ext2fs_read_bb_inode(fs, &bb_list); 553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) { 56e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall com_err("ext2fs_read_bb_inode", retval, "%s", 570c4a07264e55b42c6e30230e66b1dea7d4b94ea9Theodore Ts'o _("while reading the bad blocks inode")); 58f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o goto fatal; 593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 61efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 6374becf3c0a065f8d64e07ce4d31f9fe53be91d62Theodore Ts'o * Now read in the bad blocks from the file; if 6474becf3c0a065f8d64e07ce4d31f9fe53be91d62Theodore Ts'o * bad_blocks_file is null, then try to run the badblocks 6574becf3c0a065f8d64e07ce4d31f9fe53be91d62Theodore Ts'o * command. 663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 6774becf3c0a065f8d64e07ce4d31f9fe53be91d62Theodore Ts'o if (bad_blocks_file) { 6874becf3c0a065f8d64e07ce4d31f9fe53be91d62Theodore Ts'o f = fopen(bad_blocks_file, "r"); 6974becf3c0a065f8d64e07ce4d31f9fe53be91d62Theodore Ts'o if (!f) { 7074becf3c0a065f8d64e07ce4d31f9fe53be91d62Theodore Ts'o com_err("read_bad_blocks_file", errno, 710c4a07264e55b42c6e30230e66b1dea7d4b94ea9Theodore Ts'o _("while trying to open %s"), bad_blocks_file); 72f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o goto fatal; 7374becf3c0a065f8d64e07ce4d31f9fe53be91d62Theodore Ts'o } 7474becf3c0a065f8d64e07ce4d31f9fe53be91d62Theodore Ts'o } else { 75e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall sprintf(buf, "badblocks -b %d -X %s%s%s %llu", fs->blocksize, 761b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o (ctx->options & E2F_OPT_PREEN) ? "" : "-s ", 773ed57c27df0ba0942a19c71bc065c8eec3036567Theodore Ts'o (ctx->options & E2F_OPT_WRITECHECK) ? "-n " : "", 78e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs->device_name, ext2fs_blocks_count(fs->super)-1); 7974becf3c0a065f8d64e07ce4d31f9fe53be91d62Theodore Ts'o f = popen(buf, "r"); 8074becf3c0a065f8d64e07ce4d31f9fe53be91d62Theodore Ts'o if (!f) { 8174becf3c0a065f8d64e07ce4d31f9fe53be91d62Theodore Ts'o com_err("read_bad_blocks_file", errno, 820c4a07264e55b42c6e30230e66b1dea7d4b94ea9Theodore Ts'o _("while trying popen '%s'"), buf); 83f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o goto fatal; 8474becf3c0a065f8d64e07ce4d31f9fe53be91d62Theodore Ts'o } 853839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 863839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = ext2fs_read_bb_FILE(fs, f, &bb_list, invalid_block); 87efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o if (bad_blocks_file) 8874becf3c0a065f8d64e07ce4d31f9fe53be91d62Theodore Ts'o fclose(f); 8974becf3c0a065f8d64e07ce4d31f9fe53be91d62Theodore Ts'o else 9074becf3c0a065f8d64e07ce4d31f9fe53be91d62Theodore Ts'o pclose(f); 913839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) { 92e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall com_err("ext2fs_read_bb_FILE", retval, "%s", 930c4a07264e55b42c6e30230e66b1dea7d4b94ea9Theodore Ts'o _("while reading in list of bad blocks from file")); 94f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o goto fatal; 953839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 96efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 973839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 983839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Finally, update the bad blocks from the bad_block_map 993839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 1004f9abdcb306ff515a8009a1e0fd35041688133c9Theodore Ts'o printf("%s: Updating bad block inode.\n", ctx->device_name); 1013839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = ext2fs_update_bb_inode(fs, bb_list); 1023839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) { 103e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall com_err("ext2fs_update_bb_inode", retval, "%s", 1040c4a07264e55b42c6e30230e66b1dea7d4b94ea9Theodore Ts'o _("while updating bad block inode")); 105f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o goto fatal; 1063839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 1073839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 108cbbf031b6edf9bdf5511af2193e44cff7fdaa66aTheodore Ts'o ext2fs_badblocks_list_free(bb_list); 1093839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return; 110efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 111f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'ofatal: 112f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o ctx->flags |= E2F_FLAG_ABORT; 113f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o return; 114efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 1153839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 1163839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 117efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'ostatic int check_bb_inode_blocks(ext2_filsys fs, 118efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o blk_t *block_nr, 119544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o int blockcnt EXT2FS_ATTR((unused)), 120544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o void *priv_data EXT2FS_ATTR((unused))) 121f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o{ 122f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (!*block_nr) 123f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o return 0; 124f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 125f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o /* 126f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o * If the block number is outrageous, clear it and ignore it. 127f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o */ 128e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (*block_nr >= ext2fs_blocks_count(fs->super) || 129f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o *block_nr < fs->super->s_first_data_block) { 130f37ab68a26bacf4f5cc7643b8373e40292b7682aTheodore Ts'o printf(_("Warning: illegal block %u found in bad block inode. " 131f37ab68a26bacf4f5cc7643b8373e40292b7682aTheodore Ts'o "Cleared.\n"), *block_nr); 132f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o *block_nr = 0; 133f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o return BLOCK_CHANGED; 134f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o } 135f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 136f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o return 0; 137f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o} 138f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 139