inode.c revision 218a4864ec381655f4d5a64d264524c725ae4b70
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 Public 8 * License. 9 * %End-Header% 10 */ 11 12#include <stdio.h> 13#include <string.h> 14#if HAVE_UNISTD_H 15#include <unistd.h> 16#endif 17#if HAVE_SYS_STAT_H 18#include <sys/stat.h> 19#endif 20#if HAVE_SYS_TYPES_H 21#include <sys/types.h> 22#endif 23 24#if EXT2_FLAT_INCLUDES 25#include "ext2_fs.h" 26#else 27#include <linux/ext2_fs.h> 28#endif 29 30#include "ext2fsP.h" 31 32struct ext2_struct_inode_scan { 33 errcode_t magic; 34 ext2_filsys fs; 35 ino_t current_inode; 36 blk_t current_block; 37 dgrp_t current_group; 38 ino_t inodes_left; 39 blk_t blocks_left; 40 dgrp_t groups_left; 41 blk_t inode_buffer_blocks; 42 char * inode_buffer; 43 int inode_size; 44 char * ptr; 45 int bytes_left; 46 char *temp_buffer; 47 errcode_t (*done_group)(ext2_filsys fs, 48 ext2_inode_scan scan, 49 dgrp_t group, 50 void * priv_data); 51 void * done_group_data; 52 int bad_block_ptr; 53 int scan_flags; 54 int reserved[6]; 55}; 56 57static errcode_t create_icache(ext2_filsys fs) 58{ 59 errcode_t retval; 60 int i; 61 62 if (fs->icache) 63 return 0; 64 retval = ext2fs_get_mem(sizeof(struct ext2_inode_cache), 65 (void **) &fs->icache); 66 if (retval) 67 return retval; 68 69 memset(fs->icache, 0, sizeof(struct ext2_inode_cache)); 70 retval = ext2fs_get_mem(fs->blocksize, (void **) &fs->icache->buffer); 71 if (retval) { 72 ext2fs_free_mem((void **) &fs->icache); 73 return retval; 74 } 75 fs->icache->buffer_blk = 0; 76 fs->icache->cache_last = -1; 77 fs->icache->cache_size = 4; 78 fs->icache->refcount = 1; 79 retval = ext2fs_get_mem(sizeof(struct ext2_inode_cache_ent) 80 * fs->icache->cache_size, 81 (void **) &fs->icache->cache); 82 if (retval) { 83 ext2fs_free_mem((void **) &fs->icache->buffer); 84 ext2fs_free_mem((void **) &fs->icache); 85 return retval; 86 } 87 for (i=0; i < fs->icache->cache_size; i++) 88 fs->icache->cache[i].ino = 0; 89 return 0; 90} 91 92errcode_t ext2fs_open_inode_scan(ext2_filsys fs, int buffer_blocks, 93 ext2_inode_scan *ret_scan) 94{ 95 ext2_inode_scan scan; 96 errcode_t retval; 97 errcode_t (*save_get_blocks)(ext2_filsys f, ino_t ino, blk_t *blocks); 98 99 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); 100 101 /* 102 * If fs->badblocks isn't set, then set it --- since the inode 103 * scanning functions require it. 104 */ 105 if (fs->badblocks == 0) { 106 /* 107 * Temporarly save fs->get_blocks and set it to zero, 108 * for compatibility with old e2fsck's. 109 */ 110 save_get_blocks = fs->get_blocks; 111 fs->get_blocks = 0; 112 retval = ext2fs_read_bb_inode(fs, &fs->badblocks); 113 if (retval && fs->badblocks) { 114 badblocks_list_free(fs->badblocks); 115 fs->badblocks = 0; 116 } 117 fs->get_blocks = save_get_blocks; 118 } 119 120 retval = ext2fs_get_mem(sizeof(struct ext2_struct_inode_scan), 121 (void **) &scan); 122 if (retval) 123 return retval; 124 memset(scan, 0, sizeof(struct ext2_struct_inode_scan)); 125 126 scan->magic = EXT2_ET_MAGIC_INODE_SCAN; 127 scan->fs = fs; 128 scan->inode_size = EXT2_INODE_SIZE(fs->super); 129 scan->bytes_left = 0; 130 scan->current_group = 0; 131 scan->groups_left = fs->group_desc_count - 1; 132 scan->inode_buffer_blocks = buffer_blocks ? buffer_blocks : 8; 133 scan->current_block = scan->fs-> 134 group_desc[scan->current_group].bg_inode_table; 135 scan->inodes_left = EXT2_INODES_PER_GROUP(scan->fs->super); 136 scan->blocks_left = scan->fs->inode_blocks_per_group; 137 retval = ext2fs_get_mem((size_t) (scan->inode_buffer_blocks * 138 fs->blocksize), 139 (void **) &scan->inode_buffer); 140 scan->done_group = 0; 141 scan->done_group_data = 0; 142 scan->bad_block_ptr = 0; 143 if (retval) { 144 ext2fs_free_mem((void **) &scan); 145 return retval; 146 } 147 retval = ext2fs_get_mem(scan->inode_size, 148 (void **) &scan->temp_buffer); 149 if (retval) { 150 ext2fs_free_mem((void **) &scan->inode_buffer); 151 ext2fs_free_mem((void **) &scan); 152 return retval; 153 } 154 if (scan->fs->badblocks && scan->fs->badblocks->num) 155 scan->scan_flags |= EXT2_SF_CHK_BADBLOCKS; 156 *ret_scan = scan; 157 return 0; 158} 159 160void ext2fs_close_inode_scan(ext2_inode_scan scan) 161{ 162 if (!scan || (scan->magic != EXT2_ET_MAGIC_INODE_SCAN)) 163 return; 164 165 ext2fs_free_mem((void **) &scan->inode_buffer); 166 scan->inode_buffer = NULL; 167 ext2fs_free_mem((void **) &scan->temp_buffer); 168 scan->temp_buffer = NULL; 169 ext2fs_free_mem((void **) &scan); 170 return; 171} 172 173void ext2fs_set_inode_callback(ext2_inode_scan scan, 174 errcode_t (*done_group)(ext2_filsys fs, 175 ext2_inode_scan scan, 176 dgrp_t group, 177 void * priv_data), 178 void *done_group_data) 179{ 180 if (!scan || (scan->magic != EXT2_ET_MAGIC_INODE_SCAN)) 181 return; 182 183 scan->done_group = done_group; 184 scan->done_group_data = done_group_data; 185} 186 187int ext2fs_inode_scan_flags(ext2_inode_scan scan, int set_flags, 188 int clear_flags) 189{ 190 int old_flags; 191 192 if (!scan || (scan->magic != EXT2_ET_MAGIC_INODE_SCAN)) 193 return 0; 194 195 old_flags = scan->scan_flags; 196 scan->scan_flags &= ~clear_flags; 197 scan->scan_flags |= set_flags; 198 return old_flags; 199} 200 201/* 202 * This function is called by ext2fs_get_next_inode when it needs to 203 * get ready to read in a new blockgroup. 204 */ 205static errcode_t get_next_blockgroup(ext2_inode_scan scan) 206{ 207 scan->current_group++; 208 scan->groups_left--; 209 210 scan->current_block = scan->fs-> 211 group_desc[scan->current_group].bg_inode_table; 212 213 scan->bytes_left = 0; 214 scan->inodes_left = EXT2_INODES_PER_GROUP(scan->fs->super); 215 scan->blocks_left = scan->fs->inode_blocks_per_group; 216 return 0; 217} 218 219errcode_t ext2fs_inode_scan_goto_blockgroup(ext2_inode_scan scan, 220 int group) 221{ 222 scan->current_group = group - 1; 223 scan->groups_left = scan->fs->group_desc_count - group; 224 scan->current_inode = group * EXT2_INODES_PER_GROUP(scan->fs->super); 225 return get_next_blockgroup(scan); 226} 227 228/* 229 * This function is called by get_next_blocks() to check for bad 230 * blocks in the inode table. 231 * 232 * This function assumes that badblocks_list->list is sorted in 233 * increasing order. 234 */ 235static errcode_t check_for_inode_bad_blocks(ext2_inode_scan scan, 236 blk_t *num_blocks) 237{ 238 blk_t blk = scan->current_block; 239 badblocks_list bb = scan->fs->badblocks; 240 241 /* 242 * If the inode table is missing, then obviously there are no 243 * bad blocks. :-) 244 */ 245 if (blk == 0) 246 return 0; 247 248 /* 249 * If the current block is greater than the bad block listed 250 * in the bad block list, then advance the pointer until this 251 * is no longer the case. If we run out of bad blocks, then 252 * we don't need to do any more checking! 253 */ 254 while (blk > bb->list[scan->bad_block_ptr]) { 255 if (++scan->bad_block_ptr >= bb->num) { 256 scan->scan_flags &= ~EXT2_SF_CHK_BADBLOCKS; 257 return 0; 258 } 259 } 260 261 /* 262 * If the current block is equal to the bad block listed in 263 * the bad block list, then handle that one block specially. 264 * (We could try to handle runs of bad blocks, but that 265 * only increases CPU efficiency by a small amount, at the 266 * expense of a huge expense of code complexity, and for an 267 * uncommon case at that.) 268 */ 269 if (blk == bb->list[scan->bad_block_ptr]) { 270 scan->scan_flags |= EXT2_SF_BAD_INODE_BLK; 271 *num_blocks = 1; 272 if (++scan->bad_block_ptr >= bb->num) 273 scan->scan_flags &= ~EXT2_SF_CHK_BADBLOCKS; 274 return 0; 275 } 276 277 /* 278 * If there is a bad block in the range that we're about to 279 * read in, adjust the number of blocks to read so that we we 280 * don't read in the bad block. (Then the next block to read 281 * will be the bad block, which is handled in the above case.) 282 */ 283 if ((blk + *num_blocks) > bb->list[scan->bad_block_ptr]) 284 *num_blocks = (int) (bb->list[scan->bad_block_ptr] - blk); 285 286 return 0; 287} 288 289/* 290 * This function is called by ext2fs_get_next_inode when it needs to 291 * read in more blocks from the current blockgroup's inode table. 292 */ 293static errcode_t get_next_blocks(ext2_inode_scan scan) 294{ 295 blk_t num_blocks; 296 errcode_t retval; 297 298 /* 299 * Figure out how many blocks to read; we read at most 300 * inode_buffer_blocks, and perhaps less if there aren't that 301 * many blocks left to read. 302 */ 303 num_blocks = scan->inode_buffer_blocks; 304 if (num_blocks > scan->blocks_left) 305 num_blocks = scan->blocks_left; 306 307 /* 308 * If the past block "read" was a bad block, then mark the 309 * left-over extra bytes as also being bad. 310 */ 311 if (scan->scan_flags & EXT2_SF_BAD_INODE_BLK) { 312 if (scan->bytes_left) 313 scan->scan_flags |= EXT2_SF_BAD_EXTRA_BYTES; 314 scan->scan_flags &= ~EXT2_SF_BAD_INODE_BLK; 315 } 316 317 /* 318 * Do inode bad block processing, if necessary. 319 */ 320 if (scan->scan_flags & EXT2_SF_CHK_BADBLOCKS) { 321 retval = check_for_inode_bad_blocks(scan, &num_blocks); 322 if (retval) 323 return retval; 324 } 325 326 if ((scan->scan_flags & EXT2_SF_BAD_INODE_BLK) || 327 (scan->current_block == 0)) { 328 memset(scan->inode_buffer, 0, 329 (size_t) num_blocks * scan->fs->blocksize); 330 } else { 331 retval = io_channel_read_blk(scan->fs->io, 332 scan->current_block, 333 (int) num_blocks, 334 scan->inode_buffer); 335 if (retval) 336 return EXT2_ET_NEXT_INODE_READ; 337 } 338 scan->ptr = scan->inode_buffer; 339 scan->bytes_left = num_blocks * scan->fs->blocksize; 340 341 scan->blocks_left -= num_blocks; 342 if (scan->current_block) 343 scan->current_block += num_blocks; 344 return 0; 345} 346 347errcode_t ext2fs_get_next_inode(ext2_inode_scan scan, ino_t *ino, 348 struct ext2_inode *inode) 349{ 350 errcode_t retval; 351 int extra_bytes = 0; 352 353 EXT2_CHECK_MAGIC(scan, EXT2_ET_MAGIC_INODE_SCAN); 354 355 /* 356 * Do we need to start reading a new block group? 357 */ 358 if (scan->inodes_left <= 0) { 359 retry: 360 if (scan->done_group) { 361 retval = (scan->done_group) 362 (scan->fs, scan, scan->current_group, 363 scan->done_group_data); 364 if (retval) 365 return retval; 366 } 367 if (scan->groups_left <= 0) { 368 *ino = 0; 369 return 0; 370 } 371 retval = get_next_blockgroup(scan); 372 if (retval) 373 return retval; 374 } 375 /* 376 * This is done outside the above if statement so that the 377 * check can be done for block group #0. 378 */ 379 if (scan->current_block == 0) { 380 if (scan->scan_flags & EXT2_SF_SKIP_MISSING_ITABLE) { 381 goto retry; 382 } else 383 return EXT2_ET_MISSING_INODE_TABLE; 384 } 385 386 387 /* 388 * Have we run out of space in the inode buffer? If so, we 389 * need to read in more blocks. 390 */ 391 if (scan->bytes_left < scan->inode_size) { 392 memcpy(scan->temp_buffer, scan->ptr, scan->bytes_left); 393 extra_bytes = scan->bytes_left; 394 395 retval = get_next_blocks(scan); 396 if (retval) 397 return retval; 398 } 399 400 retval = 0; 401 if (extra_bytes) { 402 memcpy(scan->temp_buffer+extra_bytes, scan->ptr, 403 scan->inode_size - extra_bytes); 404 scan->ptr += scan->inode_size - extra_bytes; 405 scan->bytes_left -= scan->inode_size - extra_bytes; 406 407 if ((scan->fs->flags & EXT2_FLAG_SWAP_BYTES) || 408 (scan->fs->flags & EXT2_FLAG_SWAP_BYTES_READ)) 409 ext2fs_swap_inode(scan->fs, inode, 410 (struct ext2_inode *) scan->temp_buffer, 0); 411 else 412 *inode = *((struct ext2_inode *) scan->temp_buffer); 413 if (scan->scan_flags & EXT2_SF_BAD_EXTRA_BYTES) 414 retval = EXT2_ET_BAD_BLOCK_IN_INODE_TABLE; 415 scan->scan_flags &= ~EXT2_SF_BAD_EXTRA_BYTES; 416 } else { 417 if ((scan->fs->flags & EXT2_FLAG_SWAP_BYTES) || 418 (scan->fs->flags & EXT2_FLAG_SWAP_BYTES_READ)) 419 ext2fs_swap_inode(scan->fs, inode, 420 (struct ext2_inode *) scan->ptr, 0); 421 else 422 *inode = *((struct ext2_inode *) scan->ptr); 423 scan->ptr += scan->inode_size; 424 scan->bytes_left -= scan->inode_size; 425 if (scan->scan_flags & EXT2_SF_BAD_INODE_BLK) 426 retval = EXT2_ET_BAD_BLOCK_IN_INODE_TABLE; 427 } 428 429 scan->inodes_left--; 430 scan->current_inode++; 431 *ino = scan->current_inode; 432 return retval; 433} 434 435/* 436 * Functions to read and write a single inode. 437 */ 438errcode_t ext2fs_read_inode (ext2_filsys fs, ino_t ino, 439 struct ext2_inode * inode) 440{ 441 unsigned long group, block, block_nr, offset; 442 char *ptr; 443 errcode_t retval; 444 int clen, length, i; 445 446 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); 447 448 /* Check to see if user has an override function */ 449 if (fs->read_inode) { 450 retval = (fs->read_inode)(fs, ino, inode); 451 if (retval != EXT2_ET_CALLBACK_NOTHANDLED) 452 return retval; 453 } 454 /* Create inode cache if not present */ 455 if (!fs->icache) { 456 retval = create_icache(fs); 457 if (retval) 458 return retval; 459 } 460 /* Check to see if it's in the inode cache */ 461 for (i=0; i < fs->icache->cache_size; i++) { 462 if (fs->icache->cache[i].ino == ino) { 463 *inode = fs->icache->cache[i].inode; 464 return 0; 465 } 466 } 467 if (ino > fs->super->s_inodes_count) 468 return EXT2_ET_BAD_INODE_NUM; 469 group = (ino - 1) / EXT2_INODES_PER_GROUP(fs->super); 470 offset = ((ino - 1) % EXT2_INODES_PER_GROUP(fs->super)) * 471 EXT2_INODE_SIZE(fs->super); 472 block = offset >> EXT2_BLOCK_SIZE_BITS(fs->super); 473 if (!fs->group_desc[(unsigned)group].bg_inode_table) 474 return EXT2_ET_MISSING_INODE_TABLE; 475 block_nr = fs->group_desc[(unsigned)group].bg_inode_table + block; 476 if (block_nr != fs->icache->buffer_blk) { 477 retval = io_channel_read_blk(fs->io, block_nr, 1, 478 fs->icache->buffer); 479 if (retval) 480 return retval; 481 fs->icache->buffer_blk = block_nr; 482 } 483 offset &= (EXT2_BLOCK_SIZE(fs->super) - 1); 484 ptr = ((char *) fs->icache->buffer) + (unsigned) offset; 485 486 memset(inode, 0, sizeof(struct ext2_inode)); 487 length = EXT2_INODE_SIZE(fs->super); 488 if (length > sizeof(struct ext2_inode)) 489 length = sizeof(struct ext2_inode); 490 491 if ((offset + length) > EXT2_BLOCK_SIZE(fs->super)) { 492 clen = (int) (EXT2_BLOCK_SIZE(fs->super) - offset); 493 memcpy((char *) inode, ptr, clen); 494 length -= clen; 495 496 retval = io_channel_read_blk(fs->io, block_nr+1, 1, 497 fs->icache->buffer); 498 if (retval) { 499 fs->icache->buffer_blk = 0; 500 return retval; 501 } 502 fs->icache->buffer_blk = block_nr+1; 503 504 memcpy(((char *) inode) + clen, 505 fs->icache->buffer, length); 506 } else 507 memcpy((char *) inode, ptr, length); 508 509 if ((fs->flags & EXT2_FLAG_SWAP_BYTES) || 510 (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)) 511 ext2fs_swap_inode(fs, inode, inode, 0); 512 513 /* Update the inode cache */ 514 fs->icache->cache_last = (fs->icache->cache_last + 1) % 515 fs->icache->cache_size; 516 fs->icache->cache[fs->icache->cache_last].ino = ino; 517 fs->icache->cache[fs->icache->cache_last].inode = *inode; 518 519 return 0; 520} 521 522errcode_t ext2fs_write_inode(ext2_filsys fs, ino_t ino, 523 struct ext2_inode * inode) 524{ 525 unsigned long group, block, block_nr, offset; 526 errcode_t retval; 527 struct ext2_inode temp_inode; 528 char *ptr; 529 int clen, length, i; 530 531 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); 532 533 /* Check to see if user provided an override function */ 534 if (fs->write_inode) { 535 retval = (fs->write_inode)(fs, ino, inode); 536 if (retval != EXT2_ET_CALLBACK_NOTHANDLED) 537 return retval; 538 } 539 540 /* Check to see if the inode cache needs to be updated */ 541 if (fs->icache) { 542 for (i=0; i < fs->icache->cache_size; i++) { 543 if (fs->icache->cache[i].ino == ino) { 544 fs->icache->cache[i].inode = *inode; 545 break; 546 } 547 } 548 } else { 549 retval = create_icache(fs); 550 if (retval) 551 return retval; 552 } 553 554 if (!(fs->flags & EXT2_FLAG_RW)) 555 return EXT2_ET_RO_FILSYS; 556 557 if (ino > fs->super->s_inodes_count) 558 return EXT2_ET_BAD_INODE_NUM; 559 560 if ((fs->flags & EXT2_FLAG_SWAP_BYTES) || 561 (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)) 562 ext2fs_swap_inode(fs, &temp_inode, inode, 1); 563 else 564 memcpy(&temp_inode, inode, sizeof(struct ext2_inode)); 565 566 group = (ino - 1) / EXT2_INODES_PER_GROUP(fs->super); 567 offset = ((ino - 1) % EXT2_INODES_PER_GROUP(fs->super)) * 568 EXT2_INODE_SIZE(fs->super); 569 block = offset >> EXT2_BLOCK_SIZE_BITS(fs->super); 570 if (!fs->group_desc[(unsigned) group].bg_inode_table) 571 return EXT2_ET_MISSING_INODE_TABLE; 572 block_nr = fs->group_desc[(unsigned) group].bg_inode_table + block; 573 offset &= (EXT2_BLOCK_SIZE(fs->super) - 1); 574 ptr = (char *) fs->icache->buffer + (unsigned) offset; 575 576 length = EXT2_INODE_SIZE(fs->super); 577 clen = length; 578 if (length > sizeof(struct ext2_inode)) 579 length = sizeof(struct ext2_inode); 580 581 if (fs->icache->buffer_blk != block_nr) { 582 retval = io_channel_read_blk(fs->io, block_nr, 1, 583 fs->icache->buffer); 584 if (retval) 585 return retval; 586 fs->icache->buffer_blk = block_nr; 587 } 588 589 if ((offset + length) > EXT2_BLOCK_SIZE(fs->super)) { 590 clen = (int) (EXT2_BLOCK_SIZE(fs->super) - offset); 591 length -= clen; 592 } else { 593 length = 0; 594 } 595 memcpy(ptr, &temp_inode, clen); 596 retval = io_channel_write_blk(fs->io, block_nr, 1, fs->icache->buffer); 597 if (retval) 598 return retval; 599 600 if (length) { 601 retval = io_channel_read_blk(fs->io, ++block_nr, 1, 602 fs->icache->buffer); 603 if (retval) { 604 fs->icache->buffer_blk = 0; 605 return retval; 606 } 607 fs->icache->buffer_blk = block_nr; 608 memcpy(fs->icache->buffer, ((char *) &temp_inode) + clen, 609 length); 610 611 retval = io_channel_write_blk(fs->io, block_nr, 1, 612 fs->icache->buffer); 613 if (retval) 614 return retval; 615 } 616 617 fs->flags |= EXT2_FLAG_CHANGED; 618 return 0; 619} 620 621errcode_t ext2fs_get_blocks(ext2_filsys fs, ino_t ino, blk_t *blocks) 622{ 623 struct ext2_inode inode; 624 int i; 625 errcode_t retval; 626 627 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); 628 629 if (ino > fs->super->s_inodes_count) 630 return EXT2_ET_BAD_INODE_NUM; 631 632 if (fs->get_blocks) { 633 if (!(*fs->get_blocks)(fs, ino, blocks)) 634 return 0; 635 } 636 retval = ext2fs_read_inode(fs, ino, &inode); 637 if (retval) 638 return retval; 639 for (i=0; i < EXT2_N_BLOCKS; i++) 640 blocks[i] = inode.i_block[i]; 641 return 0; 642} 643 644errcode_t ext2fs_check_directory(ext2_filsys fs, ino_t ino) 645{ 646 struct ext2_inode inode; 647 errcode_t retval; 648 649 EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); 650 651 if (ino > fs->super->s_inodes_count) 652 return EXT2_ET_BAD_INODE_NUM; 653 654 if (fs->check_directory) { 655 retval = (fs->check_directory)(fs, ino); 656 if (retval != EXT2_ET_CALLBACK_NOTHANDLED) 657 return retval; 658 } 659 retval = ext2fs_read_inode(fs, ino, &inode); 660 if (retval) 661 return retval; 662 if (!LINUX_S_ISDIR(inode.i_mode)) 663 return EXT2_ET_NO_DIRECTORY; 664 return 0; 665} 666 667