Home | History | Annotate | Download | only in ext4
      1 // SPDX-License-Identifier: GPL-2.0+
      2 /*
      3  * (C) Copyright 2011 - 2012 Samsung Electronics
      4  * EXT4 filesystem implementation in Uboot by
      5  * Uma Shankar <uma.shankar (at) samsung.com>
      6  * Manjunatha C Achar <a.manjunatha (at) samsung.com>
      7  *
      8  * ext4ls and ext4load : Based on ext2 ls load support in Uboot.
      9  *
     10  * (C) Copyright 2004
     11  * esd gmbh <www.esd-electronics.com>
     12  * Reinhard Arlt <reinhard.arlt (at) esd-electronics.com>
     13  *
     14  * based on code from grub2 fs/ext2.c and fs/fshelp.c by
     15  * GRUB  --  GRand Unified Bootloader
     16  * Copyright (C) 2003, 2004  Free Software Foundation, Inc.
     17  *
     18  * ext4write : Based on generic ext4 protocol.
     19  */
     20 
     21 #include <common.h>
     22 #include <ext_common.h>
     23 #include <ext4fs.h>
     24 #include <inttypes.h>
     25 #include <malloc.h>
     26 #include <memalign.h>
     27 #include <stddef.h>
     28 #include <linux/stat.h>
     29 #include <linux/time.h>
     30 #include <asm/byteorder.h>
     31 #include "ext4_common.h"
     32 
     33 struct ext2_data *ext4fs_root;
     34 struct ext2fs_node *ext4fs_file;
     35 __le32 *ext4fs_indir1_block;
     36 int ext4fs_indir1_size;
     37 int ext4fs_indir1_blkno = -1;
     38 __le32 *ext4fs_indir2_block;
     39 int ext4fs_indir2_size;
     40 int ext4fs_indir2_blkno = -1;
     41 
     42 __le32 *ext4fs_indir3_block;
     43 int ext4fs_indir3_size;
     44 int ext4fs_indir3_blkno = -1;
     45 struct ext2_inode *g_parent_inode;
     46 static int symlinknest;
     47 
     48 #if defined(CONFIG_EXT4_WRITE)
     49 struct ext2_block_group *ext4fs_get_group_descriptor
     50 	(const struct ext_filesystem *fs, uint32_t bg_idx)
     51 {
     52 	return (struct ext2_block_group *)(fs->gdtable + (bg_idx * fs->gdsize));
     53 }
     54 
     55 static inline void ext4fs_sb_free_inodes_dec(struct ext2_sblock *sb)
     56 {
     57 	sb->free_inodes = cpu_to_le32(le32_to_cpu(sb->free_inodes) - 1);
     58 }
     59 
     60 static inline void ext4fs_sb_free_blocks_dec(struct ext2_sblock *sb)
     61 {
     62 	uint64_t free_blocks = le32_to_cpu(sb->free_blocks);
     63 	free_blocks += (uint64_t)le32_to_cpu(sb->free_blocks_high) << 32;
     64 	free_blocks--;
     65 
     66 	sb->free_blocks = cpu_to_le32(free_blocks & 0xffffffff);
     67 	sb->free_blocks_high = cpu_to_le16(free_blocks >> 32);
     68 }
     69 
     70 static inline void ext4fs_bg_free_inodes_dec
     71 	(struct ext2_block_group *bg, const struct ext_filesystem *fs)
     72 {
     73 	uint32_t free_inodes = le16_to_cpu(bg->free_inodes);
     74 	if (fs->gdsize == 64)
     75 		free_inodes += le16_to_cpu(bg->free_inodes_high) << 16;
     76 	free_inodes--;
     77 
     78 	bg->free_inodes = cpu_to_le16(free_inodes & 0xffff);
     79 	if (fs->gdsize == 64)
     80 		bg->free_inodes_high = cpu_to_le16(free_inodes >> 16);
     81 }
     82 
     83 static inline void ext4fs_bg_free_blocks_dec
     84 	(struct ext2_block_group *bg, const struct ext_filesystem *fs)
     85 {
     86 	uint32_t free_blocks = le16_to_cpu(bg->free_blocks);
     87 	if (fs->gdsize == 64)
     88 		free_blocks += le16_to_cpu(bg->free_blocks_high) << 16;
     89 	free_blocks--;
     90 
     91 	bg->free_blocks = cpu_to_le16(free_blocks & 0xffff);
     92 	if (fs->gdsize == 64)
     93 		bg->free_blocks_high = cpu_to_le16(free_blocks >> 16);
     94 }
     95 
     96 static inline void ext4fs_bg_itable_unused_dec
     97 	(struct ext2_block_group *bg, const struct ext_filesystem *fs)
     98 {
     99 	uint32_t free_inodes = le16_to_cpu(bg->bg_itable_unused);
    100 	if (fs->gdsize == 64)
    101 		free_inodes += le16_to_cpu(bg->bg_itable_unused_high) << 16;
    102 	free_inodes--;
    103 
    104 	bg->bg_itable_unused = cpu_to_le16(free_inodes & 0xffff);
    105 	if (fs->gdsize == 64)
    106 		bg->bg_itable_unused_high = cpu_to_le16(free_inodes >> 16);
    107 }
    108 
    109 uint64_t ext4fs_sb_get_free_blocks(const struct ext2_sblock *sb)
    110 {
    111 	uint64_t free_blocks = le32_to_cpu(sb->free_blocks);
    112 	free_blocks += (uint64_t)le32_to_cpu(sb->free_blocks_high) << 32;
    113 	return free_blocks;
    114 }
    115 
    116 void ext4fs_sb_set_free_blocks(struct ext2_sblock *sb, uint64_t free_blocks)
    117 {
    118 	sb->free_blocks = cpu_to_le32(free_blocks & 0xffffffff);
    119 	sb->free_blocks_high = cpu_to_le16(free_blocks >> 32);
    120 }
    121 
    122 uint32_t ext4fs_bg_get_free_blocks(const struct ext2_block_group *bg,
    123 				   const struct ext_filesystem *fs)
    124 {
    125 	uint32_t free_blocks = le16_to_cpu(bg->free_blocks);
    126 	if (fs->gdsize == 64)
    127 		free_blocks += le16_to_cpu(bg->free_blocks_high) << 16;
    128 	return free_blocks;
    129 }
    130 
    131 static inline
    132 uint32_t ext4fs_bg_get_free_inodes(const struct ext2_block_group *bg,
    133 				   const struct ext_filesystem *fs)
    134 {
    135 	uint32_t free_inodes = le16_to_cpu(bg->free_inodes);
    136 	if (fs->gdsize == 64)
    137 		free_inodes += le16_to_cpu(bg->free_inodes_high) << 16;
    138 	return free_inodes;
    139 }
    140 
    141 static inline uint16_t ext4fs_bg_get_flags(const struct ext2_block_group *bg)
    142 {
    143 	return le16_to_cpu(bg->bg_flags);
    144 }
    145 
    146 static inline void ext4fs_bg_set_flags(struct ext2_block_group *bg,
    147 				       uint16_t flags)
    148 {
    149 	bg->bg_flags = cpu_to_le16(flags);
    150 }
    151 
    152 /* Block number of the block bitmap */
    153 uint64_t ext4fs_bg_get_block_id(const struct ext2_block_group *bg,
    154 				const struct ext_filesystem *fs)
    155 {
    156 	uint64_t block_nr = le32_to_cpu(bg->block_id);
    157 	if (fs->gdsize == 64)
    158 		block_nr += (uint64_t)le32_to_cpu(bg->block_id_high) << 32;
    159 	return block_nr;
    160 }
    161 
    162 /* Block number of the inode bitmap */
    163 uint64_t ext4fs_bg_get_inode_id(const struct ext2_block_group *bg,
    164 				const struct ext_filesystem *fs)
    165 {
    166 	uint64_t block_nr = le32_to_cpu(bg->inode_id);
    167 	if (fs->gdsize == 64)
    168 		block_nr += (uint64_t)le32_to_cpu(bg->inode_id_high) << 32;
    169 	return block_nr;
    170 }
    171 #endif
    172 
    173 /* Block number of the inode table */
    174 uint64_t ext4fs_bg_get_inode_table_id(const struct ext2_block_group *bg,
    175 				      const struct ext_filesystem *fs)
    176 {
    177 	uint64_t block_nr = le32_to_cpu(bg->inode_table_id);
    178 	if (fs->gdsize == 64)
    179 		block_nr +=
    180 			(uint64_t)le32_to_cpu(bg->inode_table_id_high) << 32;
    181 	return block_nr;
    182 }
    183 
    184 #if defined(CONFIG_EXT4_WRITE)
    185 uint32_t ext4fs_div_roundup(uint32_t size, uint32_t n)
    186 {
    187 	uint32_t res = size / n;
    188 	if (res * n != size)
    189 		res++;
    190 
    191 	return res;
    192 }
    193 
    194 void put_ext4(uint64_t off, void *buf, uint32_t size)
    195 {
    196 	uint64_t startblock;
    197 	uint64_t remainder;
    198 	unsigned char *temp_ptr = NULL;
    199 	struct ext_filesystem *fs = get_fs();
    200 	int log2blksz = fs->dev_desc->log2blksz;
    201 	ALLOC_CACHE_ALIGN_BUFFER(unsigned char, sec_buf, fs->dev_desc->blksz);
    202 
    203 	startblock = off >> log2blksz;
    204 	startblock += part_offset;
    205 	remainder = off & (uint64_t)(fs->dev_desc->blksz - 1);
    206 
    207 	if (fs->dev_desc == NULL)
    208 		return;
    209 
    210 	if ((startblock + (size >> log2blksz)) >
    211 	    (part_offset + fs->total_sect)) {
    212 		printf("part_offset is " LBAFU "\n", part_offset);
    213 		printf("total_sector is %" PRIu64 "\n", fs->total_sect);
    214 		printf("error: overflow occurs\n");
    215 		return;
    216 	}
    217 
    218 	if (remainder) {
    219 		blk_dread(fs->dev_desc, startblock, 1, sec_buf);
    220 		temp_ptr = sec_buf;
    221 		memcpy((temp_ptr + remainder), (unsigned char *)buf, size);
    222 		blk_dwrite(fs->dev_desc, startblock, 1, sec_buf);
    223 	} else {
    224 		if (size >> log2blksz != 0) {
    225 			blk_dwrite(fs->dev_desc, startblock, size >> log2blksz,
    226 				   (unsigned long *)buf);
    227 		} else {
    228 			blk_dread(fs->dev_desc, startblock, 1, sec_buf);
    229 			temp_ptr = sec_buf;
    230 			memcpy(temp_ptr, buf, size);
    231 			blk_dwrite(fs->dev_desc, startblock, 1,
    232 				   (unsigned long *)sec_buf);
    233 		}
    234 	}
    235 }
    236 
    237 static int _get_new_inode_no(unsigned char *buffer)
    238 {
    239 	struct ext_filesystem *fs = get_fs();
    240 	unsigned char input;
    241 	int operand, status;
    242 	int count = 1;
    243 	int j = 0;
    244 
    245 	/* get the blocksize of the filesystem */
    246 	unsigned char *ptr = buffer;
    247 	while (*ptr == 255) {
    248 		ptr++;
    249 		count += 8;
    250 		if (count > le32_to_cpu(ext4fs_root->sblock.inodes_per_group))
    251 			return -1;
    252 	}
    253 
    254 	for (j = 0; j < fs->blksz; j++) {
    255 		input = *ptr;
    256 		int i = 0;
    257 		while (i <= 7) {
    258 			operand = 1 << i;
    259 			status = input & operand;
    260 			if (status) {
    261 				i++;
    262 				count++;
    263 			} else {
    264 				*ptr |= operand;
    265 				return count;
    266 			}
    267 		}
    268 		ptr = ptr + 1;
    269 	}
    270 
    271 	return -1;
    272 }
    273 
    274 static int _get_new_blk_no(unsigned char *buffer)
    275 {
    276 	int operand;
    277 	int count = 0;
    278 	int i;
    279 	unsigned char *ptr = buffer;
    280 	struct ext_filesystem *fs = get_fs();
    281 
    282 	while (*ptr == 255) {
    283 		ptr++;
    284 		count += 8;
    285 		if (count == (fs->blksz * 8))
    286 			return -1;
    287 	}
    288 
    289 	if (fs->blksz == 1024)
    290 		count += 1;
    291 
    292 	for (i = 0; i <= 7; i++) {
    293 		operand = 1 << i;
    294 		if (*ptr & operand) {
    295 			count++;
    296 		} else {
    297 			*ptr |= operand;
    298 			return count;
    299 		}
    300 	}
    301 
    302 	return -1;
    303 }
    304 
    305 int ext4fs_set_block_bmap(long int blockno, unsigned char *buffer, int index)
    306 {
    307 	int i, remainder, status;
    308 	unsigned char *ptr = buffer;
    309 	unsigned char operand;
    310 	i = blockno / 8;
    311 	remainder = blockno % 8;
    312 	int blocksize = EXT2_BLOCK_SIZE(ext4fs_root);
    313 
    314 	i = i - (index * blocksize);
    315 	if (blocksize != 1024) {
    316 		ptr = ptr + i;
    317 		operand = 1 << remainder;
    318 		status = *ptr & operand;
    319 		if (status)
    320 			return -1;
    321 
    322 		*ptr = *ptr | operand;
    323 		return 0;
    324 	} else {
    325 		if (remainder == 0) {
    326 			ptr = ptr + i - 1;
    327 			operand = (1 << 7);
    328 		} else {
    329 			ptr = ptr + i;
    330 			operand = (1 << (remainder - 1));
    331 		}
    332 		status = *ptr & operand;
    333 		if (status)
    334 			return -1;
    335 
    336 		*ptr = *ptr | operand;
    337 		return 0;
    338 	}
    339 }
    340 
    341 void ext4fs_reset_block_bmap(long int blockno, unsigned char *buffer, int index)
    342 {
    343 	int i, remainder, status;
    344 	unsigned char *ptr = buffer;
    345 	unsigned char operand;
    346 	i = blockno / 8;
    347 	remainder = blockno % 8;
    348 	int blocksize = EXT2_BLOCK_SIZE(ext4fs_root);
    349 
    350 	i = i - (index * blocksize);
    351 	if (blocksize != 1024) {
    352 		ptr = ptr + i;
    353 		operand = (1 << remainder);
    354 		status = *ptr & operand;
    355 		if (status)
    356 			*ptr = *ptr & ~(operand);
    357 	} else {
    358 		if (remainder == 0) {
    359 			ptr = ptr + i - 1;
    360 			operand = (1 << 7);
    361 		} else {
    362 			ptr = ptr + i;
    363 			operand = (1 << (remainder - 1));
    364 		}
    365 		status = *ptr & operand;
    366 		if (status)
    367 			*ptr = *ptr & ~(operand);
    368 	}
    369 }
    370 
    371 int ext4fs_set_inode_bmap(int inode_no, unsigned char *buffer, int index)
    372 {
    373 	int i, remainder, status;
    374 	unsigned char *ptr = buffer;
    375 	unsigned char operand;
    376 
    377 	inode_no -= (index * le32_to_cpu(ext4fs_root->sblock.inodes_per_group));
    378 	i = inode_no / 8;
    379 	remainder = inode_no % 8;
    380 	if (remainder == 0) {
    381 		ptr = ptr + i - 1;
    382 		operand = (1 << 7);
    383 	} else {
    384 		ptr = ptr + i;
    385 		operand = (1 << (remainder - 1));
    386 	}
    387 	status = *ptr & operand;
    388 	if (status)
    389 		return -1;
    390 
    391 	*ptr = *ptr | operand;
    392 
    393 	return 0;
    394 }
    395 
    396 void ext4fs_reset_inode_bmap(int inode_no, unsigned char *buffer, int index)
    397 {
    398 	int i, remainder, status;
    399 	unsigned char *ptr = buffer;
    400 	unsigned char operand;
    401 
    402 	inode_no -= (index * le32_to_cpu(ext4fs_root->sblock.inodes_per_group));
    403 	i = inode_no / 8;
    404 	remainder = inode_no % 8;
    405 	if (remainder == 0) {
    406 		ptr = ptr + i - 1;
    407 		operand = (1 << 7);
    408 	} else {
    409 		ptr = ptr + i;
    410 		operand = (1 << (remainder - 1));
    411 	}
    412 	status = *ptr & operand;
    413 	if (status)
    414 		*ptr = *ptr & ~(operand);
    415 }
    416 
    417 uint16_t ext4fs_checksum_update(uint32_t i)
    418 {
    419 	struct ext2_block_group *desc;
    420 	struct ext_filesystem *fs = get_fs();
    421 	uint16_t crc = 0;
    422 	__le32 le32_i = cpu_to_le32(i);
    423 
    424 	desc = ext4fs_get_group_descriptor(fs, i);
    425 	if (le32_to_cpu(fs->sb->feature_ro_compat) & EXT4_FEATURE_RO_COMPAT_GDT_CSUM) {
    426 		int offset = offsetof(struct ext2_block_group, bg_checksum);
    427 
    428 		crc = ext2fs_crc16(~0, fs->sb->unique_id,
    429 				   sizeof(fs->sb->unique_id));
    430 		crc = ext2fs_crc16(crc, &le32_i, sizeof(le32_i));
    431 		crc = ext2fs_crc16(crc, desc, offset);
    432 		offset += sizeof(desc->bg_checksum);	/* skip checksum */
    433 		assert(offset == sizeof(*desc));
    434 		if (offset < fs->gdsize) {
    435 			crc = ext2fs_crc16(crc, (__u8 *)desc + offset,
    436 					   fs->gdsize - offset);
    437 		}
    438 	}
    439 
    440 	return crc;
    441 }
    442 
    443 static int check_void_in_dentry(struct ext2_dirent *dir, char *filename)
    444 {
    445 	int dentry_length;
    446 	int sizeof_void_space;
    447 	int new_entry_byte_reqd;
    448 	short padding_factor = 0;
    449 
    450 	if (dir->namelen % 4 != 0)
    451 		padding_factor = 4 - (dir->namelen % 4);
    452 
    453 	dentry_length = sizeof(struct ext2_dirent) +
    454 			dir->namelen + padding_factor;
    455 	sizeof_void_space = le16_to_cpu(dir->direntlen) - dentry_length;
    456 	if (sizeof_void_space == 0)
    457 		return 0;
    458 
    459 	padding_factor = 0;
    460 	if (strlen(filename) % 4 != 0)
    461 		padding_factor = 4 - (strlen(filename) % 4);
    462 
    463 	new_entry_byte_reqd = strlen(filename) +
    464 	    sizeof(struct ext2_dirent) + padding_factor;
    465 	if (sizeof_void_space >= new_entry_byte_reqd) {
    466 		dir->direntlen = cpu_to_le16(dentry_length);
    467 		return sizeof_void_space;
    468 	}
    469 
    470 	return 0;
    471 }
    472 
    473 int ext4fs_update_parent_dentry(char *filename, int file_type)
    474 {
    475 	unsigned int *zero_buffer = NULL;
    476 	char *root_first_block_buffer = NULL;
    477 	int blk_idx;
    478 	long int first_block_no_of_root = 0;
    479 	int totalbytes = 0;
    480 	unsigned int new_entry_byte_reqd;
    481 	int sizeof_void_space = 0;
    482 	int templength = 0;
    483 	int inodeno = -1;
    484 	int status;
    485 	struct ext_filesystem *fs = get_fs();
    486 	/* directory entry */
    487 	struct ext2_dirent *dir;
    488 	char *temp_dir = NULL;
    489 	uint32_t new_blk_no;
    490 	uint32_t new_size;
    491 	uint32_t new_blockcnt;
    492 	uint32_t directory_blocks;
    493 
    494 	zero_buffer = zalloc(fs->blksz);
    495 	if (!zero_buffer) {
    496 		printf("No Memory\n");
    497 		return -1;
    498 	}
    499 	root_first_block_buffer = zalloc(fs->blksz);
    500 	if (!root_first_block_buffer) {
    501 		free(zero_buffer);
    502 		printf("No Memory\n");
    503 		return -1;
    504 	}
    505 	new_entry_byte_reqd = ROUND(strlen(filename) +
    506 				    sizeof(struct ext2_dirent), 4);
    507 restart:
    508 	directory_blocks = le32_to_cpu(g_parent_inode->size) >>
    509 		LOG2_BLOCK_SIZE(ext4fs_root);
    510 	blk_idx = directory_blocks - 1;
    511 
    512 restart_read:
    513 	/* read the block no allocated to a file */
    514 	first_block_no_of_root = read_allocated_block(g_parent_inode, blk_idx);
    515 	if (first_block_no_of_root <= 0)
    516 		goto fail;
    517 
    518 	status = ext4fs_devread((lbaint_t)first_block_no_of_root
    519 				* fs->sect_perblk,
    520 				0, fs->blksz, root_first_block_buffer);
    521 	if (status == 0)
    522 		goto fail;
    523 
    524 	if (ext4fs_log_journal(root_first_block_buffer, first_block_no_of_root))
    525 		goto fail;
    526 	dir = (struct ext2_dirent *)root_first_block_buffer;
    527 	totalbytes = 0;
    528 
    529 	while (le16_to_cpu(dir->direntlen) > 0) {
    530 		unsigned short used_len = ROUND(dir->namelen +
    531 		    sizeof(struct ext2_dirent), 4);
    532 
    533 		/* last entry of block */
    534 		if (fs->blksz - totalbytes == le16_to_cpu(dir->direntlen)) {
    535 
    536 			/* check if new entry fits */
    537 			if ((used_len + new_entry_byte_reqd) <=
    538 			    le16_to_cpu(dir->direntlen)) {
    539 				dir->direntlen = cpu_to_le16(used_len);
    540 				break;
    541 			} else {
    542 				if (blk_idx > 0) {
    543 					printf("Block full, trying previous\n");
    544 					blk_idx--;
    545 					goto restart_read;
    546 				}
    547 				printf("All blocks full: Allocate new\n");
    548 
    549 				if (le32_to_cpu(g_parent_inode->flags) &
    550 						EXT4_EXTENTS_FL) {
    551 					printf("Directory uses extents\n");
    552 					goto fail;
    553 				}
    554 				if (directory_blocks >= INDIRECT_BLOCKS) {
    555 					printf("Directory exceeds limit\n");
    556 					goto fail;
    557 				}
    558 				new_blk_no = ext4fs_get_new_blk_no();
    559 				if (new_blk_no == -1) {
    560 					printf("no block left to assign\n");
    561 					goto fail;
    562 				}
    563 				put_ext4((uint64_t)new_blk_no * fs->blksz, zero_buffer, fs->blksz);
    564 				g_parent_inode->b.blocks.
    565 					dir_blocks[directory_blocks] =
    566 					cpu_to_le32(new_blk_no);
    567 
    568 				new_size = le32_to_cpu(g_parent_inode->size);
    569 				new_size += fs->blksz;
    570 				g_parent_inode->size = cpu_to_le32(new_size);
    571 
    572 				new_blockcnt = le32_to_cpu(g_parent_inode->blockcnt);
    573 				new_blockcnt += fs->sect_perblk;
    574 				g_parent_inode->blockcnt = cpu_to_le32(new_blockcnt);
    575 
    576 				if (ext4fs_put_metadata
    577 				    (root_first_block_buffer,
    578 				     first_block_no_of_root))
    579 					goto fail;
    580 				goto restart;
    581 			}
    582 		}
    583 
    584 		templength = le16_to_cpu(dir->direntlen);
    585 		totalbytes = totalbytes + templength;
    586 		sizeof_void_space = check_void_in_dentry(dir, filename);
    587 		if (sizeof_void_space)
    588 			break;
    589 
    590 		dir = (struct ext2_dirent *)((char *)dir + templength);
    591 	}
    592 
    593 	/* make a pointer ready for creating next directory entry */
    594 	templength = le16_to_cpu(dir->direntlen);
    595 	totalbytes = totalbytes + templength;
    596 	dir = (struct ext2_dirent *)((char *)dir + templength);
    597 
    598 	/* get the next available inode number */
    599 	inodeno = ext4fs_get_new_inode_no();
    600 	if (inodeno == -1) {
    601 		printf("no inode left to assign\n");
    602 		goto fail;
    603 	}
    604 	dir->inode = cpu_to_le32(inodeno);
    605 	if (sizeof_void_space)
    606 		dir->direntlen = cpu_to_le16(sizeof_void_space);
    607 	else
    608 		dir->direntlen = cpu_to_le16(fs->blksz - totalbytes);
    609 
    610 	dir->namelen = strlen(filename);
    611 	dir->filetype = FILETYPE_REG;	/* regular file */
    612 	temp_dir = (char *)dir;
    613 	temp_dir = temp_dir + sizeof(struct ext2_dirent);
    614 	memcpy(temp_dir, filename, strlen(filename));
    615 
    616 	/* update or write  the 1st block of root inode */
    617 	if (ext4fs_put_metadata(root_first_block_buffer,
    618 				first_block_no_of_root))
    619 		goto fail;
    620 
    621 fail:
    622 	free(zero_buffer);
    623 	free(root_first_block_buffer);
    624 
    625 	return inodeno;
    626 }
    627 
    628 static int search_dir(struct ext2_inode *parent_inode, char *dirname)
    629 {
    630 	int status;
    631 	int inodeno = 0;
    632 	int offset;
    633 	int blk_idx;
    634 	long int blknr;
    635 	char *block_buffer = NULL;
    636 	struct ext2_dirent *dir = NULL;
    637 	struct ext_filesystem *fs = get_fs();
    638 	uint32_t directory_blocks;
    639 	char *direntname;
    640 
    641 	directory_blocks = le32_to_cpu(parent_inode->size) >>
    642 		LOG2_BLOCK_SIZE(ext4fs_root);
    643 
    644 	block_buffer = zalloc(fs->blksz);
    645 	if (!block_buffer)
    646 		goto fail;
    647 
    648 	/* get the block no allocated to a file */
    649 	for (blk_idx = 0; blk_idx < directory_blocks; blk_idx++) {
    650 		blknr = read_allocated_block(parent_inode, blk_idx);
    651 		if (blknr <= 0)
    652 			goto fail;
    653 
    654 		/* read the directory block */
    655 		status = ext4fs_devread((lbaint_t)blknr * fs->sect_perblk,
    656 					0, fs->blksz, (char *)block_buffer);
    657 		if (status == 0)
    658 			goto fail;
    659 
    660 		offset = 0;
    661 		do {
    662 			if (offset & 3) {
    663 				printf("Badly aligned ext2_dirent\n");
    664 				break;
    665 			}
    666 
    667 			dir = (struct ext2_dirent *)(block_buffer + offset);
    668 			direntname = (char*)(dir) + sizeof(struct ext2_dirent);
    669 
    670 			int direntlen = le16_to_cpu(dir->direntlen);
    671 			if (direntlen < sizeof(struct ext2_dirent))
    672 				break;
    673 
    674 			if (dir->inode && (strlen(dirname) == dir->namelen) &&
    675 			    (strncmp(dirname, direntname, dir->namelen) == 0)) {
    676 				inodeno = le32_to_cpu(dir->inode);
    677 				break;
    678 			}
    679 
    680 			offset += direntlen;
    681 
    682 		} while (offset < fs->blksz);
    683 
    684 		if (inodeno > 0) {
    685 			free(block_buffer);
    686 			return inodeno;
    687 		}
    688 	}
    689 
    690 fail:
    691 	free(block_buffer);
    692 
    693 	return -1;
    694 }
    695 
    696 static int find_dir_depth(char *dirname)
    697 {
    698 	char *token = strtok(dirname, "/");
    699 	int count = 0;
    700 	while (token != NULL) {
    701 		token = strtok(NULL, "/");
    702 		count++;
    703 	}
    704 	return count + 1 + 1;
    705 	/*
    706 	 * for example  for string /home/temp
    707 	 * depth=home(1)+temp(1)+1 extra for NULL;
    708 	 * so count is 4;
    709 	 */
    710 }
    711 
    712 static int parse_path(char **arr, char *dirname)
    713 {
    714 	char *token = strtok(dirname, "/");
    715 	int i = 0;
    716 
    717 	/* add root */
    718 	arr[i] = zalloc(strlen("/") + 1);
    719 	if (!arr[i])
    720 		return -ENOMEM;
    721 	memcpy(arr[i++], "/", strlen("/"));
    722 
    723 	/* add each path entry after root */
    724 	while (token != NULL) {
    725 		arr[i] = zalloc(strlen(token) + 1);
    726 		if (!arr[i])
    727 			return -ENOMEM;
    728 		memcpy(arr[i++], token, strlen(token));
    729 		token = strtok(NULL, "/");
    730 	}
    731 	arr[i] = NULL;
    732 
    733 	return 0;
    734 }
    735 
    736 int ext4fs_iget(int inode_no, struct ext2_inode *inode)
    737 {
    738 	if (ext4fs_read_inode(ext4fs_root, inode_no, inode) == 0)
    739 		return -1;
    740 
    741 	return 0;
    742 }
    743 
    744 /*
    745  * Function: ext4fs_get_parent_inode_num
    746  * Return Value: inode Number of the parent directory of  file/Directory to be
    747  * created
    748  * dirname : Input parmater, input path name of the file/directory to be created
    749  * dname : Output parameter, to be filled with the name of the directory
    750  * extracted from dirname
    751  */
    752 int ext4fs_get_parent_inode_num(const char *dirname, char *dname, int flags)
    753 {
    754 	int i;
    755 	int depth = 0;
    756 	int matched_inode_no;
    757 	int result_inode_no = -1;
    758 	char **ptr = NULL;
    759 	char *depth_dirname = NULL;
    760 	char *parse_dirname = NULL;
    761 	struct ext2_inode *parent_inode = NULL;
    762 	struct ext2_inode *first_inode = NULL;
    763 	struct ext2_inode temp_inode;
    764 
    765 	if (*dirname != '/') {
    766 		printf("Please supply Absolute path\n");
    767 		return -1;
    768 	}
    769 
    770 	/* TODO: input validation make equivalent to linux */
    771 	depth_dirname = zalloc(strlen(dirname) + 1);
    772 	if (!depth_dirname)
    773 		return -ENOMEM;
    774 
    775 	memcpy(depth_dirname, dirname, strlen(dirname));
    776 	depth = find_dir_depth(depth_dirname);
    777 	parse_dirname = zalloc(strlen(dirname) + 1);
    778 	if (!parse_dirname)
    779 		goto fail;
    780 	memcpy(parse_dirname, dirname, strlen(dirname));
    781 
    782 	/* allocate memory for each directory level */
    783 	ptr = zalloc((depth) * sizeof(char *));
    784 	if (!ptr)
    785 		goto fail;
    786 	if (parse_path(ptr, parse_dirname))
    787 		goto fail;
    788 	parent_inode = zalloc(sizeof(struct ext2_inode));
    789 	if (!parent_inode)
    790 		goto fail;
    791 	first_inode = zalloc(sizeof(struct ext2_inode));
    792 	if (!first_inode)
    793 		goto fail;
    794 	memcpy(parent_inode, ext4fs_root->inode, sizeof(struct ext2_inode));
    795 	memcpy(first_inode, parent_inode, sizeof(struct ext2_inode));
    796 	if (flags & F_FILE)
    797 		result_inode_no = EXT2_ROOT_INO;
    798 	for (i = 1; i < depth; i++) {
    799 		matched_inode_no = search_dir(parent_inode, ptr[i]);
    800 		if (matched_inode_no == -1) {
    801 			if (ptr[i + 1] == NULL && i == 1) {
    802 				result_inode_no = EXT2_ROOT_INO;
    803 				goto end;
    804 			} else {
    805 				if (ptr[i + 1] == NULL)
    806 					break;
    807 				printf("Invalid path\n");
    808 				result_inode_no = -1;
    809 				goto fail;
    810 			}
    811 		} else {
    812 			if (ptr[i + 1] != NULL) {
    813 				memset(parent_inode, '\0',
    814 				       sizeof(struct ext2_inode));
    815 				if (ext4fs_iget(matched_inode_no,
    816 						parent_inode)) {
    817 					result_inode_no = -1;
    818 					goto fail;
    819 				}
    820 				result_inode_no = matched_inode_no;
    821 			} else {
    822 				break;
    823 			}
    824 		}
    825 	}
    826 
    827 end:
    828 	if (i == 1)
    829 		matched_inode_no = search_dir(first_inode, ptr[i]);
    830 	else
    831 		matched_inode_no = search_dir(parent_inode, ptr[i]);
    832 
    833 	if (matched_inode_no != -1) {
    834 		ext4fs_iget(matched_inode_no, &temp_inode);
    835 		if (le16_to_cpu(temp_inode.mode) & S_IFDIR) {
    836 			printf("It is a Directory\n");
    837 			result_inode_no = -1;
    838 			goto fail;
    839 		}
    840 	}
    841 
    842 	if (strlen(ptr[i]) > 256) {
    843 		result_inode_no = -1;
    844 		goto fail;
    845 	}
    846 	memcpy(dname, ptr[i], strlen(ptr[i]));
    847 
    848 fail:
    849 	free(depth_dirname);
    850 	free(parse_dirname);
    851 	for (i = 0; i < depth; i++) {
    852 		if (!ptr[i])
    853 			break;
    854 		free(ptr[i]);
    855 	}
    856 	free(ptr);
    857 	free(parent_inode);
    858 	free(first_inode);
    859 
    860 	return result_inode_no;
    861 }
    862 
    863 static int unlink_filename(char *filename, unsigned int blknr)
    864 {
    865 	int status;
    866 	int inodeno = 0;
    867 	int offset;
    868 	char *block_buffer = NULL;
    869 	struct ext2_dirent *dir = NULL;
    870 	struct ext2_dirent *previous_dir;
    871 	struct ext_filesystem *fs = get_fs();
    872 	int ret = -1;
    873 	char *direntname;
    874 
    875 	block_buffer = zalloc(fs->blksz);
    876 	if (!block_buffer)
    877 		return -ENOMEM;
    878 
    879 	/* read the directory block */
    880 	status = ext4fs_devread((lbaint_t)blknr * fs->sect_perblk, 0,
    881 				fs->blksz, block_buffer);
    882 	if (status == 0)
    883 		goto fail;
    884 
    885 	offset = 0;
    886 	do {
    887 		if (offset & 3) {
    888 			printf("Badly aligned ext2_dirent\n");
    889 			break;
    890 		}
    891 
    892 		previous_dir = dir;
    893 		dir = (struct ext2_dirent *)(block_buffer + offset);
    894 		direntname = (char *)(dir) + sizeof(struct ext2_dirent);
    895 
    896 		int direntlen = le16_to_cpu(dir->direntlen);
    897 		if (direntlen < sizeof(struct ext2_dirent))
    898 			break;
    899 
    900 		if (dir->inode && (strlen(filename) == dir->namelen) &&
    901 		    (strncmp(direntname, filename, dir->namelen) == 0)) {
    902 			inodeno = le32_to_cpu(dir->inode);
    903 			break;
    904 		}
    905 
    906 		offset += direntlen;
    907 
    908 	} while (offset < fs->blksz);
    909 
    910 	if (inodeno > 0) {
    911 		printf("file found, deleting\n");
    912 		if (ext4fs_log_journal(block_buffer, blknr))
    913 			goto fail;
    914 
    915 		if (previous_dir) {
    916 			/* merge dir entry with predecessor */
    917 			uint16_t new_len;
    918 			new_len = le16_to_cpu(previous_dir->direntlen);
    919 			new_len += le16_to_cpu(dir->direntlen);
    920 			previous_dir->direntlen = cpu_to_le16(new_len);
    921 		} else {
    922 			/* invalidate dir entry */
    923 			dir->inode = 0;
    924 		}
    925 		if (ext4fs_put_metadata(block_buffer, blknr))
    926 			goto fail;
    927 		ret = inodeno;
    928 	}
    929 fail:
    930 	free(block_buffer);
    931 
    932 	return ret;
    933 }
    934 
    935 int ext4fs_filename_unlink(char *filename)
    936 {
    937 	int blk_idx;
    938 	long int blknr = -1;
    939 	int inodeno = -1;
    940 	uint32_t directory_blocks;
    941 
    942 	directory_blocks = le32_to_cpu(g_parent_inode->size) >>
    943 		LOG2_BLOCK_SIZE(ext4fs_root);
    944 
    945 	/* read the block no allocated to a file */
    946 	for (blk_idx = 0; blk_idx < directory_blocks; blk_idx++) {
    947 		blknr = read_allocated_block(g_parent_inode, blk_idx);
    948 		if (blknr <= 0)
    949 			break;
    950 		inodeno = unlink_filename(filename, blknr);
    951 		if (inodeno != -1)
    952 			return inodeno;
    953 	}
    954 
    955 	return -1;
    956 }
    957 
    958 uint32_t ext4fs_get_new_blk_no(void)
    959 {
    960 	short i;
    961 	short status;
    962 	int remainder;
    963 	unsigned int bg_idx;
    964 	static int prev_bg_bitmap_index = -1;
    965 	unsigned int blk_per_grp = le32_to_cpu(ext4fs_root->sblock.blocks_per_group);
    966 	struct ext_filesystem *fs = get_fs();
    967 	char *journal_buffer = zalloc(fs->blksz);
    968 	char *zero_buffer = zalloc(fs->blksz);
    969 	if (!journal_buffer || !zero_buffer)
    970 		goto fail;
    971 
    972 	if (fs->first_pass_bbmap == 0) {
    973 		for (i = 0; i < fs->no_blkgrp; i++) {
    974 			struct ext2_block_group *bgd = NULL;
    975 			bgd = ext4fs_get_group_descriptor(fs, i);
    976 			if (ext4fs_bg_get_free_blocks(bgd, fs)) {
    977 				uint16_t bg_flags = ext4fs_bg_get_flags(bgd);
    978 				uint64_t b_bitmap_blk =
    979 					ext4fs_bg_get_block_id(bgd, fs);
    980 				if (bg_flags & EXT4_BG_BLOCK_UNINIT) {
    981 					memcpy(fs->blk_bmaps[i], zero_buffer,
    982 					       fs->blksz);
    983 					put_ext4(b_bitmap_blk * fs->blksz,
    984 						 fs->blk_bmaps[i], fs->blksz);
    985 					bg_flags &= ~EXT4_BG_BLOCK_UNINIT;
    986 					ext4fs_bg_set_flags(bgd, bg_flags);
    987 				}
    988 				fs->curr_blkno =
    989 				    _get_new_blk_no(fs->blk_bmaps[i]);
    990 				if (fs->curr_blkno == -1)
    991 					/* block bitmap is completely filled */
    992 					continue;
    993 				fs->curr_blkno = fs->curr_blkno +
    994 						(i * fs->blksz * 8);
    995 				fs->first_pass_bbmap++;
    996 				ext4fs_bg_free_blocks_dec(bgd, fs);
    997 				ext4fs_sb_free_blocks_dec(fs->sb);
    998 				status = ext4fs_devread(b_bitmap_blk *
    999 							fs->sect_perblk,
   1000 							0, fs->blksz,
   1001 							journal_buffer);
   1002 				if (status == 0)
   1003 					goto fail;
   1004 				if (ext4fs_log_journal(journal_buffer,
   1005 						       b_bitmap_blk))
   1006 					goto fail;
   1007 				goto success;
   1008 			} else {
   1009 				debug("no space left on block group %d\n", i);
   1010 			}
   1011 		}
   1012 
   1013 		goto fail;
   1014 	} else {
   1015 		fs->curr_blkno++;
   1016 restart:
   1017 		/* get the blockbitmap index respective to blockno */
   1018 		bg_idx = fs->curr_blkno / blk_per_grp;
   1019 		if (fs->blksz == 1024) {
   1020 			remainder = fs->curr_blkno % blk_per_grp;
   1021 			if (!remainder)
   1022 				bg_idx--;
   1023 		}
   1024 
   1025 		/*
   1026 		 * To skip completely filled block group bitmaps
   1027 		 * Optimize the block allocation
   1028 		 */
   1029 		if (bg_idx >= fs->no_blkgrp)
   1030 			goto fail;
   1031 
   1032 		struct ext2_block_group *bgd = NULL;
   1033 		bgd = ext4fs_get_group_descriptor(fs, bg_idx);
   1034 		if (ext4fs_bg_get_free_blocks(bgd, fs) == 0) {
   1035 			debug("block group %u is full. Skipping\n", bg_idx);
   1036 			fs->curr_blkno = (bg_idx + 1) * blk_per_grp;
   1037 			if (fs->blksz == 1024)
   1038 				fs->curr_blkno += 1;
   1039 			goto restart;
   1040 		}
   1041 
   1042 		uint16_t bg_flags = ext4fs_bg_get_flags(bgd);
   1043 		uint64_t b_bitmap_blk = ext4fs_bg_get_block_id(bgd, fs);
   1044 		if (bg_flags & EXT4_BG_BLOCK_UNINIT) {
   1045 			memcpy(fs->blk_bmaps[bg_idx], zero_buffer, fs->blksz);
   1046 			put_ext4(b_bitmap_blk * fs->blksz,
   1047 				 zero_buffer, fs->blksz);
   1048 			bg_flags &= ~EXT4_BG_BLOCK_UNINIT;
   1049 			ext4fs_bg_set_flags(bgd, bg_flags);
   1050 		}
   1051 
   1052 		if (ext4fs_set_block_bmap(fs->curr_blkno, fs->blk_bmaps[bg_idx],
   1053 				   bg_idx) != 0) {
   1054 			debug("going for restart for the block no %ld %u\n",
   1055 			      fs->curr_blkno, bg_idx);
   1056 			fs->curr_blkno++;
   1057 			goto restart;
   1058 		}
   1059 
   1060 		/* journal backup */
   1061 		if (prev_bg_bitmap_index != bg_idx) {
   1062 			status = ext4fs_devread(b_bitmap_blk * fs->sect_perblk,
   1063 						0, fs->blksz, journal_buffer);
   1064 			if (status == 0)
   1065 				goto fail;
   1066 			if (ext4fs_log_journal(journal_buffer, b_bitmap_blk))
   1067 				goto fail;
   1068 
   1069 			prev_bg_bitmap_index = bg_idx;
   1070 		}
   1071 		ext4fs_bg_free_blocks_dec(bgd, fs);
   1072 		ext4fs_sb_free_blocks_dec(fs->sb);
   1073 		goto success;
   1074 	}
   1075 success:
   1076 	free(journal_buffer);
   1077 	free(zero_buffer);
   1078 
   1079 	return fs->curr_blkno;
   1080 fail:
   1081 	free(journal_buffer);
   1082 	free(zero_buffer);
   1083 
   1084 	return -1;
   1085 }
   1086 
   1087 int ext4fs_get_new_inode_no(void)
   1088 {
   1089 	short i;
   1090 	short status;
   1091 	unsigned int ibmap_idx;
   1092 	static int prev_inode_bitmap_index = -1;
   1093 	unsigned int inodes_per_grp = le32_to_cpu(ext4fs_root->sblock.inodes_per_group);
   1094 	struct ext_filesystem *fs = get_fs();
   1095 	char *journal_buffer = zalloc(fs->blksz);
   1096 	char *zero_buffer = zalloc(fs->blksz);
   1097 	if (!journal_buffer || !zero_buffer)
   1098 		goto fail;
   1099 	int has_gdt_chksum = le32_to_cpu(fs->sb->feature_ro_compat) &
   1100 		EXT4_FEATURE_RO_COMPAT_GDT_CSUM ? 1 : 0;
   1101 
   1102 	if (fs->first_pass_ibmap == 0) {
   1103 		for (i = 0; i < fs->no_blkgrp; i++) {
   1104 			uint32_t free_inodes;
   1105 			struct ext2_block_group *bgd = NULL;
   1106 			bgd = ext4fs_get_group_descriptor(fs, i);
   1107 			free_inodes = ext4fs_bg_get_free_inodes(bgd, fs);
   1108 			if (free_inodes) {
   1109 				uint16_t bg_flags = ext4fs_bg_get_flags(bgd);
   1110 				uint64_t i_bitmap_blk =
   1111 					ext4fs_bg_get_inode_id(bgd, fs);
   1112 				if (has_gdt_chksum)
   1113 					bgd->bg_itable_unused = free_inodes;
   1114 				if (bg_flags & EXT4_BG_INODE_UNINIT) {
   1115 					put_ext4(i_bitmap_blk * fs->blksz,
   1116 						 zero_buffer, fs->blksz);
   1117 					bg_flags &= ~EXT4_BG_INODE_UNINIT;
   1118 					ext4fs_bg_set_flags(bgd, bg_flags);
   1119 					memcpy(fs->inode_bmaps[i],
   1120 					       zero_buffer, fs->blksz);
   1121 				}
   1122 				fs->curr_inode_no =
   1123 				    _get_new_inode_no(fs->inode_bmaps[i]);
   1124 				if (fs->curr_inode_no == -1)
   1125 					/* inode bitmap is completely filled */
   1126 					continue;
   1127 				fs->curr_inode_no = fs->curr_inode_no +
   1128 							(i * inodes_per_grp);
   1129 				fs->first_pass_ibmap++;
   1130 				ext4fs_bg_free_inodes_dec(bgd, fs);
   1131 				if (has_gdt_chksum)
   1132 					ext4fs_bg_itable_unused_dec(bgd, fs);
   1133 				ext4fs_sb_free_inodes_dec(fs->sb);
   1134 				status = ext4fs_devread(i_bitmap_blk *
   1135 							fs->sect_perblk,
   1136 							0, fs->blksz,
   1137 							journal_buffer);
   1138 				if (status == 0)
   1139 					goto fail;
   1140 				if (ext4fs_log_journal(journal_buffer,
   1141 						       i_bitmap_blk))
   1142 					goto fail;
   1143 				goto success;
   1144 			} else
   1145 				debug("no inode left on block group %d\n", i);
   1146 		}
   1147 		goto fail;
   1148 	} else {
   1149 restart:
   1150 		fs->curr_inode_no++;
   1151 		/* get the blockbitmap index respective to blockno */
   1152 		ibmap_idx = fs->curr_inode_no / inodes_per_grp;
   1153 		struct ext2_block_group *bgd =
   1154 			ext4fs_get_group_descriptor(fs, ibmap_idx);
   1155 		uint16_t bg_flags = ext4fs_bg_get_flags(bgd);
   1156 		uint64_t i_bitmap_blk = ext4fs_bg_get_inode_id(bgd, fs);
   1157 
   1158 		if (bg_flags & EXT4_BG_INODE_UNINIT) {
   1159 			put_ext4(i_bitmap_blk * fs->blksz,
   1160 				 zero_buffer, fs->blksz);
   1161 			bg_flags &= ~EXT4_BG_INODE_UNINIT;
   1162 			ext4fs_bg_set_flags(bgd, bg_flags);
   1163 			memcpy(fs->inode_bmaps[ibmap_idx], zero_buffer,
   1164 				fs->blksz);
   1165 		}
   1166 
   1167 		if (ext4fs_set_inode_bmap(fs->curr_inode_no,
   1168 					  fs->inode_bmaps[ibmap_idx],
   1169 					  ibmap_idx) != 0) {
   1170 			debug("going for restart for the block no %d %u\n",
   1171 			      fs->curr_inode_no, ibmap_idx);
   1172 			goto restart;
   1173 		}
   1174 
   1175 		/* journal backup */
   1176 		if (prev_inode_bitmap_index != ibmap_idx) {
   1177 			status = ext4fs_devread(i_bitmap_blk * fs->sect_perblk,
   1178 						0, fs->blksz, journal_buffer);
   1179 			if (status == 0)
   1180 				goto fail;
   1181 			if (ext4fs_log_journal(journal_buffer,
   1182 						le32_to_cpu(bgd->inode_id)))
   1183 				goto fail;
   1184 			prev_inode_bitmap_index = ibmap_idx;
   1185 		}
   1186 		ext4fs_bg_free_inodes_dec(bgd, fs);
   1187 		if (has_gdt_chksum)
   1188 			bgd->bg_itable_unused = bgd->free_inodes;
   1189 		ext4fs_sb_free_inodes_dec(fs->sb);
   1190 		goto success;
   1191 	}
   1192 
   1193 success:
   1194 	free(journal_buffer);
   1195 	free(zero_buffer);
   1196 
   1197 	return fs->curr_inode_no;
   1198 fail:
   1199 	free(journal_buffer);
   1200 	free(zero_buffer);
   1201 
   1202 	return -1;
   1203 
   1204 }
   1205 
   1206 
   1207 static void alloc_single_indirect_block(struct ext2_inode *file_inode,
   1208 					unsigned int *total_remaining_blocks,
   1209 					unsigned int *no_blks_reqd)
   1210 {
   1211 	short i;
   1212 	short status;
   1213 	long int actual_block_no;
   1214 	long int si_blockno;
   1215 	/* si :single indirect */
   1216 	__le32 *si_buffer = NULL;
   1217 	__le32 *si_start_addr = NULL;
   1218 	struct ext_filesystem *fs = get_fs();
   1219 
   1220 	if (*total_remaining_blocks != 0) {
   1221 		si_buffer = zalloc(fs->blksz);
   1222 		if (!si_buffer) {
   1223 			printf("No Memory\n");
   1224 			return;
   1225 		}
   1226 		si_start_addr = si_buffer;
   1227 		si_blockno = ext4fs_get_new_blk_no();
   1228 		if (si_blockno == -1) {
   1229 			printf("no block left to assign\n");
   1230 			goto fail;
   1231 		}
   1232 		(*no_blks_reqd)++;
   1233 		debug("SIPB %ld: %u\n", si_blockno, *total_remaining_blocks);
   1234 
   1235 		status = ext4fs_devread((lbaint_t)si_blockno * fs->sect_perblk,
   1236 					0, fs->blksz, (char *)si_buffer);
   1237 		memset(si_buffer, '\0', fs->blksz);
   1238 		if (status == 0)
   1239 			goto fail;
   1240 
   1241 		for (i = 0; i < (fs->blksz / sizeof(int)); i++) {
   1242 			actual_block_no = ext4fs_get_new_blk_no();
   1243 			if (actual_block_no == -1) {
   1244 				printf("no block left to assign\n");
   1245 				goto fail;
   1246 			}
   1247 			*si_buffer = cpu_to_le32(actual_block_no);
   1248 			debug("SIAB %u: %u\n", *si_buffer,
   1249 				*total_remaining_blocks);
   1250 
   1251 			si_buffer++;
   1252 			(*total_remaining_blocks)--;
   1253 			if (*total_remaining_blocks == 0)
   1254 				break;
   1255 		}
   1256 
   1257 		/* write the block to disk */
   1258 		put_ext4(((uint64_t) ((uint64_t)si_blockno * (uint64_t)fs->blksz)),
   1259 			 si_start_addr, fs->blksz);
   1260 		file_inode->b.blocks.indir_block = cpu_to_le32(si_blockno);
   1261 	}
   1262 fail:
   1263 	free(si_start_addr);
   1264 }
   1265 
   1266 static void alloc_double_indirect_block(struct ext2_inode *file_inode,
   1267 					unsigned int *total_remaining_blocks,
   1268 					unsigned int *no_blks_reqd)
   1269 {
   1270 	short i;
   1271 	short j;
   1272 	short status;
   1273 	long int actual_block_no;
   1274 	/* di:double indirect */
   1275 	long int di_blockno_parent;
   1276 	long int di_blockno_child;
   1277 	__le32 *di_parent_buffer = NULL;
   1278 	__le32 *di_child_buff = NULL;
   1279 	__le32 *di_block_start_addr = NULL;
   1280 	__le32 *di_child_buff_start = NULL;
   1281 	struct ext_filesystem *fs = get_fs();
   1282 
   1283 	if (*total_remaining_blocks != 0) {
   1284 		/* double indirect parent block connecting to inode */
   1285 		di_blockno_parent = ext4fs_get_new_blk_no();
   1286 		if (di_blockno_parent == -1) {
   1287 			printf("no block left to assign\n");
   1288 			goto fail;
   1289 		}
   1290 		di_parent_buffer = zalloc(fs->blksz);
   1291 		if (!di_parent_buffer)
   1292 			goto fail;
   1293 
   1294 		di_block_start_addr = di_parent_buffer;
   1295 		(*no_blks_reqd)++;
   1296 		debug("DIPB %ld: %u\n", di_blockno_parent,
   1297 		      *total_remaining_blocks);
   1298 
   1299 		status = ext4fs_devread((lbaint_t)di_blockno_parent *
   1300 					fs->sect_perblk, 0,
   1301 					fs->blksz, (char *)di_parent_buffer);
   1302 
   1303 		if (!status) {
   1304 			printf("%s: Device read error!\n", __func__);
   1305 			goto fail;
   1306 		}
   1307 		memset(di_parent_buffer, '\0', fs->blksz);
   1308 
   1309 		/*
   1310 		 * start:for each double indirect parent
   1311 		 * block create one more block
   1312 		 */
   1313 		for (i = 0; i < (fs->blksz / sizeof(int)); i++) {
   1314 			di_blockno_child = ext4fs_get_new_blk_no();
   1315 			if (di_blockno_child == -1) {
   1316 				printf("no block left to assign\n");
   1317 				goto fail;
   1318 			}
   1319 			di_child_buff = zalloc(fs->blksz);
   1320 			if (!di_child_buff)
   1321 				goto fail;
   1322 
   1323 			di_child_buff_start = di_child_buff;
   1324 			*di_parent_buffer = cpu_to_le32(di_blockno_child);
   1325 			di_parent_buffer++;
   1326 			(*no_blks_reqd)++;
   1327 			debug("DICB %ld: %u\n", di_blockno_child,
   1328 			      *total_remaining_blocks);
   1329 
   1330 			status = ext4fs_devread((lbaint_t)di_blockno_child *
   1331 						fs->sect_perblk, 0,
   1332 						fs->blksz,
   1333 						(char *)di_child_buff);
   1334 
   1335 			if (!status) {
   1336 				printf("%s: Device read error!\n", __func__);
   1337 				goto fail;
   1338 			}
   1339 			memset(di_child_buff, '\0', fs->blksz);
   1340 			/* filling of actual datablocks for each child */
   1341 			for (j = 0; j < (fs->blksz / sizeof(int)); j++) {
   1342 				actual_block_no = ext4fs_get_new_blk_no();
   1343 				if (actual_block_no == -1) {
   1344 					printf("no block left to assign\n");
   1345 					goto fail;
   1346 				}
   1347 				*di_child_buff = cpu_to_le32(actual_block_no);
   1348 				debug("DIAB %ld: %u\n", actual_block_no,
   1349 				      *total_remaining_blocks);
   1350 
   1351 				di_child_buff++;
   1352 				(*total_remaining_blocks)--;
   1353 				if (*total_remaining_blocks == 0)
   1354 					break;
   1355 			}
   1356 			/* write the block  table */
   1357 			put_ext4(((uint64_t) ((uint64_t)di_blockno_child * (uint64_t)fs->blksz)),
   1358 				 di_child_buff_start, fs->blksz);
   1359 			free(di_child_buff_start);
   1360 			di_child_buff_start = NULL;
   1361 
   1362 			if (*total_remaining_blocks == 0)
   1363 				break;
   1364 		}
   1365 		put_ext4(((uint64_t) ((uint64_t)di_blockno_parent * (uint64_t)fs->blksz)),
   1366 			 di_block_start_addr, fs->blksz);
   1367 		file_inode->b.blocks.double_indir_block = cpu_to_le32(di_blockno_parent);
   1368 	}
   1369 fail:
   1370 	free(di_block_start_addr);
   1371 }
   1372 
   1373 static void alloc_triple_indirect_block(struct ext2_inode *file_inode,
   1374 					unsigned int *total_remaining_blocks,
   1375 					unsigned int *no_blks_reqd)
   1376 {
   1377 	short i;
   1378 	short j;
   1379 	short k;
   1380 	long int actual_block_no;
   1381 	/* ti: Triple Indirect */
   1382 	long int ti_gp_blockno;
   1383 	long int ti_parent_blockno;
   1384 	long int ti_child_blockno;
   1385 	__le32 *ti_gp_buff = NULL;
   1386 	__le32 *ti_parent_buff = NULL;
   1387 	__le32 *ti_child_buff = NULL;
   1388 	__le32 *ti_gp_buff_start_addr = NULL;
   1389 	__le32 *ti_pbuff_start_addr = NULL;
   1390 	__le32 *ti_cbuff_start_addr = NULL;
   1391 	struct ext_filesystem *fs = get_fs();
   1392 	if (*total_remaining_blocks != 0) {
   1393 		/* triple indirect grand parent block connecting to inode */
   1394 		ti_gp_blockno = ext4fs_get_new_blk_no();
   1395 		if (ti_gp_blockno == -1) {
   1396 			printf("no block left to assign\n");
   1397 			return;
   1398 		}
   1399 		ti_gp_buff = zalloc(fs->blksz);
   1400 		if (!ti_gp_buff)
   1401 			return;
   1402 
   1403 		ti_gp_buff_start_addr = ti_gp_buff;
   1404 		(*no_blks_reqd)++;
   1405 		debug("TIGPB %ld: %u\n", ti_gp_blockno,
   1406 		      *total_remaining_blocks);
   1407 
   1408 		/* for each 4 byte grand parent entry create one more block */
   1409 		for (i = 0; i < (fs->blksz / sizeof(int)); i++) {
   1410 			ti_parent_blockno = ext4fs_get_new_blk_no();
   1411 			if (ti_parent_blockno == -1) {
   1412 				printf("no block left to assign\n");
   1413 				goto fail;
   1414 			}
   1415 			ti_parent_buff = zalloc(fs->blksz);
   1416 			if (!ti_parent_buff)
   1417 				goto fail;
   1418 
   1419 			ti_pbuff_start_addr = ti_parent_buff;
   1420 			*ti_gp_buff = cpu_to_le32(ti_parent_blockno);
   1421 			ti_gp_buff++;
   1422 			(*no_blks_reqd)++;
   1423 			debug("TIPB %ld: %u\n", ti_parent_blockno,
   1424 			      *total_remaining_blocks);
   1425 
   1426 			/* for each 4 byte entry parent create one more block */
   1427 			for (j = 0; j < (fs->blksz / sizeof(int)); j++) {
   1428 				ti_child_blockno = ext4fs_get_new_blk_no();
   1429 				if (ti_child_blockno == -1) {
   1430 					printf("no block left assign\n");
   1431 					goto fail1;
   1432 				}
   1433 				ti_child_buff = zalloc(fs->blksz);
   1434 				if (!ti_child_buff)
   1435 					goto fail1;
   1436 
   1437 				ti_cbuff_start_addr = ti_child_buff;
   1438 				*ti_parent_buff = cpu_to_le32(ti_child_blockno);
   1439 				ti_parent_buff++;
   1440 				(*no_blks_reqd)++;
   1441 				debug("TICB %ld: %u\n", ti_parent_blockno,
   1442 				      *total_remaining_blocks);
   1443 
   1444 				/* fill actual datablocks for each child */
   1445 				for (k = 0; k < (fs->blksz / sizeof(int));
   1446 					k++) {
   1447 					actual_block_no =
   1448 					    ext4fs_get_new_blk_no();
   1449 					if (actual_block_no == -1) {
   1450 						printf("no block left\n");
   1451 						free(ti_cbuff_start_addr);
   1452 						goto fail1;
   1453 					}
   1454 					*ti_child_buff = cpu_to_le32(actual_block_no);
   1455 					debug("TIAB %ld: %u\n", actual_block_no,
   1456 					      *total_remaining_blocks);
   1457 
   1458 					ti_child_buff++;
   1459 					(*total_remaining_blocks)--;
   1460 					if (*total_remaining_blocks == 0)
   1461 						break;
   1462 				}
   1463 				/* write the child block */
   1464 				put_ext4(((uint64_t) ((uint64_t)ti_child_blockno *
   1465 						      (uint64_t)fs->blksz)),
   1466 					 ti_cbuff_start_addr, fs->blksz);
   1467 				free(ti_cbuff_start_addr);
   1468 
   1469 				if (*total_remaining_blocks == 0)
   1470 					break;
   1471 			}
   1472 			/* write the parent block */
   1473 			put_ext4(((uint64_t) ((uint64_t)ti_parent_blockno * (uint64_t)fs->blksz)),
   1474 				 ti_pbuff_start_addr, fs->blksz);
   1475 			free(ti_pbuff_start_addr);
   1476 
   1477 			if (*total_remaining_blocks == 0)
   1478 				break;
   1479 		}
   1480 		/* write the grand parent block */
   1481 		put_ext4(((uint64_t) ((uint64_t)ti_gp_blockno * (uint64_t)fs->blksz)),
   1482 			 ti_gp_buff_start_addr, fs->blksz);
   1483 		file_inode->b.blocks.triple_indir_block = cpu_to_le32(ti_gp_blockno);
   1484 		free(ti_gp_buff_start_addr);
   1485 		return;
   1486 	}
   1487 fail1:
   1488 	free(ti_pbuff_start_addr);
   1489 fail:
   1490 	free(ti_gp_buff_start_addr);
   1491 }
   1492 
   1493 void ext4fs_allocate_blocks(struct ext2_inode *file_inode,
   1494 				unsigned int total_remaining_blocks,
   1495 				unsigned int *total_no_of_block)
   1496 {
   1497 	short i;
   1498 	long int direct_blockno;
   1499 	unsigned int no_blks_reqd = 0;
   1500 
   1501 	/* allocation of direct blocks */
   1502 	for (i = 0; total_remaining_blocks && i < INDIRECT_BLOCKS; i++) {
   1503 		direct_blockno = ext4fs_get_new_blk_no();
   1504 		if (direct_blockno == -1) {
   1505 			printf("no block left to assign\n");
   1506 			return;
   1507 		}
   1508 		file_inode->b.blocks.dir_blocks[i] = cpu_to_le32(direct_blockno);
   1509 		debug("DB %ld: %u\n", direct_blockno, total_remaining_blocks);
   1510 
   1511 		total_remaining_blocks--;
   1512 	}
   1513 
   1514 	alloc_single_indirect_block(file_inode, &total_remaining_blocks,
   1515 				    &no_blks_reqd);
   1516 	alloc_double_indirect_block(file_inode, &total_remaining_blocks,
   1517 				    &no_blks_reqd);
   1518 	alloc_triple_indirect_block(file_inode, &total_remaining_blocks,
   1519 				    &no_blks_reqd);
   1520 	*total_no_of_block += no_blks_reqd;
   1521 }
   1522 
   1523 #endif
   1524 
   1525 static struct ext4_extent_header *ext4fs_get_extent_block
   1526 	(struct ext2_data *data, char *buf,
   1527 		struct ext4_extent_header *ext_block,
   1528 		uint32_t fileblock, int log2_blksz)
   1529 {
   1530 	struct ext4_extent_idx *index;
   1531 	unsigned long long block;
   1532 	int blksz = EXT2_BLOCK_SIZE(data);
   1533 	int i;
   1534 
   1535 	while (1) {
   1536 		index = (struct ext4_extent_idx *)(ext_block + 1);
   1537 
   1538 		if (le16_to_cpu(ext_block->eh_magic) != EXT4_EXT_MAGIC)
   1539 			return NULL;
   1540 
   1541 		if (ext_block->eh_depth == 0)
   1542 			return ext_block;
   1543 		i = -1;
   1544 		do {
   1545 			i++;
   1546 			if (i >= le16_to_cpu(ext_block->eh_entries))
   1547 				break;
   1548 		} while (fileblock >= le32_to_cpu(index[i].ei_block));
   1549 
   1550 		if (--i < 0)
   1551 			return NULL;
   1552 
   1553 		block = le16_to_cpu(index[i].ei_leaf_hi);
   1554 		block = (block << 32) + le32_to_cpu(index[i].ei_leaf_lo);
   1555 
   1556 		if (ext4fs_devread((lbaint_t)block << log2_blksz, 0, blksz,
   1557 				   buf))
   1558 			ext_block = (struct ext4_extent_header *)buf;
   1559 		else
   1560 			return NULL;
   1561 	}
   1562 }
   1563 
   1564 static int ext4fs_blockgroup
   1565 	(struct ext2_data *data, int group, struct ext2_block_group *blkgrp)
   1566 {
   1567 	long int blkno;
   1568 	unsigned int blkoff, desc_per_blk;
   1569 	int log2blksz = get_fs()->dev_desc->log2blksz;
   1570 	int desc_size = get_fs()->gdsize;
   1571 
   1572 	desc_per_blk = EXT2_BLOCK_SIZE(data) / desc_size;
   1573 
   1574 	blkno = le32_to_cpu(data->sblock.first_data_block) + 1 +
   1575 			group / desc_per_blk;
   1576 	blkoff = (group % desc_per_blk) * desc_size;
   1577 
   1578 	debug("ext4fs read %d group descriptor (blkno %ld blkoff %u)\n",
   1579 	      group, blkno, blkoff);
   1580 
   1581 	return ext4fs_devread((lbaint_t)blkno <<
   1582 			      (LOG2_BLOCK_SIZE(data) - log2blksz),
   1583 			      blkoff, desc_size, (char *)blkgrp);
   1584 }
   1585 
   1586 int ext4fs_read_inode(struct ext2_data *data, int ino, struct ext2_inode *inode)
   1587 {
   1588 	struct ext2_block_group blkgrp;
   1589 	struct ext2_sblock *sblock = &data->sblock;
   1590 	struct ext_filesystem *fs = get_fs();
   1591 	int log2blksz = get_fs()->dev_desc->log2blksz;
   1592 	int inodes_per_block, status;
   1593 	long int blkno;
   1594 	unsigned int blkoff;
   1595 
   1596 	/* It is easier to calculate if the first inode is 0. */
   1597 	ino--;
   1598 	status = ext4fs_blockgroup(data, ino / le32_to_cpu
   1599 				   (sblock->inodes_per_group), &blkgrp);
   1600 	if (status == 0)
   1601 		return 0;
   1602 
   1603 	inodes_per_block = EXT2_BLOCK_SIZE(data) / fs->inodesz;
   1604 	blkno = ext4fs_bg_get_inode_table_id(&blkgrp, fs) +
   1605 	    (ino % le32_to_cpu(sblock->inodes_per_group)) / inodes_per_block;
   1606 	blkoff = (ino % inodes_per_block) * fs->inodesz;
   1607 	/* Read the inode. */
   1608 	status = ext4fs_devread((lbaint_t)blkno << (LOG2_BLOCK_SIZE(data) -
   1609 				log2blksz), blkoff,
   1610 				sizeof(struct ext2_inode), (char *)inode);
   1611 	if (status == 0)
   1612 		return 0;
   1613 
   1614 	return 1;
   1615 }
   1616 
   1617 long int read_allocated_block(struct ext2_inode *inode, int fileblock)
   1618 {
   1619 	long int blknr;
   1620 	int blksz;
   1621 	int log2_blksz;
   1622 	int status;
   1623 	long int rblock;
   1624 	long int perblock_parent;
   1625 	long int perblock_child;
   1626 	unsigned long long start;
   1627 	/* get the blocksize of the filesystem */
   1628 	blksz = EXT2_BLOCK_SIZE(ext4fs_root);
   1629 	log2_blksz = LOG2_BLOCK_SIZE(ext4fs_root)
   1630 		- get_fs()->dev_desc->log2blksz;
   1631 
   1632 	if (le32_to_cpu(inode->flags) & EXT4_EXTENTS_FL) {
   1633 		long int startblock, endblock;
   1634 		char *buf = zalloc(blksz);
   1635 		if (!buf)
   1636 			return -ENOMEM;
   1637 		struct ext4_extent_header *ext_block;
   1638 		struct ext4_extent *extent;
   1639 		int i;
   1640 		ext_block =
   1641 			ext4fs_get_extent_block(ext4fs_root, buf,
   1642 						(struct ext4_extent_header *)
   1643 						inode->b.blocks.dir_blocks,
   1644 						fileblock, log2_blksz);
   1645 		if (!ext_block) {
   1646 			printf("invalid extent block\n");
   1647 			free(buf);
   1648 			return -EINVAL;
   1649 		}
   1650 
   1651 		extent = (struct ext4_extent *)(ext_block + 1);
   1652 
   1653 		for (i = 0; i < le16_to_cpu(ext_block->eh_entries); i++) {
   1654 			startblock = le32_to_cpu(extent[i].ee_block);
   1655 			endblock = startblock + le16_to_cpu(extent[i].ee_len);
   1656 
   1657 			if (startblock > fileblock) {
   1658 				/* Sparse file */
   1659 				free(buf);
   1660 				return 0;
   1661 
   1662 			} else if (fileblock < endblock) {
   1663 				start = le16_to_cpu(extent[i].ee_start_hi);
   1664 				start = (start << 32) +
   1665 					le32_to_cpu(extent[i].ee_start_lo);
   1666 				free(buf);
   1667 				return (fileblock - startblock) + start;
   1668 			}
   1669 		}
   1670 
   1671 		free(buf);
   1672 		return 0;
   1673 	}
   1674 
   1675 	/* Direct blocks. */
   1676 	if (fileblock < INDIRECT_BLOCKS)
   1677 		blknr = le32_to_cpu(inode->b.blocks.dir_blocks[fileblock]);
   1678 
   1679 	/* Indirect. */
   1680 	else if (fileblock < (INDIRECT_BLOCKS + (blksz / 4))) {
   1681 		if (ext4fs_indir1_block == NULL) {
   1682 			ext4fs_indir1_block = zalloc(blksz);
   1683 			if (ext4fs_indir1_block == NULL) {
   1684 				printf("** SI ext2fs read block (indir 1)"
   1685 					"malloc failed. **\n");
   1686 				return -1;
   1687 			}
   1688 			ext4fs_indir1_size = blksz;
   1689 			ext4fs_indir1_blkno = -1;
   1690 		}
   1691 		if (blksz != ext4fs_indir1_size) {
   1692 			free(ext4fs_indir1_block);
   1693 			ext4fs_indir1_block = NULL;
   1694 			ext4fs_indir1_size = 0;
   1695 			ext4fs_indir1_blkno = -1;
   1696 			ext4fs_indir1_block = zalloc(blksz);
   1697 			if (ext4fs_indir1_block == NULL) {
   1698 				printf("** SI ext2fs read block (indir 1):"
   1699 					"malloc failed. **\n");
   1700 				return -1;
   1701 			}
   1702 			ext4fs_indir1_size = blksz;
   1703 		}
   1704 		if ((le32_to_cpu(inode->b.blocks.indir_block) <<
   1705 		     log2_blksz) != ext4fs_indir1_blkno) {
   1706 			status =
   1707 			    ext4fs_devread((lbaint_t)le32_to_cpu
   1708 					   (inode->b.blocks.
   1709 					    indir_block) << log2_blksz, 0,
   1710 					   blksz, (char *)ext4fs_indir1_block);
   1711 			if (status == 0) {
   1712 				printf("** SI ext2fs read block (indir 1)"
   1713 					"failed. **\n");
   1714 				return -1;
   1715 			}
   1716 			ext4fs_indir1_blkno =
   1717 				le32_to_cpu(inode->b.blocks.
   1718 					       indir_block) << log2_blksz;
   1719 		}
   1720 		blknr = le32_to_cpu(ext4fs_indir1_block
   1721 				      [fileblock - INDIRECT_BLOCKS]);
   1722 	}
   1723 	/* Double indirect. */
   1724 	else if (fileblock < (INDIRECT_BLOCKS + (blksz / 4 *
   1725 					(blksz / 4 + 1)))) {
   1726 
   1727 		long int perblock = blksz / 4;
   1728 		long int rblock = fileblock - (INDIRECT_BLOCKS + blksz / 4);
   1729 
   1730 		if (ext4fs_indir1_block == NULL) {
   1731 			ext4fs_indir1_block = zalloc(blksz);
   1732 			if (ext4fs_indir1_block == NULL) {
   1733 				printf("** DI ext2fs read block (indir 2 1)"
   1734 					"malloc failed. **\n");
   1735 				return -1;
   1736 			}
   1737 			ext4fs_indir1_size = blksz;
   1738 			ext4fs_indir1_blkno = -1;
   1739 		}
   1740 		if (blksz != ext4fs_indir1_size) {
   1741 			free(ext4fs_indir1_block);
   1742 			ext4fs_indir1_block = NULL;
   1743 			ext4fs_indir1_size = 0;
   1744 			ext4fs_indir1_blkno = -1;
   1745 			ext4fs_indir1_block = zalloc(blksz);
   1746 			if (ext4fs_indir1_block == NULL) {
   1747 				printf("** DI ext2fs read block (indir 2 1)"
   1748 					"malloc failed. **\n");
   1749 				return -1;
   1750 			}
   1751 			ext4fs_indir1_size = blksz;
   1752 		}
   1753 		if ((le32_to_cpu(inode->b.blocks.double_indir_block) <<
   1754 		     log2_blksz) != ext4fs_indir1_blkno) {
   1755 			status =
   1756 			    ext4fs_devread((lbaint_t)le32_to_cpu
   1757 					   (inode->b.blocks.
   1758 					    double_indir_block) << log2_blksz,
   1759 					   0, blksz,
   1760 					   (char *)ext4fs_indir1_block);
   1761 			if (status == 0) {
   1762 				printf("** DI ext2fs read block (indir 2 1)"
   1763 					"failed. **\n");
   1764 				return -1;
   1765 			}
   1766 			ext4fs_indir1_blkno =
   1767 			    le32_to_cpu(inode->b.blocks.double_indir_block) <<
   1768 			    log2_blksz;
   1769 		}
   1770 
   1771 		if (ext4fs_indir2_block == NULL) {
   1772 			ext4fs_indir2_block = zalloc(blksz);
   1773 			if (ext4fs_indir2_block == NULL) {
   1774 				printf("** DI ext2fs read block (indir 2 2)"
   1775 					"malloc failed. **\n");
   1776 				return -1;
   1777 			}
   1778 			ext4fs_indir2_size = blksz;
   1779 			ext4fs_indir2_blkno = -1;
   1780 		}
   1781 		if (blksz != ext4fs_indir2_size) {
   1782 			free(ext4fs_indir2_block);
   1783 			ext4fs_indir2_block = NULL;
   1784 			ext4fs_indir2_size = 0;
   1785 			ext4fs_indir2_blkno = -1;
   1786 			ext4fs_indir2_block = zalloc(blksz);
   1787 			if (ext4fs_indir2_block == NULL) {
   1788 				printf("** DI ext2fs read block (indir 2 2)"
   1789 					"malloc failed. **\n");
   1790 				return -1;
   1791 			}
   1792 			ext4fs_indir2_size = blksz;
   1793 		}
   1794 		if ((le32_to_cpu(ext4fs_indir1_block[rblock / perblock]) <<
   1795 		     log2_blksz) != ext4fs_indir2_blkno) {
   1796 			status = ext4fs_devread((lbaint_t)le32_to_cpu
   1797 						(ext4fs_indir1_block
   1798 						 [rblock /
   1799 						  perblock]) << log2_blksz, 0,
   1800 						blksz,
   1801 						(char *)ext4fs_indir2_block);
   1802 			if (status == 0) {
   1803 				printf("** DI ext2fs read block (indir 2 2)"
   1804 					"failed. **\n");
   1805 				return -1;
   1806 			}
   1807 			ext4fs_indir2_blkno =
   1808 			    le32_to_cpu(ext4fs_indir1_block[rblock
   1809 							      /
   1810 							      perblock]) <<
   1811 			    log2_blksz;
   1812 		}
   1813 		blknr = le32_to_cpu(ext4fs_indir2_block[rblock % perblock]);
   1814 	}
   1815 	/* Tripple indirect. */
   1816 	else {
   1817 		rblock = fileblock - (INDIRECT_BLOCKS + blksz / 4 +
   1818 				      (blksz / 4 * blksz / 4));
   1819 		perblock_child = blksz / 4;
   1820 		perblock_parent = ((blksz / 4) * (blksz / 4));
   1821 
   1822 		if (ext4fs_indir1_block == NULL) {
   1823 			ext4fs_indir1_block = zalloc(blksz);
   1824 			if (ext4fs_indir1_block == NULL) {
   1825 				printf("** TI ext2fs read block (indir 2 1)"
   1826 					"malloc failed. **\n");
   1827 				return -1;
   1828 			}
   1829 			ext4fs_indir1_size = blksz;
   1830 			ext4fs_indir1_blkno = -1;
   1831 		}
   1832 		if (blksz != ext4fs_indir1_size) {
   1833 			free(ext4fs_indir1_block);
   1834 			ext4fs_indir1_block = NULL;
   1835 			ext4fs_indir1_size = 0;
   1836 			ext4fs_indir1_blkno = -1;
   1837 			ext4fs_indir1_block = zalloc(blksz);
   1838 			if (ext4fs_indir1_block == NULL) {
   1839 				printf("** TI ext2fs read block (indir 2 1)"
   1840 					"malloc failed. **\n");
   1841 				return -1;
   1842 			}
   1843 			ext4fs_indir1_size = blksz;
   1844 		}
   1845 		if ((le32_to_cpu(inode->b.blocks.triple_indir_block) <<
   1846 		     log2_blksz) != ext4fs_indir1_blkno) {
   1847 			status = ext4fs_devread
   1848 			    ((lbaint_t)
   1849 			     le32_to_cpu(inode->b.blocks.triple_indir_block)
   1850 			     << log2_blksz, 0, blksz,
   1851 			     (char *)ext4fs_indir1_block);
   1852 			if (status == 0) {
   1853 				printf("** TI ext2fs read block (indir 2 1)"
   1854 					"failed. **\n");
   1855 				return -1;
   1856 			}
   1857 			ext4fs_indir1_blkno =
   1858 			    le32_to_cpu(inode->b.blocks.triple_indir_block) <<
   1859 			    log2_blksz;
   1860 		}
   1861 
   1862 		if (ext4fs_indir2_block == NULL) {
   1863 			ext4fs_indir2_block = zalloc(blksz);
   1864 			if (ext4fs_indir2_block == NULL) {
   1865 				printf("** TI ext2fs read block (indir 2 2)"
   1866 					"malloc failed. **\n");
   1867 				return -1;
   1868 			}
   1869 			ext4fs_indir2_size = blksz;
   1870 			ext4fs_indir2_blkno = -1;
   1871 		}
   1872 		if (blksz != ext4fs_indir2_size) {
   1873 			free(ext4fs_indir2_block);
   1874 			ext4fs_indir2_block = NULL;
   1875 			ext4fs_indir2_size = 0;
   1876 			ext4fs_indir2_blkno = -1;
   1877 			ext4fs_indir2_block = zalloc(blksz);
   1878 			if (ext4fs_indir2_block == NULL) {
   1879 				printf("** TI ext2fs read block (indir 2 2)"
   1880 					"malloc failed. **\n");
   1881 				return -1;
   1882 			}
   1883 			ext4fs_indir2_size = blksz;
   1884 		}
   1885 		if ((le32_to_cpu(ext4fs_indir1_block[rblock /
   1886 						       perblock_parent]) <<
   1887 		     log2_blksz)
   1888 		    != ext4fs_indir2_blkno) {
   1889 			status = ext4fs_devread((lbaint_t)le32_to_cpu
   1890 						(ext4fs_indir1_block
   1891 						 [rblock /
   1892 						  perblock_parent]) <<
   1893 						log2_blksz, 0, blksz,
   1894 						(char *)ext4fs_indir2_block);
   1895 			if (status == 0) {
   1896 				printf("** TI ext2fs read block (indir 2 2)"
   1897 					"failed. **\n");
   1898 				return -1;
   1899 			}
   1900 			ext4fs_indir2_blkno =
   1901 			    le32_to_cpu(ext4fs_indir1_block[rblock /
   1902 							      perblock_parent])
   1903 			    << log2_blksz;
   1904 		}
   1905 
   1906 		if (ext4fs_indir3_block == NULL) {
   1907 			ext4fs_indir3_block = zalloc(blksz);
   1908 			if (ext4fs_indir3_block == NULL) {
   1909 				printf("** TI ext2fs read block (indir 2 2)"
   1910 					"malloc failed. **\n");
   1911 				return -1;
   1912 			}
   1913 			ext4fs_indir3_size = blksz;
   1914 			ext4fs_indir3_blkno = -1;
   1915 		}
   1916 		if (blksz != ext4fs_indir3_size) {
   1917 			free(ext4fs_indir3_block);
   1918 			ext4fs_indir3_block = NULL;
   1919 			ext4fs_indir3_size = 0;
   1920 			ext4fs_indir3_blkno = -1;
   1921 			ext4fs_indir3_block = zalloc(blksz);
   1922 			if (ext4fs_indir3_block == NULL) {
   1923 				printf("** TI ext2fs read block (indir 2 2)"
   1924 					"malloc failed. **\n");
   1925 				return -1;
   1926 			}
   1927 			ext4fs_indir3_size = blksz;
   1928 		}
   1929 		if ((le32_to_cpu(ext4fs_indir2_block[rblock
   1930 						       /
   1931 						       perblock_child]) <<
   1932 		     log2_blksz) != ext4fs_indir3_blkno) {
   1933 			status =
   1934 			    ext4fs_devread((lbaint_t)le32_to_cpu
   1935 					   (ext4fs_indir2_block
   1936 					    [(rblock / perblock_child)
   1937 					     % (blksz / 4)]) << log2_blksz, 0,
   1938 					   blksz, (char *)ext4fs_indir3_block);
   1939 			if (status == 0) {
   1940 				printf("** TI ext2fs read block (indir 2 2)"
   1941 				       "failed. **\n");
   1942 				return -1;
   1943 			}
   1944 			ext4fs_indir3_blkno =
   1945 			    le32_to_cpu(ext4fs_indir2_block[(rblock /
   1946 							       perblock_child) %
   1947 							      (blksz /
   1948 							       4)]) <<
   1949 			    log2_blksz;
   1950 		}
   1951 
   1952 		blknr = le32_to_cpu(ext4fs_indir3_block
   1953 				      [rblock % perblock_child]);
   1954 	}
   1955 	debug("read_allocated_block %ld\n", blknr);
   1956 
   1957 	return blknr;
   1958 }
   1959 
   1960 /**
   1961  * ext4fs_reinit_global() - Reinitialize values of ext4 write implementation's
   1962  *			    global pointers
   1963  *
   1964  * This function assures that for a file with the same name but different size
   1965  * the sequential store on the ext4 filesystem will be correct.
   1966  *
   1967  * In this function the global data, responsible for internal representation
   1968  * of the ext4 data are initialized to the reset state. Without this, during
   1969  * replacement of the smaller file with the bigger truncation of new file was
   1970  * performed.
   1971  */
   1972 void ext4fs_reinit_global(void)
   1973 {
   1974 	if (ext4fs_indir1_block != NULL) {
   1975 		free(ext4fs_indir1_block);
   1976 		ext4fs_indir1_block = NULL;
   1977 		ext4fs_indir1_size = 0;
   1978 		ext4fs_indir1_blkno = -1;
   1979 	}
   1980 	if (ext4fs_indir2_block != NULL) {
   1981 		free(ext4fs_indir2_block);
   1982 		ext4fs_indir2_block = NULL;
   1983 		ext4fs_indir2_size = 0;
   1984 		ext4fs_indir2_blkno = -1;
   1985 	}
   1986 	if (ext4fs_indir3_block != NULL) {
   1987 		free(ext4fs_indir3_block);
   1988 		ext4fs_indir3_block = NULL;
   1989 		ext4fs_indir3_size = 0;
   1990 		ext4fs_indir3_blkno = -1;
   1991 	}
   1992 }
   1993 void ext4fs_close(void)
   1994 {
   1995 	if ((ext4fs_file != NULL) && (ext4fs_root != NULL)) {
   1996 		ext4fs_free_node(ext4fs_file, &ext4fs_root->diropen);
   1997 		ext4fs_file = NULL;
   1998 	}
   1999 	if (ext4fs_root != NULL) {
   2000 		free(ext4fs_root);
   2001 		ext4fs_root = NULL;
   2002 	}
   2003 
   2004 	ext4fs_reinit_global();
   2005 }
   2006 
   2007 int ext4fs_iterate_dir(struct ext2fs_node *dir, char *name,
   2008 				struct ext2fs_node **fnode, int *ftype)
   2009 {
   2010 	unsigned int fpos = 0;
   2011 	int status;
   2012 	loff_t actread;
   2013 	struct ext2fs_node *diro = (struct ext2fs_node *) dir;
   2014 
   2015 #ifdef DEBUG
   2016 	if (name != NULL)
   2017 		printf("Iterate dir %s\n", name);
   2018 #endif /* of DEBUG */
   2019 	if (!diro->inode_read) {
   2020 		status = ext4fs_read_inode(diro->data, diro->ino, &diro->inode);
   2021 		if (status == 0)
   2022 			return 0;
   2023 	}
   2024 	/* Search the file.  */
   2025 	while (fpos < le32_to_cpu(diro->inode.size)) {
   2026 		struct ext2_dirent dirent;
   2027 
   2028 		status = ext4fs_read_file(diro, fpos,
   2029 					   sizeof(struct ext2_dirent),
   2030 					   (char *)&dirent, &actread);
   2031 		if (status < 0)
   2032 			return 0;
   2033 
   2034 		if (dirent.direntlen == 0) {
   2035 			printf("Failed to iterate over directory %s\n", name);
   2036 			return 0;
   2037 		}
   2038 
   2039 		if (dirent.namelen != 0) {
   2040 			char filename[dirent.namelen + 1];
   2041 			struct ext2fs_node *fdiro;
   2042 			int type = FILETYPE_UNKNOWN;
   2043 
   2044 			status = ext4fs_read_file(diro,
   2045 						  fpos +
   2046 						  sizeof(struct ext2_dirent),
   2047 						  dirent.namelen, filename,
   2048 						  &actread);
   2049 			if (status < 0)
   2050 				return 0;
   2051 
   2052 			fdiro = zalloc(sizeof(struct ext2fs_node));
   2053 			if (!fdiro)
   2054 				return 0;
   2055 
   2056 			fdiro->data = diro->data;
   2057 			fdiro->ino = le32_to_cpu(dirent.inode);
   2058 
   2059 			filename[dirent.namelen] = '\0';
   2060 
   2061 			if (dirent.filetype != FILETYPE_UNKNOWN) {
   2062 				fdiro->inode_read = 0;
   2063 
   2064 				if (dirent.filetype == FILETYPE_DIRECTORY)
   2065 					type = FILETYPE_DIRECTORY;
   2066 				else if (dirent.filetype == FILETYPE_SYMLINK)
   2067 					type = FILETYPE_SYMLINK;
   2068 				else if (dirent.filetype == FILETYPE_REG)
   2069 					type = FILETYPE_REG;
   2070 			} else {
   2071 				status = ext4fs_read_inode(diro->data,
   2072 							   le32_to_cpu
   2073 							   (dirent.inode),
   2074 							   &fdiro->inode);
   2075 				if (status == 0) {
   2076 					free(fdiro);
   2077 					return 0;
   2078 				}
   2079 				fdiro->inode_read = 1;
   2080 
   2081 				if ((le16_to_cpu(fdiro->inode.mode) &
   2082 				     FILETYPE_INO_MASK) ==
   2083 				    FILETYPE_INO_DIRECTORY) {
   2084 					type = FILETYPE_DIRECTORY;
   2085 				} else if ((le16_to_cpu(fdiro->inode.mode)
   2086 					    & FILETYPE_INO_MASK) ==
   2087 					   FILETYPE_INO_SYMLINK) {
   2088 					type = FILETYPE_SYMLINK;
   2089 				} else if ((le16_to_cpu(fdiro->inode.mode)
   2090 					    & FILETYPE_INO_MASK) ==
   2091 					   FILETYPE_INO_REG) {
   2092 					type = FILETYPE_REG;
   2093 				}
   2094 			}
   2095 #ifdef DEBUG
   2096 			printf("iterate >%s<\n", filename);
   2097 #endif /* of DEBUG */
   2098 			if ((name != NULL) && (fnode != NULL)
   2099 			    && (ftype != NULL)) {
   2100 				if (strcmp(filename, name) == 0) {
   2101 					*ftype = type;
   2102 					*fnode = fdiro;
   2103 					return 1;
   2104 				}
   2105 			} else {
   2106 				if (fdiro->inode_read == 0) {
   2107 					status = ext4fs_read_inode(diro->data,
   2108 								 le32_to_cpu(
   2109 								 dirent.inode),
   2110 								 &fdiro->inode);
   2111 					if (status == 0) {
   2112 						free(fdiro);
   2113 						return 0;
   2114 					}
   2115 					fdiro->inode_read = 1;
   2116 				}
   2117 				switch (type) {
   2118 				case FILETYPE_DIRECTORY:
   2119 					printf("<DIR> ");
   2120 					break;
   2121 				case FILETYPE_SYMLINK:
   2122 					printf("<SYM> ");
   2123 					break;
   2124 				case FILETYPE_REG:
   2125 					printf("      ");
   2126 					break;
   2127 				default:
   2128 					printf("< ? > ");
   2129 					break;
   2130 				}
   2131 				printf("%10u %s\n",
   2132 				       le32_to_cpu(fdiro->inode.size),
   2133 					filename);
   2134 			}
   2135 			free(fdiro);
   2136 		}
   2137 		fpos += le16_to_cpu(dirent.direntlen);
   2138 	}
   2139 	return 0;
   2140 }
   2141 
   2142 static char *ext4fs_read_symlink(struct ext2fs_node *node)
   2143 {
   2144 	char *symlink;
   2145 	struct ext2fs_node *diro = node;
   2146 	int status;
   2147 	loff_t actread;
   2148 
   2149 	if (!diro->inode_read) {
   2150 		status = ext4fs_read_inode(diro->data, diro->ino, &diro->inode);
   2151 		if (status == 0)
   2152 			return NULL;
   2153 	}
   2154 	symlink = zalloc(le32_to_cpu(diro->inode.size) + 1);
   2155 	if (!symlink)
   2156 		return NULL;
   2157 
   2158 	if (le32_to_cpu(diro->inode.size) < sizeof(diro->inode.b.symlink)) {
   2159 		strncpy(symlink, diro->inode.b.symlink,
   2160 			 le32_to_cpu(diro->inode.size));
   2161 	} else {
   2162 		status = ext4fs_read_file(diro, 0,
   2163 					   le32_to_cpu(diro->inode.size),
   2164 					   symlink, &actread);
   2165 		if ((status < 0) || (actread == 0)) {
   2166 			free(symlink);
   2167 			return NULL;
   2168 		}
   2169 	}
   2170 	symlink[le32_to_cpu(diro->inode.size)] = '\0';
   2171 	return symlink;
   2172 }
   2173 
   2174 static int ext4fs_find_file1(const char *currpath,
   2175 			     struct ext2fs_node *currroot,
   2176 			     struct ext2fs_node **currfound, int *foundtype)
   2177 {
   2178 	char fpath[strlen(currpath) + 1];
   2179 	char *name = fpath;
   2180 	char *next;
   2181 	int status;
   2182 	int type = FILETYPE_DIRECTORY;
   2183 	struct ext2fs_node *currnode = currroot;
   2184 	struct ext2fs_node *oldnode = currroot;
   2185 
   2186 	strncpy(fpath, currpath, strlen(currpath) + 1);
   2187 
   2188 	/* Remove all leading slashes. */
   2189 	while (*name == '/')
   2190 		name++;
   2191 
   2192 	if (!*name) {
   2193 		*currfound = currnode;
   2194 		return 1;
   2195 	}
   2196 
   2197 	for (;;) {
   2198 		int found;
   2199 
   2200 		/* Extract the actual part from the pathname. */
   2201 		next = strchr(name, '/');
   2202 		if (next) {
   2203 			/* Remove all leading slashes. */
   2204 			while (*next == '/')
   2205 				*(next++) = '\0';
   2206 		}
   2207 
   2208 		if (type != FILETYPE_DIRECTORY) {
   2209 			ext4fs_free_node(currnode, currroot);
   2210 			return 0;
   2211 		}
   2212 
   2213 		oldnode = currnode;
   2214 
   2215 		/* Iterate over the directory. */
   2216 		found = ext4fs_iterate_dir(currnode, name, &currnode, &type);
   2217 		if (found == 0)
   2218 			return 0;
   2219 
   2220 		if (found == -1)
   2221 			break;
   2222 
   2223 		/* Read in the symlink and follow it. */
   2224 		if (type == FILETYPE_SYMLINK) {
   2225 			char *symlink;
   2226 
   2227 			/* Test if the symlink does not loop. */
   2228 			if (++symlinknest == 8) {
   2229 				ext4fs_free_node(currnode, currroot);
   2230 				ext4fs_free_node(oldnode, currroot);
   2231 				return 0;
   2232 			}
   2233 
   2234 			symlink = ext4fs_read_symlink(currnode);
   2235 			ext4fs_free_node(currnode, currroot);
   2236 
   2237 			if (!symlink) {
   2238 				ext4fs_free_node(oldnode, currroot);
   2239 				return 0;
   2240 			}
   2241 
   2242 			debug("Got symlink >%s<\n", symlink);
   2243 
   2244 			if (symlink[0] == '/') {
   2245 				ext4fs_free_node(oldnode, currroot);
   2246 				oldnode = &ext4fs_root->diropen;
   2247 			}
   2248 
   2249 			/* Lookup the node the symlink points to. */
   2250 			status = ext4fs_find_file1(symlink, oldnode,
   2251 						    &currnode, &type);
   2252 
   2253 			free(symlink);
   2254 
   2255 			if (status == 0) {
   2256 				ext4fs_free_node(oldnode, currroot);
   2257 				return 0;
   2258 			}
   2259 		}
   2260 
   2261 		ext4fs_free_node(oldnode, currroot);
   2262 
   2263 		/* Found the node! */
   2264 		if (!next || *next == '\0') {
   2265 			*currfound = currnode;
   2266 			*foundtype = type;
   2267 			return 1;
   2268 		}
   2269 		name = next;
   2270 	}
   2271 	return -1;
   2272 }
   2273 
   2274 int ext4fs_find_file(const char *path, struct ext2fs_node *rootnode,
   2275 	struct ext2fs_node **foundnode, int expecttype)
   2276 {
   2277 	int status;
   2278 	int foundtype = FILETYPE_DIRECTORY;
   2279 
   2280 	symlinknest = 0;
   2281 	if (!path)
   2282 		return 0;
   2283 
   2284 	status = ext4fs_find_file1(path, rootnode, foundnode, &foundtype);
   2285 	if (status == 0)
   2286 		return 0;
   2287 
   2288 	/* Check if the node that was found was of the expected type. */
   2289 	if ((expecttype == FILETYPE_REG) && (foundtype != expecttype))
   2290 		return 0;
   2291 	else if ((expecttype == FILETYPE_DIRECTORY)
   2292 		   && (foundtype != expecttype))
   2293 		return 0;
   2294 
   2295 	return 1;
   2296 }
   2297 
   2298 int ext4fs_open(const char *filename, loff_t *len)
   2299 {
   2300 	struct ext2fs_node *fdiro = NULL;
   2301 	int status;
   2302 
   2303 	if (ext4fs_root == NULL)
   2304 		return -1;
   2305 
   2306 	ext4fs_file = NULL;
   2307 	status = ext4fs_find_file(filename, &ext4fs_root->diropen, &fdiro,
   2308 				  FILETYPE_REG);
   2309 	if (status == 0)
   2310 		goto fail;
   2311 
   2312 	if (!fdiro->inode_read) {
   2313 		status = ext4fs_read_inode(fdiro->data, fdiro->ino,
   2314 				&fdiro->inode);
   2315 		if (status == 0)
   2316 			goto fail;
   2317 	}
   2318 	*len = le32_to_cpu(fdiro->inode.size);
   2319 	ext4fs_file = fdiro;
   2320 
   2321 	return 0;
   2322 fail:
   2323 	ext4fs_free_node(fdiro, &ext4fs_root->diropen);
   2324 
   2325 	return -1;
   2326 }
   2327 
   2328 int ext4fs_mount(unsigned part_length)
   2329 {
   2330 	struct ext2_data *data;
   2331 	int status;
   2332 	struct ext_filesystem *fs = get_fs();
   2333 	data = zalloc(SUPERBLOCK_SIZE);
   2334 	if (!data)
   2335 		return 0;
   2336 
   2337 	/* Read the superblock. */
   2338 	status = ext4_read_superblock((char *)&data->sblock);
   2339 
   2340 	if (status == 0)
   2341 		goto fail;
   2342 
   2343 	/* Make sure this is an ext2 filesystem. */
   2344 	if (le16_to_cpu(data->sblock.magic) != EXT2_MAGIC)
   2345 		goto fail_noerr;
   2346 
   2347 
   2348 	if (le32_to_cpu(data->sblock.revision_level) == 0) {
   2349 		fs->inodesz = 128;
   2350 		fs->gdsize = 32;
   2351 	} else {
   2352 		debug("EXT4 features COMPAT: %08x INCOMPAT: %08x RO_COMPAT: %08x\n",
   2353 		      __le32_to_cpu(data->sblock.feature_compatibility),
   2354 		      __le32_to_cpu(data->sblock.feature_incompat),
   2355 		      __le32_to_cpu(data->sblock.feature_ro_compat));
   2356 
   2357 		fs->inodesz = le16_to_cpu(data->sblock.inode_size);
   2358 		fs->gdsize = le32_to_cpu(data->sblock.feature_incompat) &
   2359 			EXT4_FEATURE_INCOMPAT_64BIT ?
   2360 			le16_to_cpu(data->sblock.descriptor_size) : 32;
   2361 	}
   2362 
   2363 	debug("EXT2 rev %d, inode_size %d, descriptor size %d\n",
   2364 	      le32_to_cpu(data->sblock.revision_level),
   2365 	      fs->inodesz, fs->gdsize);
   2366 
   2367 	data->diropen.data = data;
   2368 	data->diropen.ino = 2;
   2369 	data->diropen.inode_read = 1;
   2370 	data->inode = &data->diropen.inode;
   2371 
   2372 	status = ext4fs_read_inode(data, 2, data->inode);
   2373 	if (status == 0)
   2374 		goto fail;
   2375 
   2376 	ext4fs_root = data;
   2377 
   2378 	return 1;
   2379 fail:
   2380 	printf("Failed to mount ext2 filesystem...\n");
   2381 fail_noerr:
   2382 	free(data);
   2383 	ext4fs_root = NULL;
   2384 
   2385 	return 0;
   2386 }
   2387