2 * problem.c --- report filesystem problems to the user
4 * Copyright 1996, 1997 by Theodore Ts'o
7 * This file may be redistributed under the terms of the GNU Public
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
43 * These are the prompts which are used to ask the user if they want
46 static const char *prompt[] = {
47 "(no prompt)", /* 0 */
53 "Connect to /lost+found", /* 6 */
57 "Clear inode", /* 10 */
61 "Clone duplicate/bad blocks", /* 14 */
62 "Delete file", /* 15 */
63 "Suppress messages", /* 16 */
68 * These messages are printed when we are preen mode and we will be
69 * automatically fixing the problem.
71 static const char *preen_msg[] = {
78 "RECONNECTED", /* 6 */
82 "INODE CLEARED", /* 10 */
85 "CONTINUING", /* 13 */
86 "DUPLICATE/BAD BLOCKS CLONED", /* 14 */
87 "FILE DELETED", /* 15 */
88 "SUPPRESSED", /* 16 */
92 static const struct e2fsck_problem problem_table[] = {
94 /* Pre-Pass 1 errors */
96 /* Block bitmap not in group */
97 { PR_0_BB_NOT_GROUP, "@b @B for @g %g is not in @g. (@b %b)\n",
98 PROMPT_RELOCATE, PR_LATCH_RELOC },
100 /* Inode bitmap not in group */
101 { PR_0_IB_NOT_GROUP, "@i @B for @g %g is not in @g. (@b %b)\n",
102 PROMPT_RELOCATE, PR_LATCH_RELOC },
104 /* Inode table not in group */
105 { PR_0_ITABLE_NOT_GROUP,
106 "@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 },
110 /* Superblock corrupt */
112 "\nThe @S could not be read or does not describe a correct ext2\n"
113 "@f. If the device 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 <device>\n\n",
117 PROMPT_NONE, PR_FATAL },
119 /* Filesystem size is wrong */
120 { PR_0_FS_SIZE_WRONG,
121 "The @f size (according to the @S) is %b @bs\n"
122 "The physical size of the device is %c @bs\n"
123 "Either the @S or the partition table is likely to be corrupt!\n",
126 /* Fragments not supported */
128 "@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 },
133 /* Bad blocks_per_group */
134 { PR_0_BLOCKS_PER_GROUP,
135 "@S @bs_per_group = %b, should have been %c\n",
136 PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
138 /* Bad first_data_block */
139 { PR_0_FIRST_DATA_BLOCK,
140 "@S first_data_@b = %b, should have been %c\n",
141 PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
143 /* Adding UUID to filesystem */
145 "@f did not have a UUID; generating one.\n\n",
149 { PR_0_RELOCATE_HINT,
150 "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 },
158 /* Miscellaneous superblock corruption */
159 { PR_0_MISC_CORRUPT_SUPER,
160 "Corruption found in @S. (%s = %N).\n",
161 PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
163 /* Error determing physical device size of filesystem */
164 { PR_0_GETSIZE_ERROR,
165 "Error determining size of the physical device: %m\n",
166 PROMPT_NONE, PR_FATAL },
168 /* Inode count in superblock is incorrect */
169 { PR_0_INODE_COUNT_WRONG,
170 "@i count in @S is %i, should be %j\n",
175 /* Pass 1: Checking inodes, blocks, and sizes */
177 "Pass 1: Checking @is, @bs, and sizes\n",
180 /* Root directory is not an inode */
181 { PR_1_ROOT_NO_DIR, "@r is not a @d. ",
184 /* Root directory has dtime set */
186 "@r has dtime set (probably due to old mke2fs). ",
187 PROMPT_FIX, PR_PREEN_OK },
189 /* Reserved inode has bad mode */
190 { PR_1_RESERVED_BAD_MODE,
191 "Reserved @i %i has bad mode. ",
192 PROMPT_CLEAR, PR_PREEN_OK },
194 /* Deleted inode has zero dtime */
196 "@D @i %i has zero dtime. ",
197 PROMPT_FIX, PR_PREEN_OK },
199 /* Inode in use, but dtime set */
201 "@i %i is in use, but has dtime set. ",
202 PROMPT_FIX, PR_PREEN_OK },
204 /* Zero-length directory */
205 { PR_1_ZERO_LENGTH_DIR,
206 "@i %i is a @z @d. ",
207 PROMPT_CLEAR, PR_PREEN_OK },
209 /* Block bitmap conflicts with some other fs block */
211 "@g %g's @b @B at %b @C.\n",
212 PROMPT_RELOCATE, 0 },
214 /* Inode bitmap conflicts with some other fs block */
216 "@g %g's @i @B at %b @C.\n",
217 PROMPT_RELOCATE, 0 },
219 /* Inode table conflicts with some other fs block */
220 { PR_1_ITABLE_CONFLICT,
221 "@g %g's @i table at %b @C.\n",
222 PROMPT_RELOCATE, 0 },
224 /* Block bitmap is on a bad block */
226 "@g %g's @b @B (%b) is bad. ",
227 PROMPT_RELOCATE, 0 },
229 /* Inode bitmap is on a bad block */
231 "@g %g's @i @B (%b) is bad. ",
232 PROMPT_RELOCATE, 0 },
234 /* Inode has incorrect i_size */
236 "@i %i, i_size is %Is, @s %N. ",
237 PROMPT_FIX, PR_PREEN_OK },
239 /* Inode has incorrect i_blocks */
241 "@i %i, i_@bs is %Ib, @s %N. ",
242 PROMPT_FIX, PR_PREEN_OK },
244 /* Illegal block number in inode */
245 { PR_1_ILLEGAL_BLOCK_NUM,
246 "@I @b #%B (%b) in @i %i. ",
247 PROMPT_CLEAR, PR_LATCH_BLOCK },
249 /* Block number overlaps fs metadata */
250 { PR_1_BLOCK_OVERLAPS_METADATA,
251 "@b #%B (%b) overlaps @f metadata in @i %i. ",
252 PROMPT_CLEAR, PR_LATCH_BLOCK },
254 /* Inode has illegal blocks (latch question) */
255 { PR_1_INODE_BLOCK_LATCH,
256 "@i %i has illegal @b(s). ",
259 /* Too many bad blocks in inode */
260 { PR_1_TOO_MANY_BAD_BLOCKS,
261 "Too many illegal @bs in @i %i.\n",
262 PROMPT_CLEAR_INODE, PR_NO_OK },
264 /* Illegal block number in bad block inode */
265 { PR_1_BB_ILLEGAL_BLOCK_NUM,
266 "@I @b #%B (%b) in bad @b @i. ",
267 PROMPT_CLEAR, PR_LATCH_BBLOCK },
269 /* Bad block inode has illegal blocks (latch question) */
270 { PR_1_INODE_BBLOCK_LATCH,
271 "Bad @b @i has illegal @b(s). ",
274 /* Duplicate or bad blocks in use! */
275 { PR_1_DUP_BLOCKS_PREENSTOP,
276 "Duplicate or bad @b in use!\n",
279 /* Bad block used as bad block indirect block */
280 { PR_1_BBINODE_BAD_METABLOCK,
281 "Bad @b %b used as bad @b indirect @b?!?\n",
282 PROMPT_NONE, PR_AFTER_CODE, PR_1_BBINODE_BAD_METABLOCK_PROMPT },
284 /* Inconsistency can't be fixed prompt */
285 { PR_1_BBINODE_BAD_METABLOCK_PROMPT,
286 "\nThis inconsistency can not be fixed with e2fsck; to fix it, use\n"
287 """dumpe2fs -b"" to dump out the bad @b "
288 "list and ""e2fsck -L filename""\n"
289 "to read it back in again.\n",
290 PROMPT_CONTINUE, PR_PREEN_NOMSG },
292 /* Bad primary block */
293 { PR_1_BAD_PRIMARY_BLOCK,
294 "\nIf the @b is really bad, the @f can not be fixed.\n",
295 PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK_PROMPT },
297 /* Bad primary block prompt */
298 { PR_1_BAD_PRIMARY_BLOCK_PROMPT,
299 "You can clear the this @b (and hope for the best) from the\n"
300 "bad @b list and hope that @b is really OK, but there are no\n"
302 PROMPT_CLEAR, PR_PREEN_NOMSG },
304 /* Bad primary superblock */
305 { PR_1_BAD_PRIMARY_SUPERBLOCK,
306 "The primary @S (%b) is on the bad @b list.\n",
307 PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
309 /* Bad primary block group descriptors */
310 { PR_1_BAD_PRIMARY_GROUP_DESCRIPTOR,
311 "Block %b in the primary @g descriptors "
312 "is on the bad @b list\n",
313 PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
315 /* Bad superblock in group */
316 { PR_1_BAD_SUPERBLOCK,
317 "Warning: Group %g's @S (%b) is bad.\n",
318 PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
320 /* Bad block group descriptors in group */
321 { PR_1_BAD_GROUP_DESCRIPTORS,
322 "Warning: Group %g's copy of the @g descriptors has a bad "
324 PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
326 /* Block claimed for no reason */
327 { PR_1_PROGERR_CLAIMED_BLOCK,
328 "Programming error? @b #%b claimed for no reason in "
330 PROMPT_NONE, PR_PREEN_OK },
332 /* Error allocating blocks for relocating metadata */
333 { PR_1_RELOC_BLOCK_ALLOCATE,
334 "@A %N @b(s) for %s: %m\n",
335 PROMPT_NONE, PR_PREEN_OK },
337 /* Error allocating block buffer during relocation process */
338 { PR_1_RELOC_MEMORY_ALLOCATE,
339 "@A @b buffer for relocating %s\n",
340 PROMPT_NONE, PR_PREEN_OK },
342 /* Relocating metadata group information from X to Y */
343 { PR_1_RELOC_FROM_TO,
344 "Relocating @g %g's %s from %b to %c...\n",
345 PROMPT_NONE, PR_PREEN_OK },
347 /* Relocating metatdata group information to X */
349 "Relocating @g %g's %s to %c...\n",
350 PROMPT_NONE, PR_PREEN_OK },
352 /* Block read error during relocation process */
353 { PR_1_RELOC_READ_ERR,
354 "Warning: could not read @b %b of %s: %m\n",
355 PROMPT_NONE, PR_PREEN_OK },
357 /* Block write error during relocation process */
358 { PR_1_RELOC_WRITE_ERR,
359 "Warning: could not write @b %b for %s: %m\n",
360 PROMPT_NONE, PR_PREEN_OK },
362 /* Error allocating inode bitmap */
363 { PR_1_ALLOCATE_IBITMAP_ERROR,
364 "@A @i @B (%N): %m\n",
365 PROMPT_NONE, PR_FATAL },
367 /* Error allocating block bitmap */
368 { PR_1_ALLOCATE_BBITMAP_ERROR,
369 "@A @b @B (%N): %m\n",
370 PROMPT_NONE, PR_FATAL },
372 /* Error allocating icount structure */
373 { PR_1_ALLOCATE_ICOUNT,
374 "@A icount link information: %m\n",
375 PROMPT_NONE, PR_FATAL },
377 /* Error allocating dbcount */
378 { PR_1_ALLOCATE_DBCOUNT,
379 "@A @d @b array: %m\n",
380 PROMPT_NONE, PR_FATAL },
382 /* Error while scanning inodes */
384 "Error while scanning @is (%i): %m\n",
385 PROMPT_NONE, PR_FATAL },
387 /* Error while iterating over blocks */
388 { PR_1_BLOCK_ITERATE,
389 "Error while iterating over blocks in @i %i: %m\n",
390 PROMPT_NONE, PR_FATAL },
392 /* Error while storing inode count information */
394 "Error storing @i count information (inode=%i, count=%N): %m\n",
395 PROMPT_NONE, PR_FATAL },
397 /* Error while storing directory block information */
399 "Error storing @d @b information "
400 "(inode=%i, block=%b, num=%N): %m\n",
401 PROMPT_NONE, PR_FATAL },
403 /* Error while reading inode (for clearing) */
405 "Error reading @i %i: %m\n",
406 PROMPT_NONE, PR_FATAL },
408 /* Suppress messages prompt */
409 { PR_1_SUPPRESS_MESSAGES, "", PROMPT_SUPPRESS, PR_NO_OK },
411 /* Filesystem contains large files, but has no such flag in sb */
412 { PR_1_FEATURE_LARGE_FILES,
413 "@f contains large files, but lacks LARGE_FILE flag in @S.\n",
418 /* Pass 1B: Rescan for duplicate/bad blocks */
420 "Duplicate @bs found... invoking duplicate @b passes.\n"
421 "Pass 1B: Rescan for duplicate/bad @bs\n",
424 /* Duplicate/bad block(s) header */
425 { PR_1B_DUP_BLOCK_HEADER,
426 "Duplicate/bad @b(s) in @i %i:",
429 /* Duplicate/bad block(s) in inode */
432 PROMPT_NONE, PR_LATCH_DBLOCK },
434 /* Duplicate/bad block(s) end */
435 { PR_1B_DUP_BLOCK_END,
439 /* Error while scanning inodes */
441 "Error while scanning inodes (%i): %m\n",
442 PROMPT_NONE, PR_FATAL },
444 /* Error allocating inode bitmap */
445 { PR_1B_ALLOCATE_IBITMAP_ERROR,
446 "@A @i @B (inode_dup_map): %m\n",
447 PROMPT_NONE, PR_FATAL },
450 /* Pass 1C: Scan directories for inodes with dup blocks. */
452 "Pass 1C: Scan directories for @is with dup @bs.\n",
456 /* Pass 1D: Reconciling duplicate blocks */
458 "Pass 1D: Reconciling duplicate @bs\n",
461 /* File has duplicate blocks */
463 "File %Q (@i #%i, mod time %IM) \n"
464 " has %B duplicate @b(s), shared with %N file(s):\n",
467 /* List of files sharing duplicate blocks */
468 { PR_1D_DUP_FILE_LIST,
469 "\t%Q (@i #%i, mod time %IM)\n",
472 /* File sharing blocks with filesystem metadata */
473 { PR_1D_SHARE_METADATA,
477 /* Report of how many duplicate/bad inodes */
478 { PR_1D_NUM_DUP_INODES,
479 "(There are %N @is containing duplicate/bad @bs.)\n\n",
482 /* Duplicated blocks already reassigned or cloned. */
483 { PR_1D_DUP_BLOCKS_DEALT,
484 "Duplicated @bs already reassigned or cloned.\n\n",
487 /* Clone duplicate/bad blocks? */
488 { PR_1D_CLONE_QUESTION,
489 "", PROMPT_CLONE, PR_NO_OK },
492 { PR_1D_DELETE_QUESTION,
493 "", PROMPT_DELETE, 0 },
495 /* Couldn't clone file (error) */
497 "Couldn't clone file: %m\n", PROMPT_NONE, 0 },
501 /* Pass 2: Checking directory structure */
503 "Pass 2: Checking @d structure\n",
506 /* Bad inode number for '.' */
507 { PR_2_BAD_INODE_DOT,
508 "Bad @i number for '.' in @d @i %i.\n",
511 /* Directory entry has bad inode number */
513 "@E has bad @i #: %Di.\n",
516 /* Directory entry has deleted or unused inode */
518 "@E has @D/unused @i %Di. ",
519 PROMPT_CLEAR, PR_PREEN_OK },
521 /* Directry entry is link to '.' */
526 /* Directory entry points to inode now located in a bad block */
528 "@E points to @i (%Di) located in a bad @b.\n",
531 /* Directory entry contains a link to a directory */
533 "@E @L to @d %P (%Di).\n",
536 /* Directory entry contains a link to the root directry */
538 "@E @L to the @r.\n",
541 /* Directory entry has illegal characters in its name */
543 "@E has illegal characters in its name.\n",
546 /* Missing '.' in directory inode */
548 "Missing '.' in @d @i %i.\n",
551 /* Missing '..' in directory inode */
552 { PR_2_MISSING_DOT_DOT,
553 "Missing '..' in @d @i %i.\n",
556 /* First entry in directory inode doesn't contain '.' */
558 "First @e '%Dn' (inode=%Di) in @d @i %i (%p) @s '.'\n",
561 /* Second entry in directory inode doesn't contain '..' */
562 { PR_2_2ND_NOT_DOT_DOT,
563 "Second @e '%Dn' (inode=%Di) in @d @i %i @s '..'\n",
566 /* i_faddr should be zero */
568 "i_faddr @F %IF, @s zero.\n",
571 /* i_file_acl should be zero */
572 { PR_2_FILE_ACL_ZERO,
573 "i_file_acl @F %If, @s zero.\n",
576 /* i_dir_acl should be zero */
578 "i_dir_acl @F %Id, @s zero.\n",
581 /* i_frag should be zero */
583 "i_frag @F %N, @s zero.\n",
586 /* i_fsize should be zero */
588 "i_fsize @F %N, @s zero.\n",
591 /* inode has bad mode */
593 "@i %i (%Q) has a bad mode (%Im).\n",
596 /* directory corrupted */
597 { PR_2_DIR_CORRUPTED,
598 "@d @i %i, @b %B, offset %N: @d corrupted\n",
601 /* filename too long */
602 { PR_2_FILENAME_LONG,
603 "@d @i %i, @b %B, offset %N: filename too long\n",
604 PROMPT_TRUNCATE, 0 },
606 /* Directory inode has a missing block (hole) */
607 { PR_2_DIRECTORY_HOLE,
608 "@d @i %i has an unallocated @b #%B. ",
609 PROMPT_ALLOCATE, 0 },
611 /* '.' is not NULL terminated */
612 { PR_2_DOT_NULL_TERM,
613 "'.' @d @e in @d @i %i is not NULL terminated\n",
616 /* '..' is not NULL terminated */
617 { PR_2_DOT_DOT_NULL_TERM,
618 "'..' @d @e in @d @i %i is not NULL terminated\n",
621 /* Illegal character device inode */
623 "@i %i (%Q) is an @I character device.\n",
626 /* Illegal block device inode */
627 { PR_2_BAD_BLOCK_DEV,
628 "@i %i (%Q) is an @I @b device.\n",
631 /* Duplicate '.' entry */
633 "@E is duplicate '.' @e.\n",
636 /* Duplicate '..' entry */
638 "@E is duplicate '..' @e.\n",
641 /* Internal error: couldn't find dir_info */
643 "Internal error: couldn't find dir_info for %i.\n",
644 PROMPT_NONE, PR_FATAL },
646 /* Final rec_len is wrong */
648 "@E has rec_len of %dr, should be %N.\n",
651 /* Error allocating icount structure */
652 { PR_2_ALLOCATE_ICOUNT,
653 "@A icount structure: %m\n",
654 PROMPT_NONE, PR_FATAL },
656 /* Error iterating over directory blocks */
657 { PR_2_DBLIST_ITERATE,
658 "Error interating over @d @bs: %m\n",
659 PROMPT_NONE, PR_FATAL },
661 /* Error reading directory block */
662 { PR_2_READ_DIRBLOCK,
663 "Error reading @d @b %b (@i %i): %m\n",
664 PROMPT_CONTINUE, 0 },
666 /* Error writing directory block */
667 { PR_2_WRITE_DIRBLOCK,
668 "Error writing @d @b %b (@i %i): %m\n",
669 PROMPT_CONTINUE, 0 },
671 /* Error allocating new directory block */
672 { PR_2_ALLOC_DIRBOCK,
673 "@A new @d @b for @i %i (%s): %m\n",
676 /* Error deallocating inode */
677 { PR_2_DEALLOC_INODE,
678 "Error deallocating @i %i: %m\n",
679 PROMPT_NONE, PR_FATAL },
681 /* Directory entry for '.' is big. Split? */
683 "@d @e for '.' is big. ",
684 PROMPT_SPLIT, PR_NO_OK },
686 /* Illegal FIFO inode */
688 "@i %i (%Q) is an @I FIFO.\n",
691 /* Illegal socket inode */
693 "@i %i (%Q) is an @I socket.\n",
698 /* Pass 3: Checking directory connectivity */
700 "Pass 3: Checking @d connectivity\n",
703 /* Root inode not allocated */
704 { PR_3_NO_ROOT_INODE,
705 "@r not allocated. ",
706 PROMPT_ALLOCATE, 0 },
708 /* No room in lost+found */
709 { PR_3_EXPAND_LF_DIR,
710 "No room in @l @d. ",
713 /* Unconnected directory inode */
714 { PR_3_UNCONNECTED_DIR,
715 "Unconnected @d @i %i (%p)\n",
718 /* /lost+found not found */
721 PROMPT_CREATE, PR_PREEN_OK },
723 /* .. entry is incorrect */
725 "'..' in %Q (%i) is %P (%j), @s %q (%d).\n",
728 /* Bad or non-existent /lost+found. Cannot reconnect */
730 "Bad or non-existent /@l. Cannot reconnect\n",
733 /* Could not expand /lost+found */
734 { PR_3_CANT_EXPAND_LPF,
735 "Could not expand /@l: %m\n",
738 /* Could not reconnect inode */
739 { PR_3_CANT_RECONNECT,
740 "Could not reconnect %i: %m\n",
743 /* Error while trying to find /lost+found */
745 "Error while trying to find /@l: %m\n",
748 /* Error in ext2fs_new_block while creating /lost+found */
749 { PR_3_ERR_LPF_NEW_BLOCK,
750 "ext2fs_new_@b: %m while trying to create /@l @d\n",
753 /* Error in ext2fs_new_inode while creating /lost+found */
754 { PR_3_ERR_LPF_NEW_INODE,
755 "ext2fs_new_@i: %m while trying to create /@l @d\n",
758 /* Error in ext2fs_new_dir_block while creating /lost+found */
759 { PR_3_ERR_LPF_NEW_DIR_BLOCK,
760 "ext2fs_new_dir_@b: %m while creating new @d @b\n",
763 /* Error while writing directory block for /lost+found */
764 { PR_3_ERR_LPF_WRITE_BLOCK,
765 "ext2fs_write_dir_@b: %m while writing the @d @b for /@l\n",
768 /* Error while adjusting inode count */
770 "Error while adjusting @i count on @i %i\n",
773 /* Couldn't fix parent directory -- error */
774 { PR_3_FIX_PARENT_ERR,
775 "Couldn't fix parent of @i %i: %m\n\n",
778 /* Couldn't fix parent directory -- couldn't find it */
779 { PR_3_FIX_PARENT_NOFIND,
780 "Couldn't fix parent of @i %i: Couldn't find parent @d entry\n\n",
783 /* Error allocating inode bitmap */
784 { PR_3_ALLOCATE_IBITMAP_ERROR,
785 "@A @i @B (%N): %m\n",
786 PROMPT_NONE, PR_FATAL },
788 /* Error creating root directory */
789 { PR_3_CREATE_ROOT_ERROR,
790 "Error creating root @d (%s): %m\n",
791 PROMPT_NONE, PR_FATAL },
793 /* Error creating lost and found directory */
794 { PR_3_CREATE_LPF_ERROR,
795 "Error creating /@l @d (%s): %m\n",
796 PROMPT_NONE, PR_FATAL },
798 /* Root inode is not directory; aborting */
799 { PR_3_ROOT_NOT_DIR_ABORT,
800 "@r is not a @d; aborting.\n",
801 PROMPT_NONE, PR_FATAL },
803 /* Cannot proceed without a root inode. */
804 { PR_3_NO_ROOT_INODE_ABORT,
805 "Cannot proceed without a @r.\n",
806 PROMPT_NONE, PR_FATAL },
808 /* Internal error: couldn't find dir_info */
810 "Internal error: couldn't find dir_info for %i.\n",
811 PROMPT_NONE, PR_FATAL },
813 /* Lost+found not a directory */
815 "/@l is not a @d (ino=%i)\n",
820 /* Pass 4: Checking reference counts */
822 "Pass 4: Checking reference counts\n",
825 /* Unattached zero-length inode */
826 { PR_4_ZERO_LEN_INODE,
828 PROMPT_CLEAR, PR_PREEN_OK|PR_NO_OK },
830 /* Unattached inode */
831 { PR_4_UNATTACHED_INODE,
835 /* Inode ref count wrong */
836 { PR_4_BAD_REF_COUNT,
837 "@i %i ref count is %Il, @s %N. ",
838 PROMPT_FIX, PR_PREEN_OK },
840 { PR_4_INCONSISTENT_COUNT,
841 "WARNING: PROGRAMMING BUG IN E2FSCK!\n"
842 "\tOR SOME BONEHEAD (YOU) IS CHECKING A MOUNTED (LIVE) FILESYSTEM.\n"
843 "@i_link_info[%i] is %N, @i.i_links_count is %Il. "
844 "They should be the same!\n",
849 /* Pass 5: Checking group summary information */
851 "Pass 5: Checking @g summary information\n",
854 /* Padding at end of inode bitmap is not set. */
855 { PR_5_INODE_BMAP_PADDING,
856 "Padding at end of @i @B is not set. ",
857 PROMPT_FIX, PR_PREEN_OK },
859 /* Padding at end of block bitmap is not set. */
860 { PR_5_BLOCK_BMAP_PADDING,
861 "Padding at end of @b @B is not set. ",
862 PROMPT_FIX, PR_PREEN_OK },
864 /* Block bitmap differences header */
865 { PR_5_BLOCK_BITMAP_HEADER,
866 "@b @B differences: ",
867 PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG},
869 /* Block not used, but marked in bitmap */
872 PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
874 /* Block used, but not marked used in bitmap */
877 PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
879 /* Block bitmap differences end */
880 { PR_5_BLOCK_BITMAP_END,
882 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
884 /* Inode bitmap differences header */
885 { PR_5_INODE_BITMAP_HEADER,
886 "@i @B differences: ",
887 PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
889 /* Inode not used, but marked in bitmap */
892 PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
894 /* Inode used, but not marked used in bitmap */
897 PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
899 /* Inode bitmap differences end */
900 { PR_5_INODE_BITMAP_END,
902 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
904 /* Free inodes count for group wrong */
905 { PR_5_FREE_INODE_COUNT_GROUP,
906 "Free @is count wrong for @g #%g (%i, counted=%j).\n",
907 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
909 /* Directories count for group wrong */
910 { PR_5_FREE_DIR_COUNT_GROUP,
911 "Directories count wrong for @g #%g (%i, counted=%j).\n",
912 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
914 /* Free inodes count wrong */
915 { PR_5_FREE_INODE_COUNT,
916 "Free @is count wrong (%i, counted=%j).\n",
917 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
919 /* Free blocks count for group wrong */
920 { PR_5_FREE_BLOCK_COUNT_GROUP,
921 "Free @bs count wrong for @g #%g (%b, counted=%c).\n",
922 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
924 /* Free blocks count wrong */
925 { PR_5_FREE_BLOCK_COUNT,
926 "Free @bs count wrong (%b, counted=%c).\n",
927 PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
929 /* Programming error: bitmap endpoints don't match */
930 { PR_5_BMAP_ENDPOINTS,
931 "PROGRAMMING ERROR: @f (#%N) @B endpoints (%b, %c) don't "
932 "match calculated @B endpoints (%i, %j)\n",
933 PROMPT_NONE, PR_FATAL },
935 /* Internal error: fudging end of bitmap */
936 { PR_5_FUDGE_BITMAP_ERROR,
937 "Internal error: fudging end of bitmap (%N)\n",
938 PROMPT_NONE, PR_FATAL },
944 * This is the latch flags register. It allows several problems to be
945 * "latched" together. This means that the user has to answer but one
946 * question for the set of problems, and all of the associated
947 * problems will be either fixed or not fixed.
949 static struct latch_descr pr_latch_info[] = {
950 { PR_LATCH_BLOCK, PR_1_INODE_BLOCK_LATCH, 0 },
951 { PR_LATCH_BBLOCK, PR_1_INODE_BBLOCK_LATCH, 0 },
952 { PR_LATCH_IBITMAP, PR_5_INODE_BITMAP_HEADER, PR_5_INODE_BITMAP_END },
953 { PR_LATCH_BBITMAP, PR_5_BLOCK_BITMAP_HEADER, PR_5_BLOCK_BITMAP_END },
954 { PR_LATCH_RELOC, PR_0_RELOCATE_HINT, 0 },
955 { PR_LATCH_DBLOCK, PR_1B_DUP_BLOCK_HEADER, PR_1B_DUP_BLOCK_END },
959 static const struct e2fsck_problem *find_problem(int code)
963 for (i=0; problem_table[i].e2p_code; i++) {
964 if (problem_table[i].e2p_code == code)
965 return &problem_table[i];
970 static struct latch_descr *find_latch(int code)
974 for (i=0; pr_latch_info[i].latch_code >= 0; i++) {
975 if (pr_latch_info[i].latch_code == code)
976 return &pr_latch_info[i];
981 int end_problem_latch(e2fsck_t ctx, int mask)
983 struct latch_descr *ldesc;
984 struct problem_context pctx;
987 ldesc = find_latch(mask);
988 if (ldesc->end_message && (ldesc->flags & PRL_LATCHED)) {
989 clear_problem_context(&pctx);
990 answer = fix_problem(ctx, ldesc->end_message, &pctx);
992 ldesc->flags &= ~(PRL_VARIABLE);
996 int set_latch_flags(int mask, int setflags, int clearflags)
998 struct latch_descr *ldesc;
1000 ldesc = find_latch(mask);
1003 ldesc->flags |= setflags;
1004 ldesc->flags &= ~clearflags;
1008 int get_latch_flags(int mask, int *value)
1010 struct latch_descr *ldesc;
1012 ldesc = find_latch(mask);
1015 *value = ldesc->flags;
1019 void clear_problem_context(struct problem_context *ctx)
1021 memset(ctx, 0, sizeof(struct problem_context));
1026 int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx)
1028 ext2_filsys fs = ctx->fs;
1029 const struct e2fsck_problem *ptr;
1030 struct latch_descr *ldesc = 0;
1031 const char *message;
1032 int def_yn, answer, ans;
1033 int print_answer = 0;
1036 ptr = find_problem(code);
1038 printf("Unhandled error code (%d)!\n", code);
1041 def_yn = (ptr->flags & PR_NO_DEFAULT) ? 0 : 1;
1044 * Do special latch processing. This is where we ask the
1045 * latch question, if it exists
1047 if (ptr->flags & PR_LATCH_MASK) {
1048 ldesc = find_latch(ptr->flags & PR_LATCH_MASK);
1049 if (ldesc->question && !(ldesc->flags & PRL_LATCHED)) {
1050 ans = fix_problem(ctx, ldesc->question, pctx);
1052 ldesc->flags |= PRL_YES;
1054 ldesc->flags |= PRL_NO;
1055 ldesc->flags |= PRL_LATCHED;
1057 if (ldesc->flags & PRL_SUPPRESS)
1060 if ((ptr->flags & PR_PREEN_NOMSG) &&
1061 (ctx->options & E2F_OPT_PREEN))
1064 message = ptr->e2p_description;
1065 if (ctx->options & E2F_OPT_PREEN) {
1066 printf("%s: ", ctx->device_name);
1068 if (ptr->e2p_preen_msg)
1069 message = ptr->e2p_preen_msg;
1072 print_e2fsck_message(ctx, message, pctx, 1);
1074 if (!(ptr->flags & PR_PREEN_OK) && (ptr->prompt != PROMPT_NONE))
1077 if (ptr->flags & PR_FATAL)
1078 fatal_error(ctx, 0);
1080 if (ptr->prompt == PROMPT_NONE) {
1081 if (ptr->flags & PR_NOCOLLATE)
1086 if (ctx->options & E2F_OPT_PREEN) {
1088 if (!(ptr->flags & PR_PREEN_NOMSG))
1090 } else if ((ptr->flags & PR_LATCH_MASK) &&
1091 (ldesc->flags & (PRL_YES | PRL_NO))) {
1094 if (ldesc->flags & PRL_YES)
1099 answer = ask(ctx, prompt[(int) ptr->prompt], def_yn);
1100 if (!answer && !(ptr->flags & PR_NO_OK))
1101 ext2fs_unmark_valid(fs);
1104 printf("%s.\n", answer ?
1105 preen_msg[(int) ptr->prompt] : "IGNORED");
1109 if (ptr->flags & PR_AFTER_CODE)
1110 (void) fix_problem(ctx, ptr->second_code, pctx);
1112 if ((ptr->prompt == PROMPT_ABORT) && answer)
1113 fatal_error(ctx, 0);