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