Whamcloud - gitweb
Fixed missing not_fixed branch in e2fsck so that if the frag size field in
[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         /* Clear the htree flag forcibly */
1085         { PR_2_HTREE_FCLR,
1086           N_("Forcibly clearing HTREE flag on @i %d (%q).  (Beta test code)\n"),
1087                   PROMPT_NONE, 0 },
1088
1089         /* Bad block in htree interior node */
1090         { PR_2_HTREE_BADBLK,
1091           N_("@p @h %d (%q): bad @b number %b.\n"),
1092           PROMPT_CLEAR_HTREE, 0 },
1093
1094         /* Error adjusting EA refcount */
1095         { PR_2_ADJ_EA_REFCOUNT,
1096           N_("Error addjusting refcount for @a @b %b (@i %i): %m\n"),
1097           PROMPT_NONE, PR_FATAL },
1098
1099         /* Invalid HTREE root node */
1100         { PR_2_HTREE_BAD_ROOT,
1101           N_("@p @h %d: root node is invalid\n"),
1102           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
1103
1104         /* Invalid HTREE limit */
1105         { PR_2_HTREE_BAD_LIMIT,
1106           N_("@p @h %d: node (%B) has bad limit (%N)\n"),
1107           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
1108
1109         /* Invalid HTREE count */
1110         { PR_2_HTREE_BAD_COUNT,
1111           N_("@p @h %d: node (%B) has bad count (%N)\n"),
1112           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
1113
1114         /* HTREE interior node has out-of-order hashes in table */
1115         { PR_2_HTREE_HASH_ORDER,
1116           N_("@p @h %d: node (%B) has an unordered hash table\n"),
1117           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
1118
1119         /* Node in HTREE directory has bad depth */
1120         { PR_2_HTREE_BAD_DEPTH,
1121           N_("@p @h %d: node (%B) has bad depth\n"),
1122           PROMPT_NONE, 0 },
1123         
1124         /* Duplicate directory entry found */
1125         { PR_2_DUPLICATE_DIRENT,
1126           N_("Duplicate @E found.  "),
1127           PROMPT_CLEAR, 0 },
1128         
1129         /* Non-unique filename found */
1130         { PR_2_NON_UNIQUE_FILE, /* xgettext: no-c-format */
1131           N_("@E has a non-unique filename.\nRename to %s"),
1132           PROMPT_NULL, 0 },
1133         
1134         /* Duplicate directory entry found */
1135         { PR_2_REPORT_DUP_DIRENT,
1136           N_("Duplicate @e '%Dn' found.\n\tMarking %p (%i) to be rebuilt.\n\n"),
1137           PROMPT_NONE, 0 },
1138         
1139         /* Pass 3 errors */
1140
1141         /* Pass 3: Checking directory connectivity */
1142         { PR_3_PASS_HEADER,
1143           N_("Pass 3: Checking @d connectivity\n"),
1144           PROMPT_NONE, 0 },
1145                   
1146         /* Root inode not allocated */
1147         { PR_3_NO_ROOT_INODE,
1148           N_("@r not allocated.  "),
1149           PROMPT_ALLOCATE, 0 }, 
1150                   
1151         /* No room in lost+found */
1152         { PR_3_EXPAND_LF_DIR,
1153           N_("No room in @l @d.  "),
1154           PROMPT_EXPAND, 0 },
1155
1156         /* Unconnected directory inode */
1157         { PR_3_UNCONNECTED_DIR,
1158           N_("Unconnected @d @i %i (%p)\n"),
1159           PROMPT_CONNECT, 0 },
1160
1161         /* /lost+found not found */
1162         { PR_3_NO_LF_DIR,
1163           N_("/@l not found.  "),
1164           PROMPT_CREATE, PR_PREEN_OK },
1165
1166         /* .. entry is incorrect */
1167         { PR_3_BAD_DOT_DOT,
1168           N_("'..' in %Q (%i) is %P (%j), @s %q (%d).\n"),
1169           PROMPT_FIX, 0 },
1170
1171         /* Bad or non-existent /lost+found.  Cannot reconnect */
1172         { PR_3_NO_LPF,
1173           N_("Bad or non-existent /@l.  Cannot reconnect.\n"),
1174           PROMPT_NONE, 0 },
1175
1176         /* Could not expand /lost+found */
1177         { PR_3_CANT_EXPAND_LPF,
1178           N_("Could not expand /@l: %m\n"),
1179           PROMPT_NONE, 0 },
1180
1181         /* Could not reconnect inode */
1182         { PR_3_CANT_RECONNECT,
1183           N_("Could not reconnect %i: %m\n"),
1184           PROMPT_NONE, 0 },
1185
1186         /* Error while trying to find /lost+found */
1187         { PR_3_ERR_FIND_LPF,
1188           N_("Error while trying to find /@l: %m\n"),
1189           PROMPT_NONE, 0 },
1190
1191         /* Error in ext2fs_new_block while creating /lost+found */
1192         { PR_3_ERR_LPF_NEW_BLOCK, 
1193           N_("ext2fs_new_@b: %m while trying to create /@l @d\n"),
1194           PROMPT_NONE, 0 },
1195                   
1196         /* Error in ext2fs_new_inode while creating /lost+found */
1197         { PR_3_ERR_LPF_NEW_INODE,
1198           N_("ext2fs_new_@i: %m while trying to create /@l @d\n"),
1199           PROMPT_NONE, 0 },
1200
1201         /* Error in ext2fs_new_dir_block while creating /lost+found */    
1202         { PR_3_ERR_LPF_NEW_DIR_BLOCK,
1203           N_("ext2fs_new_dir_@b: %m while creating new @d @b\n"),
1204           PROMPT_NONE, 0 },
1205                   
1206         /* Error while writing directory block for /lost+found */
1207         { PR_3_ERR_LPF_WRITE_BLOCK,
1208           N_("ext2fs_write_dir_@b: %m while writing the @d @b for /@l\n"),
1209           PROMPT_NONE, 0 },
1210
1211         /* Error while adjusting inode count */
1212         { PR_3_ADJUST_INODE,
1213           N_("Error while adjusting @i count on @i %i\n"),
1214           PROMPT_NONE, 0 },
1215
1216         /* Couldn't fix parent directory -- error */
1217         { PR_3_FIX_PARENT_ERR,
1218           N_("Couldn't fix parent of @i %i: %m\n\n"),
1219           PROMPT_NONE, 0 },
1220
1221         /* Couldn't fix parent directory -- couldn't find it */   
1222         { PR_3_FIX_PARENT_NOFIND,
1223           N_("Couldn't fix parent of @i %i: Couldn't find parent @d entry\n\n"),
1224           PROMPT_NONE, 0 },
1225
1226         /* Error allocating inode bitmap */
1227         { PR_3_ALLOCATE_IBITMAP_ERROR,
1228           N_("@A @i @B (%N): %m\n"),
1229           PROMPT_NONE, PR_FATAL },
1230
1231         /* Error creating root directory */
1232         { PR_3_CREATE_ROOT_ERROR,
1233           N_("Error creating root @d (%s): %m\n"),
1234           PROMPT_NONE, PR_FATAL },        
1235
1236         /* Error creating lost and found directory */
1237         { PR_3_CREATE_LPF_ERROR,
1238           N_("Error creating /@l @d (%s): %m\n"),
1239           PROMPT_NONE, PR_FATAL },  
1240
1241         /* Root inode is not directory; aborting */
1242         { PR_3_ROOT_NOT_DIR_ABORT,
1243           N_("@r is not a @d; aborting.\n"),
1244           PROMPT_NONE, PR_FATAL },  
1245
1246         /* Cannot proceed without a root inode. */
1247         { PR_3_NO_ROOT_INODE_ABORT,
1248           N_("Cannot proceed without a @r.\n"),
1249           PROMPT_NONE, PR_FATAL },  
1250
1251         /* Internal error: couldn't find dir_info */
1252         { PR_3_NO_DIRINFO,
1253           N_("Internal error: couldn't find dir_info for %i.\n"),
1254           PROMPT_NONE, PR_FATAL },
1255
1256         /* Lost+found not a directory */
1257         { PR_3_LPF_NOTDIR,
1258           N_("/@l is not a @d (ino=%i)\n"),
1259           PROMPT_UNLINK, 0 },
1260
1261         /* Pass 3A Directory Optimization       */
1262
1263         /* Pass 3A: Optimizing directories */
1264         { PR_3A_PASS_HEADER,
1265           N_("Pass 3A: Optimizing directories\n"),
1266           PROMPT_NONE, PR_PREEN_NOMSG },
1267
1268         /* Error iterating over directories */
1269         { PR_3A_OPTIMIZE_ITER,
1270           N_("Failed to create dirs_to_hash iterator: %m"),
1271           PROMPT_NONE, 0 },
1272
1273         /* Error rehash directory */
1274         { PR_3A_OPTIMIZE_DIR_ERR,
1275           N_("Failed to optimize directory %q (%d): %m"),
1276           PROMPT_NONE, 0 },
1277
1278         /* Rehashing dir header */
1279         { PR_3A_OPTIMIZE_DIR_HEADER,
1280           N_("Optimizing directories: "),
1281           PROMPT_NONE, PR_MSG_ONLY },
1282
1283         /* Rehashing directory %d */
1284         { PR_3A_OPTIMIZE_DIR,
1285           " %d",
1286           PROMPT_NONE, PR_LATCH_OPTIMIZE_DIR | PR_PREEN_NOHDR},
1287                   
1288         /* Rehashing dir end */   
1289         { PR_3A_OPTIMIZE_DIR_END,
1290           "\n",
1291           PROMPT_NONE, PR_PREEN_NOHDR },
1292
1293         /* Pass 4 errors */
1294         
1295         /* Pass 4: Checking reference counts */
1296         { PR_4_PASS_HEADER,
1297           N_("Pass 4: Checking reference counts\n"),
1298           PROMPT_NONE, 0 },
1299                   
1300         /* Unattached zero-length inode */
1301         { PR_4_ZERO_LEN_INODE,
1302           "@u @z @i %i.  ",
1303           PROMPT_CLEAR, PR_PREEN_OK|PR_NO_OK },
1304
1305         /* Unattached inode */
1306         { PR_4_UNATTACHED_INODE,
1307           "@u @i %i\n",
1308           PROMPT_CONNECT, 0 },
1309
1310         /* Inode ref count wrong */
1311         { PR_4_BAD_REF_COUNT,
1312           N_("@i %i ref count is %Il, @s %N.  "),
1313           PROMPT_FIX, PR_PREEN_OK },
1314
1315         { PR_4_INCONSISTENT_COUNT,
1316           N_("WARNING: PROGRAMMING BUG IN E2FSCK!\n"
1317           "\tOR SOME BONEHEAD (YOU) IS CHECKING A MOUNTED (LIVE) FILESYSTEM.\n"
1318           "@i_link_info[%i] is %N, @i.i_links_count is %Il.  "
1319           "They should be the same!\n"),
1320           PROMPT_NONE, 0 },
1321
1322         /* Pass 5 errors */
1323                   
1324         /* Pass 5: Checking group summary information */
1325         { PR_5_PASS_HEADER,
1326           N_("Pass 5: Checking @g summary information\n"),
1327           PROMPT_NONE, 0 },
1328                   
1329         /* Padding at end of inode bitmap is not set. */
1330         { PR_5_INODE_BMAP_PADDING,
1331           N_("Padding at end of @i @B is not set. "),
1332           PROMPT_FIX, PR_PREEN_OK },
1333                   
1334         /* Padding at end of block bitmap is not set. */
1335         { PR_5_BLOCK_BMAP_PADDING,
1336           N_("Padding at end of @b @B is not set. "),
1337           PROMPT_FIX, PR_PREEN_OK },
1338                 
1339         /* Block bitmap differences header */
1340         { PR_5_BLOCK_BITMAP_HEADER,
1341           N_("@b @B differences: "),
1342           PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG},
1343
1344         /* Block not used, but marked in bitmap */
1345         { PR_5_BLOCK_UNUSED,
1346           " -%b",
1347           PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
1348                   
1349         /* Block used, but not marked used in bitmap */
1350         { PR_5_BLOCK_USED,
1351           " +%b",
1352           PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
1353
1354         /* Block bitmap differences end */        
1355         { PR_5_BLOCK_BITMAP_END,
1356           "\n",
1357           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
1358
1359         /* Inode bitmap differences header */
1360         { PR_5_INODE_BITMAP_HEADER,
1361           N_("@i @B differences: "),
1362           PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
1363
1364         /* Inode not used, but marked in bitmap */
1365         { PR_5_INODE_UNUSED,
1366           " -%i",
1367           PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
1368                   
1369         /* Inode used, but not marked used in bitmap */
1370         { PR_5_INODE_USED,
1371           " +%i",
1372           PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
1373
1374         /* Inode bitmap differences end */        
1375         { PR_5_INODE_BITMAP_END,
1376           "\n",
1377           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
1378
1379         /* Free inodes count for group wrong */
1380         { PR_5_FREE_INODE_COUNT_GROUP,
1381           N_("Free @is count wrong for @g #%g (%i, counted=%j).\n"),
1382           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
1383
1384         /* Directories count for group wrong */
1385         { PR_5_FREE_DIR_COUNT_GROUP,
1386           N_("Directories count wrong for @g #%g (%i, counted=%j).\n"),
1387           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
1388
1389         /* Free inodes count wrong */
1390         { PR_5_FREE_INODE_COUNT,
1391           N_("Free @is count wrong (%i, counted=%j).\n"),
1392           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
1393
1394         /* Free blocks count for group wrong */
1395         { PR_5_FREE_BLOCK_COUNT_GROUP,
1396           N_("Free @bs count wrong for @g #%g (%b, counted=%c).\n"),
1397           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
1398
1399         /* Free blocks count wrong */
1400         { PR_5_FREE_BLOCK_COUNT,
1401           N_("Free @bs count wrong (%b, counted=%c).\n"),
1402           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
1403
1404         /* Programming error: bitmap endpoints don't match */
1405         { PR_5_BMAP_ENDPOINTS,
1406           N_("PROGRAMMING ERROR: @f (#%N) @B endpoints (%b, %c) don't "
1407           "match calculated @B endpoints (%i, %j)\n"),
1408           PROMPT_NONE, PR_FATAL },
1409
1410         /* Internal error: fudging end of bitmap */
1411         { PR_5_FUDGE_BITMAP_ERROR,
1412           N_("Internal error: fudging end of bitmap (%N)\n"),
1413           PROMPT_NONE, PR_FATAL },        
1414
1415         /* Error copying in replacement inode bitmap */
1416         { PR_5_COPY_IBITMAP_ERROR,
1417           "Error copying in replacement @i @B: %m\n",
1418           PROMPT_NONE, PR_FATAL },
1419
1420         /* Error copying in replacement block bitmap */
1421         { PR_5_COPY_BBITMAP_ERROR,
1422           "Error copying in replacement @b @B: %m\n",
1423           PROMPT_NONE, PR_FATAL },
1424                   
1425         /* Block range not used, but marked in bitmap */
1426         { PR_5_BLOCK_RANGE_UNUSED,
1427           " -(%b--%c)",
1428           PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
1429                   
1430         /* Block range used, but not marked used in bitmap */
1431         { PR_5_BLOCK_RANGE_USED,
1432           " +(%b--%c)",
1433           PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
1434
1435         /* Inode range not used, but marked in bitmap */
1436         { PR_5_INODE_RANGE_UNUSED,
1437           " -(%i--%j)",
1438           PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
1439                   
1440         /* Inode range used, but not marked used in bitmap */
1441         { PR_5_INODE_RANGE_USED,
1442           " +(%i--%j)",
1443           PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
1444
1445         { 0 }
1446 };
1447
1448 /*
1449  * This is the latch flags register.  It allows several problems to be
1450  * "latched" together.  This means that the user has to answer but one
1451  * question for the set of problems, and all of the associated
1452  * problems will be either fixed or not fixed.
1453  */
1454 static struct latch_descr pr_latch_info[] = {
1455         { PR_LATCH_BLOCK, PR_1_INODE_BLOCK_LATCH, 0 },
1456         { PR_LATCH_BBLOCK, PR_1_INODE_BBLOCK_LATCH, 0 },
1457         { PR_LATCH_IBITMAP, PR_5_INODE_BITMAP_HEADER, PR_5_INODE_BITMAP_END },
1458         { PR_LATCH_BBITMAP, PR_5_BLOCK_BITMAP_HEADER, PR_5_BLOCK_BITMAP_END },
1459         { PR_LATCH_RELOC, PR_0_RELOCATE_HINT, 0 },
1460         { PR_LATCH_DBLOCK, PR_1B_DUP_BLOCK_HEADER, PR_1B_DUP_BLOCK_END },
1461         { PR_LATCH_LOW_DTIME, PR_1_ORPHAN_LIST_REFUGEES, 0 },
1462         { PR_LATCH_TOOBIG, PR_1_INODE_TOOBIG, 0 },
1463         { PR_LATCH_OPTIMIZE_DIR, PR_3A_OPTIMIZE_DIR_HEADER, PR_3A_OPTIMIZE_DIR_END },
1464         { -1, 0, 0 },
1465 };
1466
1467 static const struct e2fsck_problem *find_problem(problem_t code)
1468 {
1469         int     i;
1470
1471         for (i=0; problem_table[i].e2p_code; i++) {
1472                 if (problem_table[i].e2p_code == code)
1473                         return &problem_table[i];
1474         }
1475         return 0;
1476 }
1477
1478 static struct latch_descr *find_latch(int code)
1479 {
1480         int     i;
1481
1482         for (i=0; pr_latch_info[i].latch_code >= 0; i++) {
1483                 if (pr_latch_info[i].latch_code == code)
1484                         return &pr_latch_info[i];
1485         }
1486         return 0;
1487 }
1488
1489 int end_problem_latch(e2fsck_t ctx, int mask)
1490 {
1491         struct latch_descr *ldesc;
1492         struct problem_context pctx;
1493         int answer = -1;
1494         
1495         ldesc = find_latch(mask);
1496         if (ldesc->end_message && (ldesc->flags & PRL_LATCHED)) {
1497                 clear_problem_context(&pctx);
1498                 answer = fix_problem(ctx, ldesc->end_message, &pctx);
1499         }
1500         ldesc->flags &= ~(PRL_VARIABLE);
1501         return answer;
1502 }
1503
1504 int set_latch_flags(int mask, int setflags, int clearflags)
1505 {
1506         struct latch_descr *ldesc;
1507
1508         ldesc = find_latch(mask);
1509         if (!ldesc)
1510                 return -1;
1511         ldesc->flags |= setflags;
1512         ldesc->flags &= ~clearflags;
1513         return 0;
1514 }
1515
1516 int get_latch_flags(int mask, int *value)
1517 {
1518         struct latch_descr *ldesc;
1519
1520         ldesc = find_latch(mask);
1521         if (!ldesc)
1522                 return -1;
1523         *value = ldesc->flags;
1524         return 0;
1525 }
1526
1527 void clear_problem_context(struct problem_context *ctx)
1528 {
1529         memset(ctx, 0, sizeof(struct problem_context));
1530         ctx->blkcount = -1;
1531         ctx->group = -1;
1532 }
1533
1534 int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx)
1535 {
1536         ext2_filsys fs = ctx->fs;
1537         const struct e2fsck_problem *ptr;
1538         struct latch_descr *ldesc = 0;
1539         const char *message;
1540         int             def_yn, answer, ans;
1541         int             print_answer = 0;
1542         int             suppress = 0;
1543
1544         ptr = find_problem(code);
1545         if (!ptr) {
1546                 printf(_("Unhandled error code (0x%x)!\n"), code);
1547                 return 0;
1548         }
1549         def_yn = 1;
1550         if ((ptr->flags & PR_NO_DEFAULT) ||
1551             ((ptr->flags & PR_PREEN_NO) && (ctx->options & E2F_OPT_PREEN)) ||
1552             (ctx->options & E2F_OPT_NO))
1553                 def_yn= 0;
1554
1555         /*
1556          * Do special latch processing.  This is where we ask the
1557          * latch question, if it exists
1558          */
1559         if (ptr->flags & PR_LATCH_MASK) {
1560                 ldesc = find_latch(ptr->flags & PR_LATCH_MASK);
1561                 if (ldesc->question && !(ldesc->flags & PRL_LATCHED)) {
1562                         ans = fix_problem(ctx, ldesc->question, pctx);
1563                         if (ans == 1)
1564                                 ldesc->flags |= PRL_YES;
1565                         if (ans == 0)
1566                                 ldesc->flags |= PRL_NO;
1567                         ldesc->flags |= PRL_LATCHED;
1568                 }
1569                 if (ldesc->flags & PRL_SUPPRESS)
1570                         suppress++;
1571         }
1572         if ((ptr->flags & PR_PREEN_NOMSG) &&
1573             (ctx->options & E2F_OPT_PREEN))
1574                 suppress++;
1575         if ((ptr->flags & PR_NO_NOMSG) &&
1576             (ctx->options & E2F_OPT_NO))
1577                 suppress++;
1578         if (!suppress) {
1579                 message = ptr->e2p_description;
1580                 if ((ctx->options & E2F_OPT_PREEN) &&
1581                     !(ptr->flags & PR_PREEN_NOHDR)) {
1582                         printf("%s: ", ctx->device_name ?
1583                                ctx->device_name : ctx->filesystem_name);
1584                 }
1585                 if (*message)
1586                         print_e2fsck_message(ctx, _(message), pctx, 1);
1587         }
1588         if (!(ptr->flags & PR_PREEN_OK) && (ptr->prompt != PROMPT_NONE))
1589                 preenhalt(ctx);
1590
1591         if (ptr->flags & PR_FATAL)
1592                 fatal_error(ctx, 0);
1593
1594         if (ptr->prompt == PROMPT_NONE) {
1595                 if (ptr->flags & PR_NOCOLLATE)
1596                         answer = -1;
1597                 else
1598                         answer = def_yn;
1599         } else {
1600                 if (ctx->options & E2F_OPT_PREEN) {
1601                         answer = def_yn;
1602                         if (!(ptr->flags & PR_PREEN_NOMSG))
1603                                 print_answer = 1;
1604                 } else if ((ptr->flags & PR_LATCH_MASK) &&
1605                            (ldesc->flags & (PRL_YES | PRL_NO))) {
1606                         if (!suppress)
1607                                 print_answer = 1;
1608                         if (ldesc->flags & PRL_YES)
1609                                 answer = 1;
1610                         else
1611                                 answer = 0;
1612                 } else
1613                         answer = ask(ctx, _(prompt[(int) ptr->prompt]), def_yn);
1614                 if (!answer && !(ptr->flags & PR_NO_OK))
1615                         ext2fs_unmark_valid(fs);
1616         
1617                 if (print_answer)
1618                         printf("%s.\n", answer ?
1619                                _(preen_msg[(int) ptr->prompt]) : _("IGNORED"));
1620         
1621         }
1622
1623         if ((ptr->prompt == PROMPT_ABORT) && answer)
1624                 fatal_error(ctx, 0);
1625
1626         if (ptr->flags & PR_AFTER_CODE)
1627                 answer = fix_problem(ctx, ptr->second_code, pctx);
1628
1629         return answer;
1630 }