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