pass1b.c revision 7abb2bdcd6c3787eafdff77bf53050f995f35054
1/* 2 * pass1b.c --- Pass #1b of e2fsck 3 * 4 * This file contains pass1B, pass1C, and pass1D of e2fsck. They are 5 * only invoked if pass 1 discovered blocks which are in use by more 6 * than one inode. 7 * 8 * Pass1B scans the data blocks of all the inodes again, generating a 9 * complete list of duplicate blocks and which inodes have claimed 10 * them. 11 * 12 * Pass1C does a tree-traversal of the filesystem, to determine the 13 * parent directories of these inodes. This step is necessary so that 14 * e2fsck can print out the pathnames of affected inodes. 15 * 16 * Pass1D is a reconciliation pass. For each inode with duplicate 17 * blocks, the user is prompted if s/he would like to clone the file 18 * (so that the file gets a fresh copy of the duplicated blocks) or 19 * simply to delete the file. 20 * 21 * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o. 22 * 23 * %Begin-Header% 24 * This file may be redistributed under the terms of the GNU Public 25 * License. 26 * %End-Header% 27 * 28 */ 29 30#include <time.h> 31#ifdef HAVE_ERRNO_H 32#include <errno.h> 33#endif 34 35#include <et/com_err.h> 36#include "e2fsck.h" 37 38#include "problem.h" 39 40/* Define an extension to the ext2 library's block count information */ 41#define BLOCK_COUNT_EXTATTR (-5) 42 43/* 44 * This is structure is allocated for each time that a block is 45 * claimed by more than one file. So if a particular block is claimed 46 * by 3 files, then three copies of this structure will be allocated, 47 * one for each conflict. 48 * 49 * The linked list structure is as follows: 50 * 51 * dup_blk --> block #34 --> block #35 --> block #47 52 * inode #12 inode #14 inode #17 53 * num_bad = 3 num_bad = 2 num_bad = 2 54 * | | | 55 * V V V 56 * block #34 block #35 block #47 57 * inode #14 inode #15 inode #23 58 * | 59 * V 60 * block #34 61 * inode #15 62 * 63 * The num_bad field indicates how many inodes are sharing a 64 * particular block, and is only stored in the first element of the 65 * linked list for a particular block. As the block conflicts are 66 * resolved, num_bad is decremented; when it reaches 1, then we no 67 * longer need to worry about that block. 68 */ 69struct dup_block { 70 blk_t block; /* Block number */ 71 ext2_ino_t ino; /* Inode number */ 72 int num_bad; 73 int flags; 74 /* Pointer to next dup record with different block */ 75 struct dup_block *next_block; 76 /* Pointer to next dup record with different inode */ 77 struct dup_block *next_inode; 78}; 79 80#define FLAG_EXTATTR (1) 81 82/* 83 * This structure stores information about a particular inode which 84 * is sharing blocks with other inodes. This information is collected 85 * to display to the user, so that the user knows what files he or she 86 * is dealing with, when trying to decide how to resolve the conflict 87 * of multiply-claimed blocks. 88 */ 89struct dup_inode { 90 ext2_ino_t ino, dir; 91 int num_dupblocks; 92 struct ext2_inode inode; 93 struct dup_inode *next; 94}; 95 96static int process_pass1b_block(ext2_filsys fs, blk_t *blocknr, 97 e2_blkcnt_t blockcnt, blk_t ref_blk, 98 int ref_offset, void *priv_data); 99static void delete_file(e2fsck_t ctx, struct dup_inode *dp, 100 char *block_buf); 101static int clone_file(e2fsck_t ctx, struct dup_inode *dp, char* block_buf); 102static int check_if_fs_block(e2fsck_t ctx, blk_t test_blk); 103 104static void pass1b(e2fsck_t ctx, char *block_buf); 105static void pass1c(e2fsck_t ctx, char *block_buf); 106static void pass1d(e2fsck_t ctx, char *block_buf); 107 108static struct dup_block *dup_blk = 0; 109static struct dup_inode *dup_ino = 0; 110static int dup_inode_count = 0; 111 112static ext2fs_inode_bitmap inode_dup_map; 113 114/* 115 * Main procedure for handling duplicate blocks 116 */ 117void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf) 118{ 119 ext2_filsys fs = ctx->fs; 120 struct dup_block *p, *q, *next_p, *next_q; 121 struct dup_inode *r, *next_r; 122 struct problem_context pctx; 123 124 clear_problem_context(&pctx); 125 126 pctx.errcode = ext2fs_allocate_inode_bitmap(fs, 127 _("multiply claimed inode map"), &inode_dup_map); 128 if (pctx.errcode) { 129 fix_problem(ctx, PR_1B_ALLOCATE_IBITMAP_ERROR, &pctx); 130 ctx->flags |= E2F_FLAG_ABORT; 131 return; 132 } 133 134 pass1b(ctx, block_buf); 135 pass1c(ctx, block_buf); 136 pass1d(ctx, block_buf); 137 138 /* 139 * Time to free all of the accumulated data structures that we 140 * don't need anymore. 141 */ 142 ext2fs_free_inode_bitmap(inode_dup_map); inode_dup_map = 0; 143 ext2fs_free_block_bitmap(ctx->block_dup_map); ctx->block_dup_map = 0; 144 for (p = dup_blk; p; p = next_p) { 145 next_p = p->next_block; 146 for (q = p; q; q = next_q) { 147 next_q = q->next_inode; 148 ext2fs_free_mem((void **) &q); 149 } 150 } 151 for (r = dup_ino; r; r = next_r) { 152 next_r = r->next; 153 ext2fs_free_mem((void **) &r); 154 } 155} 156 157/* 158 * Scan the inodes looking for inodes that contain duplicate blocks. 159 */ 160struct process_block_struct { 161 ext2_ino_t ino; 162 int dup_blocks; 163 e2fsck_t ctx; 164 struct problem_context *pctx; 165}; 166 167static void pass1b(e2fsck_t ctx, char *block_buf) 168{ 169 ext2_filsys fs = ctx->fs; 170 ext2_ino_t ino; 171 struct ext2_inode inode; 172 ext2_inode_scan scan; 173 struct process_block_struct pb; 174 struct dup_inode *dp; 175 struct problem_context pctx; 176 177 clear_problem_context(&pctx); 178 179 fix_problem(ctx, PR_1B_PASS_HEADER, &pctx); 180 pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks, 181 &scan); 182 if (pctx.errcode) { 183 fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx); 184 ctx->flags |= E2F_FLAG_ABORT; 185 return; 186 } 187 pctx.errcode = ext2fs_get_next_inode(scan, &ino, &inode); 188 if (pctx.errcode) { 189 fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx); 190 ctx->flags |= E2F_FLAG_ABORT; 191 return; 192 } 193 ctx->stashed_inode = &inode; 194 pb.ctx = ctx; 195 pb.pctx = &pctx; 196 pctx.str = "pass1b"; 197 while (ino) { 198 pctx.ino = ctx->stashed_ino = ino; 199 if ((ino != EXT2_BAD_INO) && 200 (!ext2fs_test_inode_bitmap(ctx->inode_used_map, ino) || 201 !ext2fs_inode_has_valid_blocks(&inode))) 202 goto next; 203 204 pb.ino = ino; 205 pb.dup_blocks = 0; 206 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf, 207 process_pass1b_block, &pb); 208 if (inode.i_file_acl) 209 process_pass1b_block(fs, &inode.i_file_acl, 210 BLOCK_COUNT_EXTATTR, 0, 0, &pb); 211 if (pb.dup_blocks) { 212 end_problem_latch(ctx, PR_LATCH_DBLOCK); 213 dp = (struct dup_inode *) e2fsck_allocate_memory(ctx, 214 sizeof(struct dup_inode), 215 "duplicate inode record"); 216 dp->ino = ino; 217 dp->dir = 0; 218 dp->inode = inode; 219 dp->num_dupblocks = pb.dup_blocks; 220 dp->next = dup_ino; 221 dup_ino = dp; 222 if (ino != EXT2_BAD_INO) 223 dup_inode_count++; 224 } 225 if (pctx.errcode) 226 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx); 227 next: 228 pctx.errcode = ext2fs_get_next_inode(scan, &ino, &inode); 229 if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE) 230 goto next; 231 if (pctx.errcode) { 232 fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx); 233 ctx->flags |= E2F_FLAG_ABORT; 234 return; 235 } 236 } 237 ext2fs_close_inode_scan(scan); 238 e2fsck_use_inode_shortcuts(ctx, 0); 239} 240 241static int process_pass1b_block(ext2_filsys fs, 242 blk_t *block_nr, 243 e2_blkcnt_t blockcnt, 244 blk_t ref_blk, 245 int ref_offset, 246 void *priv_data) 247{ 248 struct process_block_struct *p; 249 struct dup_block *dp, *q, *r; 250 int i; 251 e2fsck_t ctx; 252 253 if (HOLE_BLKADDR(*block_nr)) 254 return 0; 255 p = (struct process_block_struct *) priv_data; 256 ctx = p->ctx; 257 258 if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) { 259 /* OK, this is a duplicate block */ 260 if (p->ino != EXT2_BAD_INO) { 261 p->pctx->blk = *block_nr; 262 fix_problem(ctx, PR_1B_DUP_BLOCK, p->pctx); 263 } 264 p->dup_blocks++; 265 ext2fs_mark_block_bitmap(ctx->block_dup_map, *block_nr); 266 ext2fs_mark_inode_bitmap(inode_dup_map, p->ino); 267 dp = (struct dup_block *) e2fsck_allocate_memory(ctx, 268 sizeof(struct dup_block), 269 "duplicate block record"); 270 dp->block = *block_nr; 271 dp->ino = p->ino; 272 dp->num_bad = 0; 273 dp->flags = (blockcnt == BLOCK_COUNT_EXTATTR) ? 274 FLAG_EXTATTR : 0; 275 q = dup_blk; 276 while (q) { 277 if (q->block == *block_nr) 278 break; 279 q = q->next_block; 280 } 281 if (q) { 282 dp->next_inode = q->next_inode; 283 q->next_inode = dp; 284 } else { 285 dp->next_block = dup_blk; 286 dup_blk = dp; 287 } 288 } 289 /* 290 * Set the num_bad field 291 */ 292 for (q = dup_blk; q; q = q->next_block) { 293 i = 0; 294 for (r = q; r; r = r->next_inode) 295 i++; 296 q->num_bad = i; 297 } 298 return 0; 299} 300 301/* 302 * Pass 1c: Scan directories for inodes with duplicate blocks. This 303 * is used so that we can print pathnames when prompting the user for 304 * what to do. 305 */ 306struct search_dir_struct { 307 int count; 308 ext2_ino_t first_inode; 309 ext2_ino_t max_inode; 310}; 311 312static int search_dirent_proc(ext2_ino_t dir, int entry, 313 struct ext2_dir_entry *dirent, 314 int offset, int blocksize, 315 char *buf, void *priv_data) 316{ 317 struct search_dir_struct *sd; 318 struct dup_inode *p; 319 320 sd = (struct search_dir_struct *) priv_data; 321 322 if (dirent->inode > sd->max_inode) 323 /* Should abort this inode, but not everything */ 324 return 0; 325 326 if (!dirent->inode || (entry < DIRENT_OTHER_FILE) || 327 !ext2fs_test_inode_bitmap(inode_dup_map, dirent->inode)) 328 return 0; 329 330 for (p = dup_ino; p; p = p->next) { 331 if ((p->ino >= sd->first_inode) && 332 (p->ino == dirent->inode)) 333 break; 334 } 335 336 if (!p || p->dir) 337 return 0; 338 339 p->dir = dir; 340 sd->count--; 341 342 return(sd->count ? 0 : DIRENT_ABORT); 343} 344 345 346static void pass1c(e2fsck_t ctx, char *block_buf) 347{ 348 ext2_filsys fs = ctx->fs; 349 struct dup_inode *p; 350 int inodes_left = dup_inode_count; 351 struct search_dir_struct sd; 352 struct problem_context pctx; 353 354 clear_problem_context(&pctx); 355 356 fix_problem(ctx, PR_1C_PASS_HEADER, &pctx); 357 358 /* 359 * First check to see if any of the inodes with dup blocks is 360 * a special inode. (Note that the bad block inode isn't 361 * counted.) 362 */ 363 for (p = dup_ino; p; p = p->next) { 364 if ((p->ino < EXT2_FIRST_INODE(fs->super)) && 365 (p->ino != EXT2_BAD_INO)) 366 inodes_left--; 367 } 368 369 /* 370 * Search through all directories to translate inodes to names 371 * (by searching for the containing directory for that inode.) 372 */ 373 sd.count = inodes_left; 374 sd.first_inode = EXT2_FIRST_INODE(fs->super); 375 sd.max_inode = fs->super->s_inodes_count; 376 ext2fs_dblist_dir_iterate(fs->dblist, 0, block_buf, 377 search_dirent_proc, &sd); 378} 379 380static void pass1d(e2fsck_t ctx, char *block_buf) 381{ 382 ext2_filsys fs = ctx->fs; 383 struct dup_inode *p, *s; 384 struct dup_block *q, *r; 385 ext2_ino_t *shared; 386 int shared_len; 387 int i; 388 int file_ok; 389 int meta_data = 0; 390 struct problem_context pctx; 391 392 clear_problem_context(&pctx); 393 394 fix_problem(ctx, PR_1D_PASS_HEADER, &pctx); 395 e2fsck_read_bitmaps(ctx); 396 397 pctx.num = dup_inode_count; 398 fix_problem(ctx, PR_1D_NUM_DUP_INODES, &pctx); 399 shared = (ext2_ino_t *) e2fsck_allocate_memory(ctx, 400 sizeof(ext2_ino_t) * dup_inode_count, 401 "Shared inode list"); 402 for (p = dup_ino; p; p = p->next) { 403 shared_len = 0; 404 file_ok = 1; 405 if (p->ino == EXT2_BAD_INO) 406 continue; 407 408 /* 409 * Search through the duplicate records to see which 410 * inodes share blocks with this one 411 */ 412 for (q = dup_blk; q; q = q->next_block) { 413 /* 414 * See if this block is used by this inode. 415 * If it isn't, continue. 416 */ 417 for (r = q; r; r = r->next_inode) 418 if (r->ino == p->ino) 419 break; 420 if (!r) 421 continue; 422 if (q->num_bad > 1) 423 file_ok = 0; 424 if (check_if_fs_block(ctx, q->block)) { 425 file_ok = 0; 426 meta_data = 1; 427 } 428 429 /* 430 * Add all inodes used by this block to the 431 * shared[] --- which is a unique list, so 432 * if an inode is already in shared[], don't 433 * add it again. 434 */ 435 for (r = q; r; r = r->next_inode) { 436 if (r->ino == p->ino) 437 continue; 438 for (i = 0; i < shared_len; i++) 439 if (shared[i] == r->ino) 440 break; 441 if (i == shared_len) { 442 shared[shared_len++] = r->ino; 443 } 444 } 445 } 446 447 /* 448 * Report the inode that we are working on 449 */ 450 pctx.inode = &p->inode; 451 pctx.ino = p->ino; 452 pctx.dir = p->dir; 453 pctx.blkcount = p->num_dupblocks; 454 pctx.num = meta_data ? shared_len+1 : shared_len; 455 fix_problem(ctx, PR_1D_DUP_FILE, &pctx); 456 pctx.blkcount = 0; 457 pctx.num = 0; 458 459 if (meta_data) 460 fix_problem(ctx, PR_1D_SHARE_METADATA, &pctx); 461 462 for (i = 0; i < shared_len; i++) { 463 for (s = dup_ino; s; s = s->next) 464 if (s->ino == shared[i]) 465 break; 466 if (!s) 467 continue; 468 /* 469 * Report the inode that we are sharing with 470 */ 471 pctx.inode = &s->inode; 472 pctx.ino = s->ino; 473 pctx.dir = s->dir; 474 fix_problem(ctx, PR_1D_DUP_FILE_LIST, &pctx); 475 } 476 if (file_ok) { 477 fix_problem(ctx, PR_1D_DUP_BLOCKS_DEALT, &pctx); 478 continue; 479 } 480 if (fix_problem(ctx, PR_1D_CLONE_QUESTION, &pctx)) { 481 pctx.errcode = clone_file(ctx, p, block_buf); 482 if (pctx.errcode) 483 fix_problem(ctx, PR_1D_CLONE_ERROR, &pctx); 484 else 485 continue; 486 } 487 if (fix_problem(ctx, PR_1D_DELETE_QUESTION, &pctx)) 488 delete_file(ctx, p, block_buf); 489 else 490 ext2fs_unmark_valid(fs); 491 } 492 ext2fs_free_mem((void **) &shared); 493} 494 495/* 496 * Drop the refcount on the dup_block structure, and clear the entry 497 * in the block_dup_map if appropriate. 498 */ 499static void decrement_badcount(e2fsck_t ctx, struct dup_block *p) 500{ 501 p->num_bad--; 502 if (p->num_bad <= 0 || 503 (p->num_bad == 1 && !check_if_fs_block(ctx, p->block))) 504 ext2fs_unmark_block_bitmap(ctx->block_dup_map, p->block); 505} 506 507static int delete_file_block(ext2_filsys fs, 508 blk_t *block_nr, 509 e2_blkcnt_t blockcnt, 510 blk_t ref_block, 511 int ref_offset, 512 void *priv_data) 513{ 514 struct process_block_struct *pb; 515 struct dup_block *p; 516 e2fsck_t ctx; 517 518 pb = (struct process_block_struct *) priv_data; 519 ctx = pb->ctx; 520 521 if (HOLE_BLKADDR(*block_nr)) 522 return 0; 523 524 if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) { 525 for (p = dup_blk; p; p = p->next_block) 526 if (p->block == *block_nr) 527 break; 528 if (p) { 529 decrement_badcount(ctx, p); 530 } else 531 com_err("delete_file_block", 0, 532 _("internal error; can't find dup_blk for %d\n"), 533 *block_nr); 534 } else { 535 ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr); 536 ext2fs_unmark_block_bitmap(fs->block_map, *block_nr); 537 } 538 539 return 0; 540} 541 542static void delete_file(e2fsck_t ctx, struct dup_inode *dp, char* block_buf) 543{ 544 ext2_filsys fs = ctx->fs; 545 struct process_block_struct pb; 546 struct ext2_inode inode; 547 struct problem_context pctx; 548 549 clear_problem_context(&pctx); 550 pctx.ino = pb.ino = dp->ino; 551 pb.dup_blocks = dp->num_dupblocks; 552 pb.ctx = ctx; 553 pctx.str = "delete_file"; 554 555 pctx.errcode = ext2fs_block_iterate2(fs, dp->ino, 0, block_buf, 556 delete_file_block, &pb); 557 if (pctx.errcode) 558 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx); 559 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, dp->ino); 560 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, dp->ino); 561 if (ctx->inode_bad_map) 562 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, dp->ino); 563 ext2fs_unmark_inode_bitmap(fs->inode_map, dp->ino); 564 ext2fs_mark_ib_dirty(fs); 565 ext2fs_mark_bb_dirty(fs); 566 e2fsck_read_inode(ctx, dp->ino, &inode, "delete_file"); 567 inode.i_links_count = 0; 568 inode.i_dtime = time(0); 569 if (inode.i_file_acl) 570 delete_file_block(fs, &inode.i_file_acl, 571 BLOCK_COUNT_EXTATTR, 0, 0, &pb); 572 e2fsck_write_inode(ctx, dp->ino, &inode, "delete_file"); 573} 574 575struct clone_struct { 576 errcode_t errcode; 577 ext2_ino_t dir; 578 char *buf; 579 e2fsck_t ctx; 580}; 581 582static int clone_file_block(ext2_filsys fs, 583 blk_t *block_nr, 584 e2_blkcnt_t blockcnt, 585 blk_t ref_block, 586 int ref_offset, 587 void *priv_data) 588{ 589 struct dup_block *p; 590 blk_t new_block; 591 errcode_t retval; 592 struct clone_struct *cs = (struct clone_struct *) priv_data; 593 e2fsck_t ctx; 594 595 ctx = cs->ctx; 596 597 if (HOLE_BLKADDR(*block_nr)) 598 return 0; 599 600 if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) { 601 for (p = dup_blk; p; p = p->next_block) 602 if (p->block == *block_nr) 603 break; 604 if (p) { 605 retval = ext2fs_new_block(fs, 0, ctx->block_found_map, 606 &new_block); 607 if (retval) { 608 cs->errcode = retval; 609 return BLOCK_ABORT; 610 } 611 if (cs->dir && (blockcnt >= 0)) { 612 retval = ext2fs_set_dir_block(fs->dblist, 613 cs->dir, new_block, blockcnt); 614 if (retval) { 615 cs->errcode = retval; 616 return BLOCK_ABORT; 617 } 618 } 619 retval = io_channel_read_blk(fs->io, *block_nr, 1, 620 cs->buf); 621 if (retval) { 622 cs->errcode = retval; 623 return BLOCK_ABORT; 624 } 625 retval = io_channel_write_blk(fs->io, new_block, 1, 626 cs->buf); 627 if (retval) { 628 cs->errcode = retval; 629 return BLOCK_ABORT; 630 } 631 decrement_badcount(ctx, p); 632 *block_nr = new_block; 633 ext2fs_mark_block_bitmap(ctx->block_found_map, 634 new_block); 635 ext2fs_mark_block_bitmap(fs->block_map, new_block); 636 return BLOCK_CHANGED; 637 } else 638 com_err("clone_file_block", 0, 639 _("internal error; can't find dup_blk for %d\n"), 640 *block_nr); 641 } 642 return 0; 643} 644 645static int clone_file(e2fsck_t ctx, struct dup_inode *dp, char* block_buf) 646{ 647 ext2_filsys fs = ctx->fs; 648 errcode_t retval; 649 struct clone_struct cs; 650 struct problem_context pctx; 651 blk_t blk; 652 653 clear_problem_context(&pctx); 654 cs.errcode = 0; 655 cs.dir = 0; 656 cs.ctx = ctx; 657 retval = ext2fs_get_mem(fs->blocksize, (void **) &cs.buf); 658 if (retval) 659 return retval; 660 661 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dp->ino)) 662 cs.dir = dp->ino; 663 664 pctx.ino = dp->ino; 665 pctx.str = "clone_file"; 666 pctx.errcode = ext2fs_block_iterate2(fs, dp->ino, 0, block_buf, 667 clone_file_block, &cs); 668 ext2fs_mark_bb_dirty(fs); 669 if (pctx.errcode) { 670 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx); 671 retval = pctx.errcode; 672 goto errout; 673 } 674 if (cs.errcode) { 675 com_err("clone_file", cs.errcode, 676 _("returned from clone_file_block")); 677 retval = cs.errcode; 678 goto errout; 679 } 680 blk = dp->inode.i_file_acl; 681 if (blk && (clone_file_block(fs, &dp->inode.i_file_acl, 682 BLOCK_COUNT_EXTATTR, 0, 0, &cs) == 683 BLOCK_CHANGED)) { 684 struct dup_block *p, *q; 685 struct dup_inode *r; 686 687 /* 688 * If we cloned the EA block, find all other inodes 689 * which refered to that EA block, and modify 690 * them to point to the new EA block. 691 */ 692 for (p = dup_blk; p; p = p->next_block) { 693 if (p->block == blk) 694 break; 695 } 696 for (q = p; q ; q = q->next_inode) { 697 if (!(q->flags & FLAG_EXTATTR)) 698 continue; 699 for (r = dup_ino; r; r = r->next) 700 if (r->ino == q->ino) 701 break; 702 if (r) { 703 r->inode.i_file_acl = dp->inode.i_file_acl; 704 e2fsck_write_inode(ctx, q->ino, &r->inode, 705 "clone file EA"); 706 } 707 q->ino = 0; /* Should free the structure... */ 708 decrement_badcount(ctx, p); 709 } 710 } 711 retval = 0; 712errout: 713 ext2fs_free_mem((void **) &cs.buf); 714 return retval; 715} 716 717/* 718 * This routine returns 1 if a block overlaps with one of the superblocks, 719 * group descriptors, inode bitmaps, or block bitmaps. 720 */ 721static int check_if_fs_block(e2fsck_t ctx, blk_t test_block) 722{ 723 ext2_filsys fs = ctx->fs; 724 blk_t block; 725 int i; 726 727 block = fs->super->s_first_data_block; 728 for (i = 0; i < fs->group_desc_count; i++) { 729 730 /* Check superblocks/block group descriptros */ 731 if (ext2fs_bg_has_super(fs, i)) { 732 if (test_block >= block && 733 (test_block <= block + fs->desc_blocks)) 734 return 1; 735 } 736 737 /* Check the inode table */ 738 if ((fs->group_desc[i].bg_inode_table) && 739 (test_block >= fs->group_desc[i].bg_inode_table) && 740 (test_block < (fs->group_desc[i].bg_inode_table + 741 fs->inode_blocks_per_group))) 742 return 1; 743 744 /* Check the bitmap blocks */ 745 if ((test_block == fs->group_desc[i].bg_block_bitmap) || 746 (test_block == fs->group_desc[i].bg_inode_bitmap)) 747 return 1; 748 749 block += fs->super->s_blocks_per_group; 750 } 751 return 0; 752} 753