119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/* 219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * inode.c --- utility routines to read and write inodes 33984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * 419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o. 519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * 619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * %Begin-Header% 78558eab78390d1924cd6b255686ceef133f294d5Ken Sumrall * This file may be redistributed under the terms of the GNU Library 88558eab78390d1924cd6b255686ceef133f294d5Ken Sumrall * General Public License, version 2. 919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * %End-Header% 1019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 1119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 1219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <stdio.h> 1319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <string.h> 1419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#if HAVE_UNISTD_H 1519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <unistd.h> 1619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif 1719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#if HAVE_ERRNO_H 1819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <errno.h> 1919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif 203984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#include <time.h> 2119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#if HAVE_SYS_STAT_H 2219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <sys/stat.h> 2319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif 2419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#if HAVE_SYS_TYPES_H 2519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <sys/types.h> 2619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif 2719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 2819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include "ext2_fs.h" 2919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include "ext2fsP.h" 3019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include "e2image.h" 3119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 3219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstruct ext2_struct_inode_scan { 3319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project errcode_t magic; 3419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2_filsys fs; 3519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2_ino_t current_inode; 3619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project blk_t current_block; 3719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project dgrp_t current_group; 3819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2_ino_t inodes_left; 3919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project blk_t blocks_left; 4019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project dgrp_t groups_left; 4119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project blk_t inode_buffer_blocks; 4219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project char * inode_buffer; 4319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project int inode_size; 4419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project char * ptr; 4519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project int bytes_left; 4619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project char *temp_buffer; 4719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project errcode_t (*done_group)(ext2_filsys fs, 4819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2_inode_scan scan, 4919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project dgrp_t group, 5019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project void * priv_data); 5119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project void * done_group_data; 5219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project int bad_block_ptr; 5319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project int scan_flags; 5419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project int reserved[6]; 5519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}; 5619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 5719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/* 5819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * This routine flushes the icache, if it exists. 5919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 6019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projecterrcode_t ext2fs_flush_icache(ext2_filsys fs) 6119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{ 6219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project int i; 633984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 6419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (!fs->icache) 6519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return 0; 6619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 6719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project for (i=0; i < fs->icache->cache_size; i++) 6819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fs->icache->cache[i].ino = 0; 6919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 7019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fs->icache->buffer_blk = 0; 7119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return 0; 7219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project} 7319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 7419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic errcode_t create_icache(ext2_filsys fs) 7519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{ 7619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project errcode_t retval; 773984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 7819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (fs->icache) 7919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return 0; 8019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project retval = ext2fs_get_mem(sizeof(struct ext2_inode_cache), &fs->icache); 8119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (retval) 8219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return retval; 8319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 8419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project memset(fs->icache, 0, sizeof(struct ext2_inode_cache)); 8519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project retval = ext2fs_get_mem(fs->blocksize, &fs->icache->buffer); 8619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (retval) { 8719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2fs_free_mem(&fs->icache); 8819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return retval; 8919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 9019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fs->icache->buffer_blk = 0; 9119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fs->icache->cache_last = -1; 9219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fs->icache->cache_size = 4; 9319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fs->icache->refcount = 1; 9419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project retval = ext2fs_get_array(fs->icache->cache_size, 9519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project sizeof(struct ext2_inode_cache_ent), 9619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project &fs->icache->cache); 9719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (retval) { 9819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2fs_free_mem(&fs->icache->buffer); 9919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2fs_free_mem(&fs->icache); 10019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return retval; 10119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 10219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2fs_flush_icache(fs); 10319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return 0; 10419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project} 10519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 10619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projecterrcode_t ext2fs_open_inode_scan(ext2_filsys fs, int buffer_blocks, 10719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2_inode_scan *ret_scan) 10819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{ 10919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2_inode_scan scan; 11019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project errcode_t retval; 11119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project errcode_t (*save_get_blocks)(ext2_filsys f, ext2_ino_t ino, blk_t *blocks); 11219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 11319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); 11419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 11519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project /* 11619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * If fs->badblocks isn't set, then set it --- since the inode 11719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * scanning functions require it. 11819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 11919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (fs->badblocks == 0) { 12019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project /* 12119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Temporarly save fs->get_blocks and set it to zero, 12219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * for compatibility with old e2fsck's. 12319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 12419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project save_get_blocks = fs->get_blocks; 12519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fs->get_blocks = 0; 12619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project retval = ext2fs_read_bb_inode(fs, &fs->badblocks); 12719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (retval && fs->badblocks) { 12819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2fs_badblocks_list_free(fs->badblocks); 12919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fs->badblocks = 0; 13019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 13119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fs->get_blocks = save_get_blocks; 13219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 13319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 13419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project retval = ext2fs_get_mem(sizeof(struct ext2_struct_inode_scan), &scan); 13519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (retval) 13619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return retval; 13719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project memset(scan, 0, sizeof(struct ext2_struct_inode_scan)); 13819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 13919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project scan->magic = EXT2_ET_MAGIC_INODE_SCAN; 14019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project scan->fs = fs; 14119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project scan->inode_size = EXT2_INODE_SIZE(fs->super); 14219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project scan->bytes_left = 0; 14319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project scan->current_group = 0; 14419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project scan->groups_left = fs->group_desc_count - 1; 14519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project scan->inode_buffer_blocks = buffer_blocks ? buffer_blocks : 8; 14619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project scan->current_block = scan->fs-> 14719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project group_desc[scan->current_group].bg_inode_table; 14819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project scan->inodes_left = EXT2_INODES_PER_GROUP(scan->fs->super); 14919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project scan->blocks_left = scan->fs->inode_blocks_per_group; 1503984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super, 1513984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) { 1523984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt scan->inodes_left -= 1533984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt fs->group_desc[scan->current_group].bg_itable_unused; 1543984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt scan->blocks_left = 1553984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt (scan->inodes_left + 1563984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt (fs->blocksize / scan->inode_size - 1)) * 1573984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt scan->inode_size / fs->blocksize; 1583984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt } 1598558eab78390d1924cd6b255686ceef133f294d5Ken Sumrall retval = ext2fs_get_memalign(scan->inode_buffer_blocks * fs->blocksize, 1608558eab78390d1924cd6b255686ceef133f294d5Ken Sumrall fs->blocksize, &scan->inode_buffer); 16119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project scan->done_group = 0; 16219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project scan->done_group_data = 0; 16319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project scan->bad_block_ptr = 0; 16419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (retval) { 16519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2fs_free_mem(&scan); 16619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return retval; 16719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 16819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project retval = ext2fs_get_mem(scan->inode_size, &scan->temp_buffer); 16919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (retval) { 17019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2fs_free_mem(&scan->inode_buffer); 17119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2fs_free_mem(&scan); 17219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return retval; 17319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 17419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (scan->fs->badblocks && scan->fs->badblocks->num) 17519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project scan->scan_flags |= EXT2_SF_CHK_BADBLOCKS; 1763984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super, 1773984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) 17819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project scan->scan_flags |= EXT2_SF_DO_LAZY; 17919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project *ret_scan = scan; 18019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return 0; 18119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project} 18219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 18319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectvoid ext2fs_close_inode_scan(ext2_inode_scan scan) 18419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{ 18519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (!scan || (scan->magic != EXT2_ET_MAGIC_INODE_SCAN)) 18619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return; 1873984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 18819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2fs_free_mem(&scan->inode_buffer); 18919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project scan->inode_buffer = NULL; 19019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2fs_free_mem(&scan->temp_buffer); 19119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project scan->temp_buffer = NULL; 19219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2fs_free_mem(&scan); 19319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return; 19419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project} 19519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 19619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectvoid ext2fs_set_inode_callback(ext2_inode_scan scan, 19719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project errcode_t (*done_group)(ext2_filsys fs, 19819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2_inode_scan scan, 19919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project dgrp_t group, 20019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project void * priv_data), 20119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project void *done_group_data) 20219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{ 20319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (!scan || (scan->magic != EXT2_ET_MAGIC_INODE_SCAN)) 20419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return; 2053984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 20619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project scan->done_group = done_group; 20719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project scan->done_group_data = done_group_data; 20819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project} 20919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 21019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectint ext2fs_inode_scan_flags(ext2_inode_scan scan, int set_flags, 21119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project int clear_flags) 21219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{ 21319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project int old_flags; 21419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 21519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (!scan || (scan->magic != EXT2_ET_MAGIC_INODE_SCAN)) 21619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return 0; 21719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 21819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project old_flags = scan->scan_flags; 21919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project scan->scan_flags &= ~clear_flags; 22019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project scan->scan_flags |= set_flags; 22119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return old_flags; 22219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project} 22319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 22419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/* 22519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * This function is called by ext2fs_get_next_inode when it needs to 22619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * get ready to read in a new blockgroup. 22719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 22819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic errcode_t get_next_blockgroup(ext2_inode_scan scan) 22919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{ 2303984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt ext2_filsys fs = scan->fs; 2313984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 23219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project scan->current_group++; 23319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project scan->groups_left--; 2343984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 2353984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt scan->current_block =fs->group_desc[scan->current_group].bg_inode_table; 23619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 23719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project scan->current_inode = scan->current_group * 2383984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt EXT2_INODES_PER_GROUP(fs->super); 23919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 24019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project scan->bytes_left = 0; 2413984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt scan->inodes_left = EXT2_INODES_PER_GROUP(fs->super); 2423984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt scan->blocks_left = fs->inode_blocks_per_group; 2433984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super, 2443984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) { 2453984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt scan->inodes_left -= 2463984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt fs->group_desc[scan->current_group].bg_itable_unused; 2473984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt scan->blocks_left = 2483984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt (scan->inodes_left + 2493984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt (fs->blocksize / scan->inode_size - 1)) * 2503984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt scan->inode_size / fs->blocksize; 2513984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt } 2523984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 25319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return 0; 25419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project} 25519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 25619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projecterrcode_t ext2fs_inode_scan_goto_blockgroup(ext2_inode_scan scan, 25719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project int group) 25819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{ 25919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project scan->current_group = group - 1; 26019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project scan->groups_left = scan->fs->group_desc_count - group; 26119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return get_next_blockgroup(scan); 26219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project} 26319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 26419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/* 26519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * This function is called by get_next_blocks() to check for bad 26619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * blocks in the inode table. 26719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * 26819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * This function assumes that badblocks_list->list is sorted in 26919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * increasing order. 27019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 27119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic errcode_t check_for_inode_bad_blocks(ext2_inode_scan scan, 27219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project blk_t *num_blocks) 27319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{ 27419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project blk_t blk = scan->current_block; 27519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project badblocks_list bb = scan->fs->badblocks; 27619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 27719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project /* 27819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * If the inode table is missing, then obviously there are no 27919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * bad blocks. :-) 28019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 28119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (blk == 0) 28219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return 0; 28319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 28419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project /* 28519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * If the current block is greater than the bad block listed 28619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * in the bad block list, then advance the pointer until this 28719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * is no longer the case. If we run out of bad blocks, then 28819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * we don't need to do any more checking! 28919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 29019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project while (blk > bb->list[scan->bad_block_ptr]) { 29119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (++scan->bad_block_ptr >= bb->num) { 29219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project scan->scan_flags &= ~EXT2_SF_CHK_BADBLOCKS; 29319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return 0; 29419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 29519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 29619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 29719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project /* 29819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * If the current block is equal to the bad block listed in 29919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * the bad block list, then handle that one block specially. 30019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * (We could try to handle runs of bad blocks, but that 30119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * only increases CPU efficiency by a small amount, at the 30219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * expense of a huge expense of code complexity, and for an 30319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * uncommon case at that.) 30419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 30519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (blk == bb->list[scan->bad_block_ptr]) { 30619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project scan->scan_flags |= EXT2_SF_BAD_INODE_BLK; 30719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project *num_blocks = 1; 30819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (++scan->bad_block_ptr >= bb->num) 30919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project scan->scan_flags &= ~EXT2_SF_CHK_BADBLOCKS; 31019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return 0; 31119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 31219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 31319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project /* 31419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * If there is a bad block in the range that we're about to 31519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * read in, adjust the number of blocks to read so that we we 31619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * don't read in the bad block. (Then the next block to read 31719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * will be the bad block, which is handled in the above case.) 31819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 31919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if ((blk + *num_blocks) > bb->list[scan->bad_block_ptr]) 32019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project *num_blocks = (int) (bb->list[scan->bad_block_ptr] - blk); 32119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 32219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return 0; 32319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project} 32419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 32519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/* 32619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * This function is called by ext2fs_get_next_inode when it needs to 32719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * read in more blocks from the current blockgroup's inode table. 32819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 32919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic errcode_t get_next_blocks(ext2_inode_scan scan) 33019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{ 33119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project blk_t num_blocks; 33219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project errcode_t retval; 33319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 33419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project /* 33519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Figure out how many blocks to read; we read at most 33619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * inode_buffer_blocks, and perhaps less if there aren't that 33719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * many blocks left to read. 33819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 33919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project num_blocks = scan->inode_buffer_blocks; 34019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (num_blocks > scan->blocks_left) 34119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project num_blocks = scan->blocks_left; 34219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 34319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project /* 34419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * If the past block "read" was a bad block, then mark the 34519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * left-over extra bytes as also being bad. 34619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 34719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (scan->scan_flags & EXT2_SF_BAD_INODE_BLK) { 34819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (scan->bytes_left) 34919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project scan->scan_flags |= EXT2_SF_BAD_EXTRA_BYTES; 35019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project scan->scan_flags &= ~EXT2_SF_BAD_INODE_BLK; 35119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 35219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 35319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project /* 35419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Do inode bad block processing, if necessary. 35519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 35619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (scan->scan_flags & EXT2_SF_CHK_BADBLOCKS) { 35719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project retval = check_for_inode_bad_blocks(scan, &num_blocks); 35819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (retval) 35919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return retval; 36019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 3613984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 36219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if ((scan->scan_flags & EXT2_SF_BAD_INODE_BLK) || 36319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project (scan->current_block == 0)) { 36419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project memset(scan->inode_buffer, 0, 36519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project (size_t) num_blocks * scan->fs->blocksize); 36619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } else { 36719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project retval = io_channel_read_blk(scan->fs->io, 36819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project scan->current_block, 36919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project (int) num_blocks, 37019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project scan->inode_buffer); 37119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (retval) 37219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return EXT2_ET_NEXT_INODE_READ; 37319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 37419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project scan->ptr = scan->inode_buffer; 37519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project scan->bytes_left = num_blocks * scan->fs->blocksize; 37619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 37719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project scan->blocks_left -= num_blocks; 37819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (scan->current_block) 37919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project scan->current_block += num_blocks; 38019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return 0; 38119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project} 38219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 38319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#if 0 38419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/* 38519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Returns 1 if the entire inode_buffer has a non-zero size and 38619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * contains all zeros. (Not just deleted inodes, since that means 38719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * that part of the inode table was used at one point; we want all 38819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * zeros, which means that the inode table is pristine.) 38919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 39019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic inline int is_empty_scan(ext2_inode_scan scan) 39119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{ 39219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project int i; 3933984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 39419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (scan->bytes_left == 0) 39519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return 0; 39619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 39719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project for (i=0; i < scan->bytes_left; i++) 39819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (scan->ptr[i]) 39919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return 0; 40019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return 1; 40119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project} 40219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif 40319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 40419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projecterrcode_t ext2fs_get_next_inode_full(ext2_inode_scan scan, ext2_ino_t *ino, 40519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct ext2_inode *inode, int bufsize) 40619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{ 40719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project errcode_t retval; 40819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project int extra_bytes = 0; 4093984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 41019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project EXT2_CHECK_MAGIC(scan, EXT2_ET_MAGIC_INODE_SCAN); 41119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 41219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project /* 41319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Do we need to start reading a new block group? 41419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 41519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (scan->inodes_left <= 0) { 41619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project force_new_group: 41719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (scan->done_group) { 41819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project retval = (scan->done_group) 41919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project (scan->fs, scan, scan->current_group, 42019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project scan->done_group_data); 42119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (retval) 42219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return retval; 42319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 42419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (scan->groups_left <= 0) { 42519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project *ino = 0; 42619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return 0; 42719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 42819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project retval = get_next_blockgroup(scan); 42919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (retval) 43019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return retval; 43119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 43219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project /* 4333984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * These checks are done outside the above if statement so 43419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * they can be done for block group #0. 43519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 43619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if ((scan->scan_flags & EXT2_SF_DO_LAZY) && 43719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project (scan->fs->group_desc[scan->current_group].bg_flags & 43819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project EXT2_BG_INODE_UNINIT)) 43919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project goto force_new_group; 4403984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (scan->inodes_left == 0) 4413984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt goto force_new_group; 44219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (scan->current_block == 0) { 44319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (scan->scan_flags & EXT2_SF_SKIP_MISSING_ITABLE) { 44419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project goto force_new_group; 44519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } else 44619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return EXT2_ET_MISSING_INODE_TABLE; 44719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 4483984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 44919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 45019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project /* 45119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Have we run out of space in the inode buffer? If so, we 45219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * need to read in more blocks. 45319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 45419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (scan->bytes_left < scan->inode_size) { 45519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project memcpy(scan->temp_buffer, scan->ptr, scan->bytes_left); 45619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project extra_bytes = scan->bytes_left; 45719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 45819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project retval = get_next_blocks(scan); 45919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (retval) 46019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return retval; 46119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#if 0 46219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project /* 46319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * XXX test Need check for used inode somehow. 46419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * (Note: this is hard.) 46519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 46619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (is_empty_scan(scan)) 46719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project goto force_new_group; 46819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif 46919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 47019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 47119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project retval = 0; 47219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (extra_bytes) { 47319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project memcpy(scan->temp_buffer+extra_bytes, scan->ptr, 47419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project scan->inode_size - extra_bytes); 47519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project scan->ptr += scan->inode_size - extra_bytes; 47619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project scan->bytes_left -= scan->inode_size - extra_bytes; 47719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 4783984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#ifdef WORDS_BIGENDIAN 47919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project memset(inode, 0, bufsize); 4803984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt ext2fs_swap_inode_full(scan->fs, 4813984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt (struct ext2_inode_large *) inode, 4823984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt (struct ext2_inode_large *) scan->temp_buffer, 4833984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 0, bufsize); 4843984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#else 4853984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt *inode = *((struct ext2_inode *) scan->temp_buffer); 48619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif 48719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (scan->scan_flags & EXT2_SF_BAD_EXTRA_BYTES) 48819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project retval = EXT2_ET_BAD_BLOCK_IN_INODE_TABLE; 48919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project scan->scan_flags &= ~EXT2_SF_BAD_EXTRA_BYTES; 49019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } else { 4913984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#ifdef WORDS_BIGENDIAN 49219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project memset(inode, 0, bufsize); 4933984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt ext2fs_swap_inode_full(scan->fs, 49419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project (struct ext2_inode_large *) inode, 49519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project (struct ext2_inode_large *) scan->ptr, 49619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 0, bufsize); 4973984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#else 4983984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt memcpy(inode, scan->ptr, bufsize); 49919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif 50019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project scan->ptr += scan->inode_size; 50119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project scan->bytes_left -= scan->inode_size; 50219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (scan->scan_flags & EXT2_SF_BAD_INODE_BLK) 50319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project retval = EXT2_ET_BAD_BLOCK_IN_INODE_TABLE; 50419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 50519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 50619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project scan->inodes_left--; 50719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project scan->current_inode++; 50819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project *ino = scan->current_inode; 50919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return retval; 51019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project} 51119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 51219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projecterrcode_t ext2fs_get_next_inode(ext2_inode_scan scan, ext2_ino_t *ino, 51319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct ext2_inode *inode) 51419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{ 51519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return ext2fs_get_next_inode_full(scan, ino, inode, 51619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project sizeof(struct ext2_inode)); 51719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project} 51819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 51919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/* 52019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Functions to read and write a single inode. 52119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 52219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projecterrcode_t ext2fs_read_inode_full(ext2_filsys fs, ext2_ino_t ino, 52319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct ext2_inode * inode, int bufsize) 52419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{ 52519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project unsigned long group, block, block_nr, offset; 52619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project char *ptr; 52719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project errcode_t retval; 52819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project int clen, i, inodes_per_block, length; 52919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project io_channel io; 53019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 53119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); 53219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 53319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project /* Check to see if user has an override function */ 53419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (fs->read_inode) { 53519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project retval = (fs->read_inode)(fs, ino, inode); 53619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (retval != EXT2_ET_CALLBACK_NOTHANDLED) 53719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return retval; 53819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 5393984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if ((ino == 0) || (ino > fs->super->s_inodes_count)) 5403984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt return EXT2_ET_BAD_INODE_NUM; 54119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project /* Create inode cache if not present */ 54219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (!fs->icache) { 54319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project retval = create_icache(fs); 54419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (retval) 54519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return retval; 54619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 54719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project /* Check to see if it's in the inode cache */ 54819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (bufsize == sizeof(struct ext2_inode)) { 5493984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt /* only old good inode can be retrieved from the cache */ 55019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project for (i=0; i < fs->icache->cache_size; i++) { 55119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (fs->icache->cache[i].ino == ino) { 55219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project *inode = fs->icache->cache[i].inode; 55319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return 0; 55419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 55519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 55619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 55719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (fs->flags & EXT2_FLAG_IMAGE_FILE) { 55819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project inodes_per_block = fs->blocksize / EXT2_INODE_SIZE(fs->super); 55919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project block_nr = fs->image_header->offset_inode / fs->blocksize; 56019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project block_nr += (ino - 1) / inodes_per_block; 56119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project offset = ((ino - 1) % inodes_per_block) * 56219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project EXT2_INODE_SIZE(fs->super); 56319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project io = fs->image_io; 56419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } else { 56519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project group = (ino - 1) / EXT2_INODES_PER_GROUP(fs->super); 5663984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (group > fs->group_desc_count) 5673984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt return EXT2_ET_BAD_INODE_NUM; 56819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project offset = ((ino - 1) % EXT2_INODES_PER_GROUP(fs->super)) * 56919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project EXT2_INODE_SIZE(fs->super); 57019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project block = offset >> EXT2_BLOCK_SIZE_BITS(fs->super); 57119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (!fs->group_desc[(unsigned)group].bg_inode_table) 57219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return EXT2_ET_MISSING_INODE_TABLE; 5733984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt block_nr = fs->group_desc[(unsigned)group].bg_inode_table + 57419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project block; 57519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project io = fs->io; 57619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 57719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project offset &= (EXT2_BLOCK_SIZE(fs->super) - 1); 57819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 57919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project length = EXT2_INODE_SIZE(fs->super); 58019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (bufsize < length) 58119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project length = bufsize; 58219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 58319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ptr = (char *) inode; 58419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project while (length) { 58519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project clen = length; 58619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if ((offset + length) > fs->blocksize) 58719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project clen = fs->blocksize - offset; 58819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 58919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (block_nr != fs->icache->buffer_blk) { 59019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project retval = io_channel_read_blk(io, block_nr, 1, 59119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fs->icache->buffer); 59219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (retval) 59319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return retval; 59419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fs->icache->buffer_blk = block_nr; 59519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 59619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 59719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project memcpy(ptr, ((char *) fs->icache->buffer) + (unsigned) offset, 59819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project clen); 59919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 60019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project offset = 0; 60119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project length -= clen; 60219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ptr += clen; 60319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project block_nr++; 60419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 60519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 6063984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#ifdef WORDS_BIGENDIAN 6073984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt ext2fs_swap_inode_full(fs, (struct ext2_inode_large *) inode, 6083984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt (struct ext2_inode_large *) inode, 6093984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 0, bufsize); 61019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif 61119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 61219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project /* Update the inode cache */ 61319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fs->icache->cache_last = (fs->icache->cache_last + 1) % 61419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fs->icache->cache_size; 61519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fs->icache->cache[fs->icache->cache_last].ino = ino; 61619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fs->icache->cache[fs->icache->cache_last].inode = *inode; 6173984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 61819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return 0; 61919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project} 62019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 62119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projecterrcode_t ext2fs_read_inode(ext2_filsys fs, ext2_ino_t ino, 62219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct ext2_inode * inode) 62319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{ 62419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return ext2fs_read_inode_full(fs, ino, inode, 62519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project sizeof(struct ext2_inode)); 62619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project} 62719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 62819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projecterrcode_t ext2fs_write_inode_full(ext2_filsys fs, ext2_ino_t ino, 62919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct ext2_inode * inode, int bufsize) 63019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{ 63119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project unsigned long group, block, block_nr, offset; 63219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project errcode_t retval = 0; 63319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct ext2_inode_large temp_inode, *w_inode; 63419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project char *ptr; 63519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project int clen, i, length; 63619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 63719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); 63819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 63919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project /* Check to see if user provided an override function */ 64019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (fs->write_inode) { 64119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project retval = (fs->write_inode)(fs, ino, inode); 64219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (retval != EXT2_ET_CALLBACK_NOTHANDLED) 64319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return retval; 64419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 64519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 64619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project /* Check to see if the inode cache needs to be updated */ 64719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (fs->icache) { 64819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project for (i=0; i < fs->icache->cache_size; i++) { 64919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (fs->icache->cache[i].ino == ino) { 65019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fs->icache->cache[i].inode = *inode; 65119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project break; 65219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 65319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 65419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } else { 65519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project retval = create_icache(fs); 65619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (retval) 65719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return retval; 65819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 6593984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 66019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (!(fs->flags & EXT2_FLAG_RW)) 66119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return EXT2_ET_RO_FILSYS; 66219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 66319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if ((ino == 0) || (ino > fs->super->s_inodes_count)) 66419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return EXT2_ET_BAD_INODE_NUM; 66519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 66619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project length = bufsize; 66719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (length < EXT2_INODE_SIZE(fs->super)) 66819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project length = EXT2_INODE_SIZE(fs->super); 66919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 67019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (length > (int) sizeof(struct ext2_inode_large)) { 67119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project w_inode = malloc(length); 67219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (!w_inode) 67319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return ENOMEM; 67419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } else 67519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project w_inode = &temp_inode; 67619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project memset(w_inode, 0, length); 67719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 6783984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#ifdef WORDS_BIGENDIAN 6793984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt ext2fs_swap_inode_full(fs, w_inode, 6803984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt (struct ext2_inode_large *) inode, 6813984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 1, bufsize); 6823984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt#else 6833984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt memcpy(w_inode, inode, bufsize); 68419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif 6853984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 68619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project group = (ino - 1) / EXT2_INODES_PER_GROUP(fs->super); 68719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project offset = ((ino - 1) % EXT2_INODES_PER_GROUP(fs->super)) * 68819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project EXT2_INODE_SIZE(fs->super); 68919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project block = offset >> EXT2_BLOCK_SIZE_BITS(fs->super); 69019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (!fs->group_desc[(unsigned) group].bg_inode_table) { 69119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project retval = EXT2_ET_MISSING_INODE_TABLE; 69219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project goto errout; 69319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 69419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project block_nr = fs->group_desc[(unsigned) group].bg_inode_table + block; 69519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 69619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project offset &= (EXT2_BLOCK_SIZE(fs->super) - 1); 69719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 69819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project length = EXT2_INODE_SIZE(fs->super); 69919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (length > bufsize) 70019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project length = bufsize; 70119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 70219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ptr = (char *) w_inode; 70319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 70419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project while (length) { 70519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project clen = length; 70619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if ((offset + length) > fs->blocksize) 70719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project clen = fs->blocksize - offset; 70819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 70919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (fs->icache->buffer_blk != block_nr) { 71019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project retval = io_channel_read_blk(fs->io, block_nr, 1, 71119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fs->icache->buffer); 71219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (retval) 71319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project goto errout; 71419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fs->icache->buffer_blk = block_nr; 71519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 71619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 7173984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 7183984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt memcpy((char *) fs->icache->buffer + (unsigned) offset, 71919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ptr, clen); 72019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 7213984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt retval = io_channel_write_blk(fs->io, block_nr, 1, 72219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fs->icache->buffer); 72319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (retval) 72419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project goto errout; 72519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 72619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project offset = 0; 72719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ptr += clen; 72819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project length -= clen; 72919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project block_nr++; 73019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 7313984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 73219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fs->flags |= EXT2_FLAG_CHANGED; 73319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projecterrout: 73419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (w_inode && w_inode != &temp_inode) 73519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project free(w_inode); 73619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return retval; 73719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project} 73819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 73919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projecterrcode_t ext2fs_write_inode(ext2_filsys fs, ext2_ino_t ino, 74019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct ext2_inode *inode) 74119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{ 74219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return ext2fs_write_inode_full(fs, ino, inode, 74319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project sizeof(struct ext2_inode)); 74419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project} 74519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 7463984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt/* 74719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * This function should be called when writing a new inode. It makes 74819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * sure that extra part of large inodes is initialized properly. 74919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 75019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projecterrcode_t ext2fs_write_new_inode(ext2_filsys fs, ext2_ino_t ino, 75119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct ext2_inode *inode) 75219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{ 75319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct ext2_inode *buf; 75419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project int size = EXT2_INODE_SIZE(fs->super); 75519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct ext2_inode_large *large_inode; 75619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project errcode_t retval; 7573984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt __u32 t = fs->now ? fs->now : time(NULL); 7583984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 7593984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (!inode->i_ctime) 7603984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt inode->i_ctime = t; 7613984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (!inode->i_mtime) 7623984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt inode->i_mtime = t; 7633984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (!inode->i_atime) 7643984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt inode->i_atime = t; 76519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 76619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (size == sizeof(struct ext2_inode)) 76719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return ext2fs_write_inode_full(fs, ino, inode, 76819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project sizeof(struct ext2_inode)); 76919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 77019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project buf = malloc(size); 77119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (!buf) 77219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return ENOMEM; 77319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 77419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project memset(buf, 0, size); 77519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project *buf = *inode; 77619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 77719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project large_inode = (struct ext2_inode_large *) buf; 7783984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt large_inode->i_extra_isize = sizeof(struct ext2_inode_large) - 77919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project EXT2_GOOD_OLD_INODE_SIZE; 7803984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt if (!large_inode->i_crtime) 7813984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt large_inode->i_crtime = t; 78219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 78319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project retval = ext2fs_write_inode_full(fs, ino, buf, size); 78419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project free(buf); 78519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return retval; 78619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project} 78719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 7883984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 78919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projecterrcode_t ext2fs_get_blocks(ext2_filsys fs, ext2_ino_t ino, blk_t *blocks) 79019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{ 79119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct ext2_inode inode; 79219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project int i; 79319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project errcode_t retval; 7943984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 79519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); 79619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 79719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (ino > fs->super->s_inodes_count) 79819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return EXT2_ET_BAD_INODE_NUM; 79919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 80019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (fs->get_blocks) { 80119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (!(*fs->get_blocks)(fs, ino, blocks)) 80219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return 0; 80319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 80419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project retval = ext2fs_read_inode(fs, ino, &inode); 80519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (retval) 80619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return retval; 80719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project for (i=0; i < EXT2_N_BLOCKS; i++) 80819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project blocks[i] = inode.i_block[i]; 80919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return 0; 81019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project} 81119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 81219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projecterrcode_t ext2fs_check_directory(ext2_filsys fs, ext2_ino_t ino) 81319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{ 81419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct ext2_inode inode; 81519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project errcode_t retval; 8163984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 81719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS); 81819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 81919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (ino > fs->super->s_inodes_count) 82019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return EXT2_ET_BAD_INODE_NUM; 82119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 82219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (fs->check_directory) { 82319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project retval = (fs->check_directory)(fs, ino); 82419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (retval != EXT2_ET_CALLBACK_NOTHANDLED) 82519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return retval; 82619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 82719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project retval = ext2fs_read_inode(fs, ino, &inode); 82819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (retval) 82919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return retval; 83019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (!LINUX_S_ISDIR(inode.i_mode)) 83119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return EXT2_ET_NO_DIRECTORY; 83219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return 0; 83319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project} 83419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 835