Whamcloud - gitweb
aaaa2708603ac54de312c6947fae75d867601a47
[tools/e2fsprogs.git] / e2fsck / problem.c
1 /*
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"
21 #include "problemP.h"
22
23 #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
39 #define PROMPT_SUPPRESS 16
40 #define PROMPT_UNLINK   17
41 #define PROMPT_NULL     18
42
43 /*
44  * These are the prompts which are used to ask the user if they want
45  * to fix a problem.
46  */
47 static const char *prompt[] = {
48         N_("(no prompt)"),      /* 0 */
49         N_("Fix"),              /* 1 */
50         N_("Clear"),            /* 2 */
51         N_("Relocate"),         /* 3 */
52         N_("Allocate"),         /* 4 */
53         N_("Expand"),           /* 5 */
54         N_("Connect to /lost+found"), /* 6 */
55         N_("Create"),           /* 7 */ 
56         N_("Salvage"),          /* 8 */
57         N_("Truncate"),         /* 9 */
58         N_("Clear inode"),      /* 10 */
59         N_("Abort"),            /* 11 */
60         N_("Split"),            /* 12 */
61         N_("Continue"),         /* 13 */
62         N_("Clone duplicate/bad blocks"), /* 14 */
63         N_("Delete file"),      /* 15 */
64         N_("Suppress messages"),/* 16 */
65         N_("Unlink"),           /* 17 */
66         "",                     /* 18 */
67 };
68
69 /*
70  * These messages are printed when we are preen mode and we will be
71  * automatically fixing the problem.
72  */
73 static const char *preen_msg[] = {
74         N_("(NONE)"),           /* 0 */
75         N_("FIXED"),            /* 1 */
76         N_("CLEARED"),          /* 2 */
77         N_("RELOCATED"),        /* 3 */
78         N_("ALLOCATED"),        /* 4 */
79         N_("EXPANDED"),         /* 5 */
80         N_("RECONNECTED"),      /* 6 */
81         N_("CREATED"),          /* 7 */
82         N_("SALVAGED"),         /* 8 */
83         N_("TRUNCATED"),        /* 9 */
84         N_("INODE CLEARED"),    /* 10 */
85         N_("ABORTED"),          /* 11 */
86         N_("SPLIT"),            /* 12 */
87         N_("CONTINUING"),       /* 13 */
88         N_("DUPLICATE/BAD BLOCKS CLONED"), /* 14 */
89         N_("FILE DELETED"),     /* 15 */
90         N_("SUPPRESSED"),       /* 16 */
91         N_("UNLINKED"),         /* 17 */
92 };
93
94 static const struct e2fsck_problem problem_table[] = {
95
96         /* Pre-Pass 1 errors */
97
98         /* Block bitmap not in group */
99         { PR_0_BB_NOT_GROUP, N_("@b @B for @g %g is not in @g.  (@b %b)\n"),
100           PROMPT_RELOCATE, PR_LATCH_RELOC }, 
101
102         /* Inode bitmap not in group */
103         { PR_0_IB_NOT_GROUP, N_("@i @B for @g %g is not in @g.  (@b %b)\n"),
104           PROMPT_RELOCATE, PR_LATCH_RELOC }, 
105
106         /* Inode table not in group */
107         { PR_0_ITABLE_NOT_GROUP,
108           N_("@i table for @g %g is not in @g.  (@b %b)\n"
109           "WARNING: SEVERE DATA LOSS POSSIBLE.\n"),
110           PROMPT_RELOCATE, PR_LATCH_RELOC },
111
112         /* Superblock corrupt */
113         { PR_0_SB_CORRUPT,
114           N_("\nThe @S could not be read or does not describe a correct ext2\n"
115           "@f.  If the @v is valid and it really contains an ext2\n"
116           "@f (and not swap or ufs or something else), then the @S\n"
117           "is corrupt, and you might try running e2fsck with an alternate @S:\n"
118           "    e2fsck -b %S <@v>\n\n"),
119           PROMPT_NONE, PR_FATAL },
120
121         /* Filesystem size is wrong */
122         { PR_0_FS_SIZE_WRONG,
123           N_("The @f size (according to the @S) is %b @bs\n"
124           "The physical size of the @v is %c @bs\n"
125           "Either the @S or the partition table is likely to be corrupt!\n"),
126           PROMPT_ABORT, 0 },
127
128         /* Fragments not supported */             
129         { PR_0_NO_FRAGMENTS,
130           N_("@S @b_size = %b, fragsize = %c.\n"
131           "This version of e2fsck does not support fragment sizes different\n"
132           "from the @b size.\n"),
133           PROMPT_NONE, PR_FATAL },
134
135           /* Bad blocks_per_group */
136         { PR_0_BLOCKS_PER_GROUP,
137           N_("@S @bs_per_group = %b, should have been %c\n"),
138           PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
139
140         /* Bad first_data_block */
141         { PR_0_FIRST_DATA_BLOCK,
142           N_("@S first_data_@b = %b, should have been %c\n"),
143           PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
144         
145         /* Adding UUID to filesystem */
146         { PR_0_ADD_UUID,
147           N_("@f did not have a UUID; generating one.\n\n"),
148           PROMPT_NONE, 0 },
149
150         /* Relocate hint */
151         { PR_0_RELOCATE_HINT,
152           N_("Note: if there is several inode or block bitmap blocks\n"
153           "which require relocation, or one part of the inode table\n"
154           "which must be moved, you may wish to try running e2fsck\n"
155           "with the '-b %S' option first.  The problem may lie only\n"
156           "with the primary block group descriptor, and the backup\n"
157           "block group descriptor may be OK.\n\n"),
158           PROMPT_NONE, PR_PREEN_OK | PR_NOCOLLATE },
159
160         /* Miscellaneous superblock corruption */
161         { PR_0_MISC_CORRUPT_SUPER,
162           N_("Corruption found in @S.  (%s = %N).\n"),
163           PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
164
165         /* Error determing physical device size of filesystem */
166         { PR_0_GETSIZE_ERROR,     
167           N_("Error determining size of the physical @v: %m\n"),
168           PROMPT_NONE, PR_FATAL },
169
170         /* Inode count in superblock is incorrect */
171         { PR_0_INODE_COUNT_WRONG,
172           N_("@i count in @S is %i, should be %j.\n"),
173           PROMPT_FIX, 0 },
174
175         { PR_0_HURD_CLEAR_FILETYPE,
176           N_("The Hurd does not support the filetype feature.\n"),
177           PROMPT_CLEAR, 0 },
178
179         /* Journal inode is invalid */
180         { PR_0_JOURNAL_BAD_INODE,
181           N_("@S has a bad ext3 @j (@i %i).\n"),
182           PROMPT_CLEAR, PR_PREEN_OK },
183
184         /* The external journal has (unsupported) multiple filesystems */
185         { PR_0_JOURNAL_UNSUPP_MULTIFS,
186           N_("External @j has multiple @f users (unsupported).\n"),
187           PROMPT_NONE, PR_FATAL },
188
189         /* Can't find external journal */
190         { PR_0_CANT_FIND_JOURNAL,
191           N_("Can't find external @j\n"),
192           PROMPT_NONE, PR_FATAL },
193
194         /* External journal has bad superblock */
195         { PR_0_EXT_JOURNAL_BAD_SUPER,
196           N_("External @j has bad @S\n"),
197           PROMPT_NONE, PR_FATAL },
198
199         /* Superblock has a bad journal UUID */
200         { PR_0_JOURNAL_BAD_UUID,
201           N_("External @j does not support this @f\n"),
202           PROMPT_NONE, PR_FATAL },
203
204         /* Journal has an unknown superblock type */
205         { PR_0_JOURNAL_UNSUPP_SUPER,
206           N_("Ext3 @j @S is unknown type %N (unsupported).\n"
207              "It is likely that your copy of e2fsck is old and/or doesn't "
208              "support this @j format.\n"
209              "It is also possible the @j @S is corrupt.\n"),
210           PROMPT_ABORT, PR_NO_OK | PR_AFTER_CODE, PR_0_JOURNAL_BAD_SUPER },
211
212         /* Journal superblock is corrupt */
213         { PR_0_JOURNAL_BAD_SUPER,
214           N_("Ext3 @j @S is corrupt.\n"),
215           PROMPT_FIX, PR_PREEN_OK },
216
217         /* Superblock flag should be cleared */
218         { PR_0_JOURNAL_HAS_JOURNAL,
219           N_("@S doesn't have has_@j flag, but has ext3 @j %s.\n"),
220           PROMPT_CLEAR, PR_PREEN_OK },
221
222         /* Superblock flag is incorrect */
223         { PR_0_JOURNAL_RECOVER_SET,
224           N_("@S has ext3 needs_recovery flag set, but no @j.\n"),
225           PROMPT_CLEAR, PR_PREEN_OK },
226
227         /* Journal has data, but recovery flag is clear */
228         { PR_0_JOURNAL_RECOVERY_CLEAR,
229           N_("ext3 recovery flag clear, but @j has data.\n"),
230           PROMPT_NONE, 0 },
231
232         /* Ask if we should clear the journal */
233         { PR_0_JOURNAL_RESET_JOURNAL,
234           N_("Clear @j"),
235           PROMPT_NULL, PR_PREEN_NOMSG },
236
237         /* Ask if we should run the journal anyway */
238         { PR_0_JOURNAL_RUN,
239           N_("Run @j anyway"),
240           PROMPT_NULL, 0 },
241
242         /* Run the journal by default */
243         { PR_0_JOURNAL_RUN_DEFAULT,
244           N_("Recovery flag not set in backup @S, so running @j anyway.\n"),
245           PROMPT_NONE, 0 },
246
247         /* Clearing orphan inode */
248         { PR_0_ORPHAN_CLEAR_INODE,
249           N_("%s @o @i %i (uid=%Iu, gid=%Ig, mode=%Im, size=%Is)\n"),
250           PROMPT_NONE, 0 },
251
252         /* Illegal block found in orphaned inode */
253         { PR_0_ORPHAN_ILLEGAL_BLOCK_NUM,
254            N_("@I @b #%B (%b) found in @o @i %i.\n"),
255           PROMPT_NONE, 0 },
256                   
257         /* Already cleared block found in orphaned inode */
258         { PR_0_ORPHAN_ALREADY_CLEARED_BLOCK,
259            N_("Already cleared @b #%B (%b) found in @o @i %i.\n"),
260           PROMPT_NONE, 0 },
261   
262         /* Illegal orphan inode in superblock */
263         { PR_0_ORPHAN_ILLEGAL_HEAD_INODE,
264           N_("@I @o @i %i in @S.\n"),
265           PROMPT_NONE, 0 },
266
267         /* Illegal inode in orphaned inode list */
268         { PR_0_ORPHAN_ILLEGAL_INODE,
269           N_("@I @i %i in @o @i list.\n"),
270           PROMPT_NONE, 0 },
271
272         /* Filesystem revision is 0, but feature flags are set */
273         { PR_0_FS_REV_LEVEL,
274           "@f has feature flag(s) set, but is a revision 0 @f.  ",
275           PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
276
277         /* Journal superblock has an unknown read-only feature flag set */
278         { PR_0_JOURNAL_UNSUPP_ROCOMPAT,
279           N_("Ext3 @j @S has an unknown read-only feature flag set.\n"),
280           PROMPT_ABORT, 0 },
281
282         /* Journal superblock has an unknown incompatible feature flag set */
283         { PR_0_JOURNAL_UNSUPP_INCOMPAT,
284           N_("Ext3 @j @S has an unknown incompatible feature flag set.\n"),
285           PROMPT_ABORT, 0 },
286
287         /* Journal has unsupported version number */
288         { PR_0_JOURNAL_UNSUPP_VERSION,
289           N_("@j version not supported by this e2fsck.\n"),
290           PROMPT_ABORT, 0 },
291
292         /* Moving journal to hidden file */
293         { PR_0_MOVE_JOURNAL,
294           N_("Moving @j from /%s to hidden inode.\n\n"),
295           PROMPT_NONE, 0 },
296
297         /* Error moving journal to hidden file */
298         { PR_0_ERR_MOVE_JOURNAL,
299           N_("Error moving @j: %m\n\n"),
300           PROMPT_NONE, 0 },
301
302         /* Clearing V2 journal superblock */
303         { PR_0_CLEAR_V2_JOURNAL,
304           N_("Found invalid V2 @j @S fields (from V1 journal).\n"
305              "Clearing fields beyond the V1 @j @S...\n\n"),
306           PROMPT_NONE, 0 },
307
308         /* Pass 1 errors */
309         
310         /* Pass 1: Checking inodes, blocks, and sizes */
311         { PR_1_PASS_HEADER,
312           N_("Pass 1: Checking @is, @bs, and sizes\n"),
313           PROMPT_NONE, 0 },
314                   
315         /* Root directory is not an inode */
316         { PR_1_ROOT_NO_DIR, N_("@r is not a @d.  "),
317           PROMPT_CLEAR, 0 }, 
318
319         /* Root directory has dtime set */
320         { PR_1_ROOT_DTIME,
321           N_("@r has dtime set (probably due to old mke2fs).  "),
322           PROMPT_FIX, PR_PREEN_OK },
323
324         /* Reserved inode has bad mode */
325         { PR_1_RESERVED_BAD_MODE,
326           N_("Reserved @i %i %Q has bad mode.  "),
327           PROMPT_CLEAR, PR_PREEN_OK },
328
329         /* Deleted inode has zero dtime */
330         { PR_1_ZERO_DTIME,
331           N_("@D @i %i has zero dtime.  "),
332           PROMPT_FIX, PR_PREEN_OK },
333
334         /* Inode in use, but dtime set */
335         { PR_1_SET_DTIME,
336           N_("@i %i is in use, but has dtime set.  "),
337           PROMPT_FIX, PR_PREEN_OK },
338
339         /* Zero-length directory */
340         { PR_1_ZERO_LENGTH_DIR,
341           N_("@i %i is a @z @d.  "),
342           PROMPT_CLEAR, PR_PREEN_OK },
343
344         /* Block bitmap conflicts with some other fs block */
345         { PR_1_BB_CONFLICT,
346           N_("@g %g's @b @B at %b @C.\n"),
347           PROMPT_RELOCATE, 0 },
348
349         /* Inode bitmap conflicts with some other fs block */
350         { PR_1_IB_CONFLICT,
351           N_("@g %g's @i @B at %b @C.\n"),
352           PROMPT_RELOCATE, 0 },
353
354         /* Inode table conflicts with some other fs block */
355         { PR_1_ITABLE_CONFLICT,
356           N_("@g %g's @i table at %b @C.\n"),
357           PROMPT_RELOCATE, 0 },
358
359         /* Block bitmap is on a bad block */
360         { PR_1_BB_BAD_BLOCK,
361           N_("@g %g's @b @B (%b) is bad.  "),
362           PROMPT_RELOCATE, 0 },
363
364         /* Inode bitmap is on a bad block */
365         { PR_1_IB_BAD_BLOCK,
366           N_("@g %g's @i @B (%b) is bad.  "),
367           PROMPT_RELOCATE, 0 },
368
369         /* Inode has incorrect i_size */
370         { PR_1_BAD_I_SIZE,
371           N_("@i %i, i_size is %Is, @s %N.  "),
372           PROMPT_FIX, PR_PREEN_OK },
373                   
374         /* Inode has incorrect i_blocks */
375         { PR_1_BAD_I_BLOCKS,
376           N_("@i %i, i_@bs is %Ib, @s %N.  "),
377           PROMPT_FIX, PR_PREEN_OK },
378
379         /* Illegal blocknumber in inode */
380         { PR_1_ILLEGAL_BLOCK_NUM,
381           N_("@I @b #%B (%b) in @i %i.  "),
382           PROMPT_CLEAR, PR_LATCH_BLOCK },
383
384         /* Block number overlaps fs metadata */
385         { PR_1_BLOCK_OVERLAPS_METADATA,
386           N_("@b #%B (%b) overlaps @f metadata in @i %i.  "),
387           PROMPT_CLEAR, PR_LATCH_BLOCK },
388
389         /* Inode has illegal blocks (latch question) */
390         { PR_1_INODE_BLOCK_LATCH,
391           N_("@i %i has illegal @b(s).  "),
392           PROMPT_CLEAR, 0 },
393
394         /* Too many bad blocks in inode */
395         { PR_1_TOO_MANY_BAD_BLOCKS,
396           N_("Too many illegal @bs in @i %i.\n"),
397           PROMPT_CLEAR_INODE, PR_NO_OK },       
398
399         /* Illegal block number in bad block inode */
400         { PR_1_BB_ILLEGAL_BLOCK_NUM,
401           N_("@I @b #%B (%b) in bad @b @i.  "),
402           PROMPT_CLEAR, PR_LATCH_BBLOCK },
403
404         /* Bad block inode has illegal blocks (latch question) */
405         { PR_1_INODE_BBLOCK_LATCH,
406           N_("Bad @b @i has illegal @b(s).  "),
407           PROMPT_CLEAR, 0 },
408
409         /* Duplicate or bad blocks in use! */
410         { PR_1_DUP_BLOCKS_PREENSTOP,
411           N_("Duplicate or bad @b in use!\n"),
412           PROMPT_NONE, 0 },
413
414         /* Bad block used as bad block indirect block */          
415         { PR_1_BBINODE_BAD_METABLOCK,
416           N_("Bad @b %b used as bad @b indirect @b?!?\n"),
417           PROMPT_NONE, PR_AFTER_CODE, PR_1_BBINODE_BAD_METABLOCK_PROMPT },
418
419         /* Inconsistency can't be fixed prompt */         
420         { PR_1_BBINODE_BAD_METABLOCK_PROMPT,
421           N_("\nThis inconsistency can not be fixed with e2fsck; to fix it, use\n"
422           """dumpe2fs -b"" to dump out the bad @b "
423           "list and ""e2fsck -L filename""\n"
424           "to read it back in again.\n"),
425           PROMPT_CONTINUE, PR_PREEN_NOMSG },
426
427         /* Bad primary block */
428         { PR_1_BAD_PRIMARY_BLOCK,  
429           N_("\nIf the @b is really bad, the @f can not be fixed.\n"),
430           PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK_PROMPT },
431                   
432         /* Bad primary block prompt */
433         { PR_1_BAD_PRIMARY_BLOCK_PROMPT,          
434           N_("You can clear the this @b (and hope for the best) from the\n"
435           "bad @b list and hope that @b is really OK, but there are no\n"
436           "guarantees.\n\n"),
437           PROMPT_CLEAR, PR_PREEN_NOMSG },
438
439         /* Bad primary superblock */
440         { PR_1_BAD_PRIMARY_SUPERBLOCK,
441           N_("The primary @S (%b) is on the bad @b list.\n"),
442           PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
443                   
444         /* Bad primary block group descriptors */
445         { PR_1_BAD_PRIMARY_GROUP_DESCRIPTOR,
446           N_("Block %b in the primary @g descriptors "
447           "is on the bad @b list\n"),
448           PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
449                   
450         /* Bad superblock in group */
451         { PR_1_BAD_SUPERBLOCK,
452           N_("Warning: Group %g's @S (%b) is bad.\n"),
453           PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
454                   
455         /* Bad block group descriptors in group */
456         { PR_1_BAD_GROUP_DESCRIPTORS,
457           N_("Warning: Group %g's copy of the @g descriptors has a bad "
458           "@b (%b).\n"),
459           PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
460
461         /* Block claimed for no reason */         
462         { PR_1_PROGERR_CLAIMED_BLOCK,
463           N_("Programming error?  @b #%b claimed for no reason in "
464           "process_bad_@b.\n"),
465           PROMPT_NONE, PR_PREEN_OK },
466
467         /* Error allocating blocks for relocating metadata */
468         { PR_1_RELOC_BLOCK_ALLOCATE,
469           N_("@A %N @b(s) for %s: %m\n"),
470           PROMPT_NONE, PR_PREEN_OK },
471                 
472         /* Error allocating block buffer during relocation process */
473         { PR_1_RELOC_MEMORY_ALLOCATE,
474           N_("@A @b buffer for relocating %s\n"),
475           PROMPT_NONE, PR_PREEN_OK },
476                 
477         /* Relocating metadata group information from X to Y */ 
478         { PR_1_RELOC_FROM_TO,
479           N_("Relocating @g %g's %s from %b to %c...\n"),
480           PROMPT_NONE, PR_PREEN_OK },
481                 
482         /* Relocating metatdata group information to X */
483         { PR_1_RELOC_TO,
484           N_("Relocating @g %g's %s to %c...\n"),
485           PROMPT_NONE, PR_PREEN_OK },
486                 
487         /* Block read error during relocation process */
488         { PR_1_RELOC_READ_ERR,
489           N_("Warning: could not read @b %b of %s: %m\n"),
490           PROMPT_NONE, PR_PREEN_OK },
491                 
492         /* Block write error during relocation process */
493         { PR_1_RELOC_WRITE_ERR,
494           N_("Warning: could not write @b %b for %s: %m\n"),
495           PROMPT_NONE, PR_PREEN_OK },
496
497         /* Error allocating inode bitmap */
498         { PR_1_ALLOCATE_IBITMAP_ERROR,
499           "@A @i @B (%N): %m\n",
500           PROMPT_NONE, PR_FATAL },
501
502         /* Error allocating block bitmap */
503         { PR_1_ALLOCATE_BBITMAP_ERROR,
504           "@A @b @B (%N): %m\n",
505           PROMPT_NONE, PR_FATAL },
506
507         /* Error allocating icount structure */
508         { PR_1_ALLOCATE_ICOUNT,
509           N_("@A icount link information: %m\n"),
510           PROMPT_NONE, PR_FATAL },
511
512         /* Error allocating dbcount */
513         { PR_1_ALLOCATE_DBCOUNT,
514           N_("@A @d @b array: %m\n"),
515           PROMPT_NONE, PR_FATAL },
516
517         /* Error while scanning inodes */
518         { PR_1_ISCAN_ERROR,
519           N_("Error while scanning @is (%i): %m\n"),
520           PROMPT_NONE, PR_FATAL },
521
522         /* Error while iterating over blocks */
523         { PR_1_BLOCK_ITERATE,
524           N_("Error while iterating over @bs in @i %i: %m\n"),
525           PROMPT_NONE, PR_FATAL },
526
527         /* Error while storing inode count information */         
528         { PR_1_ICOUNT_STORE,
529           N_("Error storing @i count information (@i=%i, count=%N): %m\n"),
530           PROMPT_NONE, PR_FATAL },
531
532         /* Error while storing directory block information */     
533         { PR_1_ADD_DBLOCK,
534           N_("Error storing @d @b information "
535           "(@i=%i, @b=%b, num=%N): %m\n"),
536           PROMPT_NONE, PR_FATAL },
537
538         /* Error while reading inode (for clearing) */    
539         { PR_1_READ_INODE,
540           N_("Error reading @i %i: %m\n"),
541           PROMPT_NONE, PR_FATAL },
542
543         /* Suppress messages prompt */
544         { PR_1_SUPPRESS_MESSAGES, "", PROMPT_SUPPRESS, PR_NO_OK },
545                   
546         /* Imagic flag set on an inode when filesystem doesn't support it */
547         { PR_1_SET_IMAGIC,
548           N_("@i %i has imagic flag set.  "),
549           PROMPT_CLEAR, 0 },
550
551         /* Immutable flag set on a device or socket inode */
552         { PR_1_SET_IMMUTABLE,
553           N_("Special (@v/socket/fifo/symlink) file (@i %i) has immutable\n"
554              "or append-only flag set.  "),
555           PROMPT_CLEAR, PR_PREEN_OK | PR_PREEN_NO | PR_NO_OK },
556
557         /* Compression flag set on an inode when filesystem doesn't support it */
558         { PR_1_COMPR_SET,
559           N_("@i %i has @cion flag set on @f without @cion support.  "),
560           PROMPT_CLEAR, 0 },
561
562         /* Non-zero size for device, fifo or socket inode */
563         { PR_1_SET_NONZSIZE,
564           "Special (@v/socket/fifo) @i %i has non-zero size.  ",
565           PROMPT_FIX, PR_PREEN_OK },
566
567         /* Filesystem revision is 0, but feature flags are set */
568         { PR_1_FS_REV_LEVEL,
569           "@f has feature flag(s) set, but is a revision 0 @f.  ",
570           PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
571
572         /* Journal inode is not in use, but contains data */      
573         { PR_1_JOURNAL_INODE_NOT_CLEAR,
574           "@j @i is not in use, but contains data.  ",
575           PROMPT_CLEAR, PR_PREEN_OK },    
576           
577         /* Journal has bad mode */
578         { PR_1_JOURNAL_BAD_MODE,
579           N_("@j is not regular file.  "),
580           PROMPT_FIX, PR_PREEN_OK },
581
582         /* Deal with inodes that were part of orphan linked list */
583         { PR_1_LOW_DTIME,
584           N_("@i %i was part of the orphaned @i list.  "),
585           PROMPT_FIX, PR_LATCH_LOW_DTIME, 0 },    
586
587         /* Deal with inodes that were part of corrupted orphan linked
588            list (latch question) */
589         { PR_1_ORPHAN_LIST_REFUGEES,
590           N_("@is that were part of a corrupted orphan linked list found.  "),
591           PROMPT_FIX, 0 },                
592                   
593         /* Error allocating refcount structure */
594         { PR_1_ALLOCATE_REFCOUNT,
595           "@A refcount structure (%N): %m\n",
596           PROMPT_NONE, PR_FATAL },
597
598         /* Error reading extended attribute block */
599         { PR_1_READ_EA_BLOCK,
600           N_("Error reading @a @b %b for @i %i.  "),
601           PROMPT_CLEAR, 0 },
602
603         /* Invalid extended attribute block */
604         { PR_1_BAD_EA_BLOCK,
605           N_("@i %i has a bad @a @b %b.  "),
606           PROMPT_CLEAR, 0 },
607
608         /* Error reading Extended Attribute block while fixing refcount */
609         { PR_1_EXTATTR_READ_ABORT,
610           N_("Error reading @a @b %b (%m).  "),
611           PROMPT_ABORT, 0 },
612                   
613         /* Extended attribute reference count incorrect */
614         { PR_1_EXTATTR_REFCOUNT,
615           N_("@a @b %b has reference count %B, should be %N.  "),
616           PROMPT_FIX, 0 },
617                   
618         /* Error writing Extended Attribute block while fixing refcount */ 
619         { PR_1_EXTATTR_WRITE,
620           N_("Error writing @a @b %b (%m).  "),
621           PROMPT_ABORT, 0 },
622
623         /* Multiple EA blocks not supported */
624         { PR_1_EA_MULTI_BLOCK,
625           N_("@a @b %b has h_blocks > 1.  "),
626           PROMPT_CLEAR, 0},       
627
628         /* Error allocating EA region allocation structure */
629         { PR_1_EA_ALLOC_REGION,
630           N_("Error allocating @a @b %b.  "),
631           PROMPT_ABORT, 0},
632         
633         /* Error EA allocation collision */
634         { PR_1_EA_ALLOC_COLLISION,
635           N_("@a @b %b is corrupt (allocation collision).  "),
636           PROMPT_CLEAR, 0},
637         
638         /* Bad extended attribute name */
639         { PR_1_EA_BAD_NAME,
640           N_("@a @b %b is corrupt (invalid name).  "),
641           PROMPT_CLEAR, 0},       
642
643         /* Bad extended attribute value */
644         { PR_1_EA_BAD_VALUE,
645           N_("@a @b %b is corrupt (invalid value).  "),
646           PROMPT_CLEAR, 0},
647
648         /* Pass 1b errors */
649
650         /* Pass 1B: Rescan for duplicate/bad blocks */
651         { PR_1B_PASS_HEADER,
652           N_("Duplicate @bs found... invoking duplicate @b passes.\n"
653           "Pass 1B: Rescan for duplicate/bad @bs\n"),
654           PROMPT_NONE, 0 },
655
656         /* Duplicate/bad block(s) header */
657         { PR_1B_DUP_BLOCK_HEADER,         
658           N_("Duplicate/bad @b(s) in @i %i:"),
659           PROMPT_NONE, 0 },
660
661         /* Duplicate/bad block(s) in inode */
662         { PR_1B_DUP_BLOCK,        
663           " %b",
664           PROMPT_NONE, PR_LATCH_DBLOCK },
665
666         /* Duplicate/bad block(s) end */
667         { PR_1B_DUP_BLOCK_END,
668           "\n",
669           PROMPT_NONE, 0 },
670                   
671         /* Error while scanning inodes */
672         { PR_1B_ISCAN_ERROR,
673           N_("Error while scanning inodes (%i): %m\n"),
674           PROMPT_NONE, PR_FATAL },
675
676         /* Error allocating inode bitmap */
677         { PR_1B_ALLOCATE_IBITMAP_ERROR,
678           N_("@A @i @B (inode_dup_map): %m\n"),
679           PROMPT_NONE, PR_FATAL },
680
681         /* Error while iterating over blocks */
682         { PR_1B_BLOCK_ITERATE,
683           N_("Error while iterating over @bs in @i %i (%s): %m\n"),
684           PROMPT_NONE, 0 },
685                   
686         /* Pass 1C: Scan directories for inodes with dup blocks. */
687         { PR_1C_PASS_HEADER,
688           N_("Pass 1C: Scan directories for @is with dup @bs.\n"),
689           PROMPT_NONE, 0 },
690
691                   
692         /* Pass 1D: Reconciling duplicate blocks */
693         { PR_1D_PASS_HEADER,
694           N_("Pass 1D: Reconciling duplicate @bs\n"),
695           PROMPT_NONE, 0 },
696                   
697         /* File has duplicate blocks */
698         { PR_1D_DUP_FILE,
699           N_("File %Q (@i #%i, mod time %IM) \n"
700           "  has %B duplicate @b(s), shared with %N file(s):\n"),
701           PROMPT_NONE, 0 },
702                   
703         /* List of files sharing duplicate blocks */    
704         { PR_1D_DUP_FILE_LIST,
705           N_("\t%Q (@i #%i, mod time %IM)\n"),
706           PROMPT_NONE, 0 },
707           
708         /* File sharing blocks with filesystem metadata  */     
709         { PR_1D_SHARE_METADATA,
710           N_("\t<@f metadata>\n"),
711           PROMPT_NONE, 0 },
712
713         /* Report of how many duplicate/bad inodes */   
714         { PR_1D_NUM_DUP_INODES,
715           N_("(There are %N @is containing duplicate/bad @bs.)\n\n"),
716           PROMPT_NONE, 0 },
717
718         /* Duplicated blocks already reassigned or cloned. */
719         { PR_1D_DUP_BLOCKS_DEALT,
720           N_("Duplicated @bs already reassigned or cloned.\n\n"),
721           PROMPT_NONE, 0 },
722
723         /* Clone duplicate/bad blocks? */
724         { PR_1D_CLONE_QUESTION,
725           "", PROMPT_CLONE, PR_NO_OK },
726                   
727         /* Delete file? */
728         { PR_1D_DELETE_QUESTION,
729           "", PROMPT_DELETE, 0 },
730
731         /* Couldn't clone file (error) */
732         { PR_1D_CLONE_ERROR,
733           N_("Couldn't clone file: %m\n"), PROMPT_NONE, 0 },
734
735         /* Pass 2 errors */
736
737         /* Pass 2: Checking directory structure */
738         { PR_2_PASS_HEADER,
739           N_("Pass 2: Checking @d structure\n"),
740           PROMPT_NONE, 0 },
741                   
742         /* Bad inode number for '.' */
743         { PR_2_BAD_INODE_DOT,
744           N_("Bad @i number for '.' in @d @i %i.\n"),
745           PROMPT_FIX, 0 },
746
747         /* Directory entry has bad inode number */
748         { PR_2_BAD_INO, 
749           N_("@E has bad @i #: %Di.\n"),
750           PROMPT_CLEAR, 0 },
751
752         /* Directory entry has deleted or unused inode */
753         { PR_2_UNUSED_INODE, 
754           N_("@E has @D/unused @i %Di.  "),
755           PROMPT_CLEAR, PR_PREEN_OK },
756
757         /* Directry entry is link to '.' */
758         { PR_2_LINK_DOT, 
759           N_("@E @L to '.'  "),
760           PROMPT_CLEAR, 0 },
761
762         /* Directory entry points to inode now located in a bad block */
763         { PR_2_BB_INODE,
764           N_("@E points to @i (%Di) located in a bad @b.\n"),
765           PROMPT_CLEAR, 0 },
766
767         /* Directory entry contains a link to a directory */
768         { PR_2_LINK_DIR, 
769           N_("@E @L to @d %P (%Di).\n"),
770           PROMPT_CLEAR, 0 },
771
772         /* Directory entry contains a link to the root directry */
773         { PR_2_LINK_ROOT, 
774           N_("@E @L to the @r.\n"),
775           PROMPT_CLEAR, 0 },
776
777         /* Directory entry has illegal characters in its name */
778         { PR_2_BAD_NAME, 
779           N_("@E has illegal characters in its name.\n"),
780           PROMPT_FIX, 0 },
781
782         /* Missing '.' in directory inode */      
783         { PR_2_MISSING_DOT,
784           N_("Missing '.' in @d @i %i.\n"),
785           PROMPT_FIX, 0 },
786
787         /* Missing '..' in directory inode */     
788         { PR_2_MISSING_DOT_DOT,
789           N_("Missing '..' in @d @i %i.\n"),
790           PROMPT_FIX, 0 },
791
792         /* First entry in directory inode doesn't contain '.' */
793         { PR_2_1ST_NOT_DOT,
794           N_("First @e '%Dn' (inode=%Di) in @d @i %i (%p) @s '.'\n"),
795           PROMPT_FIX, 0 },
796
797         /* Second entry in directory inode doesn't contain '..' */
798         { PR_2_2ND_NOT_DOT_DOT,
799           N_("Second @e '%Dn' (inode=%Di) in @d @i %i @s '..'\n"),
800           PROMPT_FIX, 0 },
801                   
802         /* i_faddr should be zero */
803         { PR_2_FADDR_ZERO,
804           N_("i_faddr @F %IF, @s zero.\n"),
805           PROMPT_CLEAR, 0 },
806
807         /* i_file_acl should be zero */
808         { PR_2_FILE_ACL_ZERO,
809           N_("i_file_acl @F %If, @s zero.\n"),
810           PROMPT_CLEAR, 0 },
811
812         /* i_dir_acl should be zero */
813         { PR_2_DIR_ACL_ZERO,
814           N_("i_dir_acl @F %Id, @s zero.\n"),
815           PROMPT_CLEAR, 0 },
816
817         /* i_frag should be zero */
818         { PR_2_FRAG_ZERO,
819           N_("i_frag @F %N, @s zero.\n"),
820           PROMPT_CLEAR, 0 },
821
822         /* i_fsize should be zero */
823         { PR_2_FSIZE_ZERO,
824           N_("i_fsize @F %N, @s zero.\n"),
825           PROMPT_CLEAR, 0 },
826
827         /* inode has bad mode */
828         { PR_2_BAD_MODE,
829           N_("@i %i (%Q) has a bad mode (%Im).\n"),
830           PROMPT_CLEAR, 0 },
831
832         /* directory corrupted */
833         { PR_2_DIR_CORRUPTED,     
834           N_("@d @i %i, @b %B, offset %N: @d corrupted\n"),
835           PROMPT_SALVAGE, 0 },
836                   
837         /* filename too long */
838         { PR_2_FILENAME_LONG,     
839           N_("@d @i %i, @b %B, offset %N: filename too long\n"),
840           PROMPT_TRUNCATE, 0 },
841
842         /* Directory inode has a missing block (hole) */
843         { PR_2_DIRECTORY_HOLE,    
844           N_("@d @i %i has an unallocated @b #%B.  "),
845           PROMPT_ALLOCATE, 0 },
846
847         /* '.' is not NULL terminated */
848         { PR_2_DOT_NULL_TERM,
849           N_("'.' @d @e in @d @i %i is not NULL terminated\n"),
850           PROMPT_FIX, 0 },
851
852         /* '..' is not NULL terminated */
853         { PR_2_DOT_DOT_NULL_TERM,
854           N_("'..' @d @e in @d @i %i is not NULL terminated\n"),
855           PROMPT_FIX, 0 },
856
857         /* Illegal character device inode */
858         { PR_2_BAD_CHAR_DEV,
859           N_("@i %i (%Q) is an @I character @v.\n"),
860           PROMPT_CLEAR, 0 },
861
862         /* Illegal block device inode */
863         { PR_2_BAD_BLOCK_DEV,
864           N_("@i %i (%Q) is an @I @b @v.\n"),
865           PROMPT_CLEAR, 0 },
866
867         /* Duplicate '.' entry */
868         { PR_2_DUP_DOT,
869           N_("@E is duplicate '.' @e.\n"),
870           PROMPT_FIX, 0 },        
871
872         /* Duplicate '..' entry */
873         { PR_2_DUP_DOT_DOT,
874           N_("@E is duplicate '..' @e.\n"),
875           PROMPT_FIX, 0 },
876
877         /* Internal error: couldn't find dir_info */
878         { PR_2_NO_DIRINFO,
879           N_("Internal error: couldn't find dir_info for %i.\n"),
880           PROMPT_NONE, PR_FATAL },
881
882         /* Final rec_len is wrong */
883         { PR_2_FINAL_RECLEN,
884           N_("@E has rec_len of %Dr, should be %N.\n"),
885           PROMPT_FIX, 0 },
886                   
887         /* Error allocating icount structure */
888         { PR_2_ALLOCATE_ICOUNT,
889           N_("@A icount structure: %m\n"),
890           PROMPT_NONE, PR_FATAL },
891
892         /* Error iterating over directory blocks */
893         { PR_2_DBLIST_ITERATE,
894           N_("Error interating over @d @bs: %m\n"),
895           PROMPT_NONE, PR_FATAL },
896
897         /* Error reading directory block */
898         { PR_2_READ_DIRBLOCK,
899           N_("Error reading @d @b %b (@i %i): %m\n"),
900           PROMPT_CONTINUE, 0 },
901
902         /* Error writing directory block */
903         { PR_2_WRITE_DIRBLOCK,
904           N_("Error writing @d @b %b (@i %i): %m\n"),
905           PROMPT_CONTINUE, 0 },
906
907         /* Error allocating new directory block */
908         { PR_2_ALLOC_DIRBOCK,
909           N_("@A new @d @b for @i %i (%s): %m\n"),
910           PROMPT_NONE, 0 },
911
912         /* Error deallocating inode */
913         { PR_2_DEALLOC_INODE,
914           N_("Error deallocating @i %i: %m\n"),
915           PROMPT_NONE, PR_FATAL },
916
917         /* Directory entry for '.' is big.  Split? */
918         { PR_2_SPLIT_DOT,
919           N_("@d @e for '.' is big.  "),
920           PROMPT_SPLIT, PR_NO_OK },
921
922         /* Illegal FIFO inode */
923         { PR_2_BAD_FIFO,
924           N_("@i %i (%Q) is an @I FIFO.\n"),
925           PROMPT_CLEAR, 0 },
926
927         /* Illegal socket inode */
928         { PR_2_BAD_SOCKET,
929           N_("@i %i (%Q) is an @I socket.\n"),
930           PROMPT_CLEAR, 0 },
931
932         /* Directory filetype not set */
933         { PR_2_SET_FILETYPE,
934           N_("Setting filetype for @E to %N.\n"),
935           PROMPT_NONE, PR_PREEN_OK | PR_NO_OK | PR_NO_NOMSG },
936
937         /* Directory filetype incorrect */
938         { PR_2_BAD_FILETYPE,
939           N_("@E has an incorrect filetype (was %Dt, should be %N).\n"),
940           PROMPT_FIX, 0 },
941
942         /* Directory filetype set on filesystem */
943         { PR_2_CLEAR_FILETYPE,
944           N_("@E has filetype set.\n"),
945           PROMPT_CLEAR, PR_PREEN_OK },
946
947         /* Directory filename is null */
948         { PR_2_NULL_NAME,
949           N_("@E has a zero-length name.\n"),
950           PROMPT_CLEAR, 0 },
951
952         /* Invalid symlink */
953         { PR_2_INVALID_SYMLINK,
954           N_("Symlink %Q (@i #%i) is invalid.\n"),
955           PROMPT_CLEAR, 0 },
956
957         /* i_file_acl (extended attribute block) is bad */
958         { PR_2_FILE_ACL_BAD,
959           N_("@a @b @F is invalid (%If).\n"),
960           PROMPT_CLEAR, 0 },
961
962         /* Filesystem contains large files, but has no such flag in sb */
963         { PR_2_FEATURE_LARGE_FILES,
964           N_("@f contains large files, but lacks LARGE_FILE flag in @S.\n"),
965           PROMPT_FIX, 0 },
966           
967         /* Pass 3 errors */
968
969         /* Pass 3: Checking directory connectivity */
970         { PR_3_PASS_HEADER,
971           N_("Pass 3: Checking @d connectivity\n"),
972           PROMPT_NONE, 0 },
973                   
974         /* Root inode not allocated */
975         { PR_3_NO_ROOT_INODE,
976           N_("@r not allocated.  "),
977           PROMPT_ALLOCATE, 0 }, 
978                   
979         /* No room in lost+found */
980         { PR_3_EXPAND_LF_DIR,
981           N_("No room in @l @d.  "),
982           PROMPT_EXPAND, 0 },
983
984         /* Unconnected directory inode */
985         { PR_3_UNCONNECTED_DIR,
986           N_("Unconnected @d @i %i (%p)\n"),
987           PROMPT_CONNECT, 0 },
988
989         /* /lost+found not found */
990         { PR_3_NO_LF_DIR,
991           N_("/@l not found.  "),
992           PROMPT_CREATE, PR_PREEN_OK },
993
994         /* .. entry is incorrect */
995         { PR_3_BAD_DOT_DOT,
996           N_("'..' in %Q (%i) is %P (%j), @s %q (%d).\n"),
997           PROMPT_FIX, 0 },
998
999         /* Bad or non-existent /lost+found.  Cannot reconnect */
1000         { PR_3_NO_LPF,
1001           N_("Bad or non-existent /@l.  Cannot reconnect.\n"),
1002           PROMPT_NONE, 0 },
1003
1004         /* Could not expand /lost+found */
1005         { PR_3_CANT_EXPAND_LPF,
1006           N_("Could not expand /@l: %m\n"),
1007           PROMPT_NONE, 0 },
1008
1009         /* Could not reconnect inode */
1010         { PR_3_CANT_RECONNECT,
1011           N_("Could not reconnect %i: %m\n"),
1012           PROMPT_NONE, 0 },
1013
1014         /* Error while trying to find /lost+found */
1015         { PR_3_ERR_FIND_LPF,
1016           N_("Error while trying to find /@l: %m\n"),
1017           PROMPT_NONE, 0 },
1018
1019         /* Error in ext2fs_new_block while creating /lost+found */
1020         { PR_3_ERR_LPF_NEW_BLOCK, 
1021           N_("ext2fs_new_@b: %m while trying to create /@l @d\n"),
1022           PROMPT_NONE, 0 },
1023                   
1024         /* Error in ext2fs_new_inode while creating /lost+found */
1025         { PR_3_ERR_LPF_NEW_INODE,
1026           N_("ext2fs_new_@i: %m while trying to create /@l @d\n"),
1027           PROMPT_NONE, 0 },
1028
1029         /* Error in ext2fs_new_dir_block while creating /lost+found */    
1030         { PR_3_ERR_LPF_NEW_DIR_BLOCK,
1031           N_("ext2fs_new_dir_@b: %m while creating new @d @b\n"),
1032           PROMPT_NONE, 0 },
1033                   
1034         /* Error while writing directory block for /lost+found */
1035         { PR_3_ERR_LPF_WRITE_BLOCK,
1036           N_("ext2fs_write_dir_@b: %m while writing the @d @b for /@l\n"),
1037           PROMPT_NONE, 0 },
1038
1039         /* Error while adjusting inode count */
1040         { PR_3_ADJUST_INODE,
1041           N_("Error while adjusting @i count on @i %i\n"),
1042           PROMPT_NONE, 0 },
1043
1044         /* Couldn't fix parent directory -- error */
1045         { PR_3_FIX_PARENT_ERR,
1046           N_("Couldn't fix parent of @i %i: %m\n\n"),
1047           PROMPT_NONE, 0 },
1048
1049         /* Couldn't fix parent directory -- couldn't find it */   
1050         { PR_3_FIX_PARENT_NOFIND,
1051           N_("Couldn't fix parent of @i %i: Couldn't find parent @d entry\n\n"),
1052           PROMPT_NONE, 0 },
1053
1054         /* Error allocating inode bitmap */
1055         { PR_3_ALLOCATE_IBITMAP_ERROR,
1056           N_("@A @i @B (%N): %m\n"),
1057           PROMPT_NONE, PR_FATAL },
1058
1059         /* Error creating root directory */
1060         { PR_3_CREATE_ROOT_ERROR,
1061           N_("Error creating root @d (%s): %m\n"),
1062           PROMPT_NONE, PR_FATAL },        
1063
1064         /* Error creating lost and found directory */
1065         { PR_3_CREATE_LPF_ERROR,
1066           N_("Error creating /@l @d (%s): %m\n"),
1067           PROMPT_NONE, PR_FATAL },  
1068
1069         /* Root inode is not directory; aborting */
1070         { PR_3_ROOT_NOT_DIR_ABORT,
1071           N_("@r is not a @d; aborting.\n"),
1072           PROMPT_NONE, PR_FATAL },  
1073
1074         /* Cannot proceed without a root inode. */
1075         { PR_3_NO_ROOT_INODE_ABORT,
1076           N_("Cannot proceed without a @r.\n"),
1077           PROMPT_NONE, PR_FATAL },  
1078
1079         /* Internal error: couldn't find dir_info */
1080         { PR_3_NO_DIRINFO,
1081           N_("Internal error: couldn't find dir_info for %i.\n"),
1082           PROMPT_NONE, PR_FATAL },
1083
1084         /* Lost+found not a directory */
1085         { PR_3_LPF_NOTDIR,
1086           N_("/@l is not a @d (ino=%i)\n"),
1087           PROMPT_UNLINK, 0 }, 
1088
1089         /* Pass 4 errors */
1090         
1091         /* Pass 4: Checking reference counts */
1092         { PR_4_PASS_HEADER,
1093           N_("Pass 4: Checking reference counts\n"),
1094           PROMPT_NONE, 0 },
1095                   
1096         /* Unattached zero-length inode */
1097         { PR_4_ZERO_LEN_INODE,
1098           "@u @z @i %i.  ",
1099           PROMPT_CLEAR, PR_PREEN_OK|PR_NO_OK },
1100
1101         /* Unattached inode */
1102         { PR_4_UNATTACHED_INODE,
1103           "@u @i %i\n",
1104           PROMPT_CONNECT, 0 },
1105
1106         /* Inode ref count wrong */
1107         { PR_4_BAD_REF_COUNT,
1108           N_("@i %i ref count is %Il, @s %N.  "),
1109           PROMPT_FIX, PR_PREEN_OK },
1110
1111         { PR_4_INCONSISTENT_COUNT,
1112           N_("WARNING: PROGRAMMING BUG IN E2FSCK!\n"
1113           "\tOR SOME BONEHEAD (YOU) IS CHECKING A MOUNTED (LIVE) FILESYSTEM.\n"
1114           "@i_link_info[%i] is %N, @i.i_links_count is %Il.  "
1115           "They should be the same!\n"),
1116           PROMPT_NONE, 0 },
1117
1118         /* Pass 5 errors */
1119                   
1120         /* Pass 5: Checking group summary information */
1121         { PR_5_PASS_HEADER,
1122           N_("Pass 5: Checking @g summary information\n"),
1123           PROMPT_NONE, 0 },
1124                   
1125         /* Padding at end of inode bitmap is not set. */
1126         { PR_5_INODE_BMAP_PADDING,
1127           N_("Padding at end of @i @B is not set. "),
1128           PROMPT_FIX, PR_PREEN_OK },
1129                   
1130         /* Padding at end of block bitmap is not set. */
1131         { PR_5_BLOCK_BMAP_PADDING,
1132           N_("Padding at end of @b @B is not set. "),
1133           PROMPT_FIX, PR_PREEN_OK },
1134                 
1135         /* Block bitmap differences header */
1136         { PR_5_BLOCK_BITMAP_HEADER,
1137           N_("@b @B differences: "),
1138           PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG},
1139
1140         /* Block not used, but marked in bitmap */
1141         { PR_5_BLOCK_UNUSED,
1142           " -%b",
1143           PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
1144                   
1145         /* Block used, but not marked used in bitmap */
1146         { PR_5_BLOCK_USED,
1147           " +%b",
1148           PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
1149
1150         /* Block bitmap differences end */        
1151         { PR_5_BLOCK_BITMAP_END,
1152           "\n",
1153           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
1154
1155         /* Inode bitmap differences header */
1156         { PR_5_INODE_BITMAP_HEADER,
1157           N_("@i @B differences: "),
1158           PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
1159
1160         /* Inode not used, but marked in bitmap */
1161         { PR_5_INODE_UNUSED,
1162           " -%i",
1163           PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
1164                   
1165         /* Inode used, but not marked used in bitmap */
1166         { PR_5_INODE_USED,
1167           " +%i",
1168           PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
1169
1170         /* Inode bitmap differences end */        
1171         { PR_5_INODE_BITMAP_END,
1172           "\n",
1173           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
1174
1175         /* Free inodes count for group wrong */
1176         { PR_5_FREE_INODE_COUNT_GROUP,
1177           N_("Free @is count wrong for @g #%g (%i, counted=%j).\n"),
1178           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
1179
1180         /* Directories count for group wrong */
1181         { PR_5_FREE_DIR_COUNT_GROUP,
1182           N_("Directories count wrong for @g #%g (%i, counted=%j).\n"),
1183           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
1184
1185         /* Free inodes count wrong */
1186         { PR_5_FREE_INODE_COUNT,
1187           N_("Free @is count wrong (%i, counted=%j).\n"),
1188           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
1189
1190         /* Free blocks count for group wrong */
1191         { PR_5_FREE_BLOCK_COUNT_GROUP,
1192           N_("Free @bs count wrong for @g #%g (%b, counted=%c).\n"),
1193           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
1194
1195         /* Free blocks count wrong */
1196         { PR_5_FREE_BLOCK_COUNT,
1197           N_("Free @bs count wrong (%b, counted=%c).\n"),
1198           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
1199
1200         /* Programming error: bitmap endpoints don't match */
1201         { PR_5_BMAP_ENDPOINTS,
1202           N_("PROGRAMMING ERROR: @f (#%N) @B endpoints (%b, %c) don't "
1203           "match calculated @B endpoints (%i, %j)\n"),
1204           PROMPT_NONE, PR_FATAL },
1205
1206         /* Internal error: fudging end of bitmap */
1207         { PR_5_FUDGE_BITMAP_ERROR,
1208           N_("Internal error: fudging end of bitmap (%N)\n"),
1209           PROMPT_NONE, PR_FATAL },        
1210
1211         /* Error copying in replacement inode bitmap */
1212         { PR_5_COPY_IBITMAP_ERROR,
1213           "Error copying in replacement @i @B: %m\n",
1214           PROMPT_NONE, PR_FATAL },
1215
1216         /* Error copying in replacement block bitmap */
1217         { PR_5_COPY_BBITMAP_ERROR,
1218           "Error copying in replacement @b @B: %m\n",
1219           PROMPT_NONE, PR_FATAL },
1220                   
1221         /* Block range not used, but marked in bitmap */
1222         { PR_5_BLOCK_RANGE_UNUSED,
1223           " -(%b--%c)",
1224           PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
1225                   
1226         /* Block range used, but not marked used in bitmap */
1227         { PR_5_BLOCK_RANGE_USED,
1228           " +(%b--%c)",
1229           PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
1230
1231         /* Inode range not used, but marked in bitmap */
1232         { PR_5_INODE_RANGE_UNUSED,
1233           " -(%i--%j)",
1234           PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
1235                   
1236         /* Inode range used, but not marked used in bitmap */
1237         { PR_5_INODE_RANGE_USED,
1238           " +(%i--%j)",
1239           PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
1240
1241         { 0 }
1242 };
1243
1244 /*
1245  * This is the latch flags register.  It allows several problems to be
1246  * "latched" together.  This means that the user has to answer but one
1247  * question for the set of problems, and all of the associated
1248  * problems will be either fixed or not fixed.
1249  */
1250 static struct latch_descr pr_latch_info[] = {
1251         { PR_LATCH_BLOCK, PR_1_INODE_BLOCK_LATCH, 0 },
1252         { PR_LATCH_BBLOCK, PR_1_INODE_BBLOCK_LATCH, 0 },
1253         { PR_LATCH_IBITMAP, PR_5_INODE_BITMAP_HEADER, PR_5_INODE_BITMAP_END },
1254         { PR_LATCH_BBITMAP, PR_5_BLOCK_BITMAP_HEADER, PR_5_BLOCK_BITMAP_END },
1255         { PR_LATCH_RELOC, PR_0_RELOCATE_HINT, 0 },
1256         { PR_LATCH_DBLOCK, PR_1B_DUP_BLOCK_HEADER, PR_1B_DUP_BLOCK_END },
1257         { PR_LATCH_LOW_DTIME, PR_1_ORPHAN_LIST_REFUGEES, 0 },
1258         { -1, 0, 0 },
1259 };
1260
1261 static const struct e2fsck_problem *find_problem(int code)
1262 {
1263         int     i;
1264
1265         for (i=0; problem_table[i].e2p_code; i++) {
1266                 if (problem_table[i].e2p_code == code)
1267                         return &problem_table[i];
1268         }
1269         return 0;
1270 }
1271
1272 static struct latch_descr *find_latch(int code)
1273 {
1274         int     i;
1275
1276         for (i=0; pr_latch_info[i].latch_code >= 0; i++) {
1277                 if (pr_latch_info[i].latch_code == code)
1278                         return &pr_latch_info[i];
1279         }
1280         return 0;
1281 }
1282
1283 int end_problem_latch(e2fsck_t ctx, int mask)
1284 {
1285         struct latch_descr *ldesc;
1286         struct problem_context pctx;
1287         int answer = -1;
1288         
1289         ldesc = find_latch(mask);
1290         if (ldesc->end_message && (ldesc->flags & PRL_LATCHED)) {
1291                 clear_problem_context(&pctx);
1292                 answer = fix_problem(ctx, ldesc->end_message, &pctx);
1293         }
1294         ldesc->flags &= ~(PRL_VARIABLE);
1295         return answer;
1296 }
1297
1298 int set_latch_flags(int mask, int setflags, int clearflags)
1299 {
1300         struct latch_descr *ldesc;
1301
1302         ldesc = find_latch(mask);
1303         if (!ldesc)
1304                 return -1;
1305         ldesc->flags |= setflags;
1306         ldesc->flags &= ~clearflags;
1307         return 0;
1308 }
1309
1310 int get_latch_flags(int mask, int *value)
1311 {
1312         struct latch_descr *ldesc;
1313
1314         ldesc = find_latch(mask);
1315         if (!ldesc)
1316                 return -1;
1317         *value = ldesc->flags;
1318         return 0;
1319 }
1320
1321 void clear_problem_context(struct problem_context *ctx)
1322 {
1323         memset(ctx, 0, sizeof(struct problem_context));
1324         ctx->blkcount = -1;
1325         ctx->group = -1;
1326 }
1327
1328 int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx)
1329 {
1330         ext2_filsys fs = ctx->fs;
1331         const struct e2fsck_problem *ptr;
1332         struct latch_descr *ldesc = 0;
1333         const char *message;
1334         int             def_yn, answer, ans;
1335         int             print_answer = 0;
1336         int             suppress = 0;
1337
1338         ptr = find_problem(code);
1339         if (!ptr) {
1340                 printf(_("Unhandled error code (0x%x)!\n"), code);
1341                 return 0;
1342         }
1343         def_yn = 1;
1344         if ((ptr->flags & PR_NO_DEFAULT) ||
1345             ((ptr->flags & PR_PREEN_NO) && (ctx->options & E2F_OPT_PREEN)) ||
1346             (ctx->options & E2F_OPT_NO))
1347                 def_yn= 0;
1348
1349         /*
1350          * Do special latch processing.  This is where we ask the
1351          * latch question, if it exists
1352          */
1353         if (ptr->flags & PR_LATCH_MASK) {
1354                 ldesc = find_latch(ptr->flags & PR_LATCH_MASK);
1355                 if (ldesc->question && !(ldesc->flags & PRL_LATCHED)) {
1356                         ans = fix_problem(ctx, ldesc->question, pctx);
1357                         if (ans == 1)
1358                                 ldesc->flags |= PRL_YES;
1359                         if (ans == 0)
1360                                 ldesc->flags |= PRL_NO;
1361                         ldesc->flags |= PRL_LATCHED;
1362                 }
1363                 if (ldesc->flags & PRL_SUPPRESS)
1364                         suppress++;
1365         }
1366         if ((ptr->flags & PR_PREEN_NOMSG) &&
1367             (ctx->options & E2F_OPT_PREEN))
1368                 suppress++;
1369         if ((ptr->flags & PR_NO_NOMSG) &&
1370             (ctx->options & E2F_OPT_NO))
1371                 suppress++;
1372         if (!suppress) {
1373                 message = ptr->e2p_description;
1374                 if (ctx->options & E2F_OPT_PREEN) {
1375                         printf("%s: ", ctx->device_name ?
1376                                ctx->device_name : ctx->filesystem_name);
1377 #if 0
1378                         if (ptr->e2p_preen_msg)
1379                                 message = ptr->e2p_preen_msg;
1380 #endif
1381                 }
1382                 print_e2fsck_message(ctx, _(message), pctx, 1);
1383         }
1384         if (!(ptr->flags & PR_PREEN_OK) && (ptr->prompt != PROMPT_NONE))
1385                 preenhalt(ctx);
1386
1387         if (ptr->flags & PR_FATAL)
1388                 fatal_error(ctx, 0);
1389
1390         if (ptr->prompt == PROMPT_NONE) {
1391                 if (ptr->flags & PR_NOCOLLATE)
1392                         answer = -1;
1393                 else
1394                         answer = def_yn;
1395         } else {
1396                 if (ctx->options & E2F_OPT_PREEN) {
1397                         answer = def_yn;
1398                         if (!(ptr->flags & PR_PREEN_NOMSG))
1399                                 print_answer = 1;
1400                 } else if ((ptr->flags & PR_LATCH_MASK) &&
1401                            (ldesc->flags & (PRL_YES | PRL_NO))) {
1402                         if (!suppress)
1403                                 print_answer = 1;
1404                         if (ldesc->flags & PRL_YES)
1405                                 answer = 1;
1406                         else
1407                                 answer = 0;
1408                 } else
1409                         answer = ask(ctx, _(prompt[(int) ptr->prompt]), def_yn);
1410                 if (!answer && !(ptr->flags & PR_NO_OK))
1411                         ext2fs_unmark_valid(fs);
1412         
1413                 if (print_answer)
1414                         printf("%s.\n", answer ?
1415                                _(preen_msg[(int) ptr->prompt]) : _("IGNORED"));
1416         
1417         }
1418
1419         if ((ptr->prompt == PROMPT_ABORT) && answer)
1420                 fatal_error(ctx, 0);
1421
1422         if (ptr->flags & PR_AFTER_CODE)
1423                 answer = fix_problem(ctx, ptr->second_code, pctx);
1424
1425         return answer;
1426 }