xref: /aosp_15_r20/external/e2fsprogs/e2fsck/badblocks.c (revision 6a54128f25917bfc36a8a6e9d722c04a0b4641b6)
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