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