inode.c revision d1154eb460efe588eaed3d439c1caaca149fa362
1/* 2 * inode.c --- utility routines to read and write inodes 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 Library 8 * General Public License, version 2. 9 * %End-Header% 10 */ 11 12#include "config.h" 13#include <stdio.h> 14#include <string.h> 15#if HAVE_UNISTD_H 16#include <unistd.h> 17#endif 18#if HAVE_ERRNO_H 19#include <errno.h> 20#endif 21#include <time.h> 22#if HAVE_SYS_STAT_H 23#include <sys/stat.h> 24#endif 25#if HAVE_SYS_TYPES_H 26#include <sys/types.h> 27#endif 28 29#include "ext2_fs.h" 30#include "ext2fsP.h" 31#include "e2image.h" 32 33struct ext2_struct_inode_scan { 34 errcode_t magic; 35 ext2_filsys fs; 36 ext2_ino_t current_inode; 37 blk64_t current_block; 38 dgrp_t current_group; 39 ext2_ino_t inodes_left; 40 blk_t blocks_left; 41 dgrp_t groups_left; 42 blk_t inode_buffer_blocks; 43 char * inode_buffer; 44 int inode_size; 45 char * ptr; 46 int bytes_left; 47 char *temp_buffer; 48 errcode_t (*done_group)(ext2_filsys fs, 49 ext2_inode_scan scan, 50 dgrp_t group, 51 void * priv_data); 52 void * done_group_data; 53 int bad_block_ptr; 54 int scan_flags; 55 int reserved[6]; 56}; 57 58/* 59 * This routine flushes the icache, if it exists. 60 */ 61errcode_t ext2fs_flush_icache(ext2_filsys fs) 62{ 63 int i; 64 65 if (!fs->icache) 66 return 0; 67 68 for (i=0; i < fs->icache->cache_size; i++) 69 fs->icache->cache[i].ino = 0; 70 71 fs->icache->buffer_blk = 0; 72 return 0; 73} 74 75static errcode_t create_icache(ext2_filsys fs) 76{ 77 errcode_t retval; 78 79 if (fs->icache) 80 return 0; 81 retval = ext2fs_get_mem(sizeof(struct ext2_inode_cache), &fs->icache); 82 if (retval) 83 return retval; 84 85 memset(fs->icache, 0, sizeof(struct ext2_inode_cache)); 86 retval = ext2fs_get_mem(fs->blocksize, &fs->icache->buffer); 87 if (retval) { 88 ext2fs_free_mem(&fs->icache); 89 return retval; 90 } 91 fs->icache->buffer_blk = 0; 92 fs->icache->cache_last = -1; 93 fs->icache->cache_size = 4; 94 fs->icache->refcount = 1; 95 retval = ext2fs_get_array(fs->icache->cache_size, 96 sizeof(struct ext2_inode_cache_ent), 97 &fs->icache->cache); 98 if (retval) { 99 ext2fs_free_mem(&fs->icache->buffer); 100 ext2fs_free_mem(&fs->icache); 101 return retval; 102 } 103 ext2fs_flush_icache(fs); 104 return 0; 105} 106 107errcode_t ext2fs_open_inode_scan(ext2_filsys fs, int buffer_blocks, 108 ext2_inode_scan *ret_scan) 109{ 110 ext2_inode_scan scan; 111 errcode_t retval; 112 errcode_t (*save_get_blocks)(ext2_filsys f, ext2_ino_t ino, blk_t *blocks); 113 114 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); 115 116 /* 117 * If fs->badblocks isn't set, then set it --- since the inode 118 * scanning functions require it. 119 */ 120 if (fs->badblocks == 0) { 121 /* 122 * Temporarly save fs->get_blocks and set it to zero, 123 * for compatibility with old e2fsck's. 124 */ 125 save_get_blocks = fs->get_blocks; 126 fs->get_blocks = 0; 127 retval = ext2fs_read_bb_inode(fs, &fs->badblocks); 128 if (retval && fs->badblocks) { 129 ext2fs_badblocks_list_free(fs->badblocks); 130 fs->badblocks = 0; 131 } 132 fs->get_blocks = save_get_blocks; 133 } 134 135 retval = ext2fs_get_mem(sizeof(struct ext2_struct_inode_scan), &scan); 136 if (retval) 137 return retval; 138 memset(scan, 0, sizeof(struct ext2_struct_inode_scan)); 139 140 scan->magic = EXT2_ET_MAGIC_INODE_SCAN; 141 scan->fs = fs; 142 scan->inode_size = EXT2_INODE_SIZE(fs->super); 143 scan->bytes_left = 0; 144 scan->current_group = 0; 145 scan->groups_left = fs->group_desc_count - 1; 146 scan->inode_buffer_blocks = buffer_blocks ? buffer_blocks : 8; 147 scan->current_block = ext2fs_inode_table_loc(scan->fs, 148 scan->current_group); 149 scan->inodes_left = EXT2_INODES_PER_GROUP(scan->fs->super); 150 scan->blocks_left = scan->fs->inode_blocks_per_group; 151 if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super, 152 EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) { 153 scan->inodes_left -= 154 ext2fs_bg_itable_unused(fs, scan->current_group); 155 scan->blocks_left = 156 (scan->inodes_left + 157 (fs->blocksize / scan->inode_size - 1)) * 158 scan->inode_size / fs->blocksize; 159 } 160 retval = ext2fs_get_memalign(scan->inode_buffer_blocks * fs->blocksize, 161 fs->blocksize, &scan->inode_buffer); 162 scan->done_group = 0; 163 scan->done_group_data = 0; 164 scan->bad_block_ptr = 0; 165 if (retval) { 166 ext2fs_free_mem(&scan); 167 return retval; 168 } 169 retval = ext2fs_get_mem(scan->inode_size, &scan->temp_buffer); 170 if (retval) { 171 ext2fs_free_mem(&scan->inode_buffer); 172 ext2fs_free_mem(&scan); 173 return retval; 174 } 175 if (scan->fs->badblocks && scan->fs->badblocks->num) 176 scan->scan_flags |= EXT2_SF_CHK_BADBLOCKS; 177 if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super, 178 EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) 179 scan->scan_flags |= EXT2_SF_DO_LAZY; 180 *ret_scan = scan; 181 return 0; 182} 183 184void ext2fs_close_inode_scan(ext2_inode_scan scan) 185{ 186 if (!scan || (scan->magic != EXT2_ET_MAGIC_INODE_SCAN)) 187 return; 188 189 ext2fs_free_mem(&scan->inode_buffer); 190 scan->inode_buffer = NULL; 191 ext2fs_free_mem(&scan->temp_buffer); 192 scan->temp_buffer = NULL; 193 ext2fs_free_mem(&scan); 194 return; 195} 196 197void ext2fs_set_inode_callback(ext2_inode_scan scan, 198 errcode_t (*done_group)(ext2_filsys fs, 199 ext2_inode_scan scan, 200 dgrp_t group, 201 void * priv_data), 202 void *done_group_data) 203{ 204 if (!scan || (scan->magic != EXT2_ET_MAGIC_INODE_SCAN)) 205 return; 206 207 scan->done_group = done_group; 208 scan->done_group_data = done_group_data; 209} 210 211int ext2fs_inode_scan_flags(ext2_inode_scan scan, int set_flags, 212 int clear_flags) 213{ 214 int old_flags; 215 216 if (!scan || (scan->magic != EXT2_ET_MAGIC_INODE_SCAN)) 217 return 0; 218 219 old_flags = scan->scan_flags; 220 scan->scan_flags &= ~clear_flags; 221 scan->scan_flags |= set_flags; 222 return old_flags; 223} 224 225/* 226 * This function is called by ext2fs_get_next_inode when it needs to 227 * get ready to read in a new blockgroup. 228 */ 229static errcode_t get_next_blockgroup(ext2_inode_scan scan) 230{ 231 ext2_filsys fs = scan->fs; 232 233 scan->current_group++; 234 scan->groups_left--; 235 236 scan->current_block = ext2fs_inode_table_loc(scan->fs, 237 scan->current_group); 238 scan->current_inode = scan->current_group * 239 EXT2_INODES_PER_GROUP(fs->super); 240 241 scan->bytes_left = 0; 242 scan->inodes_left = EXT2_INODES_PER_GROUP(fs->super); 243 scan->blocks_left = fs->inode_blocks_per_group; 244 if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super, 245 EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) { 246 scan->inodes_left -= 247 ext2fs_bg_itable_unused(fs, scan->current_group); 248 scan->blocks_left = 249 (scan->inodes_left + 250 (fs->blocksize / scan->inode_size - 1)) * 251 scan->inode_size / fs->blocksize; 252 } 253 254 return 0; 255} 256 257errcode_t ext2fs_inode_scan_goto_blockgroup(ext2_inode_scan scan, 258 int group) 259{ 260 scan->current_group = group - 1; 261 scan->groups_left = scan->fs->group_desc_count - group; 262 return get_next_blockgroup(scan); 263} 264 265/* 266 * This function is called by get_next_blocks() to check for bad 267 * blocks in the inode table. 268 * 269 * This function assumes that badblocks_list->list is sorted in 270 * increasing order. 271 */ 272static errcode_t check_for_inode_bad_blocks(ext2_inode_scan scan, 273 blk_t *num_blocks) 274{ 275 blk_t blk = scan->current_block; 276 badblocks_list bb = scan->fs->badblocks; 277 278 /* 279 * If the inode table is missing, then obviously there are no 280 * bad blocks. :-) 281 */ 282 if (blk == 0) 283 return 0; 284 285 /* 286 * If the current block is greater than the bad block listed 287 * in the bad block list, then advance the pointer until this 288 * is no longer the case. If we run out of bad blocks, then 289 * we don't need to do any more checking! 290 */ 291 while (blk > bb->list[scan->bad_block_ptr]) { 292 if (++scan->bad_block_ptr >= bb->num) { 293 scan->scan_flags &= ~EXT2_SF_CHK_BADBLOCKS; 294 return 0; 295 } 296 } 297 298 /* 299 * If the current block is equal to the bad block listed in 300 * the bad block list, then handle that one block specially. 301 * (We could try to handle runs of bad blocks, but that 302 * only increases CPU efficiency by a small amount, at the 303 * expense of a huge expense of code complexity, and for an 304 * uncommon case at that.) 305 */ 306 if (blk == bb->list[scan->bad_block_ptr]) { 307 scan->scan_flags |= EXT2_SF_BAD_INODE_BLK; 308 *num_blocks = 1; 309 if (++scan->bad_block_ptr >= bb->num) 310 scan->scan_flags &= ~EXT2_SF_CHK_BADBLOCKS; 311 return 0; 312 } 313 314 /* 315 * If there is a bad block in the range that we're about to 316 * read in, adjust the number of blocks to read so that we we 317 * don't read in the bad block. (Then the next block to read 318 * will be the bad block, which is handled in the above case.) 319 */ 320 if ((blk + *num_blocks) > bb->list[scan->bad_block_ptr]) 321 *num_blocks = (int) (bb->list[scan->bad_block_ptr] - blk); 322 323 return 0; 324} 325 326/* 327 * This function is called by ext2fs_get_next_inode when it needs to 328 * read in more blocks from the current blockgroup's inode table. 329 */ 330static errcode_t get_next_blocks(ext2_inode_scan scan) 331{ 332 blk_t num_blocks; 333 errcode_t retval; 334 335 /* 336 * Figure out how many blocks to read; we read at most 337 * inode_buffer_blocks, and perhaps less if there aren't that 338 * many blocks left to read. 339 */ 340 num_blocks = scan->inode_buffer_blocks; 341 if (num_blocks > scan->blocks_left) 342 num_blocks = scan->blocks_left; 343 344 /* 345 * If the past block "read" was a bad block, then mark the 346 * left-over extra bytes as also being bad. 347 */ 348 if (scan->scan_flags & EXT2_SF_BAD_INODE_BLK) { 349 if (scan->bytes_left) 350 scan->scan_flags |= EXT2_SF_BAD_EXTRA_BYTES; 351 scan->scan_flags &= ~EXT2_SF_BAD_INODE_BLK; 352 } 353 354 /* 355 * Do inode bad block processing, if necessary. 356 */ 357 if (scan->scan_flags & EXT2_SF_CHK_BADBLOCKS) { 358 retval = check_for_inode_bad_blocks(scan, &num_blocks); 359 if (retval) 360 return retval; 361 } 362 363 if ((scan->scan_flags & EXT2_SF_BAD_INODE_BLK) || 364 (scan->current_block == 0)) { 365 memset(scan->inode_buffer, 0, 366 (size_t) num_blocks * scan->fs->blocksize); 367 } else { 368 retval = io_channel_read_blk64(scan->fs->io, 369 scan->current_block, 370 (int) num_blocks, 371 scan->inode_buffer); 372 if (retval) 373 return EXT2_ET_NEXT_INODE_READ; 374 } 375 scan->ptr = scan->inode_buffer; 376 scan->bytes_left = num_blocks * scan->fs->blocksize; 377 378 scan->blocks_left -= num_blocks; 379 if (scan->current_block) 380 scan->current_block += num_blocks; 381 return 0; 382} 383 384#if 0 385/* 386 * Returns 1 if the entire inode_buffer has a non-zero size and 387 * contains all zeros. (Not just deleted inodes, since that means 388 * that part of the inode table was used at one point; we want all 389 * zeros, which means that the inode table is pristine.) 390 */ 391static inline int is_empty_scan(ext2_inode_scan scan) 392{ 393 int i; 394 395 if (scan->bytes_left == 0) 396 return 0; 397 398 for (i=0; i < scan->bytes_left; i++) 399 if (scan->ptr[i]) 400 return 0; 401 return 1; 402} 403#endif 404 405errcode_t ext2fs_get_next_inode_full(ext2_inode_scan scan, ext2_ino_t *ino, 406 struct ext2_inode *inode, int bufsize) 407{ 408 errcode_t retval; 409 int extra_bytes = 0; 410 411 EXT2_CHECK_MAGIC(scan, EXT2_ET_MAGIC_INODE_SCAN); 412 413 /* 414 * Do we need to start reading a new block group? 415 */ 416 if (scan->inodes_left <= 0) { 417 force_new_group: 418 if (scan->done_group) { 419 retval = (scan->done_group) 420 (scan->fs, scan, scan->current_group, 421 scan->done_group_data); 422 if (retval) 423 return retval; 424 } 425 if (scan->groups_left <= 0) { 426 *ino = 0; 427 return 0; 428 } 429 retval = get_next_blockgroup(scan); 430 if (retval) 431 return retval; 432 } 433 /* 434 * These checks are done outside the above if statement so 435 * they can be done for block group #0. 436 */ 437 if ((scan->scan_flags & EXT2_SF_DO_LAZY) && 438 (ext2fs_bg_flags_test(scan->fs, scan->current_group, EXT2_BG_INODE_UNINIT) 439 )) 440 goto force_new_group; 441 if (scan->inodes_left == 0) 442 goto force_new_group; 443 if (scan->current_block == 0) { 444 if (scan->scan_flags & EXT2_SF_SKIP_MISSING_ITABLE) { 445 goto force_new_group; 446 } else 447 return EXT2_ET_MISSING_INODE_TABLE; 448 } 449 450 451 /* 452 * Have we run out of space in the inode buffer? If so, we 453 * need to read in more blocks. 454 */ 455 if (scan->bytes_left < scan->inode_size) { 456 memcpy(scan->temp_buffer, scan->ptr, scan->bytes_left); 457 extra_bytes = scan->bytes_left; 458 459 retval = get_next_blocks(scan); 460 if (retval) 461 return retval; 462#if 0 463 /* 464 * XXX test Need check for used inode somehow. 465 * (Note: this is hard.) 466 */ 467 if (is_empty_scan(scan)) 468 goto force_new_group; 469#endif 470 } 471 472 retval = 0; 473 if (extra_bytes) { 474 memcpy(scan->temp_buffer+extra_bytes, scan->ptr, 475 scan->inode_size - extra_bytes); 476 scan->ptr += scan->inode_size - extra_bytes; 477 scan->bytes_left -= scan->inode_size - extra_bytes; 478 479#ifdef WORDS_BIGENDIAN 480 memset(inode, 0, bufsize); 481 ext2fs_swap_inode_full(scan->fs, 482 (struct ext2_inode_large *) inode, 483 (struct ext2_inode_large *) scan->temp_buffer, 484 0, bufsize); 485#else 486 *inode = *((struct ext2_inode *) scan->temp_buffer); 487#endif 488 if (scan->scan_flags & EXT2_SF_BAD_EXTRA_BYTES) 489 retval = EXT2_ET_BAD_BLOCK_IN_INODE_TABLE; 490 scan->scan_flags &= ~EXT2_SF_BAD_EXTRA_BYTES; 491 } else { 492#ifdef WORDS_BIGENDIAN 493 memset(inode, 0, bufsize); 494 ext2fs_swap_inode_full(scan->fs, 495 (struct ext2_inode_large *) inode, 496 (struct ext2_inode_large *) scan->ptr, 497 0, bufsize); 498#else 499 memcpy(inode, scan->ptr, bufsize); 500#endif 501 scan->ptr += scan->inode_size; 502 scan->bytes_left -= scan->inode_size; 503 if (scan->scan_flags & EXT2_SF_BAD_INODE_BLK) 504 retval = EXT2_ET_BAD_BLOCK_IN_INODE_TABLE; 505 } 506 507 scan->inodes_left--; 508 scan->current_inode++; 509 *ino = scan->current_inode; 510 return retval; 511} 512 513errcode_t ext2fs_get_next_inode(ext2_inode_scan scan, ext2_ino_t *ino, 514 struct ext2_inode *inode) 515{ 516 return ext2fs_get_next_inode_full(scan, ino, inode, 517 sizeof(struct ext2_inode)); 518} 519 520/* 521 * Functions to read and write a single inode. 522 */ 523errcode_t ext2fs_read_inode_full(ext2_filsys fs, ext2_ino_t ino, 524 struct ext2_inode * inode, int bufsize) 525{ 526 blk64_t block_nr; 527 unsigned long group, block, offset; 528 char *ptr; 529 errcode_t retval; 530 int clen, i, inodes_per_block, length; 531 io_channel io; 532 533 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); 534 535 /* Check to see if user has an override function */ 536 if (fs->read_inode) { 537 retval = (fs->read_inode)(fs, ino, inode); 538 if (retval != EXT2_ET_CALLBACK_NOTHANDLED) 539 return retval; 540 } 541 if ((ino == 0) || (ino > fs->super->s_inodes_count)) 542 return EXT2_ET_BAD_INODE_NUM; 543 /* Create inode cache if not present */ 544 if (!fs->icache) { 545 retval = create_icache(fs); 546 if (retval) 547 return retval; 548 } 549 /* Check to see if it's in the inode cache */ 550 if (bufsize == sizeof(struct ext2_inode)) { 551 /* only old good inode can be retrieved from the cache */ 552 for (i=0; i < fs->icache->cache_size; i++) { 553 if (fs->icache->cache[i].ino == ino) { 554 *inode = fs->icache->cache[i].inode; 555 return 0; 556 } 557 } 558 } 559 if (fs->flags & EXT2_FLAG_IMAGE_FILE) { 560 inodes_per_block = fs->blocksize / EXT2_INODE_SIZE(fs->super); 561 block_nr = fs->image_header->offset_inode / fs->blocksize; 562 block_nr += (ino - 1) / inodes_per_block; 563 offset = ((ino - 1) % inodes_per_block) * 564 EXT2_INODE_SIZE(fs->super); 565 io = fs->image_io; 566 } else { 567 group = (ino - 1) / EXT2_INODES_PER_GROUP(fs->super); 568 if (group > fs->group_desc_count) 569 return EXT2_ET_BAD_INODE_NUM; 570 offset = ((ino - 1) % EXT2_INODES_PER_GROUP(fs->super)) * 571 EXT2_INODE_SIZE(fs->super); 572 block = offset >> EXT2_BLOCK_SIZE_BITS(fs->super); 573 if (!ext2fs_inode_table_loc(fs, (unsigned) group)) 574 return EXT2_ET_MISSING_INODE_TABLE; 575 block_nr = ext2fs_inode_table_loc(fs, group) + 576 block; 577 io = fs->io; 578 } 579 offset &= (EXT2_BLOCK_SIZE(fs->super) - 1); 580 581 length = EXT2_INODE_SIZE(fs->super); 582 if (bufsize < length) 583 length = bufsize; 584 585 ptr = (char *) inode; 586 while (length) { 587 clen = length; 588 if ((offset + length) > fs->blocksize) 589 clen = fs->blocksize - offset; 590 591 if (block_nr != fs->icache->buffer_blk) { 592 retval = io_channel_read_blk64(io, block_nr, 1, 593 fs->icache->buffer); 594 if (retval) 595 return retval; 596 fs->icache->buffer_blk = block_nr; 597 } 598 599 memcpy(ptr, ((char *) fs->icache->buffer) + (unsigned) offset, 600 clen); 601 602 offset = 0; 603 length -= clen; 604 ptr += clen; 605 block_nr++; 606 } 607 608#ifdef WORDS_BIGENDIAN 609 ext2fs_swap_inode_full(fs, (struct ext2_inode_large *) inode, 610 (struct ext2_inode_large *) inode, 611 0, bufsize); 612#endif 613 614 /* Update the inode cache */ 615 fs->icache->cache_last = (fs->icache->cache_last + 1) % 616 fs->icache->cache_size; 617 fs->icache->cache[fs->icache->cache_last].ino = ino; 618 fs->icache->cache[fs->icache->cache_last].inode = *inode; 619 620 return 0; 621} 622 623errcode_t ext2fs_read_inode(ext2_filsys fs, ext2_ino_t ino, 624 struct ext2_inode * inode) 625{ 626 return ext2fs_read_inode_full(fs, ino, inode, 627 sizeof(struct ext2_inode)); 628} 629 630errcode_t ext2fs_write_inode_full(ext2_filsys fs, ext2_ino_t ino, 631 struct ext2_inode * inode, int bufsize) 632{ 633 blk64_t block_nr; 634 unsigned long group, block, offset; 635 errcode_t retval = 0; 636 struct ext2_inode_large temp_inode, *w_inode; 637 char *ptr; 638 int clen, i, length; 639 640 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); 641 642 /* Check to see if user provided an override function */ 643 if (fs->write_inode) { 644 retval = (fs->write_inode)(fs, ino, inode); 645 if (retval != EXT2_ET_CALLBACK_NOTHANDLED) 646 return retval; 647 } 648 649 /* Check to see if the inode cache needs to be updated */ 650 if (fs->icache) { 651 for (i=0; i < fs->icache->cache_size; i++) { 652 if (fs->icache->cache[i].ino == ino) { 653 fs->icache->cache[i].inode = *inode; 654 break; 655 } 656 } 657 } else { 658 retval = create_icache(fs); 659 if (retval) 660 return retval; 661 } 662 663 if (!(fs->flags & EXT2_FLAG_RW)) 664 return EXT2_ET_RO_FILSYS; 665 666 if ((ino == 0) || (ino > fs->super->s_inodes_count)) 667 return EXT2_ET_BAD_INODE_NUM; 668 669 length = bufsize; 670 if (length < EXT2_INODE_SIZE(fs->super)) 671 length = EXT2_INODE_SIZE(fs->super); 672 673 if (length > (int) sizeof(struct ext2_inode_large)) { 674 w_inode = malloc(length); 675 if (!w_inode) { 676 retval = ENOMEM; 677 goto errout; 678 } 679 } else 680 w_inode = &temp_inode; 681 memset(w_inode, 0, length); 682 683#ifdef WORDS_BIGENDIAN 684 ext2fs_swap_inode_full(fs, w_inode, 685 (struct ext2_inode_large *) inode, 686 1, bufsize); 687#else 688 memcpy(w_inode, inode, bufsize); 689#endif 690 691 group = (ino - 1) / EXT2_INODES_PER_GROUP(fs->super); 692 offset = ((ino - 1) % EXT2_INODES_PER_GROUP(fs->super)) * 693 EXT2_INODE_SIZE(fs->super); 694 block = offset >> EXT2_BLOCK_SIZE_BITS(fs->super); 695 if (!ext2fs_inode_table_loc(fs, (unsigned) group)) { 696 retval = EXT2_ET_MISSING_INODE_TABLE; 697 goto errout; 698 } 699 block_nr = ext2fs_inode_table_loc(fs, (unsigned) group) + block; 700 701 offset &= (EXT2_BLOCK_SIZE(fs->super) - 1); 702 703 length = EXT2_INODE_SIZE(fs->super); 704 if (length > bufsize) 705 length = bufsize; 706 707 ptr = (char *) w_inode; 708 709 while (length) { 710 clen = length; 711 if ((offset + length) > fs->blocksize) 712 clen = fs->blocksize - offset; 713 714 if (fs->icache->buffer_blk != block_nr) { 715 retval = io_channel_read_blk64(fs->io, block_nr, 1, 716 fs->icache->buffer); 717 if (retval) 718 goto errout; 719 fs->icache->buffer_blk = block_nr; 720 } 721 722 723 memcpy((char *) fs->icache->buffer + (unsigned) offset, 724 ptr, clen); 725 726 retval = io_channel_write_blk64(fs->io, block_nr, 1, 727 fs->icache->buffer); 728 if (retval) 729 goto errout; 730 731 offset = 0; 732 ptr += clen; 733 length -= clen; 734 block_nr++; 735 } 736 737 fs->flags |= EXT2_FLAG_CHANGED; 738errout: 739 if (w_inode && w_inode != &temp_inode) 740 free(w_inode); 741 return retval; 742} 743 744errcode_t ext2fs_write_inode(ext2_filsys fs, ext2_ino_t ino, 745 struct ext2_inode *inode) 746{ 747 return ext2fs_write_inode_full(fs, ino, inode, 748 sizeof(struct ext2_inode)); 749} 750 751/* 752 * This function should be called when writing a new inode. It makes 753 * sure that extra part of large inodes is initialized properly. 754 */ 755errcode_t ext2fs_write_new_inode(ext2_filsys fs, ext2_ino_t ino, 756 struct ext2_inode *inode) 757{ 758 struct ext2_inode *buf; 759 int size = EXT2_INODE_SIZE(fs->super); 760 struct ext2_inode_large *large_inode; 761 errcode_t retval; 762 __u32 t = fs->now ? fs->now : time(NULL); 763 764 if (!inode->i_ctime) 765 inode->i_ctime = t; 766 if (!inode->i_mtime) 767 inode->i_mtime = t; 768 if (!inode->i_atime) 769 inode->i_atime = t; 770 771 if (size == sizeof(struct ext2_inode)) 772 return ext2fs_write_inode_full(fs, ino, inode, 773 sizeof(struct ext2_inode)); 774 775 buf = malloc(size); 776 if (!buf) 777 return ENOMEM; 778 779 memset(buf, 0, size); 780 *buf = *inode; 781 782 large_inode = (struct ext2_inode_large *) buf; 783 large_inode->i_extra_isize = sizeof(struct ext2_inode_large) - 784 EXT2_GOOD_OLD_INODE_SIZE; 785 if (!large_inode->i_crtime) 786 large_inode->i_crtime = t; 787 788 retval = ext2fs_write_inode_full(fs, ino, buf, size); 789 free(buf); 790 return retval; 791} 792 793 794errcode_t ext2fs_get_blocks(ext2_filsys fs, ext2_ino_t ino, blk_t *blocks) 795{ 796 struct ext2_inode inode; 797 int i; 798 errcode_t retval; 799 800 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); 801 802 if (ino > fs->super->s_inodes_count) 803 return EXT2_ET_BAD_INODE_NUM; 804 805 if (fs->get_blocks) { 806 if (!(*fs->get_blocks)(fs, ino, blocks)) 807 return 0; 808 } 809 retval = ext2fs_read_inode(fs, ino, &inode); 810 if (retval) 811 return retval; 812 for (i=0; i < EXT2_N_BLOCKS; i++) 813 blocks[i] = inode.i_block[i]; 814 return 0; 815} 816 817errcode_t ext2fs_check_directory(ext2_filsys fs, ext2_ino_t ino) 818{ 819 struct ext2_inode inode; 820 errcode_t retval; 821 822 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); 823 824 if (ino > fs->super->s_inodes_count) 825 return EXT2_ET_BAD_INODE_NUM; 826 827 if (fs->check_directory) { 828 retval = (fs->check_directory)(fs, ino); 829 if (retval != EXT2_ET_CALLBACK_NOTHANDLED) 830 return retval; 831 } 832 retval = ext2fs_read_inode(fs, ino, &inode); 833 if (retval) 834 return retval; 835 if (!LINUX_S_ISDIR(inode.i_mode)) 836 return EXT2_ET_NO_DIRECTORY; 837 return 0; 838} 839 840