1 /* 2 ext2.c -- generic ext2 stuff 3 Copyright (C) 1998, 1999, 2000, 2001, 2007 Free Software Foundation, Inc. 4 5 This program is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 3 of the License, or 8 (at your option) any later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program. If not, see <http://www.gnu.org/licenses/>. 17 */ 18 19 #include <config.h> 20 21 #ifndef DISCOVER_ONLY 22 23 #include <stdio.h> 24 #include <stdlib.h> 25 #include <string.h> 26 #include <time.h> 27 #include <uuid/uuid.h> 28 #include "ext2.h" 29 30 /* ext2 stuff ****************************************************************/ 31 32 unsigned char _bitmap[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80}; 33 34 int ext2_copy_block(struct ext2_fs *fs, blk_t from, blk_t to) 35 { 36 unsigned char* buf = ped_malloc (fs->blocksize); 37 38 if (!ext2_bcache_flush(fs, from)) return 0; 39 if (!ext2_bcache_flush(fs, to)) return 0; 40 41 if (!ext2_read_blocks(fs, buf, from, 1)) return 0; 42 if (!ext2_write_blocks(fs, buf, to, 1)) return 0; 43 44 return 1; 45 } 46 47 int ext2_get_block_state(struct ext2_fs *fs, blk_t block) 48 { 49 struct ext2_buffer_head *bh; 50 int group; 51 int offset; 52 int state; 53 54 block -= EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb); 55 group = block / EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb); 56 offset = block % EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb); 57 58 bh = ext2_bread(fs, EXT2_GROUP_BLOCK_BITMAP(fs->gd[group])); 59 state = bh->data[offset>>3] & _bitmap[offset&7]; 60 ext2_brelse(bh, 0); 61 62 return state; 63 } 64 65 blk_t ext2_find_free_block(struct ext2_fs *fs) 66 { 67 int i; 68 69 for (i=0;i<fs->numgroups;i++) 70 if (EXT2_GROUP_FREE_BLOCKS_COUNT(fs->gd[i])) 71 { 72 blk_t j; 73 blk_t offset; 74 75 offset = i * EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb) 76 + EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb); 77 for (j=fs->adminblocks; 78 j<EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb); 79 j++) 80 if (ext2_is_data_block(fs, offset + j) && 81 !ext2_get_block_state(fs, offset + j)) 82 return offset + j; 83 84 ped_exception_throw (PED_EXCEPTION_ERROR, 85 PED_EXCEPTION_CANCEL, 86 _("Inconsistent group descriptors!")); 87 } 88 89 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, 90 _("File system full!")); 91 return 0; 92 } 93 94 ino_t ext2_find_free_inode(struct ext2_fs *fs) 95 { 96 int i; 97 98 for (i=0;i<fs->numgroups;i++) 99 if (EXT2_GROUP_FREE_INODES_COUNT(fs->gd[i])) 100 { 101 ino_t j; 102 ino_t offset; 103 104 offset = i * EXT2_SUPER_INODES_PER_GROUP(fs->sb) + 1; 105 for (j=0;j<EXT2_SUPER_INODES_PER_GROUP(fs->sb);j++) 106 if (!ext2_get_inode_state(fs, offset + j)) 107 return offset + j; 108 109 ped_exception_throw (PED_EXCEPTION_ERROR, 110 PED_EXCEPTION_CANCEL, 111 _("Inconsistent group descriptors!")); 112 } 113 114 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, 115 _("File system full!")); 116 return 0; 117 } 118 119 int ext2_move_blocks(struct ext2_fs *fs, blk_t src, blk_t num, blk_t dest) 120 { 121 unsigned char *buf; 122 blk_t i; 123 124 ped_exception_fetch_all(); 125 if ((buf = ped_malloc(num << fs->logsize)) != NULL) 126 { 127 ped_exception_leave_all(); 128 129 if (!ext2_bcache_flush_range(fs, src, num)) return 0; 130 if (!ext2_bcache_flush_range(fs, dest, num)) return 0; 131 132 if (!ext2_read_blocks(fs, buf, src, num)) return 0; 133 if (!ext2_write_blocks(fs, buf, dest, num)) return 0; 134 135 ped_free(buf); 136 return 1; 137 } 138 ped_exception_catch(); 139 ped_exception_leave_all(); 140 141 if (src > dest) 142 { 143 for (i=0;i<num;i++) 144 if (!ext2_copy_block(fs, src+i, dest+i)) 145 return 0; 146 } 147 else 148 { 149 for (i=num;i>0;i--) 150 if (!ext2_copy_block(fs, src+i, dest+i)) 151 return 0; 152 } 153 return 1; 154 } 155 156 int ext2_read_blocks(struct ext2_fs *fs, void *ptr, blk_t block, blk_t num) 157 { 158 return fs->devhandle->ops->read(fs->devhandle->cookie, ptr, block, num); 159 } 160 161 int ext2_set_block_state(struct ext2_fs *fs, blk_t block, int state, int updatemetadata) 162 { 163 struct ext2_buffer_head *bh; 164 int group; 165 int offset; 166 167 block -= EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb); 168 group = block / EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb); 169 offset = block % EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb); 170 171 bh = ext2_bread(fs, EXT2_GROUP_BLOCK_BITMAP(fs->gd[group])); 172 bh->dirty = 1; 173 if (state) 174 bh->data[offset>>3] |= _bitmap[offset&7]; 175 else 176 bh->data[offset>>3] &= ~_bitmap[offset&7]; 177 ext2_brelse(bh, 0); 178 179 if (updatemetadata) 180 { 181 int diff; 182 183 diff = state ? -1 : 1; 184 185 fs->gd[group].bg_free_blocks_count = PED_CPU_TO_LE16 186 (EXT2_GROUP_FREE_BLOCKS_COUNT(fs->gd[group]) + diff); 187 fs->sb.s_free_blocks_count = PED_CPU_TO_LE32 188 (EXT2_SUPER_FREE_BLOCKS_COUNT(fs->sb) + diff); 189 fs->metadirty |= EXT2_META_SB | EXT2_META_GD; 190 } 191 return 1; 192 } 193 194 int ext2_write_blocks(struct ext2_fs *fs, void *ptr, blk_t block, blk_t num) 195 { 196 return fs->devhandle->ops->write(fs->devhandle->cookie, ptr, block, num); 197 } 198 199 int ext2_zero_blocks(struct ext2_fs *fs, blk_t block, blk_t num) 200 { 201 unsigned char *buf; 202 blk_t i; 203 204 ped_exception_fetch_all(); 205 buf = ped_malloc (num << fs->logsize); 206 if (buf) 207 { 208 ped_exception_leave_all(); 209 210 memset(buf, 0, num << fs->logsize); 211 if (!ext2_bcache_flush_range(fs, block, num)) 212 goto error_free_buf; 213 if (!ext2_write_blocks(fs, buf, block, num)) 214 goto error_free_buf; 215 ped_free(buf); 216 return 1; 217 } 218 ped_exception_catch(); 219 220 buf = ped_malloc (fs->blocksize); 221 if (buf) 222 { 223 ped_exception_leave_all(); 224 225 memset(buf, 0, fs->blocksize); 226 227 for (i=0;i<num;i++) 228 { 229 if (!ext2_bcache_flush(fs, block+i)) 230 goto error_free_buf; 231 if (!ext2_write_blocks(fs, buf, block+i, 1)) 232 goto error_free_buf; 233 } 234 235 ped_free(buf); 236 return 1; 237 } 238 ped_exception_catch(); 239 ped_exception_leave_all(); 240 241 for (i=0;i<num;i++) 242 { 243 struct ext2_buffer_head *bh; 244 245 bh = ext2_bcreate(fs, block+i); 246 if (!bh) 247 goto error; 248 bh->dirty = 1; 249 if (!ext2_brelse(bh, 1)) 250 goto error; 251 } 252 return 1; 253 254 error_free_buf: 255 ped_free(buf); 256 error: 257 return 0; 258 } 259 260 off_t ext2_get_inode_offset(struct ext2_fs *fs, ino_t inode, blk_t *block) 261 { 262 int group; 263 int offset; 264 265 inode--; 266 267 group = inode / EXT2_SUPER_INODES_PER_GROUP(fs->sb); 268 offset = (inode % EXT2_SUPER_INODES_PER_GROUP(fs->sb)) 269 * sizeof(struct ext2_inode); 270 271 *block = EXT2_GROUP_INODE_TABLE(fs->gd[group]) 272 + (offset >> fs->logsize); 273 274 return offset & (fs->blocksize - 1); 275 } 276 277 int ext2_get_inode_state(struct ext2_fs *fs, ino_t inode) 278 { 279 struct ext2_buffer_head *bh; 280 int group; 281 int offset; 282 int ret; 283 284 inode--; 285 group = inode / EXT2_SUPER_INODES_PER_GROUP(fs->sb); 286 offset = inode % EXT2_SUPER_INODES_PER_GROUP(fs->sb); 287 288 bh = ext2_bread(fs, EXT2_GROUP_INODE_BITMAP(fs->gd[group])); 289 ret = bh->data[offset>>3] & _bitmap[offset&7]; 290 ext2_brelse(bh, 0); 291 292 return ret; 293 } 294 295 int ext2_read_inode(struct ext2_fs *fs, ino_t inode, struct ext2_inode *data) 296 { 297 struct ext2_buffer_head *bh; 298 blk_t blk; 299 off_t off; 300 301 off = ext2_get_inode_offset(fs, inode, &blk); 302 303 bh = ext2_bread(fs, blk); 304 if (!bh) 305 return 0; 306 307 memcpy(data, bh->data + off, sizeof(struct ext2_inode)); 308 ext2_brelse(bh, 0); 309 return 1; 310 } 311 312 int ext2_set_inode_state(struct ext2_fs *fs, ino_t inode, int state, int updatemetadata) 313 { 314 struct ext2_buffer_head *bh; 315 int group; 316 int offset; 317 318 inode--; 319 group = inode / EXT2_SUPER_INODES_PER_GROUP(fs->sb); 320 offset = inode % EXT2_SUPER_INODES_PER_GROUP(fs->sb); 321 322 bh = ext2_bread(fs, EXT2_GROUP_INODE_BITMAP(fs->gd[group])); 323 if (!bh) 324 return 0; 325 bh->dirty = 1; 326 if (state) 327 bh->data[offset>>3] |= _bitmap[offset&7]; 328 else 329 bh->data[offset>>3] &= ~_bitmap[offset&7]; 330 ext2_brelse(bh, 0); 331 332 if (updatemetadata) 333 { 334 int diff; 335 336 diff = state ? -1 : 1; 337 338 fs->gd[group].bg_free_inodes_count = PED_CPU_TO_LE16 339 (EXT2_GROUP_FREE_INODES_COUNT(fs->gd[group]) + diff); 340 fs->sb.s_free_inodes_count = PED_CPU_TO_LE32 341 (EXT2_SUPER_FREE_INODES_COUNT(fs->sb) + diff); 342 fs->metadirty = EXT2_META_SB | EXT2_META_GD; 343 } 344 return 1; 345 } 346 347 static void 348 _inode_update_size(struct ext2_fs *fs, struct ext2_inode *inode, int delta) 349 { 350 int i512perblock = 1 << (fs->logsize - 9); 351 uint64_t size; 352 353 /* i_blocks is in 512 byte blocks */ 354 inode->i_blocks = PED_CPU_TO_LE32(EXT2_INODE_BLOCKS(*inode) 355 + delta * i512perblock); 356 size = EXT2_INODE_SIZE(*inode) + delta * fs->blocksize; 357 inode->i_size = PED_CPU_TO_LE32(size % (1LL << 32)); 358 inode->i_size_high = PED_CPU_TO_LE32(size / (1LL << 32)); 359 inode->i_mtime = PED_CPU_TO_LE32(time(NULL)); 360 } 361 362 int ext2_do_inode(struct ext2_fs *fs, struct ext2_inode *inode, blk_t block, 363 int action) 364 { 365 struct ext2_buffer_head *bh; 366 uint32_t *udata; 367 blk_t count = 0; 368 int i; 369 int u32perblock = fs->blocksize >> 2; 370 int i512perblock = 1 << (fs->logsize - 9); 371 372 if (block == 0 || EXT2_INODE_MODE(*inode) == 0) 373 return -1; 374 375 if (fs->opt_debug) 376 switch (action) 377 { 378 case EXT2_ACTION_ADD: 379 fprintf(stderr,"adding 0x%04x to inode\n", 380 block); 381 break; 382 case EXT2_ACTION_DELETE: 383 fprintf(stderr,"deleting 0x%04x from inode\n", 384 block); 385 break; 386 case EXT2_ACTION_FIND: 387 fprintf(stderr,"finding 0x%04x in inode\n", 388 block); 389 break; 390 } 391 392 /* Direct blocks for first 12 blocks */ 393 for (i = 0; i < EXT2_NDIR_BLOCKS; i++) 394 { 395 if (action == EXT2_ACTION_ADD && !EXT2_INODE_BLOCK(*inode, i)) 396 { 397 inode->i_block[i] = PED_CPU_TO_LE32(block); 398 _inode_update_size (fs, inode, 1); 399 ext2_set_block_state(fs, block, 1, 1); 400 return i; 401 } 402 if (EXT2_INODE_BLOCK(*inode, i) == block) 403 { 404 if (action == EXT2_ACTION_DELETE) 405 { 406 inode->i_block[i] = 0; 407 _inode_update_size (fs, inode, -1); 408 ext2_set_block_state(fs, block, 0, 1); 409 } 410 return i; 411 } 412 if (EXT2_INODE_BLOCK(*inode, i)) 413 count += i512perblock; 414 } 415 416 count += EXT2_INODE_BLOCK(*inode, EXT2_IND_BLOCK) ? i512perblock : 0; 417 count += EXT2_INODE_BLOCK(*inode, EXT2_DIND_BLOCK) ? i512perblock : 0; 418 count += EXT2_INODE_BLOCK(*inode, EXT2_TIND_BLOCK) ? i512perblock : 0; 419 420 if (!EXT2_INODE_BLOCK(*inode, EXT2_IND_BLOCK) || 421 (count >= EXT2_INODE_BLOCKS(*inode) && action != EXT2_ACTION_ADD)) 422 return -1; 423 424 bh = ext2_bread(fs, EXT2_INODE_BLOCK(*inode, EXT2_IND_BLOCK)); 425 udata = (uint32_t *)bh->data; 426 427 /* Indirect blocks for next 256/512/1024 blocks (for 1k/2k/4k blocks) */ 428 for (i = 0; i < u32perblock; i++) { 429 if (action == EXT2_ACTION_ADD && !udata[i]) { 430 bh->dirty = 1; 431 udata[i] = PED_CPU_TO_LE32(block); 432 _inode_update_size (fs, inode, 1); 433 ext2_set_block_state(fs, block, 1, 1); 434 ext2_brelse(bh, 0); 435 return EXT2_NDIR_BLOCKS + i; 436 } 437 if (PED_LE32_TO_CPU(udata[i]) == block) { 438 if (action == EXT2_ACTION_DELETE) { 439 bh->dirty = 1; 440 udata[i] = 0; 441 _inode_update_size (fs, inode, -1); 442 ext2_set_block_state(fs, block, 0, 1); 443 } 444 ext2_brelse(bh, 0); 445 return EXT2_NDIR_BLOCKS + i; 446 } 447 if (udata[i]) 448 { 449 count += i512perblock; 450 if (count >= EXT2_INODE_BLOCKS(*inode) && 451 action != EXT2_ACTION_ADD) 452 return -1; 453 } 454 } 455 456 ext2_brelse(bh, 0); 457 458 if (!EXT2_INODE_BLOCK(*inode, EXT2_DIND_BLOCK) || 459 (count >= EXT2_INODE_BLOCKS(*inode) && action != EXT2_ACTION_ADD)) 460 return -1; 461 bh = ext2_bread(fs, EXT2_INODE_BLOCK(*inode, EXT2_DIND_BLOCK)); 462 udata = (uint32_t *)bh->data; 463 464 /* Double indirect blocks for next 2^16/2^18/2^20 1k/2k/4k blocks */ 465 for (i = 0; i < u32perblock; i++) { 466 struct ext2_buffer_head *bh2; 467 uint32_t *udata2; 468 int j; 469 470 if (!udata[i]) { 471 ext2_brelse(bh, 0); 472 return -1; 473 } 474 bh2 = ext2_bread(fs, PED_LE32_TO_CPU(udata[i])); 475 udata2 = (uint32_t *)bh2->data; 476 count += i512perblock; 477 478 for (j = 0; j < u32perblock; j++) { 479 if (action == EXT2_ACTION_ADD && !udata2[j]) { 480 bh2->dirty = 1; 481 udata2[j] = PED_CPU_TO_LE32(block); 482 _inode_update_size (fs, inode, 1); 483 ext2_set_block_state(fs, block, 1, 1); 484 ext2_brelse(bh, 0); 485 ext2_brelse(bh2, 0); 486 return EXT2_NDIR_BLOCKS + i * u32perblock + j; 487 } 488 if (PED_LE32_TO_CPU(udata2[j]) == block) { 489 if (action == EXT2_ACTION_DELETE) { 490 bh2->dirty = 1; 491 udata2[j] = 0; 492 _inode_update_size (fs, inode, -1); 493 ext2_set_block_state(fs, block, 0, 1); 494 } 495 ext2_brelse(bh, 0); 496 ext2_brelse(bh2, 0); 497 return EXT2_NDIR_BLOCKS + i * u32perblock + j; 498 } 499 if (udata2[j]) 500 { 501 count += i512perblock; 502 if (count >= EXT2_INODE_BLOCKS(*inode) && 503 action != EXT2_ACTION_ADD) 504 return -1; 505 } 506 } 507 ext2_brelse(bh2, 0); 508 } 509 ext2_brelse(bh, 0); 510 511 /* FIXME: we should check for triple-indirect blocks here, but it 512 * would be nice to have a better routine to traverse blocks, and 513 * file systems that need triple-indirect blocks for the resize 514 * inode are too big to worry about yet. 515 */ 516 517 return -1; 518 } 519 520 int ext2_write_inode(struct ext2_fs *fs, ino_t inode, const struct ext2_inode *data) 521 { 522 struct ext2_buffer_head *bh; 523 blk_t blk; 524 off_t off; 525 526 off = ext2_get_inode_offset(fs, inode, &blk); 527 528 bh = ext2_bread(fs, blk); 529 if (!bh) 530 return 0; 531 bh->dirty = 1; 532 memcpy(bh->data + off, data, sizeof(struct ext2_inode)); 533 ext2_brelse(bh, 0); 534 535 return 1; 536 } 537 538 int ext2_zero_inode(struct ext2_fs *fs, ino_t inode) 539 { 540 struct ext2_inode buf; 541 542 memset(&buf, 0, sizeof(struct ext2_inode)); 543 return ext2_write_inode(fs, inode, &buf); 544 } 545 546 547 548 549 550 /* check whether y is root of x 551 * (formula grabbed from linux ext2 kernel source) */ 552 static int is_root(int x, int y) 553 { 554 if (!x) 555 return 1; 556 557 while (1) 558 { 559 if (x == 1) 560 return 1; 561 562 if (x % y) 563 return 0; 564 565 x /= y; 566 } 567 } 568 569 /* check whether group contains a superblock copy on file systems 570 * where not all groups have one (sparse superblock feature) */ 571 int ext2_is_group_sparse(struct ext2_fs *fs, int group) 572 { 573 if (!fs->sparse) 574 return 1; 575 576 if (is_root(group, 3) || is_root(group, 5) || is_root(group, 7)) 577 return 1; 578 579 return 0; 580 } 581 582 void ext2_close(struct ext2_fs *fs) 583 { 584 ext2_commit_metadata(fs, EXT2_META_PRIMARY | EXT2_META_BACKUP); 585 ext2_sync(fs); 586 587 ext2_bcache_deinit(fs); 588 589 fs->devhandle->ops->close(fs->devhandle->cookie); 590 591 ped_free(fs->gd); 592 ped_free(fs); 593 } 594 595 int ext2_commit_metadata(struct ext2_fs *fs, int copies) 596 { 597 int i; 598 int num; 599 int wmeta = fs->metadirty & copies; 600 unsigned char* sb = ped_malloc(fs->blocksize); 601 struct ext2_super_block *sb_for_io; 602 int sb_block; 603 604 /* See if there is even anything to write... */ 605 if (wmeta == EXT2_META_CLEAN) 606 return 1; 607 608 fs->sb.s_r_blocks_count = PED_CPU_TO_LE32 ( 609 fs->r_frac * (loff_t)EXT2_SUPER_BLOCKS_COUNT(fs->sb) 610 / 100); 611 612 if (!ext2_read_blocks (fs, sb, 0, 1)) 613 return 0; 614 615 if (EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb)) { 616 memcpy(sb, &fs->sb, 1024); 617 sb_for_io = (struct ext2_super_block *) sb; 618 } else { 619 memcpy(sb+1024, &fs->sb, 1024); 620 sb_for_io = (struct ext2_super_block *) (sb + 1024); 621 } 622 623 num = copies & EXT2_META_BACKUP ? fs->numgroups : 1; 624 625 for (i = 0, sb_block = EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb); i < num; 626 i++, sb_block += EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb)) 627 { 628 629 if (!ext2_is_group_sparse(fs, i)) 630 continue; 631 632 if (fs->dynamic_version) 633 sb_for_io->s_block_group_nr = PED_CPU_TO_LE16 (i); 634 635 if ((i == 0 && wmeta & EXT2_META_PRIMARY_SB) || 636 (i != 0 && wmeta & EXT2_META_SB)) 637 { 638 if (!ext2_bcache_flush_range(fs, sb_block, 1)) 639 return 0; 640 if (!ext2_write_blocks(fs, sb, sb_block, 1)) 641 return 0; 642 } 643 if ((i == 0 && wmeta & EXT2_META_PRIMARY_GD) || 644 (i != 0 && wmeta & EXT2_META_GD)) 645 { 646 if (!ext2_bcache_flush_range(fs, sb_block + 1, 647 fs->gdblocks)) 648 return 0; 649 if (!ext2_write_blocks(fs, fs->gd, sb_block + 1, 650 fs->gdblocks)) 651 return 0; 652 } 653 } 654 655 sb_for_io->s_block_group_nr = 0; 656 657 /* Clear the flags of the components we just finished writing. */ 658 fs->metadirty &= ~copies; 659 660 return 1; 661 } 662 663 int ext2_sync(struct ext2_fs *fs) 664 { 665 if (!ext2_commit_metadata(fs, EXT2_META_PRIMARY)) return 0; 666 if (!ext2_bcache_sync(fs)) return 0; 667 if (!fs->devhandle->ops->sync(fs->devhandle->cookie)) return 0; 668 return 1; 669 } 670 671 struct ext2_fs *ext2_open(struct ext2_dev_handle *handle, int state) 672 { 673 struct ext2_fs *fs; 674 675 if ((fs = (struct ext2_fs *) ped_malloc(sizeof(struct ext2_fs))) 676 == NULL) 677 goto error; 678 679 handle->ops->set_blocksize(handle->cookie, 10); 680 681 if (!handle->ops->read(handle->cookie, &fs->sb, 1, 1) 682 || EXT2_SUPER_MAGIC(fs->sb) != EXT2_SUPER_MAGIC_CONST) 683 { 684 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, 685 _("Invalid superblock. Are you sure this is an ext2 " 686 "file system?")); 687 goto error_free_fs; 688 } 689 690 691 fs->opt_debug = 1; 692 fs->opt_safe = 1; 693 fs->opt_verbose = 0; 694 695 if (EXT2_SUPER_STATE(fs->sb) & EXT2_ERROR_FS & ~(state & EXT2_ERROR_FS)) 696 { 697 if (ped_exception_throw ( 698 PED_EXCEPTION_WARNING, PED_EXCEPTION_IGNORE_CANCEL, 699 _("File system has errors! You should run e2fsck.")) 700 == PED_EXCEPTION_CANCEL) 701 goto error_free_fs; 702 } 703 704 if (!((EXT2_SUPER_STATE(fs->sb) | state) & EXT2_VALID_FS) 705 || (EXT2_SUPER_FEATURE_INCOMPAT(fs->sb) 706 & EXT3_FEATURE_INCOMPAT_RECOVER)) 707 { 708 if (ped_exception_throw ( 709 PED_EXCEPTION_ERROR, PED_EXCEPTION_IGNORE_CANCEL, 710 _("File system was not cleanly unmounted! " 711 "You should run e2fsck. Modifying an unclean " 712 "file system could cause severe corruption.")) 713 != PED_EXCEPTION_IGNORE) 714 goto error_free_fs; 715 } 716 717 fs->dynamic_version = EXT2_SUPER_REV_LEVEL (fs->sb) > 0; 718 719 if ((EXT2_SUPER_FEATURE_COMPAT(fs->sb) 720 & ~(EXT3_FEATURE_COMPAT_HAS_JOURNAL | 721 EXT2_FEATURE_COMPAT_HAS_DIR_INDEX)) || 722 (EXT2_SUPER_FEATURE_INCOMPAT(fs->sb) 723 & ~(EXT2_FEATURE_INCOMPAT_FILETYPE | 724 EXT3_FEATURE_INCOMPAT_RECOVER)) || 725 (EXT2_SUPER_FEATURE_RO_COMPAT(fs->sb) 726 & ~(EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER | 727 EXT2_FEATURE_RO_COMPAT_LARGE_FILE))) 728 { 729 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, 730 _("File system has an incompatible feature enabled.")); 731 goto error_free_fs; 732 } 733 734 fs->devhandle = handle; 735 fs->logsize = EXT2_SUPER_LOG_BLOCK_SIZE(fs->sb) + 10; 736 handle->ops->set_blocksize(handle->cookie, fs->logsize); 737 738 if (!ext2_bcache_init(fs)) 739 { 740 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, 741 _("Error allocating buffer cache.")); 742 goto error_free_fs; 743 } 744 745 fs->blocksize = 1 << fs->logsize; 746 747 fs->numgroups = ped_div_round_up (EXT2_SUPER_BLOCKS_COUNT(fs->sb) 748 - EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb), 749 EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb)); 750 fs->gdblocks = ped_div_round_up (fs->numgroups 751 * sizeof(struct ext2_group_desc), 752 fs->blocksize); 753 fs->inodeblocks = ped_div_round_up (EXT2_SUPER_INODES_PER_GROUP(fs->sb) 754 * sizeof(struct ext2_inode), 755 fs->blocksize); 756 fs->r_frac = ped_div_round_up (100 * (loff_t)EXT2_SUPER_R_BLOCKS_COUNT(fs->sb), 757 EXT2_SUPER_BLOCKS_COUNT(fs->sb)); 758 fs->adminblocks = 3 + fs->gdblocks + fs->inodeblocks; 759 760 fs->sparse = 0; 761 if (EXT2_SUPER_FEATURE_RO_COMPAT(fs->sb) 762 & EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER) 763 fs->sparse = 1; 764 765 fs->has_journal = 0 < (EXT2_SUPER_FEATURE_COMPAT(fs->sb) 766 & EXT3_FEATURE_COMPAT_HAS_JOURNAL); 767 fs->has_internal_journal 768 = fs->has_journal 769 && uuid_is_null(EXT2_SUPER_JOURNAL_UUID(fs->sb)) 770 && EXT2_SUPER_JOURNAL_INUM(fs->sb); 771 772 fs->gd = ped_malloc (fs->numgroups * sizeof (struct ext2_group_desc) 773 + fs->blocksize); 774 if (!fs->gd) 775 goto error_deinit_bcache; 776 777 ext2_read_blocks(fs, fs->gd, EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb) + 1, 778 fs->gdblocks); 779 780 fs->metadirty = 0; 781 return fs; 782 783 ped_free(fs->gd); 784 error_deinit_bcache: 785 ext2_bcache_deinit(fs); 786 error_free_fs: 787 ped_free(fs); 788 error: 789 return NULL; 790 } 791 792 #endif /* !DISCOVER_ONLY */