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