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