Newer
Older
int new_flags;
put_ext4((uint64_t)le32_to_cpu(bgd[i].inode_id) * fs->blksz,
new_flags = le16_to_cpu(bgd[i].bg_flags) & ~EXT4_BG_INODE_UNINIT;
bgd[i].bg_flags = cpu_to_le16(new_flags);
memcpy(fs->inode_bmaps[i],
zero_buffer, fs->blksz);
}
fs->curr_inode_no =
_get_new_inode_no(fs->inode_bmaps[i]);
if (fs->curr_inode_no == -1)
/* if block bitmap is completely fill */
continue;
fs->curr_inode_no = fs->curr_inode_no +
(i * inodes_per_grp);
fs->first_pass_ibmap++;
ext4fs_bg_free_inodes_dec(&bgd[i]);
if (has_gdt_chksum)
ext4fs_bg_itable_unused_dec(&bgd[i]);
ext4fs_sb_free_inodes_dec(fs->sb);
status = ext4fs_devread(
(lbaint_t)le32_to_cpu(bgd[i].inode_id) *
fs->sect_perblk, 0,
fs->blksz,
journal_buffer);
if (status == 0)
goto fail;
if (ext4fs_log_journal(journal_buffer,
le32_to_cpu(bgd[i].inode_id)))
goto fail;
goto success;
} else
debug("no inode left on block group %d\n", i);
}
goto fail;
} else {
restart:
fs->curr_inode_no++;
/* get the blockbitmap index respective to blockno */
ibmap_idx = fs->curr_inode_no / inodes_per_grp;
if (le16_to_cpu(bgd[ibmap_idx].bg_flags) & EXT4_BG_INODE_UNINIT) {
int new_flags;
put_ext4((uint64_t)le32_to_cpu(bgd[ibmap_idx].inode_id) * fs->blksz,
zero_buffer, fs->blksz);
new_flags = le16_to_cpu(bgd[ibmap_idx].bg_flags) & ~EXT4_BG_INODE_UNINIT;
bgd[ibmap_idx].bg_flags = cpu_to_le16(new_flags);
memcpy(fs->inode_bmaps[ibmap_idx], zero_buffer,
fs->blksz);
}
if (ext4fs_set_inode_bmap(fs->curr_inode_no,
fs->inode_bmaps[ibmap_idx],
ibmap_idx) != 0) {
debug("going for restart for the block no %d %u\n",
fs->curr_inode_no, ibmap_idx);
goto restart;
}
/* journal backup */
if (prev_inode_bitmap_index != ibmap_idx) {
memset(journal_buffer, '\0', fs->blksz);
status = ext4fs_devread(
(lbaint_t)le32_to_cpu(bgd[ibmap_idx].inode_id)
* fs->sect_perblk,
0, fs->blksz, journal_buffer);
if (status == 0)
goto fail;
if (ext4fs_log_journal(journal_buffer,
le32_to_cpu(bgd[ibmap_idx].inode_id)))
goto fail;
prev_inode_bitmap_index = ibmap_idx;
}
ext4fs_bg_free_inodes_dec(&bgd[ibmap_idx]);
if (has_gdt_chksum)
bgd[ibmap_idx].bg_itable_unused =
bgd[ibmap_idx].free_inodes;
ext4fs_sb_free_inodes_dec(fs->sb);
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
goto success;
}
success:
free(journal_buffer);
free(zero_buffer);
return fs->curr_inode_no;
fail:
free(journal_buffer);
free(zero_buffer);
return -1;
}
static void alloc_single_indirect_block(struct ext2_inode *file_inode,
unsigned int *total_remaining_blocks,
unsigned int *no_blks_reqd)
{
short i;
short status;
long int actual_block_no;
long int si_blockno;
/* si :single indirect */
__le32 *si_buffer = NULL;
__le32 *si_start_addr = NULL;
struct ext_filesystem *fs = get_fs();
if (*total_remaining_blocks != 0) {
si_buffer = zalloc(fs->blksz);
if (!si_buffer) {
printf("No Memory\n");
return;
}
si_start_addr = si_buffer;
si_blockno = ext4fs_get_new_blk_no();
if (si_blockno == -1) {
printf("no block left to assign\n");
goto fail;
}
(*no_blks_reqd)++;
debug("SIPB %ld: %u\n", si_blockno, *total_remaining_blocks);
status = ext4fs_devread((lbaint_t)si_blockno * fs->sect_perblk,
0, fs->blksz, (char *)si_buffer);
memset(si_buffer, '\0', fs->blksz);
if (status == 0)
goto fail;
for (i = 0; i < (fs->blksz / sizeof(int)); i++) {
actual_block_no = ext4fs_get_new_blk_no();
if (actual_block_no == -1) {
printf("no block left to assign\n");
goto fail;
}
*si_buffer = cpu_to_le32(actual_block_no);
debug("SIAB %u: %u\n", *si_buffer,
*total_remaining_blocks);
si_buffer++;
(*total_remaining_blocks)--;
if (*total_remaining_blocks == 0)
break;
}
/* write the block to disk */
put_ext4(((uint64_t) ((uint64_t)si_blockno * (uint64_t)fs->blksz)),
file_inode->b.blocks.indir_block = cpu_to_le32(si_blockno);
}
fail:
free(si_start_addr);
}
static void alloc_double_indirect_block(struct ext2_inode *file_inode,
unsigned int *total_remaining_blocks,
unsigned int *no_blks_reqd)
{
short i;
short j;
short status;
long int actual_block_no;
/* di:double indirect */
long int di_blockno_parent;
long int di_blockno_child;
__le32 *di_parent_buffer = NULL;
__le32 *di_child_buff = NULL;
__le32 *di_block_start_addr = NULL;
__le32 *di_child_buff_start = NULL;
struct ext_filesystem *fs = get_fs();
if (*total_remaining_blocks != 0) {
/* double indirect parent block connecting to inode */
di_blockno_parent = ext4fs_get_new_blk_no();
if (di_blockno_parent == -1) {
printf("no block left to assign\n");
goto fail;
}
di_parent_buffer = zalloc(fs->blksz);
if (!di_parent_buffer)
goto fail;
di_block_start_addr = di_parent_buffer;
(*no_blks_reqd)++;
debug("DIPB %ld: %u\n", di_blockno_parent,
*total_remaining_blocks);
status = ext4fs_devread((lbaint_t)di_blockno_parent *
fs->sect_perblk, 0,
fs->blksz, (char *)di_parent_buffer);
if (!status) {
printf("%s: Device read error!\n", __func__);
goto fail;
}
memset(di_parent_buffer, '\0', fs->blksz);
/*
* start:for each double indirect parent
* block create one more block
*/
for (i = 0; i < (fs->blksz / sizeof(int)); i++) {
di_blockno_child = ext4fs_get_new_blk_no();
if (di_blockno_child == -1) {
printf("no block left to assign\n");
goto fail;
}
di_child_buff = zalloc(fs->blksz);
if (!di_child_buff)
goto fail;
di_child_buff_start = di_child_buff;
*di_parent_buffer = cpu_to_le32(di_blockno_child);
di_parent_buffer++;
(*no_blks_reqd)++;
debug("DICB %ld: %u\n", di_blockno_child,
*total_remaining_blocks);
status = ext4fs_devread((lbaint_t)di_blockno_child *
fs->sect_perblk, 0,
fs->blksz,
(char *)di_child_buff);
if (!status) {
printf("%s: Device read error!\n", __func__);
goto fail;
}
memset(di_child_buff, '\0', fs->blksz);
/* filling of actual datablocks for each child */
for (j = 0; j < (fs->blksz / sizeof(int)); j++) {
actual_block_no = ext4fs_get_new_blk_no();
if (actual_block_no == -1) {
printf("no block left to assign\n");
goto fail;
}
*di_child_buff = cpu_to_le32(actual_block_no);
debug("DIAB %ld: %u\n", actual_block_no,
*total_remaining_blocks);
di_child_buff++;
(*total_remaining_blocks)--;
if (*total_remaining_blocks == 0)
break;
}
/* write the block table */
put_ext4(((uint64_t) ((uint64_t)di_blockno_child * (uint64_t)fs->blksz)),
di_child_buff_start, fs->blksz);
free(di_child_buff_start);
di_child_buff_start = NULL;
if (*total_remaining_blocks == 0)
break;
}
put_ext4(((uint64_t) ((uint64_t)di_blockno_parent * (uint64_t)fs->blksz)),
file_inode->b.blocks.double_indir_block = cpu_to_le32(di_blockno_parent);
}
fail:
free(di_block_start_addr);
}
static void alloc_triple_indirect_block(struct ext2_inode *file_inode,
unsigned int *total_remaining_blocks,
unsigned int *no_blks_reqd)
{
short i;
short j;
short k;
long int actual_block_no;
/* ti: Triple Indirect */
long int ti_gp_blockno;
long int ti_parent_blockno;
long int ti_child_blockno;
__le32 *ti_gp_buff = NULL;
__le32 *ti_parent_buff = NULL;
__le32 *ti_child_buff = NULL;
__le32 *ti_gp_buff_start_addr = NULL;
__le32 *ti_pbuff_start_addr = NULL;
__le32 *ti_cbuff_start_addr = NULL;
struct ext_filesystem *fs = get_fs();
if (*total_remaining_blocks != 0) {
/* triple indirect grand parent block connecting to inode */
ti_gp_blockno = ext4fs_get_new_blk_no();
if (ti_gp_blockno == -1) {
printf("no block left to assign\n");
return;
}
ti_gp_buff = zalloc(fs->blksz);
if (!ti_gp_buff)
return;
ti_gp_buff_start_addr = ti_gp_buff;
(*no_blks_reqd)++;
debug("TIGPB %ld: %u\n", ti_gp_blockno,
*total_remaining_blocks);
/* for each 4 byte grand parent entry create one more block */
for (i = 0; i < (fs->blksz / sizeof(int)); i++) {
ti_parent_blockno = ext4fs_get_new_blk_no();
if (ti_parent_blockno == -1) {
printf("no block left to assign\n");
goto fail;
}
ti_parent_buff = zalloc(fs->blksz);
if (!ti_parent_buff)
goto fail;
ti_pbuff_start_addr = ti_parent_buff;
*ti_gp_buff = cpu_to_le32(ti_parent_blockno);
ti_gp_buff++;
(*no_blks_reqd)++;
debug("TIPB %ld: %u\n", ti_parent_blockno,
*total_remaining_blocks);
/* for each 4 byte entry parent create one more block */
for (j = 0; j < (fs->blksz / sizeof(int)); j++) {
ti_child_blockno = ext4fs_get_new_blk_no();
if (ti_child_blockno == -1) {
printf("no block left assign\n");
goto fail1;
}
ti_child_buff = zalloc(fs->blksz);
if (!ti_child_buff)
goto fail1;
*ti_parent_buff = cpu_to_le32(ti_child_blockno);
ti_parent_buff++;
(*no_blks_reqd)++;
debug("TICB %ld: %u\n", ti_parent_blockno,
*total_remaining_blocks);
/* fill actual datablocks for each child */
for (k = 0; k < (fs->blksz / sizeof(int));
k++) {
actual_block_no =
ext4fs_get_new_blk_no();
if (actual_block_no == -1) {
printf("no block left\n");
free(ti_cbuff_start_addr);
goto fail1;
*ti_child_buff = cpu_to_le32(actual_block_no);
debug("TIAB %ld: %u\n", actual_block_no,
*total_remaining_blocks);
ti_child_buff++;
(*total_remaining_blocks)--;
if (*total_remaining_blocks == 0)
break;
}
/* write the child block */
put_ext4(((uint64_t) ((uint64_t)ti_child_blockno *
(uint64_t)fs->blksz)),
ti_cbuff_start_addr, fs->blksz);
free(ti_cbuff_start_addr);
if (*total_remaining_blocks == 0)
break;
}
/* write the parent block */
put_ext4(((uint64_t) ((uint64_t)ti_parent_blockno * (uint64_t)fs->blksz)),
ti_pbuff_start_addr, fs->blksz);
free(ti_pbuff_start_addr);
if (*total_remaining_blocks == 0)
break;
}
/* write the grand parent block */
put_ext4(((uint64_t) ((uint64_t)ti_gp_blockno * (uint64_t)fs->blksz)),
file_inode->b.blocks.triple_indir_block = cpu_to_le32(ti_gp_blockno);
free(ti_gp_buff_start_addr);
return;
fail1:
free(ti_pbuff_start_addr);
fail:
free(ti_gp_buff_start_addr);
}
void ext4fs_allocate_blocks(struct ext2_inode *file_inode,
unsigned int total_remaining_blocks,
unsigned int *total_no_of_block)
{
short i;
long int direct_blockno;
unsigned int no_blks_reqd = 0;
/* allocation of direct blocks */
for (i = 0; total_remaining_blocks && i < INDIRECT_BLOCKS; i++) {
direct_blockno = ext4fs_get_new_blk_no();
if (direct_blockno == -1) {
printf("no block left to assign\n");
return;
}
file_inode->b.blocks.dir_blocks[i] = cpu_to_le32(direct_blockno);
debug("DB %ld: %u\n", direct_blockno, total_remaining_blocks);
total_remaining_blocks--;
}
alloc_single_indirect_block(file_inode, &total_remaining_blocks,
&no_blks_reqd);
alloc_double_indirect_block(file_inode, &total_remaining_blocks,
&no_blks_reqd);
alloc_triple_indirect_block(file_inode, &total_remaining_blocks,
&no_blks_reqd);
*total_no_of_block += no_blks_reqd;
}
#endif
static struct ext4_extent_header *ext4fs_get_extent_block
(struct ext2_data *data, char *buf,
struct ext4_extent_header *ext_block,
uint32_t fileblock, int log2_blksz)
{
struct ext4_extent_idx *index;
unsigned long long block;
int blksz = EXT2_BLOCK_SIZE(data);
int i;
while (1) {
index = (struct ext4_extent_idx *)(ext_block + 1);
if (le16_to_cpu(ext_block->eh_magic) != EXT4_EXT_MAGIC)
if (ext_block->eh_depth == 0)
return ext_block;
i = -1;
do {
i++;
if (i >= le16_to_cpu(ext_block->eh_entries))
} while (fileblock >= le32_to_cpu(index[i].ei_block));
block = le16_to_cpu(index[i].ei_leaf_hi);
block = (block << 32) + le32_to_cpu(index[i].ei_leaf_lo);
if (ext4fs_devread((lbaint_t)block << log2_blksz, 0, blksz,
ext_block = (struct ext4_extent_header *)buf;
else
}
}
static int ext4fs_blockgroup
(struct ext2_data *data, int group, struct ext2_block_group *blkgrp)
{
long int blkno;
unsigned int blkoff, desc_per_blk;
int log2blksz = get_fs()->dev_desc->log2blksz;
desc_per_blk = EXT2_BLOCK_SIZE(data) / sizeof(struct ext2_block_group);
blkno = le32_to_cpu(data->sblock.first_data_block) + 1 +
group / desc_per_blk;
blkoff = (group % desc_per_blk) * sizeof(struct ext2_block_group);
debug("ext4fs read %d group descriptor (blkno %ld blkoff %u)\n",
group, blkno, blkoff);
return ext4fs_devread((lbaint_t)blkno <<
(LOG2_BLOCK_SIZE(data) - log2blksz),
blkoff, sizeof(struct ext2_block_group),
(char *)blkgrp);
}
int ext4fs_read_inode(struct ext2_data *data, int ino, struct ext2_inode *inode)
{
struct ext2_block_group blkgrp;
struct ext2_sblock *sblock = &data->sblock;
struct ext_filesystem *fs = get_fs();
int log2blksz = get_fs()->dev_desc->log2blksz;
int inodes_per_block, status;
long int blkno;
unsigned int blkoff;
/* It is easier to calculate if the first inode is 0. */
ino--;
status = ext4fs_blockgroup(data, ino / le32_to_cpu
(sblock->inodes_per_group), &blkgrp);
if (status == 0)
return 0;
inodes_per_block = EXT2_BLOCK_SIZE(data) / fs->inodesz;
blkno = le32_to_cpu(blkgrp.inode_table_id) +
(ino % le32_to_cpu(sblock->inodes_per_group)) / inodes_per_block;
blkoff = (ino % inodes_per_block) * fs->inodesz;
/* Read the inode. */
status = ext4fs_devread((lbaint_t)blkno << (LOG2_BLOCK_SIZE(data) -
log2blksz), blkoff,
sizeof(struct ext2_inode), (char *)inode);
if (status == 0)
return 0;
return 1;
}
long int read_allocated_block(struct ext2_inode *inode, int fileblock)
{
long int blknr;
int blksz;
int log2_blksz;
int status;
long int rblock;
long int perblock_parent;
long int perblock_child;
unsigned long long start;
/* get the blocksize of the filesystem */
blksz = EXT2_BLOCK_SIZE(ext4fs_root);
log2_blksz = LOG2_BLOCK_SIZE(ext4fs_root)
- get_fs()->dev_desc->log2blksz;
if (le32_to_cpu(inode->flags) & EXT4_EXTENTS_FL) {
char *buf = zalloc(blksz);
if (!buf)
return -ENOMEM;
struct ext4_extent_header *ext_block;
struct ext4_extent *extent;
int i = -1;
ext_block =
ext4fs_get_extent_block(ext4fs_root, buf,
(struct ext4_extent_header *)
inode->b.blocks.dir_blocks,
fileblock, log2_blksz);
if (!ext_block) {
printf("invalid extent block\n");
free(buf);
return -EINVAL;
}
extent = (struct ext4_extent *)(ext_block + 1);
do {
i++;
if (i >= le16_to_cpu(ext_block->eh_entries))
break;
} while (fileblock >= le32_to_cpu(extent[i].ee_block));
if (--i >= 0) {
fileblock -= le32_to_cpu(extent[i].ee_block);
if (fileblock >= le16_to_cpu(extent[i].ee_len)) {
start = le16_to_cpu(extent[i].ee_start_hi);
start = (start << 32) +
le32_to_cpu(extent[i].ee_start_lo);
free(buf);
return fileblock + start;
}
printf("Extent Error\n");
free(buf);
return -1;
}
/* Direct blocks. */
if (fileblock < INDIRECT_BLOCKS)
blknr = le32_to_cpu(inode->b.blocks.dir_blocks[fileblock]);
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
/* Indirect. */
else if (fileblock < (INDIRECT_BLOCKS + (blksz / 4))) {
if (ext4fs_indir1_block == NULL) {
ext4fs_indir1_block = zalloc(blksz);
if (ext4fs_indir1_block == NULL) {
printf("** SI ext2fs read block (indir 1)"
"malloc failed. **\n");
return -1;
}
ext4fs_indir1_size = blksz;
ext4fs_indir1_blkno = -1;
}
if (blksz != ext4fs_indir1_size) {
free(ext4fs_indir1_block);
ext4fs_indir1_block = NULL;
ext4fs_indir1_size = 0;
ext4fs_indir1_blkno = -1;
ext4fs_indir1_block = zalloc(blksz);
if (ext4fs_indir1_block == NULL) {
printf("** SI ext2fs read block (indir 1):"
"malloc failed. **\n");
return -1;
}
ext4fs_indir1_size = blksz;
}
if ((le32_to_cpu(inode->b.blocks.indir_block) <<
log2_blksz) != ext4fs_indir1_blkno) {
status =
ext4fs_devread((lbaint_t)le32_to_cpu
(inode->b.blocks.
indir_block) << log2_blksz, 0,
blksz, (char *)ext4fs_indir1_block);
if (status == 0) {
printf("** SI ext2fs read block (indir 1)"
"failed. **\n");
return 0;
}
ext4fs_indir1_blkno =
blknr = le32_to_cpu(ext4fs_indir1_block
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
[fileblock - INDIRECT_BLOCKS]);
}
/* Double indirect. */
else if (fileblock < (INDIRECT_BLOCKS + (blksz / 4 *
(blksz / 4 + 1)))) {
long int perblock = blksz / 4;
long int rblock = fileblock - (INDIRECT_BLOCKS + blksz / 4);
if (ext4fs_indir1_block == NULL) {
ext4fs_indir1_block = zalloc(blksz);
if (ext4fs_indir1_block == NULL) {
printf("** DI ext2fs read block (indir 2 1)"
"malloc failed. **\n");
return -1;
}
ext4fs_indir1_size = blksz;
ext4fs_indir1_blkno = -1;
}
if (blksz != ext4fs_indir1_size) {
free(ext4fs_indir1_block);
ext4fs_indir1_block = NULL;
ext4fs_indir1_size = 0;
ext4fs_indir1_blkno = -1;
ext4fs_indir1_block = zalloc(blksz);
if (ext4fs_indir1_block == NULL) {
printf("** DI ext2fs read block (indir 2 1)"
"malloc failed. **\n");
return -1;
}
ext4fs_indir1_size = blksz;
}
if ((le32_to_cpu(inode->b.blocks.double_indir_block) <<
log2_blksz) != ext4fs_indir1_blkno) {
status =
ext4fs_devread((lbaint_t)le32_to_cpu
(inode->b.blocks.
double_indir_block) << log2_blksz,
0, blksz,
(char *)ext4fs_indir1_block);
if (status == 0) {
printf("** DI ext2fs read block (indir 2 1)"
"failed. **\n");
return -1;
}
ext4fs_indir1_blkno =
le32_to_cpu(inode->b.blocks.double_indir_block) <<
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
log2_blksz;
}
if (ext4fs_indir2_block == NULL) {
ext4fs_indir2_block = zalloc(blksz);
if (ext4fs_indir2_block == NULL) {
printf("** DI ext2fs read block (indir 2 2)"
"malloc failed. **\n");
return -1;
}
ext4fs_indir2_size = blksz;
ext4fs_indir2_blkno = -1;
}
if (blksz != ext4fs_indir2_size) {
free(ext4fs_indir2_block);
ext4fs_indir2_block = NULL;
ext4fs_indir2_size = 0;
ext4fs_indir2_blkno = -1;
ext4fs_indir2_block = zalloc(blksz);
if (ext4fs_indir2_block == NULL) {
printf("** DI ext2fs read block (indir 2 2)"
"malloc failed. **\n");
return -1;
}
ext4fs_indir2_size = blksz;
}
if ((le32_to_cpu(ext4fs_indir1_block[rblock / perblock]) <<
status = ext4fs_devread((lbaint_t)le32_to_cpu
(ext4fs_indir1_block
[rblock /
perblock]) << log2_blksz, 0,
blksz,
(char *)ext4fs_indir2_block);
if (status == 0) {
printf("** DI ext2fs read block (indir 2 2)"
"failed. **\n");
return -1;
}
ext4fs_indir2_blkno =
le32_to_cpu(ext4fs_indir1_block[rblock
blknr = le32_to_cpu(ext4fs_indir2_block[rblock % perblock]);
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
}
/* Tripple indirect. */
else {
rblock = fileblock - (INDIRECT_BLOCKS + blksz / 4 +
(blksz / 4 * blksz / 4));
perblock_child = blksz / 4;
perblock_parent = ((blksz / 4) * (blksz / 4));
if (ext4fs_indir1_block == NULL) {
ext4fs_indir1_block = zalloc(blksz);
if (ext4fs_indir1_block == NULL) {
printf("** TI ext2fs read block (indir 2 1)"
"malloc failed. **\n");
return -1;
}
ext4fs_indir1_size = blksz;
ext4fs_indir1_blkno = -1;
}
if (blksz != ext4fs_indir1_size) {
free(ext4fs_indir1_block);
ext4fs_indir1_block = NULL;
ext4fs_indir1_size = 0;
ext4fs_indir1_blkno = -1;
ext4fs_indir1_block = zalloc(blksz);
if (ext4fs_indir1_block == NULL) {
printf("** TI ext2fs read block (indir 2 1)"
"malloc failed. **\n");
return -1;
}
ext4fs_indir1_size = blksz;
}
if ((le32_to_cpu(inode->b.blocks.triple_indir_block) <<
log2_blksz) != ext4fs_indir1_blkno) {
status = ext4fs_devread
le32_to_cpu(inode->b.blocks.triple_indir_block)
<< log2_blksz, 0, blksz,
(char *)ext4fs_indir1_block);
if (status == 0) {
printf("** TI ext2fs read block (indir 2 1)"
"failed. **\n");
return -1;
}
ext4fs_indir1_blkno =
le32_to_cpu(inode->b.blocks.triple_indir_block) <<
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
log2_blksz;
}
if (ext4fs_indir2_block == NULL) {
ext4fs_indir2_block = zalloc(blksz);
if (ext4fs_indir2_block == NULL) {
printf("** TI ext2fs read block (indir 2 2)"
"malloc failed. **\n");
return -1;
}
ext4fs_indir2_size = blksz;
ext4fs_indir2_blkno = -1;
}
if (blksz != ext4fs_indir2_size) {
free(ext4fs_indir2_block);
ext4fs_indir2_block = NULL;
ext4fs_indir2_size = 0;
ext4fs_indir2_blkno = -1;
ext4fs_indir2_block = zalloc(blksz);
if (ext4fs_indir2_block == NULL) {
printf("** TI ext2fs read block (indir 2 2)"
"malloc failed. **\n");
return -1;
}
ext4fs_indir2_size = blksz;
}
if ((le32_to_cpu(ext4fs_indir1_block[rblock /
perblock_parent]) <<
log2_blksz)
!= ext4fs_indir2_blkno) {
status = ext4fs_devread((lbaint_t)le32_to_cpu
(ext4fs_indir1_block
[rblock /
perblock_parent]) <<
log2_blksz, 0, blksz,
(char *)ext4fs_indir2_block);
if (status == 0) {
printf("** TI ext2fs read block (indir 2 2)"
"failed. **\n");
return -1;
}
ext4fs_indir2_blkno =
le32_to_cpu(ext4fs_indir1_block[rblock /
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
perblock_parent])
<< log2_blksz;
}
if (ext4fs_indir3_block == NULL) {
ext4fs_indir3_block = zalloc(blksz);
if (ext4fs_indir3_block == NULL) {
printf("** TI ext2fs read block (indir 2 2)"
"malloc failed. **\n");
return -1;
}
ext4fs_indir3_size = blksz;
ext4fs_indir3_blkno = -1;
}
if (blksz != ext4fs_indir3_size) {
free(ext4fs_indir3_block);
ext4fs_indir3_block = NULL;
ext4fs_indir3_size = 0;
ext4fs_indir3_blkno = -1;
ext4fs_indir3_block = zalloc(blksz);
if (ext4fs_indir3_block == NULL) {
printf("** TI ext2fs read block (indir 2 2)"
"malloc failed. **\n");
return -1;
}
ext4fs_indir3_size = blksz;
}
if ((le32_to_cpu(ext4fs_indir2_block[rblock
/
perblock_child]) <<
log2_blksz) != ext4fs_indir3_blkno) {
status =
ext4fs_devread((lbaint_t)le32_to_cpu
(ext4fs_indir2_block
[(rblock / perblock_child)
% (blksz / 4)]) << log2_blksz, 0,
blksz, (char *)ext4fs_indir3_block);
if (status == 0) {
printf("** TI ext2fs read block (indir 2 2)"
"failed. **\n");
return -1;
}
ext4fs_indir3_blkno =
le32_to_cpu(ext4fs_indir2_block[(rblock /
perblock_child) %
(blksz /
4)]) <<
log2_blksz;
}
blknr = le32_to_cpu(ext4fs_indir3_block
debug("read_allocated_block %ld\n", blknr);
/**
* ext4fs_reinit_global() - Reinitialize values of ext4 write implementation's
* global pointers
*
* This function assures that for a file with the same name but different size
* the sequential store on the ext4 filesystem will be correct.
*
* In this function the global data, responsible for internal representation
* of the ext4 data are initialized to the reset state. Without this, during
* replacement of the smaller file with the bigger truncation of new file was
* performed.
*/
void ext4fs_reinit_global(void)
{
if (ext4fs_indir1_block != NULL) {
free(ext4fs_indir1_block);
ext4fs_indir1_block = NULL;
ext4fs_indir1_size = 0;
ext4fs_indir1_blkno = -1;
}
if (ext4fs_indir2_block != NULL) {
free(ext4fs_indir2_block);
ext4fs_indir2_block = NULL;
ext4fs_indir2_size = 0;
ext4fs_indir2_blkno = -1;
}
if (ext4fs_indir3_block != NULL) {
free(ext4fs_indir3_block);
ext4fs_indir3_block = NULL;
ext4fs_indir3_size = 0;
ext4fs_indir3_blkno = -1;
}
}
void ext4fs_close(void)
{
if ((ext4fs_file != NULL) && (ext4fs_root != NULL)) {
ext4fs_free_node(ext4fs_file, &ext4fs_root->diropen);
ext4fs_file = NULL;
}
if (ext4fs_root != NULL) {
free(ext4fs_root);
ext4fs_root = NULL;
}
ext4fs_reinit_global();
}
int ext4fs_iterate_dir(struct ext2fs_node *dir, char *name,
struct ext2fs_node **fnode, int *ftype)
{
unsigned int fpos = 0;
int status;
struct ext2fs_node *diro = (struct ext2fs_node *) dir;
#ifdef DEBUG
if (name != NULL)
printf("Iterate dir %s\n", name);
#endif /* of DEBUG */
if (!diro->inode_read) {
status = ext4fs_read_inode(diro->data, diro->ino, &diro->inode);
if (status == 0)
return 0;
}
/* Search the file. */
while (fpos < le32_to_cpu(diro->inode.size)) {
struct ext2_dirent dirent;
status = ext4fs_read_file(diro, fpos,
sizeof(struct ext2_dirent),
(char *)&dirent, &actread);
if (status < 0)
if (dirent.direntlen == 0) {
printf("Failed to iterate over directory %s\n", name);
return 0;
}
if (dirent.namelen != 0) {
char filename[dirent.namelen + 1];
struct ext2fs_node *fdiro;
int type = FILETYPE_UNKNOWN;
status = ext4fs_read_file(diro,
fpos +
sizeof(struct ext2_dirent),
dirent.namelen, filename,
&actread);
if (status < 0)
return 0;
fdiro = zalloc(sizeof(struct ext2fs_node));
if (!fdiro)
return 0;
fdiro->data = diro->data;
fdiro->ino = le32_to_cpu(dirent.inode);
filename[dirent.namelen] = '\0';
if (dirent.filetype != FILETYPE_UNKNOWN) {
fdiro->inode_read = 0;
if (dirent.filetype == FILETYPE_DIRECTORY)
type = FILETYPE_DIRECTORY;
else if (dirent.filetype == FILETYPE_SYMLINK)
type = FILETYPE_SYMLINK;
else if (dirent.filetype == FILETYPE_REG)
type = FILETYPE_REG;
} else {
status = ext4fs_read_inode(diro->data,
(dirent.inode),
&fdiro->inode);
if (status == 0) {
free(fdiro);
return 0;
}
fdiro->inode_read = 1;
if ((le16_to_cpu(fdiro->inode.mode) &
FILETYPE_INO_MASK) ==
FILETYPE_INO_DIRECTORY) {
type = FILETYPE_DIRECTORY;
} else if ((le16_to_cpu(fdiro->inode.mode)
& FILETYPE_INO_MASK) ==
FILETYPE_INO_SYMLINK) {
type = FILETYPE_SYMLINK;
} else if ((le16_to_cpu(fdiro->inode.mode)
& FILETYPE_INO_MASK) ==
FILETYPE_INO_REG) {
type = FILETYPE_REG;
}
}
#ifdef DEBUG
printf("iterate >%s<\n", filename);
#endif /* of DEBUG */
if ((name != NULL) && (fnode != NULL)
&& (ftype != NULL)) {
if (strcmp(filename, name) == 0) {
*ftype = type;
*fnode = fdiro;
return 1;
}
} else {
if (fdiro->inode_read == 0) {
status = ext4fs_read_inode(diro->data,
dirent.inode),
&fdiro->inode);
if (status == 0) {