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