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