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