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