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