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