pass2.c revision e8254bfd3b49cb325a1ff6b21ca86570a1008744
1/* 2 * pass2.c --- check directory structure 3 * 4 * Copyright (C) 1993, 1994, 1995, 1996, 1997 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 * Pass 2 of e2fsck iterates through all active directory inodes, and 12 * applies to following tests to each directory entry in the directory 13 * blocks in the inodes: 14 * 15 * - The length of the directory entry (rec_len) should be at 16 * least 8 bytes, and no more than the remaining space 17 * left in the directory block. 18 * - The length of the name in the directory entry (name_len) 19 * should be less than (rec_len - 8). 20 * - The inode number in the directory entry should be within 21 * legal bounds. 22 * - The inode number should refer to a in-use inode. 23 * - The first entry should be '.', and its inode should be 24 * the inode of the directory. 25 * - The second entry should be '..'. 26 * 27 * To minimize disk seek time, the directory blocks are processed in 28 * sorted order of block numbers. 29 * 30 * Pass 2 also collects the following information: 31 * - The inode numbers of the subdirectories for each directory. 32 * 33 * Pass 2 relies on the following information from previous passes: 34 * - The directory information collected in pass 1. 35 * - The inode_used_map bitmap 36 * - The inode_bad_map bitmap 37 * - The inode_dir_map bitmap 38 * 39 * Pass 2 frees the following data structures 40 * - The inode_bad_map bitmap 41 * - The inode_reg_map bitmap 42 */ 43 44#include "e2fsck.h" 45#include "problem.h" 46 47#ifdef NO_INLINE_FUNCS 48#define _INLINE_ 49#else 50#define _INLINE_ inline 51#endif 52 53#undef DX_DEBUG 54 55/* 56 * Keeps track of how many times an inode is referenced. 57 */ 58static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf); 59static int check_dir_block(ext2_filsys fs, 60 struct ext2_db_entry *dir_blocks_info, 61 void *priv_data); 62static int allocate_dir_block(e2fsck_t ctx, 63 struct ext2_db_entry *dir_blocks_info, 64 char *buf, struct problem_context *pctx); 65static int update_dir_block(ext2_filsys fs, 66 blk_t *block_nr, 67 e2_blkcnt_t blockcnt, 68 blk_t ref_block, 69 int ref_offset, 70 void *priv_data); 71static void clear_htree(e2fsck_t ctx, ext2_ino_t ino); 72static EXT2_QSORT_TYPE special_dir_block_cmp(const void *a, const void *b); 73 74struct check_dir_struct { 75 char *buf; 76 struct problem_context pctx; 77 int count, max; 78 e2fsck_t ctx; 79}; 80 81void e2fsck_pass2(e2fsck_t ctx) 82{ 83 struct ext2_super_block *sb = ctx->fs->super; 84 struct problem_context pctx; 85 ext2_filsys fs = ctx->fs; 86 char *buf; 87#ifdef RESOURCE_TRACK 88 struct resource_track rtrack; 89#endif 90 struct dir_info *dir; 91 struct check_dir_struct cd; 92 struct dx_dir_info *dx_dir; 93 struct dx_dirblock_info *dx_db, *dx_parent; 94 blk_t b; 95 int i; 96 problem_t code; 97 int bad_dir; 98 99#ifdef RESOURCE_TRACK 100 init_resource_track(&rtrack); 101#endif 102 103 clear_problem_context(&cd.pctx); 104 105#ifdef MTRACE 106 mtrace_print("Pass 2"); 107#endif 108 109 if (!(ctx->options & E2F_OPT_PREEN)) 110 fix_problem(ctx, PR_2_PASS_HEADER, &cd.pctx); 111 112 cd.pctx.errcode = ext2fs_create_icount2(fs, EXT2_ICOUNT_OPT_INCREMENT, 113 0, ctx->inode_link_info, 114 &ctx->inode_count); 115 if (cd.pctx.errcode) { 116 fix_problem(ctx, PR_2_ALLOCATE_ICOUNT, &cd.pctx); 117 ctx->flags |= E2F_FLAG_ABORT; 118 return; 119 } 120 buf = (char *) e2fsck_allocate_memory(ctx, 2*fs->blocksize, 121 "directory scan buffer"); 122 123 /* 124 * Set up the parent pointer for the root directory, if 125 * present. (If the root directory is not present, we will 126 * create it in pass 3.) 127 */ 128 dir = e2fsck_get_dir_info(ctx, EXT2_ROOT_INO); 129 if (dir) 130 dir->parent = EXT2_ROOT_INO; 131 132 cd.buf = buf; 133 cd.ctx = ctx; 134 cd.count = 1; 135 cd.max = ext2fs_dblist_count(fs->dblist); 136 137 if (ctx->progress) 138 (void) (ctx->progress)(ctx, 2, 0, cd.max); 139 140 if (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) 141 ext2fs_dblist_sort(fs->dblist, special_dir_block_cmp); 142 143 cd.pctx.errcode = ext2fs_dblist_iterate(fs->dblist, check_dir_block, 144 &cd); 145 if (ctx->flags & E2F_FLAG_SIGNAL_MASK) 146 return; 147 if (cd.pctx.errcode) { 148 fix_problem(ctx, PR_2_DBLIST_ITERATE, &cd.pctx); 149 ctx->flags |= E2F_FLAG_ABORT; 150 return; 151 } 152 153#ifdef ENABLE_HTREE 154 for (i=0; (dx_dir = e2fsck_dx_dir_info_iter(ctx, &i)) != 0;) { 155 if (ctx->flags & E2F_FLAG_SIGNAL_MASK) 156 return; 157 if (dx_dir->numblocks == 0) 158 continue; 159 clear_problem_context(&pctx); 160 bad_dir = 0; 161 pctx.dir = dx_dir->ino; 162 dx_db = dx_dir->dx_block; 163 if (dx_db->flags & DX_FLAG_REFERENCED) 164 dx_db->flags |= DX_FLAG_DUP_REF; 165 else 166 dx_db->flags |= DX_FLAG_REFERENCED; 167 /* 168 * Find all of the first and last leaf blocks, and 169 * update their parent's min and max hash values 170 */ 171 for (b=0, dx_db = dx_dir->dx_block; 172 b < dx_dir->numblocks; 173 b++, dx_db++) { 174 if ((dx_db->type != DX_DIRBLOCK_LEAF) || 175 !(dx_db->flags & (DX_FLAG_FIRST | DX_FLAG_LAST))) 176 continue; 177 dx_parent = &dx_dir->dx_block[dx_db->parent]; 178 /* 179 * XXX Make sure dx_parent->min_hash > dx_db->min_hash 180 */ 181 if (dx_db->flags & DX_FLAG_FIRST) 182 dx_parent->min_hash = dx_db->min_hash; 183 /* 184 * XXX Make sure dx_parent->max_hash < dx_db->max_hash 185 */ 186 if (dx_db->flags & DX_FLAG_LAST) 187 dx_parent->max_hash = dx_db->max_hash; 188 } 189 190 for (b=0, dx_db = dx_dir->dx_block; 191 b < dx_dir->numblocks; 192 b++, dx_db++) { 193 pctx.blkcount = b; 194 pctx.group = dx_db->parent; 195 code = 0; 196 if (!(dx_db->flags & DX_FLAG_FIRST) && 197 (dx_db->min_hash < dx_db->node_min_hash)) { 198 pctx.blk = dx_db->min_hash; 199 pctx.blk2 = dx_db->node_min_hash; 200 code = PR_2_HTREE_MIN_HASH; 201 fix_problem(ctx, code, &pctx); 202 bad_dir++; 203 } 204 /* 205 * This test doesn't apply for the root block 206 * at block #0 207 */ 208 if (b && 209 (dx_db->max_hash > dx_db->node_max_hash)) { 210 pctx.blk = dx_db->max_hash; 211 pctx.blk2 = dx_db->node_max_hash; 212 code = PR_2_HTREE_MAX_HASH; 213 fix_problem(ctx, code, &pctx); 214 bad_dir++; 215 } 216 if (!(dx_db->flags & DX_FLAG_REFERENCED)) { 217 code = PR_2_HTREE_NOTREF; 218 fix_problem(ctx, code, &pctx); 219 bad_dir++; 220 } else if (dx_db->flags & DX_FLAG_DUP_REF) { 221 code = PR_2_HTREE_DUPREF; 222 fix_problem(ctx, code, &pctx); 223 bad_dir++; 224 } 225 if (code == 0) 226 continue; 227 } 228 if (bad_dir && fix_problem(ctx, PR_2_HTREE_CLEAR, &pctx)) { 229 clear_htree(ctx, dx_dir->ino); 230 dx_dir->numblocks = 0; 231 } 232#ifdef ENABLE_HTREE_CLEAR 233 if (dx_dir->numblocks) { 234 fix_problem(ctx, PR_2_HTREE_FCLR, &pctx); 235 clear_htree(ctx, dx_dir->ino); 236 dx_dir->numblocks = 0; 237 } 238#endif 239 } 240#endif 241 ext2fs_free_mem((void **) &buf); 242 ext2fs_free_dblist(fs->dblist); 243 244 if (ctx->inode_bad_map) { 245 ext2fs_free_inode_bitmap(ctx->inode_bad_map); 246 ctx->inode_bad_map = 0; 247 } 248 if (ctx->inode_reg_map) { 249 ext2fs_free_inode_bitmap(ctx->inode_reg_map); 250 ctx->inode_reg_map = 0; 251 } 252 253 clear_problem_context(&pctx); 254 if (ctx->large_files) { 255 if (!(sb->s_feature_ro_compat & 256 EXT2_FEATURE_RO_COMPAT_LARGE_FILE) && 257 fix_problem(ctx, PR_2_FEATURE_LARGE_FILES, &pctx)) { 258 sb->s_feature_ro_compat |= 259 EXT2_FEATURE_RO_COMPAT_LARGE_FILE; 260 ext2fs_mark_super_dirty(fs); 261 } 262 if (sb->s_rev_level == EXT2_GOOD_OLD_REV && 263 fix_problem(ctx, PR_1_FS_REV_LEVEL, &pctx)) { 264 ext2fs_update_dynamic_rev(fs); 265 ext2fs_mark_super_dirty(fs); 266 } 267 } else if (!ctx->large_files && 268 (sb->s_feature_ro_compat & 269 EXT2_FEATURE_RO_COMPAT_LARGE_FILE)) { 270 if (fs->flags & EXT2_FLAG_RW) { 271 sb->s_feature_ro_compat &= 272 ~EXT2_FEATURE_RO_COMPAT_LARGE_FILE; 273 ext2fs_mark_super_dirty(fs); 274 } 275 } 276 277#ifdef RESOURCE_TRACK 278 if (ctx->options & E2F_OPT_TIME2) { 279 e2fsck_clear_progbar(ctx); 280 print_resource_track("Pass 2", &rtrack); 281 } 282#endif 283} 284 285/* 286 * This is special sort function that makes sure that directory blocks 287 * with a dirblock of zero are sorted to the beginning of the list. 288 * This guarantees that the root node of the htree directories are 289 * processed first, so we know what hash version to use. 290 */ 291static EXT2_QSORT_TYPE special_dir_block_cmp(const void *a, const void *b) 292{ 293 const struct ext2_db_entry *db_a = 294 (const struct ext2_db_entry *) a; 295 const struct ext2_db_entry *db_b = 296 (const struct ext2_db_entry *) b; 297 298 if (db_a->blockcnt && !db_b->blockcnt) 299 return 1; 300 301 if (!db_a->blockcnt && db_b->blockcnt) 302 return -1; 303 304 if (db_a->blk != db_b->blk) 305 return (int) (db_a->blk - db_b->blk); 306 307 if (db_a->ino != db_b->ino) 308 return (int) (db_a->ino - db_b->ino); 309 310 return (int) (db_a->blockcnt - db_b->blockcnt); 311} 312 313 314/* 315 * Make sure the first entry in the directory is '.', and that the 316 * directory entry is sane. 317 */ 318static int check_dot(e2fsck_t ctx, 319 struct ext2_dir_entry *dirent, 320 ext2_ino_t ino, struct problem_context *pctx) 321{ 322 struct ext2_dir_entry *nextdir; 323 int status = 0; 324 int created = 0; 325 int new_len; 326 int problem = 0; 327 328 if (!dirent->inode) 329 problem = PR_2_MISSING_DOT; 330 else if (((dirent->name_len & 0xFF) != 1) || 331 (dirent->name[0] != '.')) 332 problem = PR_2_1ST_NOT_DOT; 333 else if (dirent->name[1] != '\0') 334 problem = PR_2_DOT_NULL_TERM; 335 336 if (problem) { 337 if (fix_problem(ctx, problem, pctx)) { 338 if (dirent->rec_len < 12) 339 dirent->rec_len = 12; 340 dirent->inode = ino; 341 dirent->name_len = 1; 342 dirent->name[0] = '.'; 343 dirent->name[1] = '\0'; 344 status = 1; 345 created = 1; 346 } 347 } 348 if (dirent->inode != ino) { 349 if (fix_problem(ctx, PR_2_BAD_INODE_DOT, pctx)) { 350 dirent->inode = ino; 351 status = 1; 352 } 353 } 354 if (dirent->rec_len > 12) { 355 new_len = dirent->rec_len - 12; 356 if (new_len > 12) { 357 if (created || 358 fix_problem(ctx, PR_2_SPLIT_DOT, pctx)) { 359 nextdir = (struct ext2_dir_entry *) 360 ((char *) dirent + 12); 361 dirent->rec_len = 12; 362 nextdir->rec_len = new_len; 363 nextdir->inode = 0; 364 nextdir->name_len = 0; 365 status = 1; 366 } 367 } 368 } 369 return status; 370} 371 372/* 373 * Make sure the second entry in the directory is '..', and that the 374 * directory entry is sane. We do not check the inode number of '..' 375 * here; this gets done in pass 3. 376 */ 377static int check_dotdot(e2fsck_t ctx, 378 struct ext2_dir_entry *dirent, 379 struct dir_info *dir, struct problem_context *pctx) 380{ 381 int problem = 0; 382 383 if (!dirent->inode) 384 problem = PR_2_MISSING_DOT_DOT; 385 else if (((dirent->name_len & 0xFF) != 2) || 386 (dirent->name[0] != '.') || 387 (dirent->name[1] != '.')) 388 problem = PR_2_2ND_NOT_DOT_DOT; 389 else if (dirent->name[2] != '\0') 390 problem = PR_2_DOT_DOT_NULL_TERM; 391 392 if (problem) { 393 if (fix_problem(ctx, problem, pctx)) { 394 if (dirent->rec_len < 12) 395 dirent->rec_len = 12; 396 /* 397 * Note: we don't have the parent inode just 398 * yet, so we will fill it in with the root 399 * inode. This will get fixed in pass 3. 400 */ 401 dirent->inode = EXT2_ROOT_INO; 402 dirent->name_len = 2; 403 dirent->name[0] = '.'; 404 dirent->name[1] = '.'; 405 dirent->name[2] = '\0'; 406 return 1; 407 } 408 return 0; 409 } 410 dir->dotdot = dirent->inode; 411 return 0; 412} 413 414/* 415 * Check to make sure a directory entry doesn't contain any illegal 416 * characters. 417 */ 418static int check_name(e2fsck_t ctx, 419 struct ext2_dir_entry *dirent, 420 ext2_ino_t dir_ino, struct problem_context *pctx) 421{ 422 int i; 423 int fixup = -1; 424 int ret = 0; 425 426 for ( i = 0; i < (dirent->name_len & 0xFF); i++) { 427 if (dirent->name[i] == '/' || dirent->name[i] == '\0') { 428 if (fixup < 0) { 429 fixup = fix_problem(ctx, PR_2_BAD_NAME, pctx); 430 } 431 if (fixup) { 432 dirent->name[i] = '.'; 433 ret = 1; 434 } 435 } 436 } 437 return ret; 438} 439 440/* 441 * Check the directory filetype (if present) 442 */ 443static _INLINE_ int check_filetype(e2fsck_t ctx, 444 struct ext2_dir_entry *dirent, 445 ext2_ino_t dir_ino, struct problem_context *pctx) 446{ 447 int filetype = dirent->name_len >> 8; 448 int should_be = EXT2_FT_UNKNOWN; 449 struct ext2_inode inode; 450 451 if (!(ctx->fs->super->s_feature_incompat & 452 EXT2_FEATURE_INCOMPAT_FILETYPE)) { 453 if (filetype == 0 || 454 !fix_problem(ctx, PR_2_CLEAR_FILETYPE, pctx)) 455 return 0; 456 dirent->name_len = dirent->name_len & 0xFF; 457 return 1; 458 } 459 460 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dirent->inode)) { 461 should_be = EXT2_FT_DIR; 462 } else if (ext2fs_test_inode_bitmap(ctx->inode_reg_map, 463 dirent->inode)) { 464 should_be = EXT2_FT_REG_FILE; 465 } else if (ctx->inode_bad_map && 466 ext2fs_test_inode_bitmap(ctx->inode_bad_map, 467 dirent->inode)) 468 should_be = 0; 469 else { 470 e2fsck_read_inode(ctx, dirent->inode, &inode, 471 "check_filetype"); 472 should_be = ext2_file_type(inode.i_mode); 473 } 474 if (filetype == should_be) 475 return 0; 476 pctx->num = should_be; 477 478 if (fix_problem(ctx, filetype ? PR_2_BAD_FILETYPE : PR_2_SET_FILETYPE, 479 pctx) == 0) 480 return 0; 481 482 dirent->name_len = (dirent->name_len & 0xFF) | should_be << 8; 483 return 1; 484} 485 486#ifdef ENABLE_HTREE 487static void parse_int_node(ext2_filsys fs, 488 struct ext2_db_entry *db, 489 struct check_dir_struct *cd, 490 struct dx_dir_info *dx_dir, 491 char *block_buf) 492{ 493 struct ext2_dx_root_info *root; 494 struct ext2_dx_entry *ent; 495 struct ext2_dx_countlimit *limit; 496 struct dx_dirblock_info *dx_db; 497 int i; 498 blk_t blk; 499 ext2_dirhash_t min_hash = 0xffffffff; 500 ext2_dirhash_t max_hash = 0; 501 ext2_dirhash_t hash = 0; 502 503 if (db->blockcnt == 0) { 504 root = (struct ext2_dx_root_info *) (block_buf + 24); 505 506#ifdef DX_DEBUG 507 printf("Root node dump:\n"); 508 printf("\t Reserved zero: %d\n", root->reserved_zero); 509 printf("\t Hash Version: %d\n", root->hash_version); 510 printf("\t Info length: %d\n", root->info_length); 511 printf("\t Indirect levels: %d\n", root->indirect_levels); 512 printf("\t Flags: %d\n", root->unused_flags); 513#endif 514 515 ent = (struct ext2_dx_entry *) (block_buf + 24 + root->info_length); 516 } else { 517 ent = (struct ext2_dx_entry *) (block_buf+8); 518 } 519 limit = (struct ext2_dx_countlimit *) ent; 520 521#ifdef DX_DEBUG 522 printf("Number of entries (count): %d\n", limit->count); 523 printf("Number of entries (limit): %d\n", limit->limit); 524#endif 525 526 for (i=0; i < limit->count; i++) { 527 hash = i ? (ent[i].hash & ~1) : 0; 528 /* 529 * XXX Check to make make sure the hash[i] < hash[i+1] 530 */ 531#ifdef DX_DEBUG 532 printf("Entry #%d: Hash 0x%08x, block %d\n", i, 533 hash, ent[i].block); 534#endif 535 blk = ent[i].block & 0x0ffffff; 536 /* Check to make sure the block is valid */ 537 if (blk > dx_dir->numblocks) { 538 cd->pctx.blk = blk; 539 if (fix_problem(cd->ctx, PR_2_HTREE_BADBLK, 540 &cd->pctx)) { 541 clear_htree(cd->ctx, cd->pctx.ino); 542 dx_dir->numblocks = 0; 543 return; 544 } 545 } 546 dx_db = &dx_dir->dx_block[blk]; 547 if (dx_db->flags & DX_FLAG_REFERENCED) { 548 dx_db->flags |= DX_FLAG_DUP_REF; 549 } else { 550 dx_db->flags |= DX_FLAG_REFERENCED; 551 dx_db->parent = db->blockcnt; 552 } 553 if (hash < min_hash) 554 min_hash = hash; 555 if (hash > max_hash) 556 max_hash = hash; 557 dx_db->node_min_hash = hash; 558 if ((i+1) < limit->count) 559 dx_db->node_max_hash = (ent[i+1].hash & ~1); 560 else { 561 dx_db->node_max_hash = 0xfffffffe; 562 dx_db->flags |= DX_FLAG_LAST; 563 } 564 if (i == 0) 565 dx_db->flags |= DX_FLAG_FIRST; 566 } 567#ifdef DX_DEBUG 568 printf("Blockcnt = %d, min hash 0x%08x, max hash 0x%08x\n", 569 db->blockcnt, min_hash, max_hash); 570#endif 571 dx_db = &dx_dir->dx_block[db->blockcnt]; 572 dx_db->min_hash = min_hash; 573 dx_db->max_hash = max_hash; 574} 575#endif /* ENABLE_HTREE */ 576 577/* 578 * Given a busted directory, try to salvage it somehow. 579 * 580 */ 581static int salvage_directory(ext2_filsys fs, 582 struct ext2_dir_entry *dirent, 583 struct ext2_dir_entry *prev, 584 int offset) 585{ 586 char *cp = (char *) dirent; 587 int left = fs->blocksize - offset - dirent->rec_len; 588 int prev_offset = offset - ((char *) dirent - (char *) prev); 589 590 /* 591 * Special case of directory entry of size 8: copy what's left 592 * of the directory block up to cover up the invalid hole. 593 */ 594 if ((left >= 12) && (dirent->rec_len == 8)) { 595 memmove(cp, cp+8, left); 596 memset(cp + left, 0, 8); 597 return offset; 598 } 599 /* 600 * If the directory entry is a multiple of four, so it is 601 * valid, let the previous directory entry absorb the invalid 602 * one. 603 */ 604 if (prev && dirent->rec_len && (dirent->rec_len % 4) == 0) { 605 prev->rec_len += dirent->rec_len; 606 return prev_offset; 607 } 608 /* 609 * Default salvage method --- kill all of the directory 610 * entries for the rest of the block. We will either try to 611 * absorb it into the previous directory entry, or create a 612 * new empty directory entry the rest of the directory block. 613 */ 614 if (prev) { 615 prev->rec_len += fs->blocksize - offset; 616 return prev_offset; 617 } else { 618 dirent->rec_len = fs->blocksize - offset; 619 dirent->name_len = 0; 620 dirent->inode = 0; 621 return offset; 622 } 623 624} 625 626static int check_dir_block(ext2_filsys fs, 627 struct ext2_db_entry *db, 628 void *priv_data) 629{ 630 struct dir_info *subdir, *dir; 631 struct dx_dir_info *dx_dir; 632#ifdef ENABLE_HTREE 633 struct dx_dirblock_info *dx_db = 0; 634#endif /* ENABLE_HTREE */ 635 struct ext2_dir_entry *dirent, *prev; 636 ext2_dirhash_t hash; 637 int offset = 0; 638 int dir_modified = 0; 639 int dot_state; 640 blk_t block_nr = db->blk; 641 ext2_ino_t ino = db->ino; 642 __u16 links; 643 struct check_dir_struct *cd; 644 char *buf; 645 e2fsck_t ctx; 646 int problem; 647 struct ext2_dx_root_info *root; 648 struct ext2_dx_countlimit *limit; 649 650 cd = (struct check_dir_struct *) priv_data; 651 buf = cd->buf; 652 ctx = cd->ctx; 653 654 if (ctx->flags & E2F_FLAG_SIGNAL_MASK) 655 return DIRENT_ABORT; 656 657 if (ctx->progress && (ctx->progress)(ctx, 2, cd->count++, cd->max)) 658 return DIRENT_ABORT; 659 660 /* 661 * Make sure the inode is still in use (could have been 662 * deleted in the duplicate/bad blocks pass. 663 */ 664 if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, ino))) 665 return 0; 666 667 cd->pctx.ino = ino; 668 cd->pctx.blk = block_nr; 669 cd->pctx.blkcount = db->blockcnt; 670 cd->pctx.ino2 = 0; 671 cd->pctx.dirent = 0; 672 cd->pctx.num = 0; 673 674 if (db->blk == 0) { 675 if (allocate_dir_block(ctx, db, buf, &cd->pctx)) 676 return 0; 677 block_nr = db->blk; 678 } 679 680 if (db->blockcnt) 681 dot_state = 2; 682 else 683 dot_state = 0; 684 685#if 0 686 printf("In process_dir_block block %lu, #%d, inode %lu\n", block_nr, 687 db->blockcnt, ino); 688#endif 689 690 cd->pctx.errcode = ext2fs_read_dir_block(fs, block_nr, buf); 691 if (cd->pctx.errcode == EXT2_ET_DIR_CORRUPTED) 692 cd->pctx.errcode = 0; /* We'll handle this ourselves */ 693 if (cd->pctx.errcode) { 694 if (!fix_problem(ctx, PR_2_READ_DIRBLOCK, &cd->pctx)) { 695 ctx->flags |= E2F_FLAG_ABORT; 696 return DIRENT_ABORT; 697 } 698 memset(buf, 0, fs->blocksize); 699 } 700#ifdef ENABLE_HTREE 701 dx_dir = e2fsck_get_dx_dir_info(ctx, ino); 702 if (dx_dir && dx_dir->numblocks) { 703 if (db->blockcnt >= dx_dir->numblocks) { 704 printf("XXX should never happen!!!\n"); 705 abort(); 706 } 707 dx_db = &dx_dir->dx_block[db->blockcnt]; 708 dx_db->type = DX_DIRBLOCK_LEAF; 709 dx_db->phys = block_nr; 710 dx_db->min_hash = ~0; 711 dx_db->max_hash = 0; 712 713 dirent = (struct ext2_dir_entry *) buf; 714 limit = (struct ext2_dx_countlimit *) (buf+8); 715 if (db->blockcnt == 0) { 716 root = (struct ext2_dx_root_info *) (buf + 24); 717 dx_db->type = DX_DIRBLOCK_ROOT; 718 dx_db->flags |= DX_FLAG_FIRST | DX_FLAG_LAST; 719 if ((root->reserved_zero || 720 root->info_length < 8 || 721 root->indirect_levels > 1) && 722 fix_problem(ctx, PR_2_HTREE_BAD_ROOT, &cd->pctx)) { 723 clear_htree(ctx, ino); 724 dx_dir->numblocks = 0; 725 dx_db = 0; 726 } 727 dx_dir->hashversion = root->hash_version; 728 } else if ((dirent->inode == 0) && 729 (dirent->rec_len == fs->blocksize) && 730 (dirent->name_len == 0) && 731 (limit->limit == ((fs->blocksize-8) / 732 sizeof(struct ext2_dx_entry)))) 733 dx_db->type = DX_DIRBLOCK_NODE; 734 } 735#endif /* ENABLE_HTREE */ 736 737 prev = 0; 738 do { 739 problem = 0; 740 dirent = (struct ext2_dir_entry *) (buf + offset); 741 cd->pctx.dirent = dirent; 742 cd->pctx.num = offset; 743 if (((offset + dirent->rec_len) > fs->blocksize) || 744 (dirent->rec_len < 12) || 745 ((dirent->rec_len % 4) != 0) || 746 (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) { 747 if (fix_problem(ctx, PR_2_DIR_CORRUPTED, &cd->pctx)) { 748 offset = salvage_directory(fs, dirent, 749 prev, offset); 750 dir_modified++; 751 continue; 752 } else 753 return DIRENT_ABORT; 754 } 755 if ((dirent->name_len & 0xFF) > EXT2_NAME_LEN) { 756 if (fix_problem(ctx, PR_2_FILENAME_LONG, &cd->pctx)) { 757 dirent->name_len = EXT2_NAME_LEN; 758 dir_modified++; 759 } 760 } 761 762 if (dot_state == 0) { 763 if (check_dot(ctx, dirent, ino, &cd->pctx)) 764 dir_modified++; 765 } else if (dot_state == 1) { 766 dir = e2fsck_get_dir_info(ctx, ino); 767 if (!dir) { 768 fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx); 769 ctx->flags |= E2F_FLAG_ABORT; 770 return DIRENT_ABORT; 771 } 772 if (check_dotdot(ctx, dirent, dir, &cd->pctx)) 773 dir_modified++; 774 } else if (dirent->inode == ino) { 775 problem = PR_2_LINK_DOT; 776 if (fix_problem(ctx, PR_2_LINK_DOT, &cd->pctx)) { 777 dirent->inode = 0; 778 dir_modified++; 779 goto next; 780 } 781 } 782 if (!dirent->inode) 783 goto next; 784 785 /* 786 * Make sure the inode listed is a legal one. 787 */ 788 if (((dirent->inode != EXT2_ROOT_INO) && 789 (dirent->inode < EXT2_FIRST_INODE(fs->super))) || 790 (dirent->inode > fs->super->s_inodes_count)) { 791 problem = PR_2_BAD_INO; 792 } else if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, 793 dirent->inode))) { 794 /* 795 * If the inode is unused, offer to clear it. 796 */ 797 problem = PR_2_UNUSED_INODE; 798 } else if (ctx->inode_bb_map && 799 (ext2fs_test_inode_bitmap(ctx->inode_bb_map, 800 dirent->inode))) { 801 /* 802 * If the inode is in a bad block, offer to 803 * clear it. 804 */ 805 problem = PR_2_BB_INODE; 806 } else if ((dot_state > 1) && 807 ((dirent->name_len & 0xFF) == 1) && 808 (dirent->name[0] == '.')) { 809 /* 810 * If there's a '.' entry in anything other 811 * than the first directory entry, it's a 812 * duplicate entry that should be removed. 813 */ 814 problem = PR_2_DUP_DOT; 815 } else if ((dot_state > 1) && 816 ((dirent->name_len & 0xFF) == 2) && 817 (dirent->name[0] == '.') && 818 (dirent->name[1] == '.')) { 819 /* 820 * If there's a '..' entry in anything other 821 * than the second directory entry, it's a 822 * duplicate entry that should be removed. 823 */ 824 problem = PR_2_DUP_DOT_DOT; 825 } else if ((dot_state > 1) && 826 (dirent->inode == EXT2_ROOT_INO)) { 827 /* 828 * Don't allow links to the root directory. 829 * We check this specially to make sure we 830 * catch this error case even if the root 831 * directory hasn't been created yet. 832 */ 833 problem = PR_2_LINK_ROOT; 834 } else if ((dot_state > 1) && 835 (dirent->name_len & 0xFF) == 0) { 836 /* 837 * Don't allow zero-length directory names. 838 */ 839 problem = PR_2_NULL_NAME; 840 } 841 842 if (problem) { 843 if (fix_problem(ctx, problem, &cd->pctx)) { 844 dirent->inode = 0; 845 dir_modified++; 846 goto next; 847 } else { 848 ext2fs_unmark_valid(fs); 849 if (problem == PR_2_BAD_INO) 850 goto next; 851 } 852 } 853 854 /* 855 * If the inode was marked as having bad fields in 856 * pass1, process it and offer to fix/clear it. 857 * (We wait until now so that we can display the 858 * pathname to the user.) 859 */ 860 if (ctx->inode_bad_map && 861 ext2fs_test_inode_bitmap(ctx->inode_bad_map, 862 dirent->inode)) { 863 if (e2fsck_process_bad_inode(ctx, ino, 864 dirent->inode, 865 buf + fs->blocksize)) { 866 dirent->inode = 0; 867 dir_modified++; 868 goto next; 869 } 870 if (ctx->flags & E2F_FLAG_SIGNAL_MASK) 871 return DIRENT_ABORT; 872 } 873 874 if (check_name(ctx, dirent, ino, &cd->pctx)) 875 dir_modified++; 876 877 if (check_filetype(ctx, dirent, ino, &cd->pctx)) 878 dir_modified++; 879 880#ifdef ENABLE_HTREE 881 if (dx_db) { 882 ext2fs_dirhash(dx_dir->hashversion, dirent->name, 883 (dirent->name_len & 0xFF), 884 fs->super->s_hash_seed, &hash, 0); 885 if (hash < dx_db->min_hash) 886 dx_db->min_hash = hash; 887 if (hash > dx_db->max_hash) 888 dx_db->max_hash = hash; 889 } 890#endif 891 892 /* 893 * If this is a directory, then mark its parent in its 894 * dir_info structure. If the parent field is already 895 * filled in, then this directory has more than one 896 * hard link. We assume the first link is correct, 897 * and ask the user if he/she wants to clear this one. 898 */ 899 if ((dot_state > 1) && 900 (ext2fs_test_inode_bitmap(ctx->inode_dir_map, 901 dirent->inode))) { 902 subdir = e2fsck_get_dir_info(ctx, dirent->inode); 903 if (!subdir) { 904 cd->pctx.ino = dirent->inode; 905 fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx); 906 ctx->flags |= E2F_FLAG_ABORT; 907 return DIRENT_ABORT; 908 } 909 if (subdir->parent) { 910 cd->pctx.ino2 = subdir->parent; 911 if (fix_problem(ctx, PR_2_LINK_DIR, 912 &cd->pctx)) { 913 dirent->inode = 0; 914 dir_modified++; 915 goto next; 916 } 917 cd->pctx.ino2 = 0; 918 } else 919 subdir->parent = ino; 920 } 921 922 ext2fs_icount_increment(ctx->inode_count, dirent->inode, 923 &links); 924 if (links > 1) 925 ctx->fs_links_count++; 926 ctx->fs_total_count++; 927 next: 928 prev = dirent; 929 offset += dirent->rec_len; 930 dot_state++; 931 } while (offset < fs->blocksize); 932#if 0 933 printf("\n"); 934#endif 935#ifdef ENABLE_HTREE 936 if (dx_db) { 937#ifdef DX_DEBUG 938 printf("db_block %d, type %d, min_hash 0x%0x, max_hash 0x%0x\n", 939 db->blockcnt, dx_db->type, 940 dx_db->min_hash, dx_db->max_hash); 941#endif 942 cd->pctx.dir = cd->pctx.ino; 943 if ((dx_db->type == DX_DIRBLOCK_ROOT) || 944 (dx_db->type == DX_DIRBLOCK_NODE)) 945 parse_int_node(fs, db, cd, dx_dir, buf); 946 } 947#endif /* ENABLE_HTREE */ 948 if (offset != fs->blocksize) { 949 cd->pctx.num = dirent->rec_len - fs->blocksize + offset; 950 if (fix_problem(ctx, PR_2_FINAL_RECLEN, &cd->pctx)) { 951 dirent->rec_len = cd->pctx.num; 952 dir_modified++; 953 } 954 } 955 if (dir_modified) { 956 cd->pctx.errcode = ext2fs_write_dir_block(fs, block_nr, buf); 957 if (cd->pctx.errcode) { 958 if (!fix_problem(ctx, PR_2_WRITE_DIRBLOCK, 959 &cd->pctx)) { 960 ctx->flags |= E2F_FLAG_ABORT; 961 return DIRENT_ABORT; 962 } 963 } 964 ext2fs_mark_changed(fs); 965 } 966 return 0; 967} 968 969/* 970 * This function is called to deallocate a block, and is an interator 971 * functioned called by deallocate inode via ext2fs_iterate_block(). 972 */ 973static int deallocate_inode_block(ext2_filsys fs, 974 blk_t *block_nr, 975 e2_blkcnt_t blockcnt, 976 blk_t ref_block, 977 int ref_offset, 978 void *priv_data) 979{ 980 e2fsck_t ctx = (e2fsck_t) priv_data; 981 982 if (HOLE_BLKADDR(*block_nr)) 983 return 0; 984 ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr); 985 ext2fs_block_alloc_stats(fs, *block_nr, -1); 986 return 0; 987} 988 989/* 990 * This fuction deallocates an inode 991 */ 992static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf) 993{ 994 ext2_filsys fs = ctx->fs; 995 struct ext2_inode inode; 996 struct problem_context pctx; 997 __u32 count; 998 999 ext2fs_icount_store(ctx->inode_link_info, ino, 0); 1000 e2fsck_read_inode(ctx, ino, &inode, "deallocate_inode"); 1001 inode.i_links_count = 0; 1002 inode.i_dtime = time(0); 1003 e2fsck_write_inode(ctx, ino, &inode, "deallocate_inode"); 1004 clear_problem_context(&pctx); 1005 pctx.ino = ino; 1006 1007 /* 1008 * Fix up the bitmaps... 1009 */ 1010 e2fsck_read_bitmaps(ctx); 1011 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino); 1012 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino); 1013 if (ctx->inode_bad_map) 1014 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino); 1015 ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode)); 1016 1017 if (inode.i_file_acl && 1018 (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) { 1019 pctx.errcode = ext2fs_adjust_ea_refcount(fs, inode.i_file_acl, 1020 block_buf, -1, &count); 1021 if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) { 1022 pctx.errcode = 0; 1023 count = 1; 1024 } 1025 if (pctx.errcode) { 1026 pctx.blk = inode.i_file_acl; 1027 fix_problem(ctx, PR_2_ADJ_EA_REFCOUNT, &pctx); 1028 ctx->flags |= E2F_FLAG_ABORT; 1029 return; 1030 } 1031 if (count == 0) { 1032 ext2fs_unmark_block_bitmap(ctx->block_found_map, 1033 inode.i_file_acl); 1034 ext2fs_block_alloc_stats(fs, inode.i_file_acl, -1); 1035 } 1036 inode.i_file_acl = 0; 1037 } 1038 1039 if (!ext2fs_inode_has_valid_blocks(&inode)) 1040 return; 1041 1042 if (LINUX_S_ISREG(inode.i_mode) && 1043 (inode.i_size_high || inode.i_size & 0x80000000UL)) 1044 ctx->large_files--; 1045 1046 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf, 1047 deallocate_inode_block, ctx); 1048 if (pctx.errcode) { 1049 fix_problem(ctx, PR_2_DEALLOC_INODE, &pctx); 1050 ctx->flags |= E2F_FLAG_ABORT; 1051 return; 1052 } 1053} 1054 1055/* 1056 * This fuction clears the htree flag on an inode 1057 */ 1058static void clear_htree(e2fsck_t ctx, ext2_ino_t ino) 1059{ 1060 struct ext2_inode inode; 1061 1062 e2fsck_read_inode(ctx, ino, &inode, "clear_htree"); 1063 inode.i_flags = inode.i_flags & ~EXT2_INDEX_FL; 1064 e2fsck_write_inode(ctx, ino, &inode, "clear_htree"); 1065 if (ctx->dirs_to_hash) 1066 ext2fs_u32_list_add(ctx->dirs_to_hash, ino); 1067} 1068 1069 1070extern int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir, 1071 ext2_ino_t ino, char *buf) 1072{ 1073 ext2_filsys fs = ctx->fs; 1074 struct ext2_inode inode; 1075 int inode_modified = 0; 1076 unsigned char *frag, *fsize; 1077 struct problem_context pctx; 1078 int problem = 0; 1079 1080 e2fsck_read_inode(ctx, ino, &inode, "process_bad_inode"); 1081 1082 clear_problem_context(&pctx); 1083 pctx.ino = ino; 1084 pctx.dir = dir; 1085 pctx.inode = &inode; 1086 1087 if (!LINUX_S_ISDIR(inode.i_mode) && !LINUX_S_ISREG(inode.i_mode) && 1088 !LINUX_S_ISCHR(inode.i_mode) && !LINUX_S_ISBLK(inode.i_mode) && 1089 !LINUX_S_ISLNK(inode.i_mode) && !LINUX_S_ISFIFO(inode.i_mode) && 1090 !(LINUX_S_ISSOCK(inode.i_mode))) 1091 problem = PR_2_BAD_MODE; 1092 else if (LINUX_S_ISCHR(inode.i_mode) 1093 && !e2fsck_pass1_check_device_inode(fs, &inode)) 1094 problem = PR_2_BAD_CHAR_DEV; 1095 else if (LINUX_S_ISBLK(inode.i_mode) 1096 && !e2fsck_pass1_check_device_inode(fs, &inode)) 1097 problem = PR_2_BAD_BLOCK_DEV; 1098 else if (LINUX_S_ISFIFO(inode.i_mode) 1099 && !e2fsck_pass1_check_device_inode(fs, &inode)) 1100 problem = PR_2_BAD_FIFO; 1101 else if (LINUX_S_ISSOCK(inode.i_mode) 1102 && !e2fsck_pass1_check_device_inode(fs, &inode)) 1103 problem = PR_2_BAD_SOCKET; 1104 else if (LINUX_S_ISLNK(inode.i_mode) 1105 && !e2fsck_pass1_check_symlink(fs, &inode, buf)) { 1106 problem = PR_2_INVALID_SYMLINK; 1107 } 1108 1109 if (problem) { 1110 if (fix_problem(ctx, problem, &pctx)) { 1111 deallocate_inode(ctx, ino, 0); 1112 if (ctx->flags & E2F_FLAG_SIGNAL_MASK) 1113 return 0; 1114 return 1; 1115 } 1116 problem = 0; 1117 } 1118 1119 if (inode.i_faddr && 1120 fix_problem(ctx, PR_2_FADDR_ZERO, &pctx)) { 1121 inode.i_faddr = 0; 1122 inode_modified++; 1123 } 1124 1125 switch (fs->super->s_creator_os) { 1126 case EXT2_OS_LINUX: 1127 frag = &inode.osd2.linux2.l_i_frag; 1128 fsize = &inode.osd2.linux2.l_i_fsize; 1129 break; 1130 case EXT2_OS_HURD: 1131 frag = &inode.osd2.hurd2.h_i_frag; 1132 fsize = &inode.osd2.hurd2.h_i_fsize; 1133 break; 1134 case EXT2_OS_MASIX: 1135 frag = &inode.osd2.masix2.m_i_frag; 1136 fsize = &inode.osd2.masix2.m_i_fsize; 1137 break; 1138 default: 1139 frag = fsize = 0; 1140 } 1141 if (frag && *frag) { 1142 pctx.num = *frag; 1143 if (fix_problem(ctx, PR_2_FRAG_ZERO, &pctx)) { 1144 *frag = 0; 1145 inode_modified++; 1146 } 1147 pctx.num = 0; 1148 } 1149 if (fsize && *fsize) { 1150 pctx.num = *fsize; 1151 if (fix_problem(ctx, PR_2_FSIZE_ZERO, &pctx)) { 1152 *fsize = 0; 1153 inode_modified++; 1154 } 1155 pctx.num = 0; 1156 } 1157 1158 if (inode.i_file_acl && 1159 !(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) && 1160 fix_problem(ctx, PR_2_FILE_ACL_ZERO, &pctx)) { 1161 inode.i_file_acl = 0; 1162 inode_modified++; 1163 } 1164 if (inode.i_file_acl && 1165 ((inode.i_file_acl < fs->super->s_first_data_block) || 1166 (inode.i_file_acl >= fs->super->s_blocks_count)) && 1167 fix_problem(ctx, PR_2_FILE_ACL_BAD, &pctx)) { 1168 inode.i_file_acl = 0; 1169 inode_modified++; 1170 } 1171 if (inode.i_dir_acl && 1172 LINUX_S_ISDIR(inode.i_mode) && 1173 fix_problem(ctx, PR_2_DIR_ACL_ZERO, &pctx)) { 1174 inode.i_dir_acl = 0; 1175 inode_modified++; 1176 } 1177 if (inode_modified) 1178 e2fsck_write_inode(ctx, ino, &inode, "process_bad_inode"); 1179 return 0; 1180} 1181 1182 1183/* 1184 * allocate_dir_block --- this function allocates a new directory 1185 * block for a particular inode; this is done if a directory has 1186 * a "hole" in it, or if a directory has a illegal block number 1187 * that was zeroed out and now needs to be replaced. 1188 */ 1189static int allocate_dir_block(e2fsck_t ctx, 1190 struct ext2_db_entry *db, 1191 char *buf, struct problem_context *pctx) 1192{ 1193 ext2_filsys fs = ctx->fs; 1194 blk_t blk; 1195 char *block; 1196 struct ext2_inode inode; 1197 1198 if (fix_problem(ctx, PR_2_DIRECTORY_HOLE, pctx) == 0) 1199 return 1; 1200 1201 /* 1202 * Read the inode and block bitmaps in; we'll be messing with 1203 * them. 1204 */ 1205 e2fsck_read_bitmaps(ctx); 1206 1207 /* 1208 * First, find a free block 1209 */ 1210 pctx->errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk); 1211 if (pctx->errcode) { 1212 pctx->str = "ext2fs_new_block"; 1213 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx); 1214 return 1; 1215 } 1216 ext2fs_mark_block_bitmap(ctx->block_found_map, blk); 1217 ext2fs_mark_block_bitmap(fs->block_map, blk); 1218 ext2fs_mark_bb_dirty(fs); 1219 1220 /* 1221 * Now let's create the actual data block for the inode 1222 */ 1223 if (db->blockcnt) 1224 pctx->errcode = ext2fs_new_dir_block(fs, 0, 0, &block); 1225 else 1226 pctx->errcode = ext2fs_new_dir_block(fs, db->ino, 1227 EXT2_ROOT_INO, &block); 1228 1229 if (pctx->errcode) { 1230 pctx->str = "ext2fs_new_dir_block"; 1231 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx); 1232 return 1; 1233 } 1234 1235 pctx->errcode = ext2fs_write_dir_block(fs, blk, block); 1236 ext2fs_free_mem((void **) &block); 1237 if (pctx->errcode) { 1238 pctx->str = "ext2fs_write_dir_block"; 1239 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx); 1240 return 1; 1241 } 1242 1243 /* 1244 * Update the inode block count 1245 */ 1246 e2fsck_read_inode(ctx, db->ino, &inode, "allocate_dir_block"); 1247 inode.i_blocks += fs->blocksize / 512; 1248 if (inode.i_size < (db->blockcnt+1) * fs->blocksize) 1249 inode.i_size = (db->blockcnt+1) * fs->blocksize; 1250 e2fsck_write_inode(ctx, db->ino, &inode, "allocate_dir_block"); 1251 1252 /* 1253 * Finally, update the block pointers for the inode 1254 */ 1255 db->blk = blk; 1256 pctx->errcode = ext2fs_block_iterate2(fs, db->ino, BLOCK_FLAG_HOLE, 1257 0, update_dir_block, db); 1258 if (pctx->errcode) { 1259 pctx->str = "ext2fs_block_iterate"; 1260 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx); 1261 return 1; 1262 } 1263 1264 return 0; 1265} 1266 1267/* 1268 * This is a helper function for allocate_dir_block(). 1269 */ 1270static int update_dir_block(ext2_filsys fs, 1271 blk_t *block_nr, 1272 e2_blkcnt_t blockcnt, 1273 blk_t ref_block, 1274 int ref_offset, 1275 void *priv_data) 1276{ 1277 struct ext2_db_entry *db; 1278 1279 db = (struct ext2_db_entry *) priv_data; 1280 if (db->blockcnt == (int) blockcnt) { 1281 *block_nr = db->blk; 1282 return BLOCK_CHANGED; 1283 } 1284 return 0; 1285} 1286