problem.c revision e8a3ee628ad693cbae231089b18886e6ba0e59d3
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_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	/* Filesystem contains large files, but has no such flag in sb */
519	{ PR_1_FEATURE_LARGE_FILES,
520	  N_("@f contains large files, but lacks LARGE_FILE flag in @S.\n"),
521	  PROMPT_FIX, 0 },
522
523	/* Imagic flag set on an inode when filesystem doesn't support it */
524	{ PR_1_SET_IMAGIC,
525	  N_("@i %i has imagic flag set.  "),
526	  PROMPT_CLEAR, 0 },
527
528	/* Immutable flag set on a device or socket inode */
529	{ PR_1_SET_IMMUTABLE,
530	  N_("Special (@v/socket/fifo) @i %i has immutable or "
531	     "append-only flag set.\n"),
532	  PROMPT_CLEAR, PR_PREEN_OK | PR_PREEN_NO | PR_NO_OK },
533
534	/* Compression flag set on an inode when filesystem doesn't support it */
535	{ PR_1_COMPR_SET,
536	  N_("@i %i has @cion flag set on @f without @cion support.  "),
537	  PROMPT_CLEAR, 0 },
538
539	/* Non-zero size for device, fifo or socket inode */
540	{ PR_1_SET_NONZSIZE,
541	  "Special (@v/socket/fifo) @i %i has non-zero size.  ",
542	  PROMPT_FIX, PR_PREEN_OK },
543
544	/* Filesystem revision is 0, but feature flags are set */
545	{ PR_1_FS_REV_LEVEL,
546	  "@f has feature flag(s) set, but is a revision 0 @f.  ",
547	  PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
548
549	/* Journal inode is not in use, but contains data */
550	{ PR_1_JOURNAL_INODE_NOT_CLEAR,
551	  "@j @i is not in use, but contains data.  ",
552	  PROMPT_CLEAR, PR_PREEN_OK },
553
554	/* Journal has bad mode */
555	{ PR_1_JOURNAL_BAD_MODE,
556	  N_("@j is not regular file.  "),
557	  PROMPT_FIX, PR_PREEN_OK },
558
559	/* Deal with inodes that were part of orphan linked list */
560	{ PR_1_LOW_DTIME,
561	  N_("@i %i was part of the orphaned @i list.  "),
562	  PROMPT_FIX, PR_LATCH_LOW_DTIME, 0 },
563
564	/* Deal with inodes that were part of corrupted orphan linked
565	   list (latch question) */
566	{ PR_1_ORPHAN_LIST_REFUGEES,
567	  N_("@is that were part of a corrupted orphan linked list found.  "),
568	  PROMPT_FIX, 0 },
569
570	/* Error allocating refcount structure */
571	{ PR_1_ALLOCATE_REFCOUNT,
572	  "@A refcount structure (%N): %m\n",
573	  PROMPT_NONE, PR_FATAL },
574
575	/* Error reading extended attribute block */
576	{ PR_1_READ_EA_BLOCK,
577	  N_("Error reading @a @b %b for @i %i.  "),
578	  PROMPT_CLEAR, 0 },
579
580	/* Invalid extended attribute block */
581	{ PR_1_BAD_EA_BLOCK,
582	  N_("@i %i has a bad @a @b %b.  "),
583	  PROMPT_CLEAR, 0 },
584
585	/* Error reading Extended Attribute block while fixing refcount */
586	{ PR_1_EXTATTR_READ_ABORT,
587	  N_("Error reading @a @b %b (%m).  "),
588	  PROMPT_ABORT, 0 },
589
590	/* Extended attribute reference count incorrect */
591	{ PR_1_EXTATTR_REFCOUNT,
592	  N_("@a @b %b has reference count %B, should be %N.  "),
593	  PROMPT_FIX, 0 },
594
595	/* Error writing Extended Attribute block while fixing refcount */
596	{ PR_1_EXTATTR_WRITE,
597	  N_("Error writing @a @b %b (%m).  "),
598	  PROMPT_ABORT, 0 },
599
600	/* Pass 1b errors */
601
602	/* Pass 1B: Rescan for duplicate/bad blocks */
603	{ PR_1B_PASS_HEADER,
604	  N_("Duplicate @bs found... invoking duplicate @b passes.\n"
605	  "Pass 1B: Rescan for duplicate/bad @bs\n"),
606	  PROMPT_NONE, 0 },
607
608	/* Duplicate/bad block(s) header */
609	{ PR_1B_DUP_BLOCK_HEADER,
610	  N_("Duplicate/bad @b(s) in @i %i:"),
611	  PROMPT_NONE, 0 },
612
613	/* Duplicate/bad block(s) in inode */
614	{ PR_1B_DUP_BLOCK,
615	  " %b",
616	  PROMPT_NONE, PR_LATCH_DBLOCK },
617
618	/* Duplicate/bad block(s) end */
619	{ PR_1B_DUP_BLOCK_END,
620	  "\n",
621	  PROMPT_NONE, 0 },
622
623	/* Error while scanning inodes */
624	{ PR_1B_ISCAN_ERROR,
625	  N_("Error while scanning inodes (%i): %m\n"),
626	  PROMPT_NONE, PR_FATAL },
627
628	/* Error allocating inode bitmap */
629	{ PR_1B_ALLOCATE_IBITMAP_ERROR,
630	  N_("@A @i @B (inode_dup_map): %m\n"),
631	  PROMPT_NONE, PR_FATAL },
632
633	/* Error while iterating over blocks */
634	{ PR_1B_BLOCK_ITERATE,
635	  N_("Error while iterating over @bs in @i %i (%s): %m\n"),
636	  PROMPT_NONE, 0 },
637
638	/* Pass 1C: Scan directories for inodes with dup blocks. */
639	{ PR_1C_PASS_HEADER,
640	  N_("Pass 1C: Scan directories for @is with dup @bs.\n"),
641	  PROMPT_NONE, 0 },
642
643
644	/* Pass 1D: Reconciling duplicate blocks */
645	{ PR_1D_PASS_HEADER,
646	  N_("Pass 1D: Reconciling duplicate @bs\n"),
647	  PROMPT_NONE, 0 },
648
649	/* File has duplicate blocks */
650	{ PR_1D_DUP_FILE,
651	  N_("File %Q (@i #%i, mod time %IM) \n"
652	  "  has %B duplicate @b(s), shared with %N file(s):\n"),
653	  PROMPT_NONE, 0 },
654
655	/* List of files sharing duplicate blocks */
656	{ PR_1D_DUP_FILE_LIST,
657	  N_("\t%Q (@i #%i, mod time %IM)\n"),
658	  PROMPT_NONE, 0 },
659
660	/* File sharing blocks with filesystem metadata  */
661	{ PR_1D_SHARE_METADATA,
662	  N_("\t<@f metadata>\n"),
663	  PROMPT_NONE, 0 },
664
665	/* Report of how many duplicate/bad inodes */
666	{ PR_1D_NUM_DUP_INODES,
667	  N_("(There are %N @is containing duplicate/bad @bs.)\n\n"),
668	  PROMPT_NONE, 0 },
669
670	/* Duplicated blocks already reassigned or cloned. */
671	{ PR_1D_DUP_BLOCKS_DEALT,
672	  N_("Duplicated @bs already reassigned or cloned.\n\n"),
673	  PROMPT_NONE, 0 },
674
675	/* Clone duplicate/bad blocks? */
676	{ PR_1D_CLONE_QUESTION,
677	  "", PROMPT_CLONE, PR_NO_OK },
678
679	/* Delete file? */
680	{ PR_1D_DELETE_QUESTION,
681	  "", PROMPT_DELETE, 0 },
682
683	/* Couldn't clone file (error) */
684	{ PR_1D_CLONE_ERROR,
685	  N_("Couldn't clone file: %m\n"), PROMPT_NONE, 0 },
686
687	/* Pass 2 errors */
688
689	/* Pass 2: Checking directory structure */
690	{ PR_2_PASS_HEADER,
691	  N_("Pass 2: Checking @d structure\n"),
692	  PROMPT_NONE, 0 },
693
694	/* Bad inode number for '.' */
695	{ PR_2_BAD_INODE_DOT,
696	  N_("Bad @i number for '.' in @d @i %i.\n"),
697	  PROMPT_FIX, 0 },
698
699	/* Directory entry has bad inode number */
700	{ PR_2_BAD_INO,
701	  N_("@E has bad @i #: %Di.\n"),
702	  PROMPT_CLEAR, 0 },
703
704	/* Directory entry has deleted or unused inode */
705	{ PR_2_UNUSED_INODE,
706	  N_("@E has @D/unused @i %Di.  "),
707	  PROMPT_CLEAR, PR_PREEN_OK },
708
709	/* Directry entry is link to '.' */
710	{ PR_2_LINK_DOT,
711	  N_("@E @L to '.'  "),
712	  PROMPT_CLEAR, 0 },
713
714	/* Directory entry points to inode now located in a bad block */
715	{ PR_2_BB_INODE,
716	  N_("@E points to @i (%Di) located in a bad @b.\n"),
717	  PROMPT_CLEAR, 0 },
718
719	/* Directory entry contains a link to a directory */
720	{ PR_2_LINK_DIR,
721	  N_("@E @L to @d %P (%Di).\n"),
722	  PROMPT_CLEAR, 0 },
723
724	/* Directory entry contains a link to the root directry */
725	{ PR_2_LINK_ROOT,
726	  N_("@E @L to the @r.\n"),
727	  PROMPT_CLEAR, 0 },
728
729	/* Directory entry has illegal characters in its name */
730	{ PR_2_BAD_NAME,
731	  N_("@E has illegal characters in its name.\n"),
732	  PROMPT_FIX, 0 },
733
734	/* Missing '.' in directory inode */
735	{ PR_2_MISSING_DOT,
736	  N_("Missing '.' in @d @i %i.\n"),
737	  PROMPT_FIX, 0 },
738
739	/* Missing '..' in directory inode */
740	{ PR_2_MISSING_DOT_DOT,
741	  N_("Missing '..' in @d @i %i.\n"),
742	  PROMPT_FIX, 0 },
743
744	/* First entry in directory inode doesn't contain '.' */
745	{ PR_2_1ST_NOT_DOT,
746	  N_("First @e '%Dn' (inode=%Di) in @d @i %i (%p) @s '.'\n"),
747	  PROMPT_FIX, 0 },
748
749	/* Second entry in directory inode doesn't contain '..' */
750	{ PR_2_2ND_NOT_DOT_DOT,
751	  N_("Second @e '%Dn' (inode=%Di) in @d @i %i @s '..'\n"),
752	  PROMPT_FIX, 0 },
753
754	/* i_faddr should be zero */
755	{ PR_2_FADDR_ZERO,
756	  N_("i_faddr @F %IF, @s zero.\n"),
757	  PROMPT_CLEAR, 0 },
758
759  	/* i_file_acl should be zero */
760	{ PR_2_FILE_ACL_ZERO,
761	  N_("i_file_acl @F %If, @s zero.\n"),
762	  PROMPT_CLEAR, 0 },
763
764  	/* i_dir_acl should be zero */
765	{ PR_2_DIR_ACL_ZERO,
766	  N_("i_dir_acl @F %Id, @s zero.\n"),
767	  PROMPT_CLEAR, 0 },
768
769  	/* i_frag should be zero */
770	{ PR_2_FRAG_ZERO,
771	  N_("i_frag @F %N, @s zero.\n"),
772	  PROMPT_CLEAR, 0 },
773
774  	/* i_fsize should be zero */
775	{ PR_2_FSIZE_ZERO,
776	  N_("i_fsize @F %N, @s zero.\n"),
777	  PROMPT_CLEAR, 0 },
778
779	/* inode has bad mode */
780	{ PR_2_BAD_MODE,
781	  N_("@i %i (%Q) has a bad mode (%Im).\n"),
782	  PROMPT_CLEAR, 0 },
783
784	/* directory corrupted */
785	{ PR_2_DIR_CORRUPTED,
786	  N_("@d @i %i, @b %B, offset %N: @d corrupted\n"),
787	  PROMPT_SALVAGE, 0 },
788
789	/* filename too long */
790	{ PR_2_FILENAME_LONG,
791	  N_("@d @i %i, @b %B, offset %N: filename too long\n"),
792	  PROMPT_TRUNCATE, 0 },
793
794	/* Directory inode has a missing block (hole) */
795	{ PR_2_DIRECTORY_HOLE,
796	  N_("@d @i %i has an unallocated @b #%B.  "),
797	  PROMPT_ALLOCATE, 0 },
798
799	/* '.' is not NULL terminated */
800	{ PR_2_DOT_NULL_TERM,
801	  N_("'.' @d @e in @d @i %i is not NULL terminated\n"),
802	  PROMPT_FIX, 0 },
803
804	/* '..' is not NULL terminated */
805	{ PR_2_DOT_DOT_NULL_TERM,
806	  N_("'..' @d @e in @d @i %i is not NULL terminated\n"),
807	  PROMPT_FIX, 0 },
808
809	/* Illegal character device inode */
810	{ PR_2_BAD_CHAR_DEV,
811	  N_("@i %i (%Q) is an @I character @v.\n"),
812	  PROMPT_CLEAR, 0 },
813
814	/* Illegal block device inode */
815	{ PR_2_BAD_BLOCK_DEV,
816	  N_("@i %i (%Q) is an @I @b @v.\n"),
817	  PROMPT_CLEAR, 0 },
818
819	/* Duplicate '.' entry */
820	{ PR_2_DUP_DOT,
821	  N_("@E is duplicate '.' @e.\n"),
822	  PROMPT_FIX, 0 },
823
824	/* Duplicate '..' entry */
825	{ PR_2_DUP_DOT_DOT,
826	  N_("@E is duplicate '..' @e.\n"),
827	  PROMPT_FIX, 0 },
828
829	/* Internal error: couldn't find dir_info */
830	{ PR_2_NO_DIRINFO,
831	  N_("Internal error: couldn't find dir_info for %i.\n"),
832	  PROMPT_NONE, PR_FATAL },
833
834	/* Final rec_len is wrong */
835	{ PR_2_FINAL_RECLEN,
836	  N_("@E has rec_len of %dr, should be %N.\n"),
837	  PROMPT_FIX, 0 },
838
839	/* Error allocating icount structure */
840	{ PR_2_ALLOCATE_ICOUNT,
841	  N_("@A icount structure: %m\n"),
842	  PROMPT_NONE, PR_FATAL },
843
844	/* Error iterating over directory blocks */
845	{ PR_2_DBLIST_ITERATE,
846	  N_("Error interating over @d @bs: %m\n"),
847	  PROMPT_NONE, PR_FATAL },
848
849	/* Error reading directory block */
850	{ PR_2_READ_DIRBLOCK,
851	  N_("Error reading @d @b %b (@i %i): %m\n"),
852	  PROMPT_CONTINUE, 0 },
853
854	/* Error writing directory block */
855	{ PR_2_WRITE_DIRBLOCK,
856	  N_("Error writing @d @b %b (@i %i): %m\n"),
857	  PROMPT_CONTINUE, 0 },
858
859	/* Error allocating new directory block */
860	{ PR_2_ALLOC_DIRBOCK,
861	  N_("@A new @d @b for @i %i (%s): %m\n"),
862	  PROMPT_NONE, 0 },
863
864	/* Error deallocating inode */
865	{ PR_2_DEALLOC_INODE,
866	  N_("Error deallocating @i %i: %m\n"),
867	  PROMPT_NONE, PR_FATAL },
868
869	/* Directory entry for '.' is big.  Split? */
870	{ PR_2_SPLIT_DOT,
871	  N_("@d @e for '.' is big.  "),
872	  PROMPT_SPLIT, PR_NO_OK },
873
874	/* Illegal FIFO inode */
875	{ PR_2_BAD_FIFO,
876	  N_("@i %i (%Q) is an @I FIFO.\n"),
877	  PROMPT_CLEAR, 0 },
878
879	/* Illegal socket inode */
880	{ PR_2_BAD_SOCKET,
881	  N_("@i %i (%Q) is an @I socket.\n"),
882	  PROMPT_CLEAR, 0 },
883
884	/* Directory filetype not set */
885	{ PR_2_SET_FILETYPE,
886	  N_("Setting filetype for @E to %N.\n"),
887	  PROMPT_NONE, PR_PREEN_OK | PR_NO_OK | PR_NO_NOMSG },
888
889	/* Directory filetype incorrect */
890	{ PR_2_BAD_FILETYPE,
891	  N_("@E has an incorrect filetype (was %dt, should be %N)\n"),
892	  PROMPT_FIX, 0 },
893
894	/* Directory filetype set on filesystem */
895	{ PR_2_CLEAR_FILETYPE,
896	  N_("@E has filetype set\n"),
897	  PROMPT_CLEAR, PR_PREEN_OK },
898
899	/* Directory filename is null */
900	{ PR_2_NULL_NAME,
901	  N_("@E has a zero-length name\n"),
902	  PROMPT_CLEAR, 0 },
903
904	/* Invalid fast symlink size */
905	{ PR_2_SYMLINK_SIZE,
906	  N_("@i %i (%Q) is a fast symlink with a bad size (%Is)\n"),
907	  PROMPT_CLEAR, 0 },
908
909  	/* i_file_acl (extended attribute block) is bad */
910	{ PR_2_FILE_ACL_BAD,
911	  N_("@a @b @F is invalid (%If).\n"),
912	  PROMPT_CLEAR, 0 },
913
914	/* Pass 3 errors */
915
916	/* Pass 3: Checking directory connectivity */
917	{ PR_3_PASS_HEADER,
918	  N_("Pass 3: Checking @d connectivity\n"),
919	  PROMPT_NONE, 0 },
920
921	/* Root inode not allocated */
922	{ PR_3_NO_ROOT_INODE,
923	  N_("@r not allocated.  "),
924	  PROMPT_ALLOCATE, 0 },
925
926	/* No room in lost+found */
927	{ PR_3_EXPAND_LF_DIR,
928	  N_("No room in @l @d.  "),
929	  PROMPT_EXPAND, 0 },
930
931	/* Unconnected directory inode */
932	{ PR_3_UNCONNECTED_DIR,
933	  N_("Unconnected @d @i %i (%p)\n"),
934	  PROMPT_CONNECT, 0 },
935
936	/* /lost+found not found */
937	{ PR_3_NO_LF_DIR,
938	  N_("/@l not found.  "),
939	  PROMPT_CREATE, PR_PREEN_OK },
940
941	/* .. entry is incorrect */
942	{ PR_3_BAD_DOT_DOT,
943	  N_("'..' in %Q (%i) is %P (%j), @s %q (%d).\n"),
944	  PROMPT_FIX, 0 },
945
946	/* Bad or non-existent /lost+found.  Cannot reconnect */
947	{ PR_3_NO_LPF,
948	  N_("Bad or non-existent /@l.  Cannot reconnect\n"),
949	  PROMPT_NONE, 0 },
950
951	/* Could not expand /lost+found */
952	{ PR_3_CANT_EXPAND_LPF,
953	  N_("Could not expand /@l: %m\n"),
954	  PROMPT_NONE, 0 },
955
956	/* Could not reconnect inode */
957	{ PR_3_CANT_RECONNECT,
958	  N_("Could not reconnect %i: %m\n"),
959	  PROMPT_NONE, 0 },
960
961	/* Error while trying to find /lost+found */
962	{ PR_3_ERR_FIND_LPF,
963	  N_("Error while trying to find /@l: %m\n"),
964	  PROMPT_NONE, 0 },
965
966	/* Error in ext2fs_new_block while creating /lost+found */
967	{ PR_3_ERR_LPF_NEW_BLOCK,
968	  N_("ext2fs_new_@b: %m while trying to create /@l @d\n"),
969	  PROMPT_NONE, 0 },
970
971	/* Error in ext2fs_new_inode while creating /lost+found */
972	{ PR_3_ERR_LPF_NEW_INODE,
973	  N_("ext2fs_new_@i: %m while trying to create /@l @d\n"),
974	  PROMPT_NONE, 0 },
975
976	/* Error in ext2fs_new_dir_block while creating /lost+found */
977	{ PR_3_ERR_LPF_NEW_DIR_BLOCK,
978	  N_("ext2fs_new_dir_@b: %m while creating new @d @b\n"),
979	  PROMPT_NONE, 0 },
980
981	/* Error while writing directory block for /lost+found */
982	{ PR_3_ERR_LPF_WRITE_BLOCK,
983	  N_("ext2fs_write_dir_@b: %m while writing the @d @b for /@l\n"),
984	  PROMPT_NONE, 0 },
985
986	/* Error while adjusting inode count */
987	{ PR_3_ADJUST_INODE,
988	  N_("Error while adjusting @i count on @i %i\n"),
989	  PROMPT_NONE, 0 },
990
991	/* Couldn't fix parent directory -- error */
992	{ PR_3_FIX_PARENT_ERR,
993	  N_("Couldn't fix parent of @i %i: %m\n\n"),
994	  PROMPT_NONE, 0 },
995
996	/* Couldn't fix parent directory -- couldn't find it */
997	{ PR_3_FIX_PARENT_NOFIND,
998	  N_("Couldn't fix parent of @i %i: Couldn't find parent @d entry\n\n"),
999	  PROMPT_NONE, 0 },
1000
1001	/* Error allocating inode bitmap */
1002	{ PR_3_ALLOCATE_IBITMAP_ERROR,
1003	  N_("@A @i @B (%N): %m\n"),
1004	  PROMPT_NONE, PR_FATAL },
1005
1006	/* Error creating root directory */
1007	{ PR_3_CREATE_ROOT_ERROR,
1008	  N_("Error creating root @d (%s): %m\n"),
1009	  PROMPT_NONE, PR_FATAL },
1010
1011	/* Error creating lost and found directory */
1012	{ PR_3_CREATE_LPF_ERROR,
1013	  N_("Error creating /@l @d (%s): %m\n"),
1014	  PROMPT_NONE, PR_FATAL },
1015
1016	/* Root inode is not directory; aborting */
1017	{ PR_3_ROOT_NOT_DIR_ABORT,
1018	  N_("@r is not a @d; aborting.\n"),
1019	  PROMPT_NONE, PR_FATAL },
1020
1021	/* Cannot proceed without a root inode. */
1022	{ PR_3_NO_ROOT_INODE_ABORT,
1023	  N_("Cannot proceed without a @r.\n"),
1024	  PROMPT_NONE, PR_FATAL },
1025
1026	/* Internal error: couldn't find dir_info */
1027	{ PR_3_NO_DIRINFO,
1028	  N_("Internal error: couldn't find dir_info for %i.\n"),
1029	  PROMPT_NONE, PR_FATAL },
1030
1031	/* Lost+found not a directory */
1032	{ PR_3_LPF_NOTDIR,
1033	  N_("/@l is not a @d (ino=%i)\n"),
1034	  PROMPT_UNLINK, 0 },
1035
1036	/* Pass 4 errors */
1037
1038	/* Pass 4: Checking reference counts */
1039	{ PR_4_PASS_HEADER,
1040	  N_("Pass 4: Checking reference counts\n"),
1041	  PROMPT_NONE, 0 },
1042
1043	/* Unattached zero-length inode */
1044	{ PR_4_ZERO_LEN_INODE,
1045	  "@u @z @i %i.  ",
1046	  PROMPT_CLEAR, PR_PREEN_OK|PR_NO_OK },
1047
1048	/* Unattached inode */
1049	{ PR_4_UNATTACHED_INODE,
1050	  "@u @i %i\n",
1051	  PROMPT_CONNECT, 0 },
1052
1053	/* Inode ref count wrong */
1054	{ PR_4_BAD_REF_COUNT,
1055	  N_("@i %i ref count is %Il, @s %N.  "),
1056	  PROMPT_FIX, PR_PREEN_OK },
1057
1058	{ PR_4_INCONSISTENT_COUNT,
1059	  N_("WARNING: PROGRAMMING BUG IN E2FSCK!\n"
1060	  "\tOR SOME BONEHEAD (YOU) IS CHECKING A MOUNTED (LIVE) FILESYSTEM.\n"
1061	  "@i_link_info[%i] is %N, @i.i_links_count is %Il.  "
1062	  "They should be the same!\n"),
1063	  PROMPT_NONE, 0 },
1064
1065	/* Pass 5 errors */
1066
1067	/* Pass 5: Checking group summary information */
1068	{ PR_5_PASS_HEADER,
1069	  N_("Pass 5: Checking @g summary information\n"),
1070	  PROMPT_NONE, 0 },
1071
1072	/* Padding at end of inode bitmap is not set. */
1073	{ PR_5_INODE_BMAP_PADDING,
1074	  N_("Padding at end of @i @B is not set. "),
1075	  PROMPT_FIX, PR_PREEN_OK },
1076
1077	/* Padding at end of block bitmap is not set. */
1078	{ PR_5_BLOCK_BMAP_PADDING,
1079	  N_("Padding at end of @b @B is not set. "),
1080	  PROMPT_FIX, PR_PREEN_OK },
1081
1082	/* Block bitmap differences header */
1083	{ PR_5_BLOCK_BITMAP_HEADER,
1084	  N_("@b @B differences: "),
1085	  PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG},
1086
1087	/* Block not used, but marked in bitmap */
1088	{ PR_5_UNUSED_BLOCK,
1089	  " -%b",
1090	  PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
1091
1092	/* Block used, but not marked used in bitmap */
1093	{ PR_5_BLOCK_USED,
1094	  " +%b",
1095	  PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
1096
1097	/* Block bitmap differences end */
1098	{ PR_5_BLOCK_BITMAP_END,
1099	  "\n",
1100	  PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
1101
1102	/* Inode bitmap differences header */
1103	{ PR_5_INODE_BITMAP_HEADER,
1104	  N_("@i @B differences: "),
1105	  PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
1106
1107	/* Inode not used, but marked in bitmap */
1108	{ PR_5_UNUSED_INODE,
1109	  " -%i",
1110	  PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
1111
1112	/* Inode used, but not marked used in bitmap */
1113	{ PR_5_INODE_USED,
1114	  " +%i",
1115	  PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
1116
1117	/* Inode bitmap differences end */
1118	{ PR_5_INODE_BITMAP_END,
1119	  "\n",
1120	  PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
1121
1122	/* Free inodes count for group wrong */
1123	{ PR_5_FREE_INODE_COUNT_GROUP,
1124	  N_("Free @is count wrong for @g #%g (%i, counted=%j).\n"),
1125	  PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
1126
1127	/* Directories count for group wrong */
1128	{ PR_5_FREE_DIR_COUNT_GROUP,
1129	  N_("Directories count wrong for @g #%g (%i, counted=%j).\n"),
1130	  PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
1131
1132	/* Free inodes count wrong */
1133	{ PR_5_FREE_INODE_COUNT,
1134	  N_("Free @is count wrong (%i, counted=%j).\n"),
1135	  PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
1136
1137	/* Free blocks count for group wrong */
1138	{ PR_5_FREE_BLOCK_COUNT_GROUP,
1139	  N_("Free @bs count wrong for @g #%g (%b, counted=%c).\n"),
1140	  PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
1141
1142	/* Free blocks count wrong */
1143	{ PR_5_FREE_BLOCK_COUNT,
1144	  N_("Free @bs count wrong (%b, counted=%c).\n"),
1145	  PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
1146
1147	/* Programming error: bitmap endpoints don't match */
1148	{ PR_5_BMAP_ENDPOINTS,
1149	  N_("PROGRAMMING ERROR: @f (#%N) @B endpoints (%b, %c) don't "
1150	  "match calculated @B endpoints (%i, %j)\n"),
1151	  PROMPT_NONE, PR_FATAL },
1152
1153	/* Internal error: fudging end of bitmap */
1154	{ PR_5_FUDGE_BITMAP_ERROR,
1155	  N_("Internal error: fudging end of bitmap (%N)\n"),
1156	  PROMPT_NONE, PR_FATAL },
1157
1158	/* Error copying in replacement inode bitmap */
1159	{ PR_5_COPY_IBITMAP_ERROR,
1160	  "Error copying in replacement @i @B: %m\n",
1161	  PROMPT_NONE, PR_FATAL },
1162
1163	/* Error copying in replacement block bitmap */
1164	{ PR_5_COPY_BBITMAP_ERROR,
1165	  "Error copying in replacement @b @B: %m\n",
1166	  PROMPT_NONE, PR_FATAL },
1167
1168	{ 0 }
1169};
1170
1171/*
1172 * This is the latch flags register.  It allows several problems to be
1173 * "latched" together.  This means that the user has to answer but one
1174 * question for the set of problems, and all of the associated
1175 * problems will be either fixed or not fixed.
1176 */
1177static struct latch_descr pr_latch_info[] = {
1178	{ PR_LATCH_BLOCK, PR_1_INODE_BLOCK_LATCH, 0 },
1179	{ PR_LATCH_BBLOCK, PR_1_INODE_BBLOCK_LATCH, 0 },
1180	{ PR_LATCH_IBITMAP, PR_5_INODE_BITMAP_HEADER, PR_5_INODE_BITMAP_END },
1181	{ PR_LATCH_BBITMAP, PR_5_BLOCK_BITMAP_HEADER, PR_5_BLOCK_BITMAP_END },
1182	{ PR_LATCH_RELOC, PR_0_RELOCATE_HINT, 0 },
1183	{ PR_LATCH_DBLOCK, PR_1B_DUP_BLOCK_HEADER, PR_1B_DUP_BLOCK_END },
1184	{ PR_LATCH_LOW_DTIME, PR_1_ORPHAN_LIST_REFUGEES, 0 },
1185	{ -1, 0, 0 },
1186};
1187
1188static const struct e2fsck_problem *find_problem(int code)
1189{
1190	int 	i;
1191
1192	for (i=0; problem_table[i].e2p_code; i++) {
1193		if (problem_table[i].e2p_code == code)
1194			return &problem_table[i];
1195	}
1196	return 0;
1197}
1198
1199static struct latch_descr *find_latch(int code)
1200{
1201	int	i;
1202
1203	for (i=0; pr_latch_info[i].latch_code >= 0; i++) {
1204		if (pr_latch_info[i].latch_code == code)
1205			return &pr_latch_info[i];
1206	}
1207	return 0;
1208}
1209
1210int end_problem_latch(e2fsck_t ctx, int mask)
1211{
1212	struct latch_descr *ldesc;
1213	struct problem_context pctx;
1214	int answer = -1;
1215
1216	ldesc = find_latch(mask);
1217	if (ldesc->end_message && (ldesc->flags & PRL_LATCHED)) {
1218		clear_problem_context(&pctx);
1219		answer = fix_problem(ctx, ldesc->end_message, &pctx);
1220	}
1221	ldesc->flags &= ~(PRL_VARIABLE);
1222	return answer;
1223}
1224
1225int set_latch_flags(int mask, int setflags, int clearflags)
1226{
1227	struct latch_descr *ldesc;
1228
1229	ldesc = find_latch(mask);
1230	if (!ldesc)
1231		return -1;
1232	ldesc->flags |= setflags;
1233	ldesc->flags &= ~clearflags;
1234	return 0;
1235}
1236
1237int get_latch_flags(int mask, int *value)
1238{
1239	struct latch_descr *ldesc;
1240
1241	ldesc = find_latch(mask);
1242	if (!ldesc)
1243		return -1;
1244	*value = ldesc->flags;
1245	return 0;
1246}
1247
1248void clear_problem_context(struct problem_context *ctx)
1249{
1250	memset(ctx, 0, sizeof(struct problem_context));
1251	ctx->blkcount = -1;
1252	ctx->group = -1;
1253}
1254
1255int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx)
1256{
1257	ext2_filsys fs = ctx->fs;
1258	const struct e2fsck_problem *ptr;
1259	struct latch_descr *ldesc = 0;
1260	const char *message;
1261	int 		def_yn, answer, ans;
1262	int		print_answer = 0;
1263	int		suppress = 0;
1264
1265	ptr = find_problem(code);
1266	if (!ptr) {
1267		printf(_("Unhandled error code (%d)!\n"), code);
1268		return 0;
1269	}
1270	def_yn = 1;
1271	if ((ptr->flags & PR_NO_DEFAULT) ||
1272	    ((ptr->flags & PR_PREEN_NO) && (ctx->options & E2F_OPT_PREEN)) ||
1273	    (ctx->options & E2F_OPT_NO))
1274		def_yn= 0;
1275
1276	/*
1277	 * Do special latch processing.  This is where we ask the
1278	 * latch question, if it exists
1279	 */
1280	if (ptr->flags & PR_LATCH_MASK) {
1281		ldesc = find_latch(ptr->flags & PR_LATCH_MASK);
1282		if (ldesc->question && !(ldesc->flags & PRL_LATCHED)) {
1283			ans = fix_problem(ctx, ldesc->question, pctx);
1284			if (ans == 1)
1285				ldesc->flags |= PRL_YES;
1286			if (ans == 0)
1287				ldesc->flags |= PRL_NO;
1288			ldesc->flags |= PRL_LATCHED;
1289		}
1290		if (ldesc->flags & PRL_SUPPRESS)
1291			suppress++;
1292	}
1293	if ((ptr->flags & PR_PREEN_NOMSG) &&
1294	    (ctx->options & E2F_OPT_PREEN))
1295		suppress++;
1296	if ((ptr->flags & PR_NO_NOMSG) &&
1297	    (ctx->options & E2F_OPT_NO))
1298		suppress++;
1299	if (!suppress) {
1300		message = ptr->e2p_description;
1301		if (ctx->options & E2F_OPT_PREEN) {
1302			printf("%s: ", ctx->device_name);
1303#if 0
1304			if (ptr->e2p_preen_msg)
1305				message = ptr->e2p_preen_msg;
1306#endif
1307		}
1308		print_e2fsck_message(ctx, _(message), pctx, 1);
1309	}
1310	if (!(ptr->flags & PR_PREEN_OK) && (ptr->prompt != PROMPT_NONE))
1311		preenhalt(ctx);
1312
1313	if (ptr->flags & PR_FATAL)
1314		fatal_error(ctx, 0);
1315
1316	if (ptr->prompt == PROMPT_NONE) {
1317		if (ptr->flags & PR_NOCOLLATE)
1318			answer = -1;
1319		else
1320			answer = def_yn;
1321	} else {
1322		if (ctx->options & E2F_OPT_PREEN) {
1323			answer = def_yn;
1324			if (!(ptr->flags & PR_PREEN_NOMSG))
1325				print_answer = 1;
1326		} else if ((ptr->flags & PR_LATCH_MASK) &&
1327			   (ldesc->flags & (PRL_YES | PRL_NO))) {
1328			if (!suppress)
1329				print_answer = 1;
1330			if (ldesc->flags & PRL_YES)
1331				answer = 1;
1332			else
1333				answer = 0;
1334		} else
1335			answer = ask(ctx, _(prompt[(int) ptr->prompt]), def_yn);
1336		if (!answer && !(ptr->flags & PR_NO_OK))
1337			ext2fs_unmark_valid(fs);
1338
1339		if (print_answer)
1340			printf("%s.\n", answer ?
1341			       _(preen_msg[(int) ptr->prompt]) : _("IGNORED"));
1342
1343	}
1344
1345	if ((ptr->prompt == PROMPT_ABORT) && answer)
1346		fatal_error(ctx, 0);
1347
1348	if (ptr->flags & PR_AFTER_CODE)
1349		answer = fix_problem(ctx, ptr->second_code, pctx);
1350
1351	return answer;
1352}
1353