blob: e9ef1cff3cdd805465bc195af325c33ff59d326b [file] [log] [blame]
Theodore Ts'o21c84b71997-04-29 16:15:03 +00001/*
2 * problem.c --- report filesystem problems to the user
3 *
4 * Copyright 1996, 1997 by Theodore Ts'o
5 *
6 * %Begin-Header%
7 * This file may be redistributed under the terms of the GNU Public
8 * License.
9 * %End-Header%
10 */
11
12#include <stdlib.h>
13#include <unistd.h>
14#include <string.h>
15#include <ctype.h>
16#include <termios.h>
17
18#include "e2fsck.h"
19
20#include "problem.h"
Theodore Ts'of8188ff1997-11-14 05:23:04 +000021#include "problemP.h"
Theodore Ts'o21c84b71997-04-29 16:15:03 +000022
Theodore Ts'o1b6bf171997-10-03 17:48:10 +000023#define PROMPT_NONE 0
24#define PROMPT_FIX 1
25#define PROMPT_CLEAR 2
26#define PROMPT_RELOCATE 3
27#define PROMPT_ALLOCATE 4
28#define PROMPT_EXPAND 5
29#define PROMPT_CONNECT 6
30#define PROMPT_CREATE 7
31#define PROMPT_SALVAGE 8
32#define PROMPT_TRUNCATE 9
33#define PROMPT_CLEAR_INODE 10
34#define PROMPT_ABORT 11
35#define PROMPT_SPLIT 12
36#define PROMPT_CONTINUE 13
37#define PROMPT_CLONE 14
38#define PROMPT_DELETE 15
Theodore Ts'of8188ff1997-11-14 05:23:04 +000039#define PROMPT_SUPPRESS 16
Theodore Ts'o21c84b71997-04-29 16:15:03 +000040
41/*
42 * These are the prompts which are used to ask the user if they want
43 * to fix a problem.
44 */
45static const char *prompt[] = {
Theodore Ts'o1b6bf171997-10-03 17:48:10 +000046 "(no prompt)", /* 0 */
47 "Fix", /* 1 */
48 "Clear", /* 2 */
49 "Relocate", /* 3 */
50 "Allocate", /* 4 */
51 "Expand", /* 5 */
52 "Connect to /lost+found", /* 6 */
53 "Create", /* 7 */
54 "Salvage", /* 8 */
55 "Truncate", /* 9 */
56 "Clear inode", /* 10 */
57 "Abort", /* 11 */
58 "Split", /* 12 */
59 "Continue", /* 13 */
60 "Clone duplicate/bad blocks", /* 14 */
61 "Delete file", /* 15 */
Theodore Ts'of8188ff1997-11-14 05:23:04 +000062 "Suppress messages", /* 16 */
Theodore Ts'o1b6bf171997-10-03 17:48:10 +000063};
Theodore Ts'o21c84b71997-04-29 16:15:03 +000064
65/*
66 * These messages are printed when we are preen mode and we will be
67 * automatically fixing the problem.
68 */
69static const char *preen_msg[] = {
Theodore Ts'o1b6bf171997-10-03 17:48:10 +000070 "(NONE)", /* 0 */
71 "FIXED", /* 1 */
72 "CLEARED", /* 2 */
73 "RELOCATED", /* 3 */
74 "ALLOCATED", /* 4 */
75 "EXPANDED", /* 5 */
76 "RECONNECTED", /* 6 */
77 "CREATED", /* 7 */
78 "SALVAGED", /* 8 */
79 "TRUNCATED", /* 9 */
80 "INODE CLEARED", /* 10 */
81 "ABORTED", /* 11 */
82 "SPLIT", /* 12 */
83 "CONTINUING", /* 13 */
84 "DUPLICATE/BAD BLOCKS CLONED", /* 14 */
85 "FILE DELETED", /* 15 */
Theodore Ts'of8188ff1997-11-14 05:23:04 +000086 "SUPPRESSED", /* 16 */
Theodore Ts'o21c84b71997-04-29 16:15:03 +000087};
88
Theodore Ts'o1b6bf171997-10-03 17:48:10 +000089static const struct e2fsck_problem problem_table[] = {
Theodore Ts'o21c84b71997-04-29 16:15:03 +000090
91 /* Pre-Pass 1 errors */
92
93 /* Block bitmap not in group */
94 { PR_0_BB_NOT_GROUP, "@b @B for @g %g is not in @g. (@b %b)\n",
Theodore Ts'o1b6bf171997-10-03 17:48:10 +000095 PROMPT_RELOCATE, PR_LATCH_RELOC },
Theodore Ts'o21c84b71997-04-29 16:15:03 +000096
97 /* Inode bitmap not in group */
98 { PR_0_IB_NOT_GROUP, "@i @B for @g %g is not in @g. (@b %b)\n",
Theodore Ts'o1b6bf171997-10-03 17:48:10 +000099 PROMPT_RELOCATE, PR_LATCH_RELOC },
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000100
101 /* Inode table not in group */
102 { PR_0_ITABLE_NOT_GROUP,
103 "@i table for @g %g is not in @g. (@b %b)\n"
104 "WARNING: SEVERE DATA LOSS POSSIBLE.\n",
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000105 PROMPT_RELOCATE, PR_LATCH_RELOC },
106
107 /* Superblock corrupt */
108 { PR_0_SB_CORRUPT,
109 "\nThe @S could not be read or does not describe a correct ext2\n"
110 "@f. If the device is valid and it really contains an ext2\n"
111 "@f (and not swap or ufs or something else), then the @S\n"
112 "is corrupt, and you might try running e2fsck with an alternate @S:\n"
113 " e2fsck -b %S <device>\n\n",
114 PROMPT_NONE, PR_FATAL },
115
116 /* Filesystem size is wrong */
117 { PR_0_FS_SIZE_WRONG,
118 "The @f size (according to the @S) is %b @bs\n"
119 "The physical size of the device is %c @bs\n"
120 "Either the @S or the partition table is likely to be corrupt!\n",
121 PROMPT_ABORT, 0 },
122
123 /* Fragments not supported */
124 { PR_0_NO_FRAGMENTS,
125 "@S @b_size = %b, fragsize = %c.\n"
126 "This version of e2fsck does not support fragment sizes different\n"
127 "from the @b size.\n",
128 PROMPT_NONE, PR_FATAL },
129
130 /* Bad blocks_per_group */
131 { PR_0_BLOCKS_PER_GROUP,
132 "@S @bs_per_group = %b, should have been %c\n",
133 PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
134
135 /* Bad first_data_block */
136 { PR_0_FIRST_DATA_BLOCK,
137 "@S first_data_@b = %b, should have been %c\n",
138 PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000139
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000140 /* Adding UUID to filesystem */
141 { PR_0_ADD_UUID,
142 "@f did not have a UUID; generating one.\n\n",
143 PROMPT_NONE, 0 },
144
145 /* Relocate hint */
146 { PR_0_RELOCATE_HINT,
147 "Note: if there is several inode or block bitmap blocks\n"
148 "which require relocation, or one part of the inode table\n"
149 "which must be moved, you may wish to try running e2fsck\n"
150 "with the '-b %S' option first. The problem may lie only\n"
151 "with the primary block group descriptor, and the backup\n"
152 "block group descriptor may be OK.\n\n",
153 PROMPT_NONE, PR_PREEN_OK | PR_NOCOLLATE },
154
155 /* Miscellaneous superblock corruption */
156 { PR_0_MISC_CORRUPT_SUPER,
157 "Corruption found in @S. (%s = %N).\n",
158 PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
159
160 /* Error determing physical device size of filesystem */
161 { PR_0_GETSIZE_ERROR,
162 "Error determining size of the physical device: %m\n",
163 PROMPT_NONE, PR_FATAL },
164
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000165 /* Pass 1 errors */
166
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000167 /* Pass 1: Checking inodes, blocks, and sizes */
168 { PR_1_PASS_HEADER,
169 "Pass 1: Checking @is, @bs, and sizes\n",
170 PROMPT_NONE, 0 },
171
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000172 /* Root directory is not an inode */
173 { PR_1_ROOT_NO_DIR, "@r is not a @d. ",
174 PROMPT_CLEAR, 0 },
175
176 /* Root directory has dtime set */
177 { PR_1_ROOT_DTIME,
178 "@r has dtime set (probably due to old mke2fs). ",
179 PROMPT_FIX, PR_PREEN_OK },
180
181 /* Reserved inode has bad mode */
182 { PR_1_RESERVED_BAD_MODE,
183 "Reserved @i %i has bad mode. ",
184 PROMPT_CLEAR, PR_PREEN_OK },
185
186 /* Deleted inode has zero dtime */
187 { PR_1_ZERO_DTIME,
188 "@D @i %i has zero dtime. ",
189 PROMPT_FIX, PR_PREEN_OK },
190
191 /* Inode in use, but dtime set */
192 { PR_1_SET_DTIME,
193 "@i %i is in use, but has dtime set. ",
194 PROMPT_FIX, PR_PREEN_OK },
195
196 /* Zero-length directory */
197 { PR_1_ZERO_LENGTH_DIR,
198 "@i %i is a @z @d. ",
199 PROMPT_CLEAR, PR_PREEN_OK },
200
201 /* Block bitmap conflicts with some other fs block */
202 { PR_1_BB_CONFLICT,
Theodore Ts'oda2e97f1997-06-12 04:28:07 +0000203 "@g %g's @b @B at %b @C.\n",
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000204 PROMPT_RELOCATE, 0 },
205
206 /* Inode bitmap conflicts with some other fs block */
207 { PR_1_IB_CONFLICT,
Theodore Ts'oda2e97f1997-06-12 04:28:07 +0000208 "@g %g's @i @B at %b @C.\n",
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000209 PROMPT_RELOCATE, 0 },
210
211 /* Inode table conflicts with some other fs block */
212 { PR_1_ITABLE_CONFLICT,
213 "@g %g's @i table at %b @C.\n",
214 PROMPT_RELOCATE, 0 },
215
216 /* Block bitmap is on a bad block */
217 { PR_1_BB_BAD_BLOCK,
218 "@g %g's @b @B (%b) is bad. ",
219 PROMPT_RELOCATE, 0 },
220
221 /* Inode bitmap is on a bad block */
222 { PR_1_IB_BAD_BLOCK,
223 "@g %g's @i @B (%b) is bad. ",
224 PROMPT_RELOCATE, 0 },
225
226 /* Inode has incorrect i_size */
227 { PR_1_BAD_I_SIZE,
228 "@i %i, i_size is %Is, @s %N. ",
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000229 PROMPT_FIX, PR_PREEN_OK },
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000230
231 /* Inode has incorrect i_blocks */
232 { PR_1_BAD_I_BLOCKS,
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000233 "@i %i, i_@bs is %Ib, @s %N. ",
234 PROMPT_FIX, PR_PREEN_OK },
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000235
236 /* Illegal block number in inode */
237 { PR_1_ILLEGAL_BLOCK_NUM,
Theodore Ts'o7cf73dc1997-08-14 17:17:16 +0000238 "@I @b #%B (%b) in @i %i. ",
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000239 PROMPT_CLEAR, PR_LATCH_BLOCK },
240
241 /* Block number overlaps fs metadata */
242 { PR_1_BLOCK_OVERLAPS_METADATA,
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000243 "@b #%B (%b) overlaps @f metadata in @i %i. ",
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000244 PROMPT_CLEAR, PR_LATCH_BLOCK },
245
246 /* Inode has illegal blocks (latch question) */
247 { PR_1_INODE_BLOCK_LATCH,
248 "@i %i has illegal @b(s). ",
249 PROMPT_CLEAR, 0 },
250
251 /* Too many bad blocks in inode */
252 { PR_1_TOO_MANY_BAD_BLOCKS,
253 "Too many illegal @bs in @i %i.\n",
254 PROMPT_CLEAR_INODE, PR_NO_OK },
255
256 /* Illegal block number in bad block inode */
257 { PR_1_BB_ILLEGAL_BLOCK_NUM,
Theodore Ts'o7cf73dc1997-08-14 17:17:16 +0000258 "@I @b #%B (%b) in bad @b @i. ",
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000259 PROMPT_CLEAR, PR_LATCH_BBLOCK },
260
261 /* Bad block inode has illegal blocks (latch question) */
262 { PR_1_INODE_BBLOCK_LATCH,
263 "Bad @b @i has illegal @b(s). ",
264 PROMPT_CLEAR, 0 },
265
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000266 /* Duplicate or bad blocks in use! */
267 { PR_1_DUP_BLOCKS_PREENSTOP,
268 "Duplicate or bad @b in use!\n",
269 PROMPT_NONE, 0 },
270
271 /* Bad block used as bad block indirect block */
272 { PR_1_BBINODE_BAD_METABLOCK,
273 "Bad @b %b used as bad @b indirect @b?!?\n",
274 PROMPT_NONE, PR_AFTER_CODE, PR_1_BBINODE_BAD_METABLOCK_PROMPT },
275
276 /* Inconsistency can't be fixed prompt */
277 { PR_1_BBINODE_BAD_METABLOCK_PROMPT,
278 "\nThis inconsistency can not be fixed with e2fsck; to fix it, use\n"
279 """dumpe2fs -b"" to dump out the bad @b "
280 "list and ""e2fsck -L filename""\n"
281 "to read it back in again.\n",
282 PROMPT_CONTINUE, PR_PREEN_NOMSG },
283
284 /* Bad primary block */
285 { PR_1_BAD_PRIMARY_BLOCK,
286 "\nIf the @b is really bad, the @f can not be fixed.\n",
287 PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK_PROMPT },
288
289 /* Bad primary block prompt */
290 { PR_1_BAD_PRIMARY_BLOCK_PROMPT,
291 "You can clear the this @b (and hope for the best) from the\n"
292 "bad @b list and hope that @b is really OK, but there are no\n"
293 "guarantees.\n\n",
294 PROMPT_CLEAR, PR_PREEN_NOMSG },
295
296 /* Bad primary superblock */
297 { PR_1_BAD_PRIMARY_SUPERBLOCK,
298 "The primary @S (%b) is on the bad @b list.\n",
299 PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
300
301 /* Bad primary block group descriptors */
302 { PR_1_BAD_PRIMARY_GROUP_DESCRIPTOR,
303 "Block %b in the primary @g descriptors "
Theodore Ts'of8188ff1997-11-14 05:23:04 +0000304 "is on the bad @b list\n",
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000305 PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
306
307 /* Bad superblock in group */
308 { PR_1_BAD_SUPERBLOCK,
309 "Warning: Group %g's @S (%b) is bad.\n",
310 PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
311
312 /* Bad block group descriptors in group */
313 { PR_1_BAD_GROUP_DESCRIPTORS,
314 "Warning: Group %d's copy of the @g descriptors has a bad "
315 "@b (%b).\n",
316 PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
317
318 /* Block claimed for no reason */
319 { PR_1_PROGERR_CLAIMED_BLOCK,
320 "Programming error? @b #%b claimed for no reason in "
321 "process_bad_@b.\n",
322 PROMPT_NONE, PR_PREEN_OK },
323
Theodore Ts'of8188ff1997-11-14 05:23:04 +0000324 /* Error allocating blocks for relocating metadata */
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000325 { PR_1_RELOC_BLOCK_ALLOCATE,
Theodore Ts'of8188ff1997-11-14 05:23:04 +0000326 "@A %N @b(s) for %s: %m\n",
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000327 PROMPT_NONE, PR_PREEN_OK },
328
Theodore Ts'of8188ff1997-11-14 05:23:04 +0000329 /* Error allocating block buffer during relocation process */
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000330 { PR_1_RELOC_MEMORY_ALLOCATE,
Theodore Ts'of8188ff1997-11-14 05:23:04 +0000331 "@A @b buffer for relocating %s\n",
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000332 PROMPT_NONE, PR_PREEN_OK },
333
334 /* Relocating metadata group information from X to Y */
335 { PR_1_RELOC_FROM_TO,
336 "Relocating @g %g's %s from %b to %c...\n",
337 PROMPT_NONE, PR_PREEN_OK },
338
339 /* Relocating metatdata group information to X */
340 { PR_1_RELOC_TO,
341 "Relocating @g %g's %s to %c...\n",
342 PROMPT_NONE, PR_PREEN_OK },
343
344 /* Block read error during relocation process */
345 { PR_1_RELOC_READ_ERR,
346 "Warning: could not read @b %b of %s: %m\n",
347 PROMPT_NONE, PR_PREEN_OK },
348
349 /* Block write error during relocation process */
350 { PR_1_RELOC_WRITE_ERR,
351 "Warning: could not write @b %b for %s: %m\n",
352 PROMPT_NONE, PR_PREEN_OK },
353
354 /* Error allocating inode bitmap */
355 { PR_1_ALLOCATE_IBITMAP_ERROR,
Theodore Ts'of8188ff1997-11-14 05:23:04 +0000356 "@A @i @B (%N): %m\n",
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000357 PROMPT_NONE, PR_FATAL },
358
359 /* Error allocating block bitmap */
360 { PR_1_ALLOCATE_BBITMAP_ERROR,
Theodore Ts'of8188ff1997-11-14 05:23:04 +0000361 "@A @b @B (%N): %m\n",
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000362 PROMPT_NONE, PR_FATAL },
363
364 /* Error allocating icount structure */
365 { PR_1_ALLOCATE_ICOUNT,
Theodore Ts'of8188ff1997-11-14 05:23:04 +0000366 "@A icount link information: %m\n",
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000367 PROMPT_NONE, PR_FATAL },
368
369 /* Error allocating dbcount */
370 { PR_1_ALLOCATE_DBCOUNT,
Theodore Ts'of8188ff1997-11-14 05:23:04 +0000371 "@A @d @b array: %m\n",
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000372 PROMPT_NONE, PR_FATAL },
373
374 /* Error while scanning inodes */
375 { PR_1_ISCAN_ERROR,
Theodore Ts'of8188ff1997-11-14 05:23:04 +0000376 "Error while scanning @is (%i): %m\n",
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000377 PROMPT_NONE, PR_FATAL },
378
379 /* Error while iterating over blocks */
380 { PR_1_BLOCK_ITERATE,
Theodore Ts'of8188ff1997-11-14 05:23:04 +0000381 "Error while iterating over blocks in @i %i: %m\n",
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000382 PROMPT_NONE, PR_FATAL },
383
384 /* Error while storing inode count information */
385 { PR_1_ICOUNT_STORE,
Theodore Ts'of8188ff1997-11-14 05:23:04 +0000386 "Error storing @i count information (inode=%i, count=%N): %m\n",
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000387 PROMPT_NONE, PR_FATAL },
388
389 /* Error while storing directory block information */
390 { PR_1_ADD_DBLOCK,
Theodore Ts'of8188ff1997-11-14 05:23:04 +0000391 "Error storing @d @b information "
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000392 "(inode=%i, block=%b, num=%N): %m\n",
393 PROMPT_NONE, PR_FATAL },
394
395 /* Error while reading inode (for clearing) */
396 { PR_1_READ_INODE,
Theodore Ts'of8188ff1997-11-14 05:23:04 +0000397 "Error reading @i %i: %m\n",
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000398 PROMPT_NONE, PR_FATAL },
Theodore Ts'of8188ff1997-11-14 05:23:04 +0000399
400 /* Suppress messages prompt */
401 { PR_1_SUPPRESS_MESSAGES, "", PROMPT_SUPPRESS, PR_NO_OK },
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000402
Theodore Ts'o246501c1998-03-24 16:22:38 +0000403 /* Filesystem contains large files, but has no such flag in sb */
404 { PR_1_FEATURE_LARGE_FILES,
405 "@f contains large files, but lacks LARGE_FILE flag in @S.\n",
406 PROMPT_FIX, 0 },
407
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000408 /* Pass 1b errors */
409
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000410 /* Pass 1B: Rescan for duplicate/bad blocks */
411 { PR_1B_PASS_HEADER,
412 "Duplicate @bs found... invoking duplicate @b passes.\n"
413 "Pass 1B: Rescan for duplicate/bad @bs\n",
414 PROMPT_NONE, 0 },
415
416 /* Duplicate/bad block(s) header */
417 { PR_1B_DUP_BLOCK_HEADER,
418 "Duplicate/bad @b(s) in @i %i:",
419 PROMPT_NONE, 0 },
420
421 /* Duplicate/bad block(s) in inode */
422 { PR_1B_DUP_BLOCK,
423 " %b",
424 PROMPT_NONE, PR_LATCH_DBLOCK },
425
426 /* Duplicate/bad block(s) end */
427 { PR_1B_DUP_BLOCK_END,
428 "\n",
429 PROMPT_NONE, 0 },
430
431 /* Error while scanning inodes */
432 { PR_1B_ISCAN_ERROR,
433 "Error while scanning inodes (%i): %m\n",
434 PROMPT_NONE, PR_FATAL },
435
436 /* Error allocating inode bitmap */
437 { PR_1B_ALLOCATE_IBITMAP_ERROR,
Theodore Ts'of8188ff1997-11-14 05:23:04 +0000438 "@A @i @B (inode_dup_map): %m\n",
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000439 PROMPT_NONE, PR_FATAL },
440
441
442 /* Pass 1C: Scan directories for inodes with dup blocks. */
443 { PR_1C_PASS_HEADER,
444 "Pass 1C: Scan directories for @is with dup @bs.\n",
445 PROMPT_NONE, 0 },
446
447
448 /* Pass 1D: Reconciling duplicate blocks */
449 { PR_1D_PASS_HEADER,
450 "Pass 1D: Reconciling duplicate @bs\n",
451 PROMPT_NONE, 0 },
452
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000453 /* File has duplicate blocks */
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000454 { PR_1D_DUP_FILE,
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000455 "File %Q (@i #%i, mod time %IM) \n"
456 " has %B duplicate @b(s), shared with %N file(s):\n",
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000457 PROMPT_NONE, 0 },
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000458
459 /* List of files sharing duplicate blocks */
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000460 { PR_1D_DUP_FILE_LIST,
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000461 "\t%Q (@i #%i, mod time %IM)\n",
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000462 PROMPT_NONE, 0 },
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000463
Theodore Ts'o521e3681997-04-29 17:48:10 +0000464 /* File sharing blocks with filesystem metadata */
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000465 { PR_1D_SHARE_METADATA,
466 "\t<@f metadata>\n",
467 PROMPT_NONE, 0 },
468
469 /* Report of how many duplicate/bad inodes */
470 { PR_1D_NUM_DUP_INODES,
471 "(There are %N @is containing duplicate/bad @bs.)\n\n",
472 PROMPT_NONE, 0 },
473
474 /* Duplicated blocks already reassigned or cloned. */
475 { PR_1D_DUP_BLOCKS_DEALT,
476 "Duplicated @bs already reassigned or cloned.\n\n",
477 PROMPT_NONE, 0 },
478
479 /* Clone duplicate/bad blocks? */
480 { PR_1D_CLONE_QUESTION,
481 "", PROMPT_CLONE, PR_NO_OK },
482
483 /* Delete file? */
484 { PR_1D_DELETE_QUESTION,
485 "", PROMPT_DELETE, 0 },
486
487 /* Couldn't clone file (error) */
488 { PR_1D_CLONE_ERROR,
489 "Couldn't clone file: %m\n", PROMPT_NONE, 0 },
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000490
491 /* Pass 2 errors */
492
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000493 /* Pass 2: Checking directory structure */
494 { PR_2_PASS_HEADER,
495 "Pass 2: Checking @d structure\n",
496 PROMPT_NONE, 0 },
497
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000498 /* Bad inode number for '.' */
499 { PR_2_BAD_INODE_DOT,
500 "Bad @i number for '.' in @d @i %i.\n",
501 PROMPT_FIX, 0 },
502
503 /* Directory entry has bad inode number */
504 { PR_2_BAD_INO,
505 "@E has bad @i #: %Di.\n",
506 PROMPT_CLEAR, 0 },
507
508 /* Directory entry has deleted or unused inode */
509 { PR_2_UNUSED_INODE,
510 "@E has @D/unused @i %Di. ",
511 PROMPT_CLEAR, PR_PREEN_OK },
512
513 /* Directry entry is link to '.' */
514 { PR_2_LINK_DOT,
515 "@E @L to '.' ",
516 PROMPT_CLEAR, 0 },
517
518 /* Directory entry points to inode now located in a bad block */
519 { PR_2_BB_INODE,
520 "@E points to @i (%Di) located in a bad @b.\n",
521 PROMPT_CLEAR, 0 },
522
523 /* Directory entry contains a link to a directory */
524 { PR_2_LINK_DIR,
525 "@E @L to @d %P (%Di).\n",
526 PROMPT_CLEAR, 0 },
527
528 /* Directory entry contains a link to the root directry */
529 { PR_2_LINK_ROOT,
530 "@E @L to the @r.\n",
531 PROMPT_CLEAR, 0 },
532
533 /* Directory entry has illegal characters in its name */
534 { PR_2_BAD_NAME,
535 "@E has illegal characters in its name.\n",
536 PROMPT_FIX, 0 },
537
538 /* Missing '.' in directory inode */
539 { PR_2_MISSING_DOT,
540 "Missing '.' in @d @i %i.\n",
541 PROMPT_FIX, 0 },
542
543 /* Missing '..' in directory inode */
544 { PR_2_MISSING_DOT_DOT,
545 "Missing '..' in @d @i %i.\n",
546 PROMPT_FIX, 0 },
547
548 /* First entry in directory inode doesn't contain '.' */
549 { PR_2_1ST_NOT_DOT,
550 "First @e '%Dn' (inode=%Di) in @d @i %i (%p) @s '.'\n",
551 PROMPT_FIX, 0 },
552
553 /* Second entry in directory inode doesn't contain '..' */
554 { PR_2_2ND_NOT_DOT_DOT,
555 "Second @e '%Dn' (inode=%Di) in @d @i %i @s '..'\n",
556 PROMPT_FIX, 0 },
557
558 /* i_faddr should be zero */
559 { PR_2_FADDR_ZERO,
560 "i_faddr @F %IF, @s zero.\n",
561 PROMPT_CLEAR, 0 },
562
563 /* i_file_acl should be zero */
564 { PR_2_FILE_ACL_ZERO,
565 "i_file_acl @F %If, @s zero.\n",
566 PROMPT_CLEAR, 0 },
567
568 /* i_dir_acl should be zero */
569 { PR_2_DIR_ACL_ZERO,
570 "i_dir_acl @F %Id, @s zero.\n",
571 PROMPT_CLEAR, 0 },
572
573 /* i_frag should be zero */
574 { PR_2_FRAG_ZERO,
575 "i_frag @F %N, @s zero.\n",
576 PROMPT_CLEAR, 0 },
577
578 /* i_fsize should be zero */
579 { PR_2_FSIZE_ZERO,
580 "i_fsize @F %N, @s zero.\n",
581 PROMPT_CLEAR, 0 },
582
583 /* inode has bad mode */
584 { PR_2_BAD_MODE,
585 "@i %i (%Q) has a bad mode (%Im).\n",
586 PROMPT_CLEAR, 0 },
587
588 /* directory corrupted */
589 { PR_2_DIR_CORRUPTED,
590 "@d @i %i, @b %B, offset %N: @d corrupted\n",
591 PROMPT_SALVAGE, 0 },
592
593 /* filename too long */
594 { PR_2_FILENAME_LONG,
595 "@d @i %i, @b %B, offset %N: filename too long\n",
596 PROMPT_TRUNCATE, 0 },
597
598 /* Directory inode has a missing block (hole) */
599 { PR_2_DIRECTORY_HOLE,
600 "@d @i %i has an unallocated @b #%B. ",
601 PROMPT_ALLOCATE, 0 },
602
603 /* '.' is not NULL terminated */
604 { PR_2_DOT_NULL_TERM,
Theodore Ts'of8188ff1997-11-14 05:23:04 +0000605 "'.' @d @e in @d @i %i is not NULL terminated\n",
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000606 PROMPT_FIX, 0 },
607
608 /* '..' is not NULL terminated */
609 { PR_2_DOT_DOT_NULL_TERM,
Theodore Ts'of8188ff1997-11-14 05:23:04 +0000610 "'..' @d @e in @d @i %i is not NULL terminated\n",
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000611 PROMPT_FIX, 0 },
612
Theodore Ts'o7cf73dc1997-08-14 17:17:16 +0000613 /* Illegal character device inode */
614 { PR_2_BAD_CHAR_DEV,
615 "@i %i (%Q) is an @I character device.\n",
616 PROMPT_CLEAR, 0 },
617
618 /* Illegal block device inode */
619 { PR_2_BAD_BLOCK_DEV,
620 "@i %i (%Q) is an @I @b device.\n",
621 PROMPT_CLEAR, 0 },
622
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000623 /* Duplicate '.' entry */
624 { PR_2_DUP_DOT,
625 "@E is duplicate '.' @e.\n",
626 PROMPT_FIX, 0 },
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000627
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000628 /* Duplicate '..' entry */
629 { PR_2_DUP_DOT_DOT,
630 "@E is duplicate '..' @e.\n",
631 PROMPT_FIX, 0 },
632
633 /* Internal error: couldn't find dir_info */
634 { PR_2_NO_DIRINFO,
635 "Internal error: couldn't find dir_info for %i.\n",
636 PROMPT_NONE, PR_FATAL },
637
638 /* Final rec_len is wrong */
639 { PR_2_FINAL_RECLEN,
640 "@E has rec_len of %dr, should be %N.\n",
641 PROMPT_FIX, 0 },
642
643 /* Error allocating icount structure */
644 { PR_2_ALLOCATE_ICOUNT,
Theodore Ts'of8188ff1997-11-14 05:23:04 +0000645 "@A icount structure: %m\n",
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000646 PROMPT_NONE, PR_FATAL },
647
648 /* Error iterating over directory blocks */
649 { PR_2_DBLIST_ITERATE,
Theodore Ts'of8188ff1997-11-14 05:23:04 +0000650 "Error interating over @d @bs: %m\n",
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000651 PROMPT_NONE, PR_FATAL },
652
653 /* Error reading directory block */
654 { PR_2_READ_DIRBLOCK,
Theodore Ts'of8188ff1997-11-14 05:23:04 +0000655 "Error reading @d @b %b (@i %i): %m\n",
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000656 PROMPT_CONTINUE, 0 },
657
658 /* Error writing directory block */
659 { PR_2_WRITE_DIRBLOCK,
Theodore Ts'of8188ff1997-11-14 05:23:04 +0000660 "Error writing @d @b %b (@i %i): %m\n",
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000661 PROMPT_CONTINUE, 0 },
662
663 /* Error allocating new directory block */
664 { PR_2_ALLOC_DIRBOCK,
Theodore Ts'of8188ff1997-11-14 05:23:04 +0000665 "@A new @d @b for @i %i (%s): %m\n",
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000666 PROMPT_NONE, 0 },
667
668 /* Error deallocating inode */
669 { PR_2_DEALLOC_INODE,
Theodore Ts'of8188ff1997-11-14 05:23:04 +0000670 "Error deallocating @i %i: %m\n",
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000671 PROMPT_NONE, PR_FATAL },
672
Theodore Ts'of8188ff1997-11-14 05:23:04 +0000673 /* Directory entry for '.' is big. Split? */
674 { PR_2_SPLIT_DOT,
675 "@d @e for '.' is big. ",
676 PROMPT_SPLIT, PR_NO_OK },
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000677
Theodore Ts'o1dde43f1998-11-14 04:18:28 +0000678 /* Illegal FIFO inode */
679 { PR_2_BAD_FIFO,
680 "@i %i (%Q) is an @I FIFO.\n",
681 PROMPT_CLEAR, 0 },
682
683 /* Illegal socket inode */
684 { PR_2_BAD_SOCKET,
685 "@i %i (%Q) is an @I socket.\n",
686 PROMPT_CLEAR, 0 },
687
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000688 /* Pass 3 errors */
689
690 /* Pass 3: Checking directory connectivity */
691 { PR_3_PASS_HEADER,
692 "Pass 3: Checking @d connectivity\n",
693 PROMPT_NONE, 0 },
694
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000695 /* Root inode not allocated */
696 { PR_3_NO_ROOT_INODE,
697 "@r not allocated. ",
698 PROMPT_ALLOCATE, 0 },
699
700 /* No room in lost+found */
701 { PR_3_EXPAND_LF_DIR,
702 "No room in @l @d. ",
703 PROMPT_EXPAND, 0 },
704
705 /* Unconnected directory inode */
706 { PR_3_UNCONNECTED_DIR,
707 "Unconnected @d @i %i (%p)\n",
708 PROMPT_CONNECT, 0 },
709
710 /* /lost+found not found */
711 { PR_3_NO_LF_DIR,
712 "/@l not found. ",
713 PROMPT_CREATE, 0 },
714
715 /* .. entry is incorrect */
716 { PR_3_BAD_DOT_DOT,
717 "'..' in %Q (%i) is %P (%j), @s %q (%d).\n",
718 PROMPT_FIX, 0 },
719
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000720 /* Bad or non-existent /lost+found. Cannot reconnect */
721 { PR_3_NO_LPF,
722 "Bad or non-existent /@l. Cannot reconnect\n",
723 PROMPT_NONE, 0 },
724
725 /* Could not expand /lost+found */
726 { PR_3_CANT_EXPAND_LPF,
727 "Could not expand /@l: %m\n",
728 PROMPT_NONE, 0 },
729
730 /* Could not reconnect inode */
731 { PR_3_CANT_RECONNECT,
732 "Could not reconnect %i: %m\n",
733 PROMPT_NONE, 0 },
734
735 /* Error while trying to find /lost+found */
736 { PR_3_ERR_FIND_LPF,
737 "Error while trying to find /@l: %m\n",
738 PROMPT_NONE, 0 },
739
740 /* Error in ext2fs_new_block while creating /lost+found */
741 { PR_3_ERR_LPF_NEW_BLOCK,
742 "ext2fs_new_@b: %m while trying to create /@l @d\n",
743 PROMPT_NONE, 0 },
744
745 /* Error in ext2fs_new_inode while creating /lost+found */
746 { PR_3_ERR_LPF_NEW_INODE,
747 "ext2fs_new_@i: %m while trying to create /@l @d\n",
748 PROMPT_NONE, 0 },
749
750 /* Error in ext2fs_new_dir_block while creating /lost+found */
751 { PR_3_ERR_LPF_NEW_DIR_BLOCK,
752 "ext2fs_new_dir_@b: %m while creating new @d @b\n",
753 PROMPT_NONE, 0 },
754
755 /* Error while writing directory block for /lost+found */
756 { PR_3_ERR_LPF_WRITE_BLOCK,
757 "ext2fs_write_dir_@b: %m while writing the @d @b for /@l\n",
758 PROMPT_NONE, 0 },
759
760 /* Error while adjusting inode count */
761 { PR_3_ADJUST_INODE,
762 "Error while adjusting @i count on @i %i\n",
763 PROMPT_NONE, 0 },
764
765 /* Couldn't fix parent directory -- error */
766 { PR_3_FIX_PARENT_ERR,
767 "Couldn't fix parent of @i %i: %m\n\n",
768 PROMPT_NONE, 0 },
769
770 /* Couldn't fix parent directory -- couldn't find it */
771 { PR_3_FIX_PARENT_NOFIND,
772 "Couldn't fix parent of @i %i: Couldn't find parent @d entry\n\n",
773 PROMPT_NONE, 0 },
774
775 /* Error allocating inode bitmap */
776 { PR_3_ALLOCATE_IBITMAP_ERROR,
Theodore Ts'of8188ff1997-11-14 05:23:04 +0000777 "@A @i @B (%N): %m\n",
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000778 PROMPT_NONE, PR_FATAL },
779
780 /* Error creating root directory */
781 { PR_3_CREATE_ROOT_ERROR,
782 "Error creating root @d (%s): %m\n",
783 PROMPT_NONE, PR_FATAL },
784
785 /* Error creating lost and found directory */
786 { PR_3_CREATE_LPF_ERROR,
787 "Error creating /@l @d (%s): %m\n",
788 PROMPT_NONE, PR_FATAL },
789
Theodore Ts'of8188ff1997-11-14 05:23:04 +0000790 /* Root inode is not directory; aborting */
791 { PR_3_ROOT_NOT_DIR_ABORT,
792 "@r is not a @d; aborting.\n",
793 PROMPT_NONE, PR_FATAL },
794
795 /* Cannot proceed without a root inode. */
796 { PR_3_NO_ROOT_INODE_ABORT,
797 "Cannot proceed without a @r.\n",
798 PROMPT_NONE, PR_FATAL },
799
Theodore Ts'o7f813ba1998-09-03 01:26:03 +0000800 /* Internal error: couldn't find dir_info */
801 { PR_3_NO_DIRINFO,
802 "Internal error: couldn't find dir_info for %i.\n",
803 PROMPT_NONE, PR_FATAL },
804
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000805 /* Pass 4 errors */
806
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000807 /* Pass 4: Checking reference counts */
808 { PR_4_PASS_HEADER,
809 "Pass 4: Checking reference counts\n",
810 PROMPT_NONE, 0 },
811
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000812 /* Unattached zero-length inode */
813 { PR_4_ZERO_LEN_INODE,
814 "@u @z @i %i. ",
815 PROMPT_CLEAR, PR_PREEN_OK|PR_NO_OK },
816
817 /* Unattached inode */
818 { PR_4_UNATTACHED_INODE,
819 "@u @i %i\n",
820 PROMPT_CONNECT, 0 },
821
822 /* Inode ref count wrong */
823 { PR_4_BAD_REF_COUNT,
824 "@i %i ref count is %Il, @s %N. ",
825 PROMPT_FIX, PR_PREEN_OK },
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000826
827 { PR_4_INCONSISTENT_COUNT,
828 "WARNING: PROGRAMMING BUG IN E2FSCK!\n"
829 "\tOR SOME BONEHEAD (YOU) IS CHECKING A MOUNTED (LIVE) FILESYSTEM.\n"
830 "@i_link_info[%i] is %N, @i.i_links_count is %Il. "
831 "They should be the same!\n",
832 PROMPT_NONE, 0 },
833
834 /* Pass 5 errors */
835
836 /* Pass 5: Checking group summary information */
837 { PR_5_PASS_HEADER,
838 "Pass 5: Checking @g summary information\n",
839 PROMPT_NONE, 0 },
840
841 /* Padding at end of inode bitmap is not set. */
842 { PR_5_INODE_BMAP_PADDING,
843 "Padding at end of @i @B is not set. ",
844 PROMPT_FIX, PR_PREEN_OK },
845
846 /* Padding at end of block bitmap is not set. */
847 { PR_5_BLOCK_BMAP_PADDING,
848 "Padding at end of @b @B is not set. ",
849 PROMPT_FIX, PR_PREEN_OK },
850
851 /* Block bitmap differences header */
852 { PR_5_BLOCK_BITMAP_HEADER,
853 "@b @B differences: ",
854 PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG},
855
856 /* Block not used, but marked in bitmap */
857 { PR_5_UNUSED_BLOCK,
858 " -%b",
859 PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
860
861 /* Block used, but not marked used in bitmap */
862 { PR_5_BLOCK_USED,
863 " +%b",
864 PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
865
866 /* Block bitmap differences end */
867 { PR_5_BLOCK_BITMAP_END,
868 "\n",
869 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
870
871 /* Inode bitmap differences header */
872 { PR_5_INODE_BITMAP_HEADER,
873 "@i @B differences: ",
874 PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
875
876 /* Inode not used, but marked in bitmap */
877 { PR_5_UNUSED_INODE,
878 " -%i",
879 PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
880
881 /* Inode used, but not marked used in bitmap */
882 { PR_5_INODE_USED,
883 " +%i",
884 PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
885
886 /* Inode bitmap differences end */
887 { PR_5_INODE_BITMAP_END,
888 "\n",
889 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
890
891 /* Free inodes count for group wrong */
892 { PR_5_FREE_INODE_COUNT_GROUP,
893 "Free @is count wrong for @g #%g (%i, counted=%j).\n",
894 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
895
896 /* Directories count for group wrong */
897 { PR_5_FREE_DIR_COUNT_GROUP,
898 "Directories count wrong for @g #%g (%i, counted=%j).\n",
899 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
900
901 /* Free inodes count wrong */
902 { PR_5_FREE_INODE_COUNT,
903 "Free @is count wrong (%i, counted=%j).\n",
904 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
905
906 /* Free blocks count for group wrong */
907 { PR_5_FREE_BLOCK_COUNT_GROUP,
908 "Free @bs count wrong for @g #%g (%b, counted=%c).\n",
909 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
910
911 /* Free blocks count wrong */
912 { PR_5_FREE_BLOCK_COUNT,
913 "Free @bs count wrong (%b, counted=%c).\n",
914 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
915
916 /* Programming error: bitmap endpoints don't match */
917 { PR_5_BMAP_ENDPOINTS,
918 "PROGRAMMING ERROR: @f (#%N) @B endpoints (%b, %c) don't "
919 "match calculated @B endpoints (%i, %j)\n",
920 PROMPT_NONE, PR_FATAL },
921
922 /* Internal error: fudging end of bitmap */
923 { PR_5_FUDGE_BITMAP_ERROR,
924 "Internal error: fudging end of bitmap (%N)\n",
925 PROMPT_NONE, PR_FATAL },
926
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000927 { 0 }
928};
929
930/*
931 * This is the latch flags register. It allows several problems to be
932 * "latched" together. This means that the user has to answer but one
933 * question for the set of problems, and all of the associated
934 * problems will be either fixed or not fixed.
935 */
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000936static struct latch_descr pr_latch_info[] = {
937 { PR_LATCH_BLOCK, PR_1_INODE_BLOCK_LATCH, 0 },
938 { PR_LATCH_BBLOCK, PR_1_INODE_BBLOCK_LATCH, 0 },
939 { PR_LATCH_IBITMAP, PR_5_INODE_BITMAP_HEADER, PR_5_INODE_BITMAP_END },
940 { PR_LATCH_BBITMAP, PR_5_BLOCK_BITMAP_HEADER, PR_5_BLOCK_BITMAP_END },
941 { PR_LATCH_RELOC, PR_0_RELOCATE_HINT, 0 },
942 { PR_LATCH_DBLOCK, PR_1B_DUP_BLOCK_HEADER, PR_1B_DUP_BLOCK_END },
943 { -1, 0, 0 },
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000944};
945
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000946static const struct e2fsck_problem *find_problem(int code)
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000947{
948 int i;
949
950 for (i=0; problem_table[i].e2p_code; i++) {
951 if (problem_table[i].e2p_code == code)
952 return &problem_table[i];
953 }
954 return 0;
955}
956
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000957static struct latch_descr *find_latch(int code)
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000958{
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000959 int i;
960
961 for (i=0; pr_latch_info[i].latch_code >= 0; i++) {
962 if (pr_latch_info[i].latch_code == code)
963 return &pr_latch_info[i];
964 }
965 return 0;
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000966}
967
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000968int end_problem_latch(e2fsck_t ctx, int mask)
Theodore Ts'o21c84b71997-04-29 16:15:03 +0000969{
Theodore Ts'o1b6bf171997-10-03 17:48:10 +0000970 struct latch_descr *ldesc;
971 struct problem_context pctx;
972 int answer = -1;
973
974 ldesc = find_latch(mask);
975 if (ldesc->end_message && (ldesc->flags & PRL_LATCHED)) {
976 clear_problem_context(&pctx);
977 answer = fix_problem(ctx, ldesc->end_message, &pctx);
978 }
979 ldesc->flags &= ~(PRL_VARIABLE);
980 return answer;
981}
982
983int set_latch_flags(int mask, int setflags, int clearflags)
984{
985 struct latch_descr *ldesc;
986
987 ldesc = find_latch(mask);
988 if (!ldesc)
989 return -1;
990 ldesc->flags |= setflags;
991 ldesc->flags &= ~clearflags;
992 return 0;
993}
994
995int get_latch_flags(int mask, int *value)
996{
997 struct latch_descr *ldesc;
998
999 ldesc = find_latch(mask);
1000 if (!ldesc)
1001 return -1;
1002 *value = ldesc->flags;
1003 return 0;
Theodore Ts'o21c84b71997-04-29 16:15:03 +00001004}
1005
1006void clear_problem_context(struct problem_context *ctx)
1007{
1008 memset(ctx, 0, sizeof(struct problem_context));
1009 ctx->blkcount = -1;
1010 ctx->group = -1;
1011}
1012
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001013int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx)
Theodore Ts'o21c84b71997-04-29 16:15:03 +00001014{
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001015 ext2_filsys fs = ctx->fs;
1016 const struct e2fsck_problem *ptr;
1017 struct latch_descr *ldesc = 0;
1018 const char *message;
1019 int def_yn, answer, ans;
Theodore Ts'o21c84b71997-04-29 16:15:03 +00001020 int print_answer = 0;
1021 int suppress = 0;
1022
1023 ptr = find_problem(code);
1024 if (!ptr) {
1025 printf("Unhandled error code (%d)!\n", code);
1026 return 0;
1027 }
1028 def_yn = (ptr->flags & PR_NO_DEFAULT) ? 0 : 1;
1029
1030 /*
1031 * Do special latch processing. This is where we ask the
1032 * latch question, if it exists
1033 */
1034 if (ptr->flags & PR_LATCH_MASK) {
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001035 ldesc = find_latch(ptr->flags & PR_LATCH_MASK);
1036 if (ldesc->question && !(ldesc->flags & PRL_LATCHED)) {
1037 ans = fix_problem(ctx, ldesc->question, pctx);
1038 if (ans == 1)
1039 ldesc->flags |= PRL_YES;
1040 if (ans == 0)
1041 ldesc->flags |= PRL_NO;
1042 ldesc->flags |= PRL_LATCHED;
1043 }
1044 if (ldesc->flags & PRL_SUPPRESS)
Theodore Ts'o21c84b71997-04-29 16:15:03 +00001045 suppress++;
1046 }
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001047 if ((ptr->flags & PR_PREEN_NOMSG) &&
1048 (ctx->options & E2F_OPT_PREEN))
1049 suppress++;
Theodore Ts'o21c84b71997-04-29 16:15:03 +00001050 if (!suppress) {
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001051 message = ptr->e2p_description;
1052 if (ctx->options & E2F_OPT_PREEN) {
1053 printf("%s: ", ctx->device_name);
1054#if 0
1055 if (ptr->e2p_preen_msg)
1056 message = ptr->e2p_preen_msg;
1057#endif
1058 }
1059 print_e2fsck_message(ctx, message, pctx, 1);
Theodore Ts'o21c84b71997-04-29 16:15:03 +00001060 }
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001061 if (!(ptr->flags & PR_PREEN_OK) && (ptr->prompt != PROMPT_NONE))
1062 preenhalt(ctx);
Theodore Ts'o21c84b71997-04-29 16:15:03 +00001063
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001064 if (ptr->flags & PR_FATAL)
Theodore Ts'of8188ff1997-11-14 05:23:04 +00001065 fatal_error(ctx, 0);
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001066
1067 if (ptr->prompt == PROMPT_NONE) {
1068 if (ptr->flags & PR_NOCOLLATE)
1069 answer = -1;
Theodore Ts'o21c84b71997-04-29 16:15:03 +00001070 else
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001071 answer = def_yn;
1072 } else {
1073 if (ctx->options & E2F_OPT_PREEN) {
1074 answer = def_yn;
1075 if (!(ptr->flags & PR_PREEN_NOMSG))
1076 print_answer = 1;
1077 } else if ((ptr->flags & PR_LATCH_MASK) &&
1078 (ldesc->flags & (PRL_YES | PRL_NO))) {
1079 if (!suppress)
1080 print_answer = 1;
1081 if (ldesc->flags & PRL_YES)
1082 answer = 1;
1083 else
1084 answer = 0;
1085 } else
1086 answer = ask(ctx, prompt[(int) ptr->prompt], def_yn);
1087 if (!answer && !(ptr->flags & PR_NO_OK))
1088 ext2fs_unmark_valid(fs);
Theodore Ts'o21c84b71997-04-29 16:15:03 +00001089
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001090 if (print_answer)
1091 printf("%s.\n", answer ?
1092 preen_msg[(int) ptr->prompt] : "IGNORED");
Theodore Ts'o21c84b71997-04-29 16:15:03 +00001093
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001094 }
1095
1096 if (ptr->flags & PR_AFTER_CODE)
1097 (void) fix_problem(ctx, ptr->second_code, pctx);
1098
Theodore Ts'of8188ff1997-11-14 05:23:04 +00001099 if ((ptr->prompt == PROMPT_ABORT) && answer)
1100 fatal_error(ctx, 0);
Theodore Ts'o1b6bf171997-10-03 17:48:10 +00001101
Theodore Ts'o21c84b71997-04-29 16:15:03 +00001102 return answer;
1103}