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