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