diff options
Diffstat (limited to 'e2fsprogs/e2fsck/badblocks.c')
-rw-r--r-- | e2fsprogs/e2fsck/badblocks.c | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/e2fsprogs/e2fsck/badblocks.c b/e2fsprogs/e2fsck/badblocks.c new file mode 100644 index 000000000..09ef3ab1b --- /dev/null +++ b/e2fsprogs/e2fsck/badblocks.c | |||
@@ -0,0 +1,136 @@ | |||
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 %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); | ||
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 | retval = ext2fs_update_bb_inode(fs, bb_list); | ||
101 | if (retval) { | ||
102 | com_err("ext2fs_update_bb_inode", retval, | ||
103 | _("while updating bad block inode")); | ||
104 | goto fatal; | ||
105 | } | ||
106 | |||
107 | ext2fs_badblocks_list_free(bb_list); | ||
108 | return; | ||
109 | |||
110 | fatal: | ||
111 | ctx->flags |= E2F_FLAG_ABORT; | ||
112 | return; | ||
113 | |||
114 | } | ||
115 | |||
116 | static int check_bb_inode_blocks(ext2_filsys fs, | ||
117 | blk_t *block_nr, | ||
118 | int blockcnt EXT2FS_ATTR((unused)), | ||
119 | void *priv_data EXT2FS_ATTR((unused))) | ||
120 | { | ||
121 | if (!*block_nr) | ||
122 | return 0; | ||
123 | |||
124 | /* | ||
125 | * If the block number is outrageous, clear it and ignore it. | ||
126 | */ | ||
127 | if (*block_nr >= fs->super->s_blocks_count || | ||
128 | *block_nr < fs->super->s_first_data_block) { | ||
129 | printf(_("Warning illegal block %u found in bad block inode. Cleared.\n"), *block_nr); | ||
130 | *block_nr = 0; | ||
131 | return BLOCK_CHANGED; | ||
132 | } | ||
133 | |||
134 | return 0; | ||
135 | } | ||
136 | |||