tizen 2.3.1 release
[platform/kernel/u-boot.git] / fs / ext4 / ext4fswrite.c
1 /*
2  * (C) Copyright 2011 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  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation; either version 2 of the License, or
10  *  (at your option) any later version.
11  *
12  *  This program is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License
18  *  along with this program; if not, write to the Free Software
19  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  */
21
22 #include <common.h>
23 #include <ext2fs.h>
24 #include <malloc.h>
25 #include <asm/byteorder.h>
26 #include <linux/stat.h>
27 #include <linux/time.h>
28 #include "../ext4/crc16.h"
29 #include <div64.h>
30 //#define DEBUG_LOG 1
31
32 #define YES 1
33 #define NO 0
34 /* Maximum entries in 1 journal transaction */
35 #define MAX_JOURNAL_ENTRIES 80
36 struct journal_log {
37                 char *buf;
38                 int blknr;
39         };
40
41 struct dirty_blocks {
42                 char *buf;
43                 int blknr;
44         };
45
46 int gindex = 0;
47 int gd_index = 0;
48 int j_blkindex = 1;
49 struct journal_log *journal_ptr[MAX_JOURNAL_ENTRIES];
50 struct dirty_blocks *dirty_block_ptr[MAX_JOURNAL_ENTRIES];
51
52 void log_journal(char *journal_buffer,unsigned int blknr);
53 void put_metadata(char *metadata_buffer,unsigned int blknr);
54 void ext4fs_update(block_dev_desc_t *dev_desc);
55
56 #define EXT2_JOURNAL_INO                        8       /* Journal inode */
57 #define EXT2_JOURNAL_SUPERBLOCK                 0       /* Journal  Superblock number */
58 #define S_IFLNK                                 0120000 /* symbolic link */
59
60 #define JBD2_FEATURE_COMPAT_CHECKSUM            0x00000001
61 #define EXT3_JOURNAL_MAGIC_NUMBER               0xc03b3998U
62 #define TRANSACTION_RUNNING                     1
63 #define TRANSACTION_COMPLETE                    0
64 #define EXT3_FEATURE_INCOMPAT_RECOVER           0x0004 /* Needs recovery */
65 #define EXT3_JOURNAL_DESCRIPTOR_BLOCK           1
66 #define EXT3_JOURNAL_COMMIT_BLOCK               2
67 #define EXT3_JOURNAL_SUPERBLOCK_V1              3
68 #define EXT3_JOURNAL_SUPERBLOCK_V2              4
69 #define EXT3_JOURNAL_REVOKE_BLOCK               5
70 #define EXT3_JOURNAL_FLAG_ESCAPE                1
71 #define EXT3_JOURNAL_FLAG_SAME_UUID             2
72 #define EXT3_JOURNAL_FLAG_DELETED               4
73 #define EXT3_JOURNAL_FLAG_LAST_TAG              8
74         
75 /*
76  * Standard header for all descriptor blocks:
77  */
78 typedef struct journal_header_s
79 {
80         __u32   h_magic;
81         __u32   h_blocktype;
82         __u32   h_sequence;
83 } journal_header_t;
84
85 /*
86  * The journal superblock.  All fields are in big-endian byte order.
87  */
88 typedef struct journal_superblock_s
89 {
90         /* 0x0000 */
91         journal_header_t s_header;
92
93         /* 0x000C */
94         /* Static information describing the journal */
95         __u32 s_blocksize;      /* journal device blocksize */
96         __u32 s_maxlen;         /* total blocks in journal file */
97         __u32 s_first;          /* first block of log information */
98
99         /* 0x0018 */
100         /* Dynamic information describing the current state of the log */
101         __u32 s_sequence;       /* first commit ID expected in log */
102         __u32 s_start;  /* blocknr of start of log */
103
104         /* 0x0020 */
105         /* Error value, as set by journal_abort(). */
106         __s32 s_errno;
107
108         /* 0x0024 */
109         /* Remaining fields are only valid in a version-2 superblock */
110         __u32 s_feature_compat;         /* compatible feature set */
111         __u32 s_feature_incompat;       /* incompatible feature set */
112         __u32 s_feature_ro_compat;      /* readonly-compatible feature set */
113         /* 0x0030 */
114         __u8    s_uuid[16];     /* 128-bit uuid for journal */
115
116         /* 0x0040 */
117         __u32 s_nr_users;       /* Nr of filesystems sharing log */
118
119         __u32 s_dynsuper;       /* Blocknr of dynamic superblock copy*/
120
121         /* 0x0048 */
122         __u32 s_max_transaction;        /* Limit of journal blocks per trans.*/
123         __u32 s_max_trans_data; /* Limit of data blocks per trans. */
124
125         /* 0x0050 */
126         __u32 s_padding[44];
127
128         /* 0x0100 */
129         __u8    s_users[16*48];         /* ids of all fs'es sharing the log */
130         /* 0x0400 */
131 } journal_superblock_t;
132
133 /* To convert big endian journal superblock entries to little endian */
134 unsigned int be_le(unsigned int num)
135 {
136         unsigned int swapped;
137         swapped = (((num>>24)&0xff) | // move byte 3 to byte 0
138                 ((num<<8)&0xff0000) | // move byte 1 to byte 2
139                 ((num>>8)&0xff00) | // move byte 2 to byte 1
140                 ((num<<24)&0xff000000)); // byte 0 to byte 3
141                 return swapped;
142 }
143
144 // 4-byte number
145 unsigned int le_be(unsigned int num)
146 {
147          return((num&0xff)<<24)+((num&0xff00)<<8)+((num&0xff0000)>>8)+((num>>24)&0xff);
148 }
149
150 struct ext3_journal_block_tag
151 {
152         uint32_t block;
153         uint32_t flags;
154 };
155
156 extern int ext2fs_devread(int sector, int byte_offset, int byte_len, char *buf);
157
158 /* Magic value used to identify an ext2 filesystem.  */
159 #define EXT2_MAGIC                              0xEF53
160 /* Amount of indirect blocks in an inode.  */
161 #define INDIRECT_BLOCKS                         12
162 /* Maximum lenght of a pathname.  */
163 #define EXT2_PATH_MAX                           4096
164 /* Maximum nesting of symlinks, used to prevent a loop.  */
165 #define EXT2_MAX_SYMLINKCNT                     8
166
167 /* Filetype used in directory entry.  */
168 #define FILETYPE_UNKNOWN                        0
169 #define FILETYPE_REG                            1
170 #define FILETYPE_DIRECTORY                      2
171 #define FILETYPE_SYMLINK                        7
172
173 /* Filetype information as used in inodes.  */
174 #define FILETYPE_INO_MASK                       0170000
175 #define FILETYPE_INO_REG                        0100000
176 #define FILETYPE_INO_DIRECTORY                  0040000
177 #define FILETYPE_INO_SYMLINK                    0120000
178 #define EXT2_ROOT_INO                           2 /* Root inode */
179
180 /* Bits used as offset in sector */
181 #define DISK_SECTOR_BITS                        9
182
183 /* Log2 size of ext2 block in 512 blocks.  */
184 #define LOG2_EXT2_BLOCK_SIZE(data) (__le32_to_cpu (data->sblock.log2_block_size) + 1)
185
186 /* Log2 size of ext2 block in bytes.  */
187 #define LOG2_BLOCK_SIZE(data)      (__le32_to_cpu (data->sblock.log2_block_size) + 10)
188
189 /* The size of an ext2 block in bytes.  */
190 #define EXT2_BLOCK_SIZE(data)      (1 << LOG2_BLOCK_SIZE(data))
191
192 #define INODE_SIZE_FILESYSTEM(data)     (__le32_to_cpu (data->sblock.inode_size))
193 #define EXT4_EXTENTS_FLAG                       0x80000
194 #define EXT4_EXT_MAGIC                          0xf30a
195
196 #define EXT2_FT_DIR                             2
197 #define SUCCESS                                 1
198
199 #define EXT_MAX_FILE_LEN 256
200 // All fields are little-endian
201 struct ext4_dir {
202         uint32_t inode1;
203         uint16_t rec_len1;
204         uint8_t name_len1;
205         uint8_t file_type1;
206         char    name1[4];
207         uint32_t inode2;
208         uint16_t rec_len2;
209         uint8_t name_len2;
210         uint8_t file_type2;
211         char    name2[4];
212         uint32_t inode3;
213         uint16_t rec_len3;
214         uint8_t name_len3;
215         uint8_t file_type3;
216         char    name3[12];
217 };
218
219 /* The ext2 superblock.  */
220 struct ext2_sblock {
221         uint32_t total_inodes;
222         uint32_t total_blocks;
223         uint32_t reserved_blocks;
224         uint32_t free_blocks;
225         uint32_t free_inodes;
226         uint32_t first_data_block;
227         uint32_t log2_block_size;
228         uint32_t log2_fragment_size;
229         uint32_t blocks_per_group;
230         uint32_t fragments_per_group;
231         uint32_t inodes_per_group;
232         uint32_t mtime;
233         uint32_t utime;
234         uint16_t mnt_count;
235         uint16_t max_mnt_count;
236         uint16_t magic;
237         uint16_t fs_state;
238         uint16_t error_handling;
239         uint16_t minor_revision_level;
240         uint32_t lastcheck;
241         uint32_t checkinterval;
242         uint32_t creator_os;
243         uint32_t revision_level;
244         uint16_t uid_reserved;
245         uint16_t gid_reserved;
246         uint32_t first_inode;
247         uint16_t inode_size;
248         uint16_t block_group_number;
249         uint32_t feature_compatibility;
250         uint32_t feature_incompat;
251         uint32_t feature_ro_compat;
252         uint32_t unique_id[4];
253         char volume_name[16];
254         char last_mounted_on[64];
255         uint32_t compression_info;
256 };
257
258 struct ext2_block_group
259 {
260         __u32 block_id; /* Blocks bitmap block */
261         __u32 inode_id; /* Inodes bitmap block */
262         __u32 inode_table_id;   /* Inodes table block */
263         __u16 free_blocks;      /* Free blocks count */
264         __u16 free_inodes;      /* Free inodes count */
265         __u16 used_dir_cnt;     /* Directories count */
266         __u16 bg_flags;
267         __u32 bg_reserved[2];
268         __u16 bg_itable_unused; /* Unused inodes count */
269         __u16 bg_checksum;      /* crc16(s_uuid+grouo_num+group_desc)*/
270 };
271
272 /* The ext2 inode.  */
273 struct ext2_inode {
274         uint16_t mode;
275         uint16_t uid;
276         uint32_t size;
277         uint32_t atime;
278         uint32_t ctime;
279         uint32_t mtime;
280         uint32_t dtime;
281         uint16_t gid;
282         uint16_t nlinks;
283         uint32_t blockcnt;      /* Blocks of 512 bytes!! */
284         uint32_t flags;
285         uint32_t osd1;
286         union {
287                 struct datablocks {
288                         uint32_t dir_blocks[INDIRECT_BLOCKS];
289                         uint32_t indir_block;
290                         uint32_t double_indir_block;
291                         uint32_t tripple_indir_block;
292                 } blocks;
293                 char symlink[60];
294         } b;
295         uint32_t version;
296         uint32_t acl;
297         uint32_t dir_acl;
298         uint32_t fragment_addr;
299         uint32_t osd2[3];
300 };
301
302 /* The header of an ext2 directory entry.  */
303 struct ext2_dirent {
304         uint32_t inode;
305         uint16_t direntlen;
306         uint8_t namelen;
307         uint8_t filetype;
308 };
309
310 struct ext2fs_node {
311         struct ext2_data *data;
312         struct ext2_inode inode;
313         int ino;
314         int inode_read;
315 };
316
317 struct ext4_extent_header {
318         uint16_t magic;
319         uint16_t entries;
320         uint16_t max;
321         uint16_t depth;
322         uint32_t generation;
323 };
324
325 struct ext4_extent {
326         uint32_t block;
327         uint16_t len;
328         uint16_t start_hi;
329         uint32_t start;
330 };
331
332 struct ext4_extent_idx {
333         uint32_t block;
334         uint32_t leaf;
335         uint16_t leaf_hi;
336         uint16_t unused;
337 };
338
339 /* Information about a "mounted" ext2 filesystem.  */
340 struct ext2_data {
341         struct ext2_sblock sblock;
342         struct ext2_inode *inode;
343         struct ext2fs_node diropen;
344 };
345
346 typedef struct ext2fs_node *ext2fs_node_t;
347
348 struct ext2_data *ext4fs_root = NULL;
349 ext2fs_node_t ext4fs_file = NULL;
350 int ext4fs_symlinknest = 0;
351 uint32_t *ext4fs_indir1_block = NULL;
352 int ext4fs_indir1_size = 0;
353 int ext4fs_indir1_blkno = -1;
354 uint32_t *ext4fs_indir2_block = NULL;
355 int ext4fs_indir2_size = 0;
356 int ext4fs_indir2_blkno = -1;
357
358 uint32_t *ext4fs_indir3_block = NULL;
359 int ext4fs_indir3_size = 0;
360 int ext4fs_indir3_blkno = -1;
361 static unsigned int inode_size;
362
363 #define BLOCK_NO_ONE                    1
364 #define SUPERBLOCK_SECTOR               2
365 #define SUPERBLOCK_SIZE                 1024
366
367 static int blocksize;
368 static int inodesize;
369 static int sector_per_block;
370 static unsigned long blockno = 0;
371 static unsigned long inode_no = 0;
372 static int first_execution = 0;
373 static int first_execution_inode = 0;
374 static int  no_blockgroup;
375 static unsigned char *gd_table = NULL;
376 static unsigned int   gd_table_block_no = 0;
377
378 /*superblock*/
379 static struct ext2_sblock *sb = NULL;
380 /*blockgroup bitmaps*/
381 static unsigned char **bg = NULL;
382 /*inode bitmaps*/
383 static unsigned char **inode_bmaps = NULL;
384 /*block group descritpor table*/
385 static struct ext2_block_group *gd = NULL;
386 /* number of blocks required for gdtable */
387 int no_blk_req_per_gdt;
388 static struct ext2_inode *g_parent_inode = NULL;
389 /*
390  * Macro-instructions used to manage several block sizes
391  */
392 #define EXT2_MIN_BLOCK_LOG_SIZE                 10 /* 1024 */
393 #define EXT2_MAX_BLOCK_LOG_SIZE                 16 /* 65536 */
394 #define EXT2_MIN_BLOCK_SIZE                     (1 << EXT2_MIN_BLOCK_LOG_SIZE)
395 #define EXT2_MAX_BLOCK_SIZE                     (1 << EXT2_MAX_BLOCK_LOG_SIZE)
396
397 #define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER     0x0001
398
399 #define EXT4_BG_INODE_UNINIT                    0x0001 /* Inode table/bitmap not in use */
400 #define EXT4_BG_BLOCK_UNINIT                    0x0002 /* Block bitmap not in use */
401 #define EXT4_BG_INODE_ZEROED                    0x0004 /* On-disk itable initialized to zero */
402
403 #define EXT4_FEATURE_RO_COMPAT_GDT_CSUM         0x0010
404 #define EXT4_FEATURE_INCOMPAT_EXTENTS           0x0040 /* extents support */
405
406 #ifndef offsetof
407 #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
408 #endif
409
410 int get_parent_inode_num(block_dev_desc_t *dev_desc,char *dirname, char *dname);
411 int  iget(unsigned int inode_no,struct ext2_inode* inode);
412
413 // taken from mkfs_minix.c. libbb candidate?
414 // "uint32_t size", since we never use it for anything >32 bits
415 static uint32_t ext4fs_div_roundup(uint32_t size, uint32_t n)
416 {
417         // Overflow-resistant
418         uint32_t res = size / n;
419         if (res * n != size)
420                 res++;
421         return res;
422 }
423
424 #ifdef DEBUG_LOG
425 void ext4fs_dump_the_block_group_before_writing()
426 {
427         int i,j;
428         int blocksize;
429         blocksize=EXT2_BLOCK_SIZE(ext4fs_root);
430         for(i=0;i<no_blockgroup;i++)
431         {
432                 printf("\n-----------------\n");
433                 printf("[BEFORE WRITING ]block group  %d\n",i);
434                 printf("-----------------\n");
435                 for(j=0;j<blocksize;j++)
436                 {
437                         printf("%u",*(bg[i]+j));
438                 }
439         }
440 }
441
442 void ext4fs_dump_the_block_group_after_writing()
443 {
444         int i,j;
445         int blocksize;
446         blocksize=EXT2_BLOCK_SIZE(ext4fs_root);
447         for(i=0;i<no_blockgroup;i++)
448         {
449                 printf("\n-----------------\n");
450                 printf("[AFTER WRITING]block group %d\n",i);
451                 printf("-----------------\n");
452                 for(j=0;j<blocksize;j++)
453                 {
454                         printf("%u",*(bg[i]+j));
455                 }
456         }
457 }
458
459 void ext4fs_dump_the_inode_group_before_writing()
460 {
461         int i,j;
462         int blocksize;
463         blocksize=EXT2_BLOCK_SIZE(ext4fs_root);
464         for(i=0;i<no_blockgroup;i++)
465         {
466                 printf("\n-----------------\n");
467                 printf("[BEFORE WRITING ]block group  %d\n",i);
468                 printf("-----------------\n");
469                 for(j=0;j<blocksize;j++)
470                 {
471                         printf("%u",*(inode_bmaps[i]+j));
472                 }
473         }
474 }
475
476 void ext4fs_dump_the_inode_group_after_writing()
477 {
478         int i,j;
479         int blocksize;
480         blocksize=EXT2_BLOCK_SIZE(ext4fs_root);
481         for(i=0;i<no_blockgroup;i++)
482         {
483                 printf("\n-----------------\n");
484                 printf("[AFTER WRITING]block group %d\n",i);
485                 printf("-----------------\n");
486                 for(j=0;j<blocksize;j++)
487                 {
488                         printf("%u",*(inode_bmaps[i]+j));
489                 }
490         }
491 }
492 #endif
493
494 static int ext4fs_blockgroup
495         (struct ext2_data *data, int group, struct ext2_block_group *blkgrp)
496 {
497         unsigned int blkno;
498         unsigned int blkoff;
499         unsigned int desc_per_blk;
500
501         desc_per_blk = EXT2_BLOCK_SIZE(data) / sizeof(struct ext2_block_group);
502
503         blkno = __le32_to_cpu(data->sblock.first_data_block) + 1
504                 + group / desc_per_blk;
505         blkoff = (group % desc_per_blk) * sizeof(struct ext2_block_group);
506 #ifdef DEBUG
507         printf ("ext4fs read %d group descriptor (blkno %d blkoff %d)\n",
508                 group, blkno, blkoff);
509 #endif
510         return (ext2fs_devread (blkno << LOG2_EXT2_BLOCK_SIZE(data),
511                 blkoff, sizeof(struct ext2_block_group), (char *)blkgrp));
512 }
513
514 static struct ext4_extent_header * ext4fs_find_leaf (struct ext2_data *data,
515         char *buf, struct ext4_extent_header *ext_block, uint32_t fileblock)
516 {
517         struct ext4_extent_idx *index;
518
519         while (1)
520         {
521                 int i;
522                 unsigned int block;
523
524                 index = (struct ext4_extent_idx *) (ext_block + 1);
525
526                 if (le32_to_cpu(ext_block->magic) != EXT4_EXT_MAGIC)
527                         return 0;
528
529                 if (ext_block->depth == 0)
530                         return ext_block;
531
532                 for (i = 0; i < le32_to_cpu (ext_block->entries); i++) {
533                         if (fileblock < le32_to_cpu(index[i].block))
534                                 break;
535                 }
536
537                 if (--i < 0)
538                         return 0;
539
540                 block = le32_to_cpu (index[i].leaf_hi);
541                 block = (block << 32) + le32_to_cpu (index[i].leaf);
542
543                 if (ext2fs_devread (block << LOG2_EXT2_BLOCK_SIZE (data),
544                   0, EXT2_BLOCK_SIZE(data), buf))
545                         {
546                         ext_block = (struct ext4_extent_header *) buf;
547                         return ext_block;
548                         }
549                 else
550                         return 0;
551         }
552 }
553
554 static int ext4fs_read_inode
555         (struct ext2_data *data, int ino, struct ext2_inode *inode)
556 {
557         struct ext2_block_group blkgrp;
558         struct ext2_sblock *sblock = &data->sblock;
559         int inodes_per_block;
560         int status;
561
562         unsigned int blkno;
563         unsigned int blkoff;
564
565 #ifdef DEBUG
566         printf ("ext4fs read inode %d, inode_size %d\n", ino, inode_size);
567 #endif
568         /* It is easier to calculate if the first inode is 0.  */
569         ino--;
570         status = ext4fs_blockgroup (data, ino / __le32_to_cpu
571             (sblock->inodes_per_group), &blkgrp);
572
573         if (status == 0)
574                 return (0);
575
576         inodes_per_block = EXT2_BLOCK_SIZE(data) / inode_size;
577
578         blkno = __le32_to_cpu (blkgrp.inode_table_id) +
579                 (ino % __le32_to_cpu (sblock->inodes_per_group))
580                 / inodes_per_block;
581         blkoff = (ino % inodes_per_block) * inode_size;
582 #ifdef DEBUG
583         printf ("ext4fs read inode blkno %d blkoff %d\n", blkno, blkoff);
584 #endif
585         /* Read the inode.  */
586         status = ext2fs_devread (blkno << LOG2_EXT2_BLOCK_SIZE (data), blkoff,
587                 sizeof (struct ext2_inode), (char *) inode);
588         if (status == 0)
589                 return (0);
590
591         return (1);
592 }
593
594 void ext4fs_free_node (ext2fs_node_t node, ext2fs_node_t currroot)
595 {
596         if ((node != &ext4fs_root->diropen) && (node != currroot))
597                 free (node);
598 }
599
600 int ext4fs_read_allocated_block(struct ext2_inode *inode, int fileblock)
601 {
602         int blknr;
603         int blksz ;
604         int log2_blksz;
605         int status;
606         unsigned int rblock;
607         unsigned int perblock;
608         unsigned int perblock_parent;
609         unsigned int perblock_child;
610
611         /*get the blocksize of the filesystem*/
612         blksz=EXT2_BLOCK_SIZE(ext4fs_root);
613         log2_blksz = LOG2_EXT2_BLOCK_SIZE (ext4fs_root);
614
615         if (le32_to_cpu(inode->flags) & EXT4_EXTENTS_FLAG) {
616                 ALLOC_CACHE_ALIGN_BUFFER(char, buf, EXT2_BLOCK_SIZE(ext4fs_root));
617                 struct ext4_extent_header *leaf;
618                 struct ext4_extent *ext;
619                 int i;
620
621                 leaf = ext4fs_find_leaf (ext4fs_root, buf,
622                         (struct ext4_extent_header *) inode->b.blocks.dir_blocks,
623                         fileblock);
624                 if (!leaf) {
625                         printf ("invalid extent \n");
626                         return -1;
627                 }
628
629                 ext = (struct ext4_extent *) (leaf + 1);
630
631                 for (i = 0; i < le32_to_cpu (leaf->entries); i++) {
632                         if (fileblock < le32_to_cpu (ext[i].block))
633                                 break;
634                 }
635
636                 if (--i >= 0) {
637                         fileblock -= le32_to_cpu (ext[i].block);
638                         if (fileblock >= le32_to_cpu (ext[i].len)) {
639                                 return 0;
640                         } else {
641                                 unsigned int start;
642                                 start = le32_to_cpu (ext[i].start_hi);
643                                 start = (start << 32) + le32_to_cpu (ext[i].start);
644                                 return fileblock + start;
645                         }
646                 } else {
647                         printf("something wrong with extent \n");
648                         return -1;
649                 }
650         }
651
652         /* Direct blocks.  */
653         if (fileblock < INDIRECT_BLOCKS) {
654                 blknr = __le32_to_cpu (inode->b.blocks.dir_blocks[fileblock]);
655         }
656         /* Indirect.  */
657         else if (fileblock < (INDIRECT_BLOCKS + (blksz / 4))) {
658                 if (ext4fs_indir1_block == NULL) {
659                         ext4fs_indir1_block = (uint32_t *) memalign(ARCH_DMA_MINALIGN, blksz);
660                         if (ext4fs_indir1_block == NULL) {
661                                 printf ("** SI ext2fs read block (indir 1) malloc failed. **\n");
662                                 return (-1);
663                         }
664                         ext4fs_indir1_size = blksz;
665                         ext4fs_indir1_blkno = -1;
666                 }
667                 if (blksz != ext4fs_indir1_size) {
668                         free (ext4fs_indir1_block);
669                         ext4fs_indir1_block = NULL;
670                         ext4fs_indir1_size = 0;
671                         ext4fs_indir1_blkno = -1;
672                         ext4fs_indir1_block = (uint32_t *) memalign(ARCH_DMA_MINALIGN, blksz);
673                         if (ext4fs_indir1_block == NULL) {
674                                 printf ("** SI ext2fs read block (indir 1) malloc failed. **\n");
675                                 return (-1);
676                         }
677                         ext4fs_indir1_size = blksz;
678                 }
679                 if ((__le32_to_cpu (inode->b.blocks.indir_block) <<
680                      log2_blksz) != ext4fs_indir1_blkno) {
681                         status = ext2fs_devread (__le32_to_cpu(inode->b.blocks.indir_block) << log2_blksz,
682                                                  0, blksz,
683                                                  (char *) ext4fs_indir1_block);
684                         if (status == 0) {
685                                 printf ("** SI ext2fs read block (indir 1) failed. **\n");
686                                 return (0);
687                         }
688                         ext4fs_indir1_blkno =
689                                 __le32_to_cpu (inode->b.blocks.
690                                                indir_block) << log2_blksz;
691                 }
692                 blknr = __le32_to_cpu (ext4fs_indir1_block
693                                        [fileblock - INDIRECT_BLOCKS]);
694         }
695         /* Double indirect.  */
696         else if (fileblock <
697                  (INDIRECT_BLOCKS + (blksz / 4 * (blksz / 4 + 1)))) {
698
699                 unsigned int perblock = blksz / 4;
700                 unsigned int rblock = fileblock - (INDIRECT_BLOCKS
701                                                    + blksz / 4);
702
703                 if (ext4fs_indir1_block == NULL) {
704                         ext4fs_indir1_block = (uint32_t *) memalign(ARCH_DMA_MINALIGN, blksz);
705                         if (ext4fs_indir1_block == NULL) {
706                                 printf ("** DI ext2fs read block (indir 2 1) malloc failed. **\n");
707                                 return (-1);
708                         }
709                         ext4fs_indir1_size = blksz;
710                         ext4fs_indir1_blkno = -1;
711                 }
712                 if (blksz != ext4fs_indir1_size) {
713                         free (ext4fs_indir1_block);
714                         ext4fs_indir1_block = NULL;
715                         ext4fs_indir1_size = 0;
716                         ext4fs_indir1_blkno = -1;
717                         ext4fs_indir1_block = (uint32_t *) memalign(ARCH_DMA_MINALIGN, blksz);
718                         if (ext4fs_indir1_block == NULL) {
719                                 printf ("** DI ext2fs read block (indir 2 1) malloc failed. **\n");
720                                 return (-1);
721                         }
722                         ext4fs_indir1_size = blksz;
723                 }
724                 if ((__le32_to_cpu (inode->b.blocks.double_indir_block) <<
725                      log2_blksz) != ext4fs_indir1_blkno) {
726                         status = ext2fs_devread (__le32_to_cpu(inode->b.blocks.double_indir_block) << log2_blksz,
727                                                 0, blksz,
728                                                 (char *) ext4fs_indir1_block);
729                         if (status == 0) {
730                                 printf ("** DI ext2fs read block (indir 2 1) failed. **\n");
731                                 return (-1);
732                         }
733                         ext4fs_indir1_blkno =
734                                 __le32_to_cpu (inode->b.blocks.double_indir_block) << log2_blksz;
735                 }
736
737                 if (ext4fs_indir2_block == NULL) {
738                         ext4fs_indir2_block = (uint32_t *) memalign(ARCH_DMA_MINALIGN, blksz);
739                         if (ext4fs_indir2_block == NULL) {
740                                 printf ("** DI ext2fs read block (indir 2 2) malloc failed. **\n");
741                                 return (-1);
742                         }
743                         ext4fs_indir2_size = blksz;
744                         ext4fs_indir2_blkno = -1;
745                 }
746                 if (blksz != ext4fs_indir2_size) {
747                         free (ext4fs_indir2_block);
748                         ext4fs_indir2_block = NULL;
749                         ext4fs_indir2_size = 0;
750                         ext4fs_indir2_blkno = -1;
751                         ext4fs_indir2_block = (uint32_t *) memalign(ARCH_DMA_MINALIGN, blksz);
752                         if (ext4fs_indir2_block == NULL) {
753                                 printf ("** DI ext2fs read block (indir 2 2) malloc failed. **\n");
754                                 return (-1);
755                         }
756                         ext4fs_indir2_size = blksz;
757                 }
758                 if ((__le32_to_cpu (ext4fs_indir1_block[rblock / perblock]) <<
759                      log2_blksz) != ext4fs_indir2_blkno) {
760                         status = ext2fs_devread (__le32_to_cpu(ext4fs_indir1_block[rblock / perblock]) << log2_blksz,
761                                                  0, blksz,
762                                                  (char *) ext4fs_indir2_block);
763                         if (status == 0) {
764                                 printf ("** DI ext2fs read block (indir 2 2) failed. **\n");
765                                 return (-1);
766                         }
767                         ext4fs_indir2_blkno =
768                                 __le32_to_cpu (ext4fs_indir1_block[rblock / perblock]) << log2_blksz;
769                 }
770                 blknr = __le32_to_cpu (ext4fs_indir2_block[rblock % perblock]);
771         }
772         /* Tripple indirect.  */
773         else {
774                 rblock = fileblock - (INDIRECT_BLOCKS + blksz / 4 + (blksz / 4 * blksz / 4));
775                 perblock_child = blksz / 4;
776                 perblock_parent = ((blksz / 4) * (blksz / 4));
777                 
778                 if (ext4fs_indir1_block == NULL) {
779                         ext4fs_indir1_block = (uint32_t *) memalign(ARCH_DMA_MINALIGN, blksz);
780                         if (ext4fs_indir1_block == NULL) {
781                                 printf ("** TI ext2fs read block (indir 2 1) malloc failed. **\n");
782                                 return (-1);
783                         }
784                         ext4fs_indir1_size = blksz;
785                         ext4fs_indir1_blkno = -1;
786                 }
787                 if (blksz != ext4fs_indir1_size) {
788                         free (ext4fs_indir1_block);
789                         ext4fs_indir1_block = NULL;
790                         ext4fs_indir1_size = 0;
791                         ext4fs_indir1_blkno = -1;
792                         ext4fs_indir1_block = (uint32_t *) memalign(ARCH_DMA_MINALIGN, blksz);
793                         if (ext4fs_indir1_block == NULL) {
794                                 printf ("** TI ext2fs read block (indir 2 1) malloc failed. **\n");
795                                 return (-1);
796                         }
797                         ext4fs_indir1_size = blksz;
798                 }
799                 if ((__le32_to_cpu (inode->b.blocks.tripple_indir_block) <<
800                           log2_blksz) != ext4fs_indir1_blkno) {
801                         status = ext2fs_devread
802                                 (__le32_to_cpu(inode->b.blocks.tripple_indir_block) << log2_blksz,
803                                 0, blksz,
804                                 (char *) ext4fs_indir1_block);
805                         if (status == 0) {
806                                 printf ("** TI ext2fs read block (indir 2 1) failed. **\n");
807                                 return (-1);
808                         }
809                         ext4fs_indir1_blkno =
810                                 __le32_to_cpu (inode->b.blocks.tripple_indir_block) << log2_blksz;
811                 }
812                 
813                 if (ext4fs_indir2_block == NULL) {
814                         ext4fs_indir2_block = (uint32_t *) memalign(ARCH_DMA_MINALIGN, blksz);
815                         if (ext4fs_indir2_block == NULL) {
816                                 printf ("** TI ext2fs read block (indir 2 2) malloc failed. **\n");
817                                 return (-1);
818                         }
819                         ext4fs_indir2_size = blksz;
820                         ext4fs_indir2_blkno = -1;
821                 }
822                 if (blksz != ext4fs_indir2_size) {
823                         free (ext4fs_indir2_block);
824                         ext4fs_indir2_block = NULL;
825                         ext4fs_indir2_size = 0;
826                         ext4fs_indir2_blkno = -1;
827                         ext4fs_indir2_block = (uint32_t *) memalign(ARCH_DMA_MINALIGN, blksz);
828                         if (ext4fs_indir2_block == NULL) {
829                                 printf ("** TI ext2fs read block (indir 2 2) malloc failed. **\n");
830                                 return (-1);
831                         }
832                         ext4fs_indir2_size = blksz;
833                 }
834                 if ((__le32_to_cpu (ext4fs_indir1_block[rblock / perblock_parent]) <<
835                           log2_blksz) != ext4fs_indir2_blkno) {
836                         status = ext2fs_devread (__le32_to_cpu(ext4fs_indir1_block[rblock / perblock_parent]) << log2_blksz,
837                                                  0, blksz,
838                                                  (char *) ext4fs_indir2_block);
839                         if (status == 0) {
840                                 printf ("** TI ext2fs read block (indir 2 2) failed. **\n");
841                                 return (-1);
842                         }
843                         ext4fs_indir2_blkno =
844                                 __le32_to_cpu (ext4fs_indir1_block[rblock / perblock_parent]) << log2_blksz;
845                 }
846                 
847                 if (ext4fs_indir3_block == NULL) {
848                         ext4fs_indir3_block = (uint32_t *) memalign(ARCH_DMA_MINALIGN, blksz);
849                         if (ext4fs_indir3_block == NULL) {
850                                 printf ("** TI ext2fs read block (indir 2 2) malloc failed. **\n");
851                                 return (-1);
852                         }
853                         ext4fs_indir3_size = blksz;
854                         ext4fs_indir3_blkno = -1;
855                 }
856                 if (blksz != ext4fs_indir3_size) {
857                         free (ext4fs_indir3_block);
858                         ext4fs_indir3_block = NULL;
859                         ext4fs_indir3_size = 0;
860                         ext4fs_indir3_blkno = -1;
861                         ext4fs_indir3_block = (uint32_t *) memalign(ARCH_DMA_MINALIGN, blksz);
862                         if (ext4fs_indir3_block == NULL) {
863                                 printf ("** TI ext2fs read block (indir 2 2) malloc failed. **\n");
864                                 return (-1);
865                         }
866                         ext4fs_indir3_size = blksz;
867                 }
868                 if ((__le32_to_cpu (ext4fs_indir2_block[rblock / perblock_child]) <<
869                           log2_blksz) != ext4fs_indir3_blkno) {
870                         status = ext2fs_devread (__le32_to_cpu(ext4fs_indir2_block[(rblock / perblock_child)
871                                                                         %(blksz/4)]) << log2_blksz,0, blksz,
872                                                                         (char *) ext4fs_indir3_block);
873                         if (status == 0) {
874                                 printf ("** TI ext2fs read block (indir 2 2) failed. **\n");
875                                 return (-1);
876                         }
877                         ext4fs_indir3_blkno =
878                                 __le32_to_cpu (ext4fs_indir2_block[(rblock / perblock_child)%(blksz/4)]) << log2_blksz;
879                 }
880                 
881                 blknr = __le32_to_cpu (ext4fs_indir3_block[rblock % perblock_child]);
882         }
883 #ifdef DEBUG
884         printf ("ext4fs_read_block %08x\n", blknr);
885 #endif
886         return (blknr);
887 }
888
889 static int ext4fs_read_block (ext2fs_node_t node, int fileblock)
890 {
891         struct ext2_data *data = node->data;
892         struct ext2_inode *inode = &node->inode;
893         int blknr;
894         int blksz = EXT2_BLOCK_SIZE (data);
895         int log2_blksz = LOG2_EXT2_BLOCK_SIZE (data);
896         int status;
897         unsigned int rblock;
898         unsigned int perblock;
899         unsigned int perblock_parent;
900         unsigned int perblock_child;
901
902         if (le32_to_cpu(inode->flags) & EXT4_EXTENTS_FLAG) {
903                 ALLOC_CACHE_ALIGN_BUFFER(char, buf, EXT2_BLOCK_SIZE(data));
904                 struct ext4_extent_header *leaf;
905                 struct ext4_extent *ext;
906                 int i;
907
908                 leaf = ext4fs_find_leaf (data, buf,
909                         (struct ext4_extent_header *) inode->b.blocks.dir_blocks,
910                         fileblock);
911                 if (!leaf) {
912                         printf ("invalid extent \n");
913                         return -1;
914                 }
915
916                 ext = (struct ext4_extent *) (leaf + 1);
917
918                 for (i = 0; i < le32_to_cpu (leaf->entries); i++) {
919                         if (fileblock < le32_to_cpu (ext[i].block))
920                                 break;
921                 }
922
923                 if (--i >= 0) {
924                         fileblock -= le32_to_cpu (ext[i].block);
925                         if (fileblock >= le32_to_cpu (ext[i].len)) {
926                                 return 0;
927                         } else {
928                                 unsigned int start;
929
930                                 start = le32_to_cpu (ext[i].start_hi);
931                                 start = (start << 32) + le32_to_cpu (ext[i].start);
932
933                                 return fileblock + start;
934                         }
935                 } else {
936                         printf("something wrong with extent \n");
937                         return -1;
938                 }
939         }
940
941         /* Direct blocks.  */
942         if (fileblock < INDIRECT_BLOCKS) {
943                 blknr = __le32_to_cpu (inode->b.blocks.dir_blocks[fileblock]);
944         }
945
946         /* Indirect.  */
947         else if (fileblock < (INDIRECT_BLOCKS + (blksz / 4))) {
948                 if (ext4fs_indir1_block == NULL) {
949                         ext4fs_indir1_block = (uint32_t *) memalign(ARCH_DMA_MINALIGN, blksz);
950                         if (ext4fs_indir1_block == NULL) {
951                                 printf ("** SI ext2fs read block (indir 1) malloc failed. **\n");
952                                 return (-1);
953                         }
954                         ext4fs_indir1_size = blksz;
955                         ext4fs_indir1_blkno = -1;
956                 }
957                 if (blksz != ext4fs_indir1_size) {
958                         free (ext4fs_indir1_block);
959                         ext4fs_indir1_block = NULL;
960                         ext4fs_indir1_size = 0;
961                         ext4fs_indir1_blkno = -1;
962                         ext4fs_indir1_block = (uint32_t *) memalign(ARCH_DMA_MINALIGN, blksz);
963                         if (ext4fs_indir1_block == NULL) {
964                                 printf ("** SI ext2fs read block (indir 1) malloc failed. **\n");
965                                 return (-1);
966                         }
967                         ext4fs_indir1_size = blksz;
968                 }
969                 if ((__le32_to_cpu (inode->b.blocks.indir_block) <<
970                      log2_blksz) != ext4fs_indir1_blkno) {
971                         status = ext2fs_devread (__le32_to_cpu(inode->b.blocks.indir_block) << log2_blksz,
972                                  0, blksz, (char *) ext4fs_indir1_block);
973                         if (status == 0) {
974                                 printf ("** SI ext2fs read block (indir 1) failed. **\n");
975                                 return (0);
976                         }
977                         ext4fs_indir1_blkno = __le32_to_cpu (inode->b.blocks.
978                                indir_block) << log2_blksz;
979                 }
980                 blknr = __le32_to_cpu (ext4fs_indir1_block[fileblock - INDIRECT_BLOCKS]);
981         }
982         /* Double indirect.  */
983
984         else if (fileblock <
985                 (INDIRECT_BLOCKS + (blksz / 4 * (blksz / 4 + 1)))) {
986                 perblock = blksz / 4;
987                 rblock = fileblock - (INDIRECT_BLOCKS + blksz / 4);
988
989                 if (ext4fs_indir1_block == NULL) {
990                         ext4fs_indir1_block = (uint32_t *) memalign(ARCH_DMA_MINALIGN, blksz);
991                         if (ext4fs_indir1_block == NULL) {
992                                 printf ("** DI ext2fs read block (indir 2 1) malloc failed. **\n");
993                                 return (-1);
994                         }
995                         ext4fs_indir1_size = blksz;
996                         ext4fs_indir1_blkno = -1;
997                 }
998                 if (blksz != ext4fs_indir1_size) {
999                         free (ext4fs_indir1_block);
1000                         ext4fs_indir1_block = NULL;
1001                         ext4fs_indir1_size = 0;
1002                         ext4fs_indir1_blkno = -1;
1003                         ext4fs_indir1_block = (uint32_t *) memalign(ARCH_DMA_MINALIGN, blksz);
1004                         if (ext4fs_indir1_block == NULL) {
1005                                 printf ("** DI ext2fs read block (indir 2 1) malloc failed. **\n");
1006                                 return (-1);
1007                         }
1008                         ext4fs_indir1_size = blksz;
1009                 }
1010                 if ((__le32_to_cpu (inode->b.blocks.double_indir_block) <<
1011                      log2_blksz) != ext4fs_indir1_blkno) {
1012                         status = ext2fs_devread
1013                                 (__le32_to_cpu(inode->b.blocks.double_indir_block) << log2_blksz,
1014                                 0, blksz,
1015                                 (char *) ext4fs_indir1_block);
1016                         if (status == 0) {
1017                                 printf ("** DI ext2fs read block (indir 2 1) failed. **\n");
1018                                 return (-1);
1019                         }
1020                         ext4fs_indir1_blkno =
1021                                 __le32_to_cpu (inode->b.blocks.double_indir_block) << log2_blksz;
1022                 }
1023
1024                 if (ext4fs_indir2_block == NULL) {
1025                         ext4fs_indir2_block = (uint32_t *) memalign(ARCH_DMA_MINALIGN, blksz);
1026                         if (ext4fs_indir2_block == NULL) {
1027                                 printf ("** DI ext2fs read block (indir 2 2) malloc failed. **\n");
1028                                 return (-1);
1029                         }
1030                         ext4fs_indir2_size = blksz;
1031                         ext4fs_indir2_blkno = -1;
1032                 }
1033                 if (blksz != ext4fs_indir2_size) {
1034                         free (ext4fs_indir2_block);
1035                         ext4fs_indir2_block = NULL;
1036                         ext4fs_indir2_size = 0;
1037                         ext4fs_indir2_blkno = -1;
1038                         ext4fs_indir2_block = (uint32_t *) memalign(ARCH_DMA_MINALIGN, blksz);
1039                         if (ext4fs_indir2_block == NULL) {
1040                                 printf ("** DI ext2fs read block (indir 2 2) malloc failed. **\n");
1041                                 return (-1);
1042                         }
1043                         ext4fs_indir2_size = blksz;
1044                 }
1045                 if ((__le32_to_cpu (ext4fs_indir1_block[rblock / perblock]) <<
1046                      log2_blksz) != ext4fs_indir2_blkno) {
1047                         status = ext2fs_devread (__le32_to_cpu(ext4fs_indir1_block[rblock / perblock]) << log2_blksz,
1048                                                  0, blksz,
1049                                                  (char *) ext4fs_indir2_block);
1050                         if (status == 0) {
1051                                 printf ("** DI ext2fs read block (indir 2 2) failed. **\n");
1052                                 return (-1);
1053                         }
1054                         ext4fs_indir2_blkno =
1055                                 __le32_to_cpu (ext4fs_indir1_block[rblock / perblock]) << log2_blksz;
1056                 }
1057                 blknr = __le32_to_cpu (ext4fs_indir2_block[rblock % perblock]);
1058         }
1059         /* Tripple indirect.  */
1060         else {
1061                 rblock = fileblock - (INDIRECT_BLOCKS + blksz / 4 + (blksz / 4 * blksz / 4));
1062                 perblock_child = blksz / 4;
1063                 perblock_parent = ((blksz / 4) * (blksz / 4));
1064                 
1065                 if (ext4fs_indir1_block == NULL) {
1066                                         ext4fs_indir1_block = (uint32_t *) memalign(ARCH_DMA_MINALIGN, blksz);
1067                         if (ext4fs_indir1_block == NULL) {
1068                                 printf ("** TI ext2fs read block (indir 2 1) malloc failed. **\n");
1069                                 return (-1);
1070                         }
1071                         ext4fs_indir1_size = blksz;
1072                         ext4fs_indir1_blkno = -1;
1073                 }
1074                 if (blksz != ext4fs_indir1_size) {
1075                                 free (ext4fs_indir1_block);
1076                         ext4fs_indir1_block = NULL;
1077                         ext4fs_indir1_size = 0;
1078                         ext4fs_indir1_blkno = -1;
1079                         ext4fs_indir1_block = (uint32_t *) memalign(ARCH_DMA_MINALIGN, blksz);
1080                         if (ext4fs_indir1_block == NULL) {
1081                                 printf ("** TI ext2fs read block (indir 2 1) malloc failed. **\n");
1082                                 return (-1);
1083                         }
1084                         ext4fs_indir1_size = blksz;
1085                 }
1086                 if ((__le32_to_cpu (inode->b.blocks.tripple_indir_block) <<
1087                           log2_blksz) != ext4fs_indir1_blkno) {
1088                         status = ext2fs_devread
1089                                 (__le32_to_cpu(inode->b.blocks.tripple_indir_block) << log2_blksz,
1090                                 0, blksz,
1091                                 (char *) ext4fs_indir1_block);
1092                         if (status == 0) {
1093                                 printf ("** TI ext2fs read block (indir 2 1) failed. **\n");
1094                                 return (-1);
1095                         }
1096                         ext4fs_indir1_blkno =
1097                                 __le32_to_cpu (inode->b.blocks.tripple_indir_block) << log2_blksz;
1098                 }
1099                 
1100                 if (ext4fs_indir2_block == NULL) {
1101                         ext4fs_indir2_block = (uint32_t *) memalign(ARCH_DMA_MINALIGN, blksz);
1102                         if (ext4fs_indir2_block == NULL) {
1103                                 printf ("** TI ext2fs read block (indir 2 2) malloc failed. **\n");
1104                                 return (-1);
1105                         }
1106                         ext4fs_indir2_size = blksz;
1107                         ext4fs_indir2_blkno = -1;
1108                 }
1109                 if (blksz != ext4fs_indir2_size) {
1110                         free (ext4fs_indir2_block);
1111                         ext4fs_indir2_block = NULL;
1112                         ext4fs_indir2_size = 0;
1113                         ext4fs_indir2_blkno = -1;
1114                         ext4fs_indir2_block = (uint32_t *) memalign(ARCH_DMA_MINALIGN, blksz);
1115                         if (ext4fs_indir2_block == NULL) {
1116                                 printf ("** TI ext2fs read block (indir 2 2) malloc failed. **\n");
1117                                 return (-1);
1118                         }
1119                         ext4fs_indir2_size = blksz;
1120                 }
1121                 if ((__le32_to_cpu (ext4fs_indir1_block[rblock / perblock_parent]) <<
1122                           log2_blksz) != ext4fs_indir2_blkno) {
1123                         status = ext2fs_devread (__le32_to_cpu(ext4fs_indir1_block[rblock / perblock_parent])
1124                                                                 << log2_blksz, 0, blksz,(char *) ext4fs_indir2_block);
1125                         if (status == 0) {
1126                                 printf ("** TI ext2fs read block (indir 2 2) failed. **\n");
1127                                 return (-1);
1128                         }
1129                         ext4fs_indir2_blkno =
1130                                 __le32_to_cpu (ext4fs_indir1_block[rblock / perblock_parent]) << log2_blksz;
1131                 }
1132                 
1133                 if (ext4fs_indir3_block == NULL) {
1134                         ext4fs_indir3_block = (uint32_t *) memalign(ARCH_DMA_MINALIGN, blksz);
1135                         if (ext4fs_indir3_block == NULL) {
1136                                 printf ("** TI ext2fs read block (indir 2 2) malloc failed. **\n");
1137                                 return (-1);
1138                         }
1139                         ext4fs_indir3_size = blksz;
1140                         ext4fs_indir3_blkno = -1;
1141                 }
1142                 if (blksz != ext4fs_indir3_size) {
1143                         free (ext4fs_indir3_block);
1144                         ext4fs_indir3_block = NULL;
1145                         ext4fs_indir3_size = 0;
1146                         ext4fs_indir3_blkno = -1;
1147                         ext4fs_indir3_block = (uint32_t *) memalign(ARCH_DMA_MINALIGN, blksz);
1148                         if (ext4fs_indir3_block == NULL) {
1149                                 printf ("** TI ext2fs read block (indir 2 2) malloc failed. **\n");
1150                                 return (-1);
1151                         }
1152                         ext4fs_indir3_size = blksz;
1153                 }
1154                 if ((__le32_to_cpu (ext4fs_indir2_block[rblock / perblock_child]) <<
1155                           log2_blksz) != ext4fs_indir3_blkno) {
1156                         status = ext2fs_devread (__le32_to_cpu(ext4fs_indir2_block[(rblock / perblock_child)%(blksz/4)])
1157                                                                         << log2_blksz, 0, blksz,(char *) ext4fs_indir3_block);
1158                         if (status == 0) {
1159                                 printf ("** TI ext2fs read block (indir 2 2) failed. **\n");
1160                                 return (-1);
1161                         }
1162                         ext4fs_indir3_blkno =
1163                                 __le32_to_cpu (ext4fs_indir2_block[(rblock / perblock_child)%(blksz/4)]) << log2_blksz;
1164                 }
1165                 
1166                 blknr = __le32_to_cpu (ext4fs_indir3_block[rblock % perblock_child]);
1167         }
1168 #ifdef DEBUG
1169         printf ("ext4fs_read_block %08x\n", blknr);
1170 #endif
1171         return (blknr);
1172 }
1173
1174 int ext4fs_read_file
1175         (ext2fs_node_t node, int pos, unsigned int len, char *buf) {
1176
1177         int i;
1178         int blockcnt;
1179         int log2blocksize = LOG2_EXT2_BLOCK_SIZE (node->data);
1180         int blocksize = 1 << (log2blocksize + DISK_SECTOR_BITS);
1181         unsigned int filesize = __le32_to_cpu(node->inode.size);
1182         int previous_block_number = -1;
1183         int delayed_start = 0;
1184         int delayed_extent = 0;
1185         int delayed_skipfirst = 0;
1186         int delayed_next = 0;
1187         char * delayed_buf = NULL;
1188         int status;
1189
1190         /* Adjust len so it we can't read past the end of the file.  */
1191         if (len > filesize)
1192                 len = filesize;
1193
1194         blockcnt = ((len + pos) + blocksize - 1) / blocksize;
1195
1196         for (i = pos / blocksize; i < blockcnt; i++) {
1197                 int blknr;
1198                 int blockoff = pos % blocksize;
1199                 int blockend = blocksize;
1200                 int skipfirst = 0;
1201                 blknr = ext4fs_read_block (node, i);
1202                 if (blknr < 0) {
1203                         return (-1);
1204                 }
1205                 blknr = blknr << log2blocksize;
1206
1207                 /* Last block.  */
1208                 if (i == blockcnt - 1) {
1209                         blockend = (len + pos) % blocksize;
1210
1211                         /* The last portion is exactly blocksize.  */
1212                         if (!blockend)
1213                                 blockend = blocksize;
1214                 }
1215
1216                 /* First block.  */
1217                 if (i == pos / blocksize) {
1218                         skipfirst = blockoff;
1219                         blockend -= skipfirst;
1220                 }
1221                 if (blknr) {
1222                         int status;
1223
1224                         if (previous_block_number != -1) {
1225                                 if (delayed_next == blknr) {
1226                                 delayed_extent += blockend;
1227                                 delayed_next += blockend >> SECTOR_BITS;
1228                                 } else { /* spill */
1229                                         status = ext2fs_devread(delayed_start,
1230                                                 delayed_skipfirst, delayed_extent,
1231                                                         delayed_buf);
1232                                         if (status == 0)
1233                                                 return -1;
1234                                         previous_block_number = blknr;
1235                                         delayed_start = blknr;
1236                                         delayed_extent = blockend;
1237                                         delayed_skipfirst = skipfirst;
1238                                         delayed_buf = buf;
1239                                         delayed_next = blknr +
1240                                                 (blockend >> SECTOR_BITS);
1241                                 }
1242                         } else {
1243                                 previous_block_number = blknr;
1244                                 delayed_start = blknr;
1245                                 delayed_extent = blockend;
1246                                 delayed_skipfirst = skipfirst;
1247                                 delayed_buf = buf;
1248                                 delayed_next = blknr + (blockend >> SECTOR_BITS);
1249                         }
1250                 } else {
1251                         if (previous_block_number != -1) {
1252                                 /* spill */
1253                                 status = ext2fs_devread(delayed_start,
1254                                         delayed_skipfirst, delayed_extent,
1255                                                  delayed_buf);
1256                                 if (status == 0)
1257                                         return -1;
1258                                 previous_block_number = -1;
1259                         }
1260                         memset(buf, 0, blocksize - skipfirst);
1261                 }
1262                 buf += blocksize - skipfirst;
1263         }
1264         if (previous_block_number != -1) {
1265                 /* spill */
1266                 status = ext2fs_devread(delayed_start,
1267                          delayed_skipfirst, delayed_extent, delayed_buf);
1268                 if (status == 0)
1269                         return -1;
1270                 previous_block_number = -1;
1271         }
1272         return (len);
1273 }
1274
1275 int ext4fs_write_file
1276         (block_dev_desc_t *dev_desc, struct ext2_inode *file_inode, int pos, unsigned int len, char *buf) {
1277
1278         int i;
1279         int blockcnt;
1280         int log2blocksize = LOG2_EXT2_BLOCK_SIZE (ext4fs_root);
1281         unsigned int filesize = __le32_to_cpu(file_inode->size);
1282         int previous_block_number = -1;
1283         int delayed_start = 0;
1284         int delayed_extent = 0;
1285         int delayed_next = 0;
1286         char * delayed_buf = NULL;
1287
1288         /* Adjust len so it we can't read past the end of the file.  */
1289         if (len > filesize)
1290                 len = filesize;
1291
1292         blockcnt = ((len + pos) + blocksize - 1) / blocksize;
1293
1294         for (i = pos / blocksize; i < blockcnt; i++) {
1295                 int blknr;
1296                 int blockend = blocksize;
1297                 int skipfirst = 0;
1298                 blknr = ext4fs_read_allocated_block (file_inode, i);
1299                 if (blknr < 0) {
1300                         return (-1);
1301                 }
1302                 blknr = blknr << log2blocksize;
1303
1304                 if (blknr) {
1305                         if (previous_block_number != -1) {
1306                                 if (delayed_next == blknr) {
1307                                 delayed_extent += blockend;
1308                                 delayed_next += blockend >> SECTOR_BITS;
1309                                 } else { /* spill */    
1310                                         put_ext4(dev_desc,(uint64_t)(delayed_start*SECTOR_SIZE), delayed_buf,
1311                                                                         (uint32_t)delayed_extent);
1312                                         previous_block_number = blknr;
1313                                         delayed_start = blknr;
1314                                         delayed_extent = blockend;
1315                                         delayed_buf = buf;
1316                                         delayed_next = blknr +
1317                                                 (blockend >> SECTOR_BITS);
1318                                 }
1319                         } else {
1320                                 previous_block_number = blknr;
1321                                 delayed_start = blknr;
1322                                 delayed_extent = blockend;
1323                                 delayed_buf = buf;
1324                                 delayed_next = blknr + (blockend >> SECTOR_BITS);
1325                         }
1326                 } else {
1327                         if (previous_block_number != -1) {
1328                                 /* spill */
1329                                 put_ext4(dev_desc,(uint64_t)(delayed_start*SECTOR_SIZE), delayed_buf,
1330                                                                         (uint32_t)delayed_extent);
1331
1332                                 previous_block_number = -1;
1333                         }
1334                         memset(buf, 0, blocksize - skipfirst);
1335                 }
1336                 buf += blocksize - skipfirst;
1337         }
1338         if (previous_block_number != -1) {
1339                 /* spill */
1340                 put_ext4(dev_desc,(uint64_t)(delayed_start*SECTOR_SIZE), delayed_buf, (uint32_t)delayed_extent);
1341
1342                 previous_block_number = -1;
1343         }
1344         return (len);
1345 }
1346
1347 static int ext4fs_iterate_dir (ext2fs_node_t dir, char *name, ext2fs_node_t * fnode, int *ftype)
1348 {
1349         unsigned int fpos = 0;
1350         int status;
1351         struct ext2fs_node *diro = (struct ext2fs_node *) dir;
1352
1353 #ifdef DEBUG
1354         if (name != NULL)
1355                 printf ("Iterate dir %s\n", name);
1356 #endif /* of DEBUG */
1357         if (!diro->inode_read) {
1358                 status = ext4fs_read_inode (diro->data, diro->ino,
1359                                             &diro->inode);
1360                 if (status == 0)
1361                         return (0);
1362         }
1363         /* Search the file.  */
1364         while (fpos < __le32_to_cpu (diro->inode.size)) {
1365                 struct ext2_dirent dirent;
1366                 status = ext4fs_read_file (diro, fpos,
1367                         sizeof (struct ext2_dirent),
1368                         (char *) &dirent);
1369                 if (status < 1)
1370                         return (0);
1371
1372                 if (dirent.namelen != 0) {
1373                         char filename[dirent.namelen + 1];
1374                         ext2fs_node_t fdiro;
1375                         int type = FILETYPE_UNKNOWN;
1376
1377                         status = ext4fs_read_file (diro,
1378                                                    fpos + sizeof (struct ext2_dirent),
1379                                                    dirent.namelen, filename);
1380                         if (status < 1)
1381                                 return (0);
1382
1383                         fdiro = memalign(ARCH_DMA_MINALIGN, sizeof (struct ext2fs_node));
1384                         if (!fdiro) {
1385                                 return (0);
1386                         }
1387
1388                         fdiro->data = diro->data;
1389                         fdiro->ino = __le32_to_cpu (dirent.inode);
1390
1391                         filename[dirent.namelen] = '\0';
1392
1393                         if (dirent.filetype != FILETYPE_UNKNOWN) {
1394                                 fdiro->inode_read = 0;
1395
1396                                 if (dirent.filetype == FILETYPE_DIRECTORY) {
1397                                         type = FILETYPE_DIRECTORY;
1398                                 } else if (dirent.filetype ==
1399                                            FILETYPE_SYMLINK) {
1400                                         type = FILETYPE_SYMLINK;
1401                                 } else if (dirent.filetype == FILETYPE_REG) {
1402                                         type = FILETYPE_REG;
1403                                 } 
1404                         } else {
1405                                 /* The filetype can not be read from the dirent, get it from inode */
1406
1407                                 status = ext4fs_read_inode (diro->data,
1408                                         __le32_to_cpu(dirent.inode),
1409                                         &fdiro->inode);
1410                                 if (status == 0) {
1411                                         free (fdiro);
1412                                         return (0);
1413                                 }
1414                                 fdiro->inode_read = 1;
1415
1416                                 if ((__le16_to_cpu (fdiro->inode.mode) &
1417                                         FILETYPE_INO_MASK) == FILETYPE_INO_DIRECTORY) {
1418                                         type = FILETYPE_DIRECTORY;
1419                                 } else if ((__le16_to_cpu (fdiro->inode.mode)
1420                                         & FILETYPE_INO_MASK) ==
1421                                         FILETYPE_INO_SYMLINK) {
1422                                         type = FILETYPE_SYMLINK;
1423                                 } else if ((__le16_to_cpu (fdiro->inode.mode)
1424                                         & FILETYPE_INO_MASK) ==
1425                                         FILETYPE_INO_REG) {
1426                                         type = FILETYPE_REG;
1427                                 }
1428                         }
1429 #ifdef DEBUG
1430                         printf ("iterate >%s<\n", filename);
1431 #endif /* of DEBUG */
1432                         if ((name != NULL) && (fnode != NULL)
1433                                 && (ftype != NULL)) {
1434                                 if (strcmp (filename, name) == 0) {
1435                                         *ftype = type;
1436                                         *fnode = fdiro;
1437                                         return (1);
1438                                 }
1439                         } else {
1440                                 if (fdiro->inode_read == 0) {
1441                                         status = ext4fs_read_inode (diro->data,
1442                                         __le32_to_cpu (dirent.inode),
1443                                         &fdiro->inode);
1444                                         if (status == 0) {
1445                                                 free (fdiro);
1446                                                 return (0);
1447                                         }
1448                                         fdiro->inode_read = 1;
1449                                 }
1450                                 switch (type) {
1451                                 case FILETYPE_DIRECTORY:
1452                                         printf ("<DIR> ");
1453                                         break;
1454                                 case FILETYPE_SYMLINK:
1455                                         printf ("<SYM> ");
1456                                         break;
1457                                 case FILETYPE_REG:
1458                                         printf ("      ");
1459                                         break;
1460                                 default:
1461                                         printf ("< ? > ");
1462                                         break;
1463                                 }
1464                                 printf ("%10d %s\n",
1465                                         __le32_to_cpu (fdiro->inode.size),
1466                                         filename);
1467                         }
1468                         free (fdiro);
1469                 }
1470                 fpos += __le16_to_cpu (dirent.direntlen);
1471         }
1472         return (0);
1473 }
1474
1475 static char *ext4fs_read_symlink (ext2fs_node_t node)
1476 {
1477         char *symlink;
1478         struct ext2fs_node *diro = node;
1479         int status;
1480
1481         if (!diro->inode_read) {
1482                 status = ext4fs_read_inode (diro->data, diro->ino,
1483                                             &diro->inode);
1484                 if (status == 0)
1485                         return (0);
1486         }
1487         symlink = memalign(ARCH_DMA_MINALIGN, __le32_to_cpu (diro->inode.size) + 1);
1488         if (!symlink)
1489                 return (0);
1490
1491         /* If the filesize of the symlink is bigger than
1492            60 the symlink is stored in a separate block,
1493            otherwise it is stored in the inode.  */
1494         if (__le32_to_cpu (diro->inode.size) <= 60) {
1495                 strncpy (symlink, diro->inode.b.symlink,
1496                          __le32_to_cpu (diro->inode.size));
1497         } else {
1498                 status = ext4fs_read_file (diro, 0,
1499                    __le32_to_cpu (diro->inode.size), symlink);
1500                 if (status == 0) {
1501                         free (symlink);
1502                         return (0);
1503                 }
1504         }
1505         symlink[__le32_to_cpu (diro->inode.size)] = '\0';
1506         return (symlink);
1507 }
1508
1509 int ext4fs_find_file1
1510         (const char *currpath,
1511          ext2fs_node_t currroot, ext2fs_node_t * currfound, int *foundtype)
1512 {
1513         char fpath[strlen (currpath) + 1];
1514         char *name = fpath;
1515         char *next;
1516         int status;
1517         int type = FILETYPE_DIRECTORY;
1518         ext2fs_node_t currnode = currroot;
1519         ext2fs_node_t oldnode = currroot;
1520
1521         strncpy (fpath, currpath, strlen (currpath) + 1);
1522
1523         /* Remove all leading slashes.  */
1524         while (*name == '/') {
1525                 name++;
1526         }
1527         if (!*name) {
1528                 *currfound = currnode;
1529                 return (1);
1530         }
1531
1532         for (;;) {
1533                 int found;
1534
1535                 /* Extract the actual part from the pathname.  */
1536                 next = strchr (name, '/');
1537                 if (next) {
1538                         /* Remove all leading slashes.  */
1539                         while (*next == '/') {
1540                                 *(next++) = '\0';
1541                         }
1542                 }
1543
1544                 /* At this point it is expected that the current node
1545                         is a directory, check if this is true.  */
1546                 if (type != FILETYPE_DIRECTORY) {
1547                         ext4fs_free_node (currnode, currroot);
1548                         return (0);
1549                 }
1550
1551                 oldnode = currnode;
1552
1553                 /* Iterate over the directory.  */
1554                 found = ext4fs_iterate_dir (currnode, name, &currnode, &type);
1555                 if (found == 0)
1556                         return (0);
1557                 if (found == -1)
1558                         break;
1559
1560                 /* Read in the symlink and follow it.  */
1561                 if (type == FILETYPE_SYMLINK) {
1562                         char *symlink;
1563
1564                         /* Test if the symlink does not loop.  */
1565                         if (++ext4fs_symlinknest == 8) {
1566                                 ext4fs_free_node (currnode, currroot);
1567                                 ext4fs_free_node (oldnode, currroot);
1568                                 return (0);
1569                         }
1570
1571                         symlink = ext4fs_read_symlink (currnode);
1572                         ext4fs_free_node (currnode, currroot);
1573
1574                         if (!symlink) {
1575                                 ext4fs_free_node (oldnode, currroot);
1576                                 return (0);
1577                         }
1578 #ifdef DEBUG
1579                         printf ("Got symlink >%s<\n", symlink);
1580 #endif /* of DEBUG */
1581                         /* The symlink is an absolute path, go back to the root inode.  */
1582                         if (symlink[0] == '/') {
1583                                 ext4fs_free_node (oldnode, currroot);
1584                                 oldnode = &ext4fs_root->diropen;
1585                         }
1586
1587                         /* Lookup the node the symlink points to.  */
1588                         status = ext4fs_find_file1 (symlink, oldnode,
1589                                 &currnode, &type);
1590
1591                         free (symlink);
1592
1593                         if (status == 0) {
1594                                 ext4fs_free_node (oldnode, currroot);
1595                                 return (0);
1596                         }
1597                 }
1598
1599                 ext4fs_free_node (oldnode, currroot);
1600
1601                 /* Found the node!  */
1602                 if (!next || *next == '\0') {
1603                         *currfound = currnode;
1604                         *foundtype = type;
1605                         return (1);
1606                 }
1607                 name = next;
1608         }
1609         return (-1);
1610 }
1611
1612 int ext4fs_find_file
1613         (const char *path,
1614          ext2fs_node_t rootnode, ext2fs_node_t * foundnode, int expecttype)
1615 {
1616         int status;
1617         int foundtype = FILETYPE_DIRECTORY;
1618
1619         ext4fs_symlinknest = 0;
1620         if (!path)
1621                 return (0);
1622
1623         status = ext4fs_find_file1 (path, rootnode, foundnode, &foundtype);
1624         if (status == 0)
1625                 return (0);
1626
1627         /* Check if the node that was found was of the expected type.  */
1628         if ((expecttype == FILETYPE_REG) && (foundtype != expecttype)) {
1629                 return (0);
1630         } else if ((expecttype == FILETYPE_DIRECTORY)
1631                    && (foundtype != expecttype)) {
1632                 return (0);
1633         }
1634         return (1);
1635 }
1636
1637 int  ext4fs_get_inode_no_from_inodebitmap(unsigned char *buffer)
1638 {
1639         int j=0;
1640         unsigned char input;
1641         int operand;
1642         int status;
1643         int count =1;
1644
1645         /*get the blocksize of the filesystem*/
1646         unsigned char *ptr=buffer;
1647         while(*ptr==255)
1648         {
1649                 ptr++;
1650                 count+=8;
1651                 if(count>(uint32_t)ext4fs_root->sblock.inodes_per_group)
1652                         return -1;
1653         }
1654         
1655         for(j=0;j<blocksize;j++)
1656         {
1657                 input=*ptr;
1658                 int i=0;
1659                 while(i<=7)
1660                 {
1661                         operand=1<<i;
1662                         status = input & operand;
1663                         if(status)
1664                         {
1665                                 i++;
1666                                 count++;
1667                         }
1668                         else
1669                         {
1670                                 *ptr|= operand;
1671                                 return count;
1672                         }
1673                 }
1674                  ptr=ptr+1;
1675         }
1676         return -1;
1677 }
1678
1679 int  ext4fs_get_block_no_from_blockbitmap(unsigned char *buffer)
1680 {
1681         int j=0;
1682         unsigned char input;
1683         int operand;
1684         int status;
1685         int count =0;
1686         int blocksize;
1687
1688         /*get the blocksize of the filesystem*/
1689         blocksize=EXT2_BLOCK_SIZE(ext4fs_root);
1690         unsigned char *ptr=buffer;
1691         if(blocksize!=1024)
1692                 count=0;
1693         else
1694                 count=1;
1695         
1696         while(*ptr==255)
1697         {
1698                 ptr++;
1699                 count+=8;
1700                 if(count==(blocksize *8))
1701                         return -1;
1702         }
1703         
1704         for(j=0;j<blocksize;j++)
1705         {
1706                 input=*ptr;
1707                 int i=0;
1708                 while(i<=7)
1709                 {
1710                         operand=1<<i;
1711                         status = input & operand;
1712                         if(status)
1713                         {
1714                                 i++;
1715                                 count++;
1716                         }
1717                         else
1718                         {
1719                                 *ptr|= operand;
1720                                 return count;
1721                         }
1722                 }
1723                  ptr=ptr+1;
1724         }
1725         return -1;
1726 }
1727
1728 int ext4fs_update_bmap_with_one(unsigned long blockno, unsigned char * buffer, int index)
1729 {
1730         unsigned int i;
1731         unsigned int remainder;
1732         unsigned char  *ptr=buffer;
1733         unsigned char operand;
1734         int status;
1735         int blocksize;
1736         i=blockno/8;
1737         remainder=blockno%8;
1738
1739         /*get the blocksize of the filesystem*/
1740         blocksize=EXT2_BLOCK_SIZE(ext4fs_root);
1741         i=i-(index * blocksize);
1742         if(blocksize!=1024)
1743         {
1744                 ptr=ptr+i;
1745                 operand=1<<remainder;
1746                 status=*ptr & operand;
1747                 if(status)
1748                 {
1749                         return -1;
1750                 }
1751                 else
1752                 {
1753                         *ptr=*ptr|operand;
1754                         return 0;
1755                 }
1756         }
1757         else
1758         {
1759                 if(remainder==0)
1760                 {
1761                         ptr=ptr+i-1;
1762                         operand=(1<<7);
1763                 }
1764                 else
1765                 {
1766                         ptr=ptr+i;
1767                         operand=(1<<(remainder-1));
1768                 }
1769                 status=*ptr & operand;
1770                 if(status)
1771                 {
1772                         return -1;
1773                 }
1774                 else
1775                 {
1776                         *ptr=*ptr|operand;
1777                         return 0;
1778                 } 
1779         }
1780 }
1781
1782 int ext4fs_update_bmap_with_zero(unsigned long blockno, unsigned char * buffer, int index)
1783 {
1784         unsigned int i;
1785         unsigned int remainder;
1786         unsigned char  *ptr=buffer;
1787         unsigned char operand;
1788         int status;
1789         i=blockno/8;
1790         remainder=blockno%8;
1791         int blocksize;
1792
1793         /*get the blocksize of the filesystem*/
1794         blocksize=EXT2_BLOCK_SIZE(ext4fs_root);
1795         i=i-(index * blocksize);
1796         if(blocksize!=1024)
1797         {
1798                 ptr=ptr+i;
1799                 operand=(1<<remainder);
1800                 status=*ptr & operand;
1801                 if(status)
1802                 {
1803                         *ptr=*ptr & ~(operand);
1804                         return 0;
1805                 }
1806                 else
1807                 {
1808                         return -1;
1809                 }
1810         }
1811         else
1812         {
1813                 if(remainder==0)
1814                 {
1815                         ptr=ptr+i-1;
1816                         operand=(1<<7);
1817                 }
1818                 else
1819                 {
1820                         ptr=ptr+i;
1821                         operand=(1<<(remainder-1));
1822                 }
1823                 status=*ptr & operand;
1824                 if(status)
1825                 {
1826                         *ptr=*ptr & ~(operand);
1827                         return 0;
1828                 
1829                 }
1830                 else
1831                 {
1832                         return -1;
1833                 }
1834         }
1835 }
1836
1837 int ext4fs_update_inode_bmap_with_one(unsigned long inode_no, unsigned char * buffer, int index)
1838 {
1839         unsigned int i;
1840         unsigned int remainder;
1841         unsigned char  *ptr=buffer;
1842         unsigned char operand;
1843         int status;
1844         
1845         inode_no -= (index * (uint32_t)ext4fs_root->sblock.inodes_per_group);
1846         
1847         i=inode_no/8;
1848         remainder=inode_no%8;
1849         if(remainder==0)
1850         {
1851                 ptr=ptr+i-1;
1852                 operand=(1<<7);
1853         }
1854         else
1855         {
1856                 ptr=ptr+i;
1857                 operand=(1<<(remainder-1));
1858         }       
1859         status=*ptr & operand;
1860         if(status)
1861         {
1862                 return -1;
1863         }
1864         else
1865         {
1866                 *ptr=*ptr|operand;
1867                 return 0;
1868         }
1869 }
1870
1871 int ext4fs_update_inode_bmap_with_zero(unsigned long inode_no, unsigned char * buffer,int index)
1872 {
1873         unsigned int i;
1874         unsigned int remainder;
1875         unsigned char  *ptr=buffer;
1876         unsigned char operand;
1877         int status;
1878
1879         inode_no -= (index * (uint32_t)ext4fs_root->sblock.inodes_per_group);
1880         i=inode_no/8;
1881         remainder=inode_no%8;
1882         if(remainder==0)
1883         {
1884                 ptr=ptr+i-1;
1885                 operand=(1<<7);
1886         }
1887         else
1888         {
1889                 ptr=ptr+i;
1890                 operand=(1<<(remainder-1));
1891         }
1892         status=*ptr & operand;
1893         if(status)
1894         {
1895                 *ptr=*ptr & ~(operand);
1896                 return 0;
1897         }
1898         else
1899         {
1900                 return -1;
1901         }
1902 }
1903
1904 unsigned long ext4fs_get_next_available_block_no(block_dev_desc_t *dev_desc,int part_no)
1905 {
1906         int i;
1907         int status;
1908         int remainder;
1909         int sector_per_block;
1910         int blocksize;
1911         unsigned int bg_bitmap_index;
1912         static int prev_bg_bitmap_index = -1;
1913         unsigned char *zero_buffer=NULL;
1914         unsigned char *journal_buffer=NULL;
1915         
1916         /*get the blocksize of the filesystem*/
1917         blocksize=EXT2_BLOCK_SIZE(ext4fs_root);
1918
1919         /*calucalate sector per block*/
1920         sector_per_block=blocksize/SECTOR_SIZE;
1921         struct ext2_block_group *gd=(struct ext2_block_group*)gd_table;
1922         
1923         if(first_execution==0)
1924         {
1925                 for(i=0;i<no_blockgroup;i++)
1926                 {
1927                         if(gd[i].free_blocks)
1928                         {
1929 #ifdef DEBUG_LOG
1930                                 printf("Block group reading is %d\n",i);
1931 #endif
1932                                 if(gd[i].bg_flags & EXT4_BG_BLOCK_UNINIT)
1933                                 {
1934                                         printf("block uninit set for group %d\n",i);
1935                                         zero_buffer = (unsigned char *)xzalloc(blocksize);
1936                                         put_ext4(dev_desc,((uint64_t)(gd[i].block_id * blocksize)),
1937                                                                         zero_buffer, blocksize);
1938                                         gd[i].bg_flags = gd[i].bg_flags & ~EXT4_BG_BLOCK_UNINIT;
1939                                         memcpy(bg[i],zero_buffer,blocksize);
1940                                         if(zero_buffer)
1941                                         {
1942                                                 free(zero_buffer);
1943                                                 zero_buffer = NULL;
1944                                         }
1945                                 }
1946                                 blockno=ext4fs_get_block_no_from_blockbitmap(bg[i]);
1947                                 if(blockno==-1) /*if block bitmap is completely fill*/
1948                                 {
1949                                         continue;
1950                                 }
1951                                 blockno=blockno +(i*blocksize*8);
1952 #ifdef DEBUG_LOG
1953                                 printf("every first block no getting is %d\n",blockno);
1954 #endif
1955                                 first_execution++;
1956                                 gd[i].free_blocks--;
1957                                 sb->free_blocks--;
1958                                 //journal backup
1959                                 journal_buffer = (unsigned char *)xzalloc(blocksize);
1960                                 status = ext2fs_devread (gd[i].block_id*sector_per_block, 0, blocksize,journal_buffer);
1961                                 if(status==0){
1962                                         free(journal_buffer);
1963                                         return -1;
1964                                 }
1965                                 log_journal(journal_buffer,gd[i].block_id);
1966                                 free(journal_buffer);
1967                                 return  blockno;
1968                         }
1969                         else
1970                         {
1971 #ifdef DEBUG_LOG
1972                                 printf("no space left on the block group %d \n",i);
1973 #endif
1974                         }
1975                 }
1976                 return -1;
1977         }
1978         else
1979         {
1980                 restart:
1981                 blockno++;
1982                 /*get the blockbitmap index respective to blockno */
1983                 if(blocksize!=1024)
1984                 {
1985                         bg_bitmap_index=blockno/(uint32_t)ext4fs_root->sblock.blocks_per_group;
1986                 }
1987                 else
1988                 {
1989                         bg_bitmap_index=blockno/(uint32_t)ext4fs_root->sblock.blocks_per_group; 
1990                         remainder = blockno%(uint32_t)ext4fs_root->sblock.blocks_per_group;
1991                         if(!remainder)
1992                                 bg_bitmap_index--;
1993                 }
1994                 
1995                 /*To skip completely filled block group bitmaps : Optimize the block allocation*/
1996                 if(bg_bitmap_index >= no_blockgroup)
1997                         return -1;
1998                 
1999                 if(gd[bg_bitmap_index].free_blocks==0)
2000                 {
2001 #ifdef DEBUG_LOG
2002                         printf("block group %d is full. Skipping\n",bg_bitmap_index);
2003 #endif
2004                         blockno= blockno + ext4fs_root->sblock.blocks_per_group;
2005                         blockno--;
2006                         goto restart;
2007                 }
2008         
2009                 if(gd[bg_bitmap_index].bg_flags & EXT4_BG_BLOCK_UNINIT)
2010                 {
2011                         zero_buffer = (unsigned char *)xzalloc(blocksize);
2012                         put_ext4(dev_desc,((uint64_t)(gd[bg_bitmap_index].block_id * blocksize)),
2013                                                         zero_buffer, blocksize);
2014                         memcpy(bg[bg_bitmap_index],zero_buffer,blocksize);
2015                         gd[bg_bitmap_index].bg_flags = gd[bg_bitmap_index].bg_flags & ~EXT4_BG_BLOCK_UNINIT;
2016                         if(zero_buffer)
2017                         {
2018                                 free(zero_buffer);
2019                                 zero_buffer = NULL;
2020                         }
2021                 }
2022                 
2023                 if(ext4fs_update_bmap_with_one(blockno,bg[bg_bitmap_index],bg_bitmap_index)!=0)
2024                 {
2025 #ifdef DEBUG_LOG
2026                         printf("going for restart for the block no %u %d\n",blockno,bg_bitmap_index);
2027 #endif
2028                         goto restart;
2029                 }
2030
2031                 //journal backup
2032                 if(prev_bg_bitmap_index != bg_bitmap_index){
2033                         journal_buffer = (unsigned char *)xzalloc(blocksize);
2034                         status = ext2fs_devread (gd[bg_bitmap_index].block_id*sector_per_block,
2035                                                                         0, blocksize,journal_buffer);
2036                         if(status==0){
2037                                 free(journal_buffer);
2038                                 return -1;
2039                         }
2040                         log_journal(journal_buffer,gd[bg_bitmap_index].block_id);
2041                         prev_bg_bitmap_index = bg_bitmap_index;
2042                         free(journal_buffer);
2043                 }
2044                 gd[bg_bitmap_index].free_blocks--;
2045                 sb->free_blocks--;
2046                 return blockno;
2047         }
2048 }
2049
2050 unsigned long ext4fs_get_next_available_inode_no(block_dev_desc_t *dev_desc,int part_no)
2051 {
2052         int i;
2053         int status;
2054         unsigned int inode_bitmap_index;
2055         static int prev_inode_bitmap_index = -1;
2056         unsigned char *zero_buffer=NULL;
2057         unsigned char *journal_buffer=NULL;
2058         
2059         struct ext2_block_group *gd=(struct ext2_block_group*)gd_table;
2060         
2061         if(first_execution_inode==0)
2062         {
2063                 for(i=0;i<no_blockgroup;i++)
2064                 {
2065                         if(gd[i].free_inodes)
2066                         {
2067 #ifdef DEBUG_LOG
2068                                 printf("Block group reading is %d\n",i);
2069 #endif
2070                                 if (gd[i].bg_itable_unused !=
2071                                                  gd[i].free_inodes)
2072                                         gd[i].bg_itable_unused =
2073                                                  gd[i].free_inodes;
2074                                 if(gd[i].bg_flags & EXT4_BG_INODE_UNINIT)
2075                                 {
2076                                         zero_buffer = (unsigned char *)xzalloc(blocksize);
2077                                         put_ext4(dev_desc,((uint64_t)(gd[i].inode_id * blocksize)),
2078                                                                 zero_buffer, blocksize);
2079                                         gd[i].bg_flags = gd[i].bg_flags & ~EXT4_BG_INODE_UNINIT;
2080                                         memcpy(inode_bmaps[i],zero_buffer,blocksize);
2081                                         if(zero_buffer)
2082                                         {
2083                                                 free(zero_buffer);
2084                                                 zero_buffer = NULL;
2085                                         }
2086                                 }
2087                                 inode_no=ext4fs_get_inode_no_from_inodebitmap(inode_bmaps[i]);
2088                                 if(inode_no==-1) /*if block bitmap is completely fill*/
2089                                 {
2090                                         continue;
2091                                 }
2092                                 inode_no=inode_no +(i*ext4fs_root->sblock.inodes_per_group);
2093 #ifdef DEBUG_LOG
2094                                 printf("every first inode no getting is %d\n",inode_no);
2095 #endif
2096                                 first_execution_inode++;
2097                                 gd[i].free_inodes--;
2098                                 gd[i].bg_itable_unused--;
2099                                 sb->free_inodes--;
2100                                 //journal backup
2101                                 journal_buffer = (unsigned char *)xzalloc(blocksize);
2102                                 status = ext2fs_devread (gd[i].inode_id*sector_per_block, 0, blocksize,journal_buffer);
2103                                 if(status==0)
2104                                 {
2105                                         free(journal_buffer);
2106                                         return -1;
2107                                 }
2108                                 log_journal(journal_buffer,gd[i].inode_id);
2109                                 free(journal_buffer);
2110                                 return  inode_no;
2111                         }
2112                         else
2113                         {
2114 #ifdef DEBUG_LOG
2115                                 printf("no inode left on the block group %d \n",i);
2116 #endif
2117                         }
2118                 }
2119                 return -1;
2120         }
2121         else
2122         {
2123                 restart:
2124                 inode_no++;
2125                 /*get the blockbitmap index respective to blockno */
2126                 inode_bitmap_index=inode_no/(uint32_t)ext4fs_root->sblock.inodes_per_group;
2127                 if(gd[inode_bitmap_index].bg_flags & EXT4_BG_INODE_UNINIT)
2128                 {
2129                         zero_buffer = (unsigned char *)xzalloc(blocksize);
2130                         put_ext4(dev_desc,((uint64_t)(gd[inode_bitmap_index].inode_id * blocksize)),
2131                                                         zero_buffer, blocksize);
2132                         gd[inode_bitmap_index].bg_flags = gd[inode_bitmap_index].bg_flags & ~EXT4_BG_INODE_UNINIT;
2133                         memcpy(inode_bmaps[inode_bitmap_index],zero_buffer,blocksize);
2134                         if(zero_buffer)
2135                         {
2136                                 free(zero_buffer);
2137                                 zero_buffer = NULL;
2138                         }
2139                 }
2140                 
2141                 if(ext4fs_update_inode_bmap_with_one(inode_no,inode_bmaps[inode_bitmap_index],inode_bitmap_index)!=0)
2142                 {
2143 #ifdef DEBUG_LOG
2144                         printf("going for restart for the block no %u %d\n",inode_no,inode_bitmap_index);
2145 #endif
2146                         goto restart;
2147                 }
2148
2149                 //journal backup
2150                 if(prev_inode_bitmap_index != inode_bitmap_index){
2151                         journal_buffer = (unsigned char *)xzalloc(blocksize);
2152                         status = ext2fs_devread (gd[inode_bitmap_index].inode_id*sector_per_block,
2153                                                                                 0,blocksize,journal_buffer);
2154                         if(status==0){
2155                                 free(journal_buffer);
2156                                 return -1;
2157                         }
2158                         log_journal(journal_buffer,gd[inode_bitmap_index].inode_id);
2159                         prev_inode_bitmap_index = inode_bitmap_index;
2160                         free(journal_buffer);
2161                 }
2162                 if (gd[inode_bitmap_index].bg_itable_unused !=
2163                                 gd[inode_bitmap_index].free_inodes)
2164                         gd[inode_bitmap_index].bg_itable_unused =
2165                                 gd[inode_bitmap_index].free_inodes;
2166                 gd[inode_bitmap_index].free_inodes--;
2167                 gd[inode_bitmap_index].bg_itable_unused--;
2168                 sb->free_inodes--;
2169                 return inode_no;
2170         }
2171 }
2172
2173 int ext4fs_existing_filename_check(block_dev_desc_t *dev_desc,char *filename)
2174 {
2175         unsigned int direct_blk_idx=0;
2176         unsigned int blknr=-1;
2177         int inodeno=-1;
2178
2179         /*read the block no allocated to a file*/
2180         for(direct_blk_idx=0;direct_blk_idx<INDIRECT_BLOCKS;direct_blk_idx++)
2181         {
2182                 blknr=ext4fs_read_allocated_block(g_parent_inode, direct_blk_idx);
2183                 if(blknr==0)
2184                 {
2185                         break;
2186                 }
2187                 inodeno= ext4fs_if_filename_exists_in_root(dev_desc,filename,blknr);
2188                 if(inodeno!=-1)
2189                 {
2190                         return inodeno;
2191                 }
2192         }
2193         return -1;
2194 }
2195
2196 int ext4fs_if_filename_exists_in_root(block_dev_desc_t *dev_desc,char *filename, unsigned int blknr)
2197 {
2198         unsigned char *root_first_block_buffer;
2199         unsigned char *root_first_block_addr;
2200         unsigned int first_block_no_of_root;
2201         int blocksize;
2202         int sector_per_block;
2203         struct ext2_dirent *dir = NULL;
2204         struct ext2_dirent *previous_dir = NULL;
2205         int totalbytes=0;
2206         int templength=0;
2207         int status;
2208         int found=0;
2209         unsigned char *ptr;
2210         int inodeno;
2211
2212         /*get the blocksize of the filesystem*/
2213         blocksize=EXT2_BLOCK_SIZE(ext4fs_root);
2214
2215         /*get the first block of root*/
2216         first_block_no_of_root=blknr;
2217         
2218         /*calucalate sector per block*/
2219         sector_per_block=blocksize/SECTOR_SIZE;
2220         
2221         /*read the first block of root directory inode*/
2222         root_first_block_buffer=xzalloc (blocksize);
2223         root_first_block_addr=root_first_block_buffer;
2224         status = ext2fs_devread (first_block_no_of_root*sector_per_block, 0,
2225                                                         blocksize,(char *)root_first_block_buffer);
2226         if (status == 0)
2227         {
2228                 goto fail;
2229         }
2230         else
2231         {
2232                 dir=(struct ext2_dirent *) root_first_block_buffer;
2233                 ptr=(unsigned char*)dir;
2234                 totalbytes=0;
2235                 while(dir->direntlen>=0)
2236                 {
2237                         /*blocksize-totalbytes because last directory length i.e.,
2238                         *dir->direntlen is free availble space in the block that means
2239                         *it is a last entry of directory entry
2240                         */
2241 #ifdef DEBUG_LOG
2242                         printf("in deleting the entry---------------------------\n");
2243                         printf("current inode no is %d\n",dir->inode);
2244                         printf("current directory entry length is %d\n",dir->direntlen);
2245                         printf("current name length is %d\n",dir->namelen);
2246                         printf("current fileltype is %d\n",dir->filetype);
2247                         printf("dir->name is %s\n",ptr+sizeof(struct ext2_dirent));
2248                         printf("-------------------------------------\n");
2249 #endif
2250
2251                         if(strlen(filename)==dir->namelen)
2252                         {
2253                                 if(strncmp(filename,ptr+sizeof(struct ext2_dirent),dir->namelen)==0)
2254                                 {
2255                                 printf("file found deleting\n");
2256                                 previous_dir->direntlen+=dir->direntlen;
2257                                 inodeno=dir->inode;
2258                                 memset(ptr+sizeof(struct ext2_dirent),'\0',dir->namelen);
2259                                 dir->inode=0;
2260                                 found=1;
2261                                 break;
2262                                 }
2263                         }
2264
2265                         if(blocksize-totalbytes==dir->direntlen)
2266                         {
2267                                 break;
2268                         }
2269                         /*traversing the each directory entry*/
2270                         templength=dir->direntlen;
2271                         totalbytes=totalbytes+templength;
2272                         previous_dir=dir;
2273                         dir=(unsigned char*)dir;
2274                         dir=(unsigned char*)dir+templength;
2275                         dir=(struct ext2_dirent*)dir;
2276                         ptr=dir;
2277                 }
2278         }
2279
2280         if(found==1)
2281         {
2282                 put_metadata(root_first_block_addr,first_block_no_of_root);
2283                 if(root_first_block_addr)
2284                         free(root_first_block_addr);
2285                 return inodeno;
2286         }
2287         else
2288         {
2289                 goto fail;
2290         }
2291
2292 fail:
2293         if(root_first_block_addr)
2294             free(root_first_block_addr);
2295          return -1;
2296 }
2297
2298 int ext4fs_delete_file(block_dev_desc_t *dev_desc, unsigned int inodeno)
2299 {
2300         struct ext2_data *diro=ext4fs_root;
2301         struct ext2_inode inode;
2302         int status;
2303         unsigned int i,j;
2304         int remainder;
2305         int sector_per_block;
2306         unsigned int blknr;
2307         unsigned int inode_no;
2308         int bg_bitmap_index;
2309         int inode_bitmap_index;
2310         unsigned char* read_buffer;
2311         unsigned char* start_block_address=NULL;
2312         unsigned int* double_indirect_buffer;
2313         unsigned int* DIB_start_addr=NULL;
2314         unsigned int* triple_indirect_grand_parent_buffer=NULL;
2315         unsigned int* TIB_start_addr=NULL;
2316         unsigned int* triple_indirect_parent_buffer=NULL;
2317         unsigned int* TIPB_start_addr=NULL;
2318         struct ext2_block_group *gd;
2319         unsigned int no_blocks;
2320
2321         static int prev_bg_bitmap_index = -1;
2322         unsigned char *journal_buffer=NULL;
2323         unsigned int inodes_per_block;
2324         unsigned int blkno;
2325         unsigned int blkoff;
2326         struct ext2_inode *inode_buffer;
2327
2328         /*get the block group descriptor table*/
2329         gd=(struct ext2_block_group*)gd_table;
2330         status = ext4fs_read_inode (diro,inodeno,&inode);
2331         if (status == 0)
2332         {
2333                 goto fail;
2334         }
2335         
2336         /*calucalate sector per block*/
2337         sector_per_block=blocksize/SECTOR_SIZE;
2338
2339         /*read the block no allocated to a file*/
2340         no_blocks= inode.size/blocksize;
2341         if(inode.size%blocksize)
2342         no_blocks++;
2343
2344         if (le32_to_cpu(inode.flags) & EXT4_EXTENTS_FLAG)
2345         {
2346                 ext2fs_node_t node_inode=(ext2fs_node_t)xzalloc(sizeof (struct ext2fs_node));
2347                 node_inode->data=ext4fs_root;
2348                 node_inode->ino=inodeno;
2349                 node_inode->inode_read=0;
2350                 memcpy(&(node_inode->inode),&inode,sizeof(struct ext2_inode));
2351
2352                 for(i=0;i<no_blocks;i++)
2353                 {
2354                         blknr=ext4fs_read_block(node_inode, i);
2355                         if(blocksize!=1024)
2356                         {
2357                                 bg_bitmap_index=blknr/(uint32_t)ext4fs_root->sblock.blocks_per_group;
2358                         }
2359                         else
2360                         {
2361                                 bg_bitmap_index=blknr/(uint32_t)ext4fs_root->sblock.blocks_per_group;
2362                                 remainder = blknr%(uint32_t)ext4fs_root->sblock.blocks_per_group;
2363                                 if(!remainder)
2364                                         bg_bitmap_index--;
2365                         }
2366                         ext4fs_update_bmap_with_zero(blknr,bg[bg_bitmap_index],bg_bitmap_index);
2367 #ifdef DEBUG_LOG
2368                         printf("EXT4_EXTENTS Block releasing %u: %d\n",blknr,bg_bitmap_index);
2369 #endif
2370                         gd[bg_bitmap_index].free_blocks++;
2371                         sb->free_blocks++;
2372
2373                         //journal backup
2374                         if(prev_bg_bitmap_index != bg_bitmap_index){
2375                                 journal_buffer = (unsigned char *)xzalloc(blocksize);
2376                                 status = ext2fs_devread (gd[bg_bitmap_index].block_id*sector_per_block,
2377                                                                                 0, blocksize,journal_buffer);
2378                                 if(status==0){
2379                                         free(journal_buffer);
2380                                         return -1;
2381                                 }
2382                                 log_journal(journal_buffer,gd[bg_bitmap_index].block_id);
2383                                 prev_bg_bitmap_index = bg_bitmap_index;
2384                                 free(journal_buffer);
2385                         }
2386                 }
2387                 if(node_inode)
2388                 {
2389                         free(node_inode);
2390                         node_inode=NULL;
2391                 }
2392         }
2393         else
2394         {
2395                 /*deleting the single indirect block associated with inode*/
2396                 if(inode.b.blocks.indir_block!=0)
2397                 {
2398 #ifdef DEBUG_LOG
2399                         printf("SIPB releasing %d\n",inode.b.blocks.indir_block);
2400 #endif
2401                         blknr=inode.b.blocks.indir_block;
2402                         if(blocksize!=1024)
2403                         {
2404                                 bg_bitmap_index=blknr/(uint32_t)ext4fs_root->sblock.blocks_per_group;
2405                         }
2406                         else
2407                         {
2408                                 bg_bitmap_index=blknr/(uint32_t)ext4fs_root->sblock.blocks_per_group;   
2409                                 remainder = blknr%(uint32_t)ext4fs_root->sblock.blocks_per_group;
2410                                 if(!remainder)
2411                                         bg_bitmap_index--;
2412                         }
2413                         ext4fs_update_bmap_with_zero(blknr,bg[bg_bitmap_index],bg_bitmap_index);
2414                         gd[bg_bitmap_index].free_blocks++;
2415                         sb->free_blocks++;
2416                         //journal backup
2417                         if(prev_bg_bitmap_index != bg_bitmap_index){
2418                                 journal_buffer = (unsigned char *)xzalloc(blocksize);
2419                                 status = ext2fs_devread (gd[bg_bitmap_index].block_id*sector_per_block,
2420                                                                                 0, blocksize,journal_buffer);
2421                                 if(status==0){
2422                                         free(journal_buffer);
2423                                         return -1;
2424                                 }
2425                                 log_journal(journal_buffer,gd[bg_bitmap_index].block_id);
2426                                 prev_bg_bitmap_index = bg_bitmap_index;
2427                                 free(journal_buffer);
2428                         }
2429                 }
2430
2431                 /*deleting the double indirect blocks */
2432                 if(inode.b.blocks.double_indir_block!=0)
2433                 {
2434                         double_indirect_buffer=(unsigned int*)xzalloc(blocksize);
2435                         DIB_start_addr=(unsigned int*)double_indirect_buffer;
2436                         blknr=inode.b.blocks.double_indir_block;
2437                         status = ext2fs_devread (blknr*sector_per_block, 0, blocksize,
2438                                                         (unsigned int *)double_indirect_buffer);
2439                         for(i=0;i<blocksize/sizeof(unsigned int);i++)
2440                         {
2441                                 if(*double_indirect_buffer==0)
2442                                         break;
2443 #ifdef DEBUG_LOG
2444                                 printf("DICB releasing %d\n",*double_indirect_buffer);
2445 #endif
2446                                 if(blocksize!=1024)
2447                                 {
2448                                         bg_bitmap_index=(*double_indirect_buffer)/(uint32_t)ext4fs_root->sblock.blocks_per_group;
2449                                 }
2450                                 else
2451                                 {
2452                                         bg_bitmap_index=(*double_indirect_buffer)/(uint32_t)ext4fs_root->sblock.blocks_per_group;
2453                                         remainder = (*double_indirect_buffer)%(uint32_t)ext4fs_root->sblock.blocks_per_group;
2454                                         if(!remainder)
2455                                                 bg_bitmap_index--;
2456                                 }
2457                                 ext4fs_update_bmap_with_zero(*double_indirect_buffer,bg[bg_bitmap_index],bg_bitmap_index);
2458                                 double_indirect_buffer++;
2459                                 gd[bg_bitmap_index].free_blocks++;
2460                                 sb->free_blocks++;
2461                                 //journal backup
2462                                 if(prev_bg_bitmap_index != bg_bitmap_index){
2463                                         journal_buffer = (unsigned char *)xzalloc(blocksize);
2464                                         status = ext2fs_devread (gd[bg_bitmap_index].block_id*sector_per_block,
2465                                                                                 0, blocksize,journal_buffer);
2466                                         if(status==0){
2467                                                 free(journal_buffer);
2468                                                 return -1;
2469                                         }
2470                                         log_journal(journal_buffer,gd[bg_bitmap_index].block_id);
2471                                         prev_bg_bitmap_index = bg_bitmap_index;
2472                                         free(journal_buffer);
2473                                 }
2474                         }
2475
2476                         /*removing the parent double indirect block*/
2477                         /*find the bitmap index*/
2478                         blknr=inode.b.blocks.double_indir_block;
2479                         if(blocksize!=1024)
2480                         {
2481                                 bg_bitmap_index=blknr/(uint32_t)ext4fs_root->sblock.blocks_per_group;
2482                         }
2483                         else
2484                         {
2485                                 bg_bitmap_index=blknr/(uint32_t)ext4fs_root->sblock.blocks_per_group;
2486                                 remainder = blknr%(uint32_t)ext4fs_root->sblock.blocks_per_group;
2487                                 if(!remainder)
2488                                         bg_bitmap_index--;
2489                         }
2490                         ext4fs_update_bmap_with_zero(blknr,bg[bg_bitmap_index],bg_bitmap_index);
2491                         gd[bg_bitmap_index].free_blocks++;
2492                         sb->free_blocks++;
2493                         //journal backup
2494                         if(prev_bg_bitmap_index != bg_bitmap_index){
2495                                 journal_buffer = (unsigned char *)xzalloc(blocksize);
2496                                 status = ext2fs_devread (gd[bg_bitmap_index].block_id*sector_per_block,
2497                                                                                 0, blocksize,journal_buffer);
2498                                 if(status==0){
2499                                         free(journal_buffer);
2500                                         return -1;
2501                                 }
2502                                 log_journal(journal_buffer,gd[bg_bitmap_index].block_id);
2503                                 prev_bg_bitmap_index = bg_bitmap_index;
2504                                 free(journal_buffer);
2505                         }
2506 #ifdef DEBUG_LOG
2507                         printf("DIPB releasing %d\n",blknr);
2508 #endif
2509                         if(DIB_start_addr)
2510                                 free(DIB_start_addr);
2511                 }
2512
2513                 /*deleting the triple indirect blocks */
2514                 if(inode.b.blocks.tripple_indir_block!=0)
2515                 {
2516                         triple_indirect_grand_parent_buffer=(unsigned int*)xzalloc(blocksize);
2517                         TIB_start_addr=(unsigned int*)triple_indirect_grand_parent_buffer;
2518                         blknr=inode.b.blocks.tripple_indir_block;
2519                         status = ext2fs_devread (blknr*sector_per_block, 0, blocksize,
2520                                                         (unsigned int *)triple_indirect_grand_parent_buffer);
2521                         for(i=0;i<blocksize/sizeof(unsigned int);i++)
2522                         {
2523                                 if(*triple_indirect_grand_parent_buffer==0)
2524                                         break;
2525 #ifdef DEBUG_LOG
2526                                 printf("TIGPB releasing %d\n",*triple_indirect_grand_parent_buffer);
2527 #endif
2528                                 triple_indirect_parent_buffer=(unsigned int*)xzalloc(blocksize);
2529                                 TIPB_start_addr = (unsigned int*)triple_indirect_parent_buffer;
2530                                 status = ext2fs_devread ((*triple_indirect_grand_parent_buffer)*sector_per_block, 0,
2531                                                                                 blocksize,(unsigned int *)triple_indirect_parent_buffer);
2532                                 for(j=0;j<blocksize/sizeof(unsigned int);j++)
2533                                 {
2534                                         if(*triple_indirect_parent_buffer==0)
2535                                         break;
2536                                         
2537                                         if(blocksize!=1024)
2538                                         {
2539                                                 bg_bitmap_index=(*triple_indirect_parent_buffer)/
2540                                                                                         (uint32_t)ext4fs_root->sblock.blocks_per_group;
2541                                         }
2542                                         else
2543                                         {
2544                                                 bg_bitmap_index=(*triple_indirect_parent_buffer)/
2545                                                                                 (uint32_t)ext4fs_root->sblock.blocks_per_group;
2546                                                 remainder = (*triple_indirect_parent_buffer)%
2547                                                                                 (uint32_t)ext4fs_root->sblock.blocks_per_group;
2548                                                 if(!remainder)
2549                                                         bg_bitmap_index--;
2550                                         }
2551                                         
2552                                         ext4fs_update_bmap_with_zero(*triple_indirect_parent_buffer,
2553                                                                         bg[bg_bitmap_index],bg_bitmap_index);
2554                                         triple_indirect_parent_buffer++;
2555                                         gd[bg_bitmap_index].free_blocks++;
2556                                         sb->free_blocks++;
2557                                         //journal backup
2558                                         if(prev_bg_bitmap_index != bg_bitmap_index){
2559                                                 journal_buffer = (unsigned char *)xzalloc(blocksize);
2560                                                 status = ext2fs_devread (gd[bg_bitmap_index].block_id*sector_per_block,
2561                                                                                                 0, blocksize,journal_buffer);
2562                                                 if(status==0){
2563                                                         free(journal_buffer);
2564                                                         return -1;
2565                                                 }
2566                                                 log_journal(journal_buffer,gd[bg_bitmap_index].block_id);
2567                                                 prev_bg_bitmap_index = bg_bitmap_index;
2568                                                 free(journal_buffer);
2569                                         }
2570                                 }
2571                                 if(TIPB_start_addr)
2572                                         free(TIPB_start_addr);
2573
2574                                 /*removing the grand parent blocks which is connected to inode*/
2575                                 if(blocksize!=1024)
2576                                 {
2577                                         bg_bitmap_index=(*triple_indirect_grand_parent_buffer)/
2578                                                                 (uint32_t)ext4fs_root->sblock.blocks_per_group;
2579                                 }
2580                                 else
2581                                 {
2582                                         bg_bitmap_index=(*triple_indirect_grand_parent_buffer)/
2583                                                                                         (uint32_t)ext4fs_root->sblock.blocks_per_group;
2584                                         remainder = (*triple_indirect_grand_parent_buffer)%
2585                                                                                         (uint32_t)ext4fs_root->sblock.blocks_per_group;
2586                                         if(!remainder)
2587                                                 bg_bitmap_index--;
2588                                 }
2589                                 ext4fs_update_bmap_with_zero(*triple_indirect_grand_parent_buffer,
2590                                                                         bg[bg_bitmap_index],bg_bitmap_index);
2591                                 triple_indirect_grand_parent_buffer++;
2592                                 gd[bg_bitmap_index].free_blocks++;
2593                                 sb->free_blocks++;
2594                                 //journal backup
2595                                 if(prev_bg_bitmap_index != bg_bitmap_index){
2596                                         journal_buffer = (unsigned char *)xzalloc(blocksize);
2597                                         status = ext2fs_devread (gd[bg_bitmap_index].block_id*sector_per_block,
2598                                                                                         0, blocksize,journal_buffer);
2599                                         if(status==0){
2600                                                 free(journal_buffer);
2601                                                 return -1;
2602                                         }
2603                                         log_journal(journal_buffer,gd[bg_bitmap_index].block_id);
2604                                         prev_bg_bitmap_index = bg_bitmap_index;
2605                                         free(journal_buffer);
2606                                 }
2607                 }
2608
2609                 /*removing the grand parent triple indirect block*/
2610                 /*find the bitmap index*/
2611                 blknr=inode.b.blocks.tripple_indir_block;
2612                 if(blocksize!=1024)
2613                 {
2614                         bg_bitmap_index=blknr/(uint32_t)ext4fs_root->sblock.blocks_per_group;
2615                 }
2616                 else
2617                 {
2618                         bg_bitmap_index=blknr/(uint32_t)ext4fs_root->sblock.blocks_per_group;
2619                         remainder = blknr%(uint32_t)ext4fs_root->sblock.blocks_per_group;
2620                         if(!remainder)
2621                                 bg_bitmap_index--;
2622                 }
2623                 ext4fs_update_bmap_with_zero(blknr,bg[bg_bitmap_index],bg_bitmap_index);                
2624                 gd[bg_bitmap_index].free_blocks++;
2625                 sb->free_blocks++;
2626                 //journal backup
2627                 if(prev_bg_bitmap_index != bg_bitmap_index){
2628                         journal_buffer = (unsigned char *)xzalloc(blocksize);
2629                         status = ext2fs_devread (gd[bg_bitmap_index].block_id*sector_per_block,
2630                                                                         0, blocksize,journal_buffer);
2631                         if(status==0){
2632                                 free(journal_buffer);
2633                                 return -1;
2634                         }
2635                         log_journal(journal_buffer,gd[bg_bitmap_index].block_id);
2636                         prev_bg_bitmap_index = bg_bitmap_index;
2637                         free(journal_buffer);
2638                 }
2639 #ifdef DEBUG_LOG
2640                         printf("TIGPB iteself releasing %d\n",blknr);
2641 #endif
2642                         if(TIB_start_addr)
2643                                 free(TIB_start_addr);
2644                 }
2645
2646                 /*read the block no allocated to a file*/
2647                 no_blocks= inode.size/blocksize;
2648                 if(inode.size%blocksize)
2649                 no_blocks++;
2650                 for(i=0;i<no_blocks;i++)
2651                 {
2652                         blknr = ext4fs_read_allocated_block(&inode, i);
2653                         if(blocksize!=1024)
2654                         {
2655                                 bg_bitmap_index=blknr/(uint32_t)ext4fs_root->sblock.blocks_per_group;
2656                         }
2657                         else
2658                         {
2659                                 bg_bitmap_index=blknr/(uint32_t)ext4fs_root->sblock.blocks_per_group;
2660                                 remainder = blknr%(uint32_t)ext4fs_root->sblock.blocks_per_group;
2661                                 if(!remainder)
2662                                 bg_bitmap_index--;
2663                         }
2664                         ext4fs_update_bmap_with_zero(blknr,bg[bg_bitmap_index],bg_bitmap_index);        
2665 #ifdef DEBUG_LOG
2666                         printf("ActualB releasing %d: %d\n",blknr,bg_bitmap_index);
2667 #endif
2668                         gd[bg_bitmap_index].free_blocks++;
2669                         sb->free_blocks++;
2670                         //journal backup
2671                         if(prev_bg_bitmap_index != bg_bitmap_index){
2672                                 journal_buffer = (unsigned char *)xzalloc(blocksize);
2673                                 status = ext2fs_devread (gd[bg_bitmap_index].block_id*sector_per_block,
2674                                                                                 0, blocksize,journal_buffer);
2675                                 if(status==0){
2676                                         free(journal_buffer);
2677                                         return -1;
2678                                 }
2679                                 log_journal(journal_buffer,gd[bg_bitmap_index].block_id);
2680                                 prev_bg_bitmap_index = bg_bitmap_index;
2681                                 free(journal_buffer);
2682                         }
2683                 }
2684         }
2685
2686         /*from the inode no to blockno*/
2687         inodes_per_block = EXT2_BLOCK_SIZE(ext4fs_root) / inode_size;
2688         inode_bitmap_index = inodeno / (uint32_t)ext4fs_root->sblock.inodes_per_group;
2689
2690         /*get the block no*/
2691         inodeno--;
2692         blkno = __le32_to_cpu (gd[inode_bitmap_index].inode_table_id) +
2693         (inodeno % __le32_to_cpu (ext4fs_root->sblock.inodes_per_group))/ inodes_per_block;
2694
2695         /*get the offset of the inode*/
2696         blkoff = ((inodeno) % inodes_per_block) * inode_size;
2697
2698         /*read the block no containing the inode*/
2699         read_buffer=xzalloc(blocksize);
2700         start_block_address=read_buffer;
2701         status = ext2fs_devread (blkno* sector_per_block, 0, blocksize,(unsigned  char *) read_buffer);
2702         if(status == 0) {
2703                 goto fail;
2704         }
2705         log_journal(read_buffer,blkno);
2706
2707         read_buffer = read_buffer+blkoff;
2708         inode_buffer = (struct ext2_inode*)read_buffer;
2709         memset(inode_buffer,'\0',sizeof(struct ext2_inode));
2710
2711         /*write the inode to original position in inode table*/
2712         put_metadata(start_block_address,blkno);
2713
2714         /*update the respective inode bitmaps*/
2715         inode_no = ++inodeno;
2716         ext4fs_update_inode_bmap_with_zero(inode_no,inode_bmaps[inode_bitmap_index],inode_bitmap_index);
2717         gd[inode_bitmap_index].free_inodes++;
2718         sb->free_inodes++;
2719         //journal backup
2720         journal_buffer = (unsigned char *)xzalloc(blocksize);
2721         status = ext2fs_devread (gd[inode_bitmap_index].inode_id*sector_per_block, 0, blocksize,journal_buffer);
2722         if(status == 0) {
2723                 free(journal_buffer);
2724                 return -1;
2725         }
2726         log_journal(journal_buffer,gd[inode_bitmap_index].inode_id);
2727         free(journal_buffer);
2728
2729         ext4fs_update(dev_desc);
2730         ext4fs_deinit(dev_desc);
2731
2732         if(ext4fs_init(dev_desc) != 0) {
2733                 printf("error in File System init\n");
2734                 return -1;
2735         }
2736
2737         /*free*/
2738         if(start_block_address)
2739                 free(start_block_address);
2740         return 0;
2741
2742 fail:
2743         if(DIB_start_addr)
2744                 free(DIB_start_addr);
2745         if(start_block_address)
2746                 free(start_block_address);
2747         return -1;
2748 }
2749
2750 int ext4fs_get_bgdtable(void )
2751 {
2752         int blocksize, i;
2753         int sector_per_block;
2754         int status;
2755         int grp_desc_size;
2756         unsigned char *temp;
2757         unsigned int var = gd_table_block_no;
2758         
2759         /*get the blocksize of the filesystem*/
2760         blocksize=EXT2_BLOCK_SIZE(ext4fs_root);
2761
2762         /*calucalate sector per block*/
2763         sector_per_block=blocksize/SECTOR_SIZE;
2764         grp_desc_size = sizeof(struct ext2_block_group);
2765         no_blk_req_per_gdt = (no_blockgroup * grp_desc_size)/ blocksize;
2766         if((no_blockgroup * grp_desc_size)% blocksize)
2767                 no_blk_req_per_gdt++;
2768
2769 #ifdef DEBUG_LOG
2770         printf("size of grp desc =%d\n",grp_desc_size);
2771         printf("number of block groups =%d\n",no_blockgroup);
2772         printf("Number of blocks reqd for grp desc table =%d\n",no_blk_req_per_gdt);
2773         printf("gdtable block no is %d\n",gd_table_block_no);
2774 #endif
2775
2776         /*allocate mem for gdtable*/
2777         gd_table= (char *)xzalloc(blocksize * no_blk_req_per_gdt);
2778         temp = gd_table;
2779         /*Read the first group descriptor table*/
2780         status = ext2fs_devread (gd_table_block_no * sector_per_block, 0,
2781                                                 blocksize * no_blk_req_per_gdt,gd_table);
2782         if (status == 0)
2783         {
2784                 goto fail;
2785         }
2786
2787         for(i =0;i < no_blk_req_per_gdt ;i++) {
2788                 journal_ptr[gindex]->buf = (char *)xzalloc(blocksize);
2789                 memcpy(journal_ptr[gindex]->buf,temp,blocksize);
2790                 temp += blocksize;
2791                 journal_ptr[gindex++]->blknr = var++;
2792         }
2793         return 0;
2794
2795 fail:
2796         if(gd_table) {
2797                 free(gd_table);
2798                 gd_table = NULL;
2799         }
2800         return -1;
2801 }
2802
2803 void ext4fs_deinit(block_dev_desc_t *dev_desc)
2804 {
2805         int i;
2806         struct ext2_inode inode_journal;
2807         journal_superblock_t *jsb;
2808         unsigned int blknr;
2809         char *temp_buff = (char *)xzalloc(blocksize);
2810         ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO,&inode_journal);
2811         blknr = ext4fs_read_allocated_block (&inode_journal, EXT2_JOURNAL_SUPERBLOCK);
2812         ext2fs_devread(blknr * sector_per_block, 0, blocksize, temp_buff);
2813         jsb=(journal_superblock_t*)temp_buff;
2814
2815         jsb->s_start= le_be(0);
2816         put_ext4(dev_desc,(uint64_t)(blknr * blocksize),
2817                         (struct journal_superblock_t*)temp_buff,(uint32_t)blocksize);
2818
2819         /*get the superblock*/
2820         ext2fs_devread (SUPERBLOCK_SECTOR, 0, SUPERBLOCK_SIZE, sb);
2821         sb->feature_incompat &= ~EXT3_FEATURE_INCOMPAT_RECOVER;
2822         put_ext4(dev_desc,(uint64_t)(SUPERBLOCK_SIZE),(struct ext2_sblock*)sb,(uint32_t)SUPERBLOCK_SIZE);
2823         if(temp_buff) {
2824                 free(temp_buff);
2825                 temp_buff=NULL;
2826         }
2827
2828         if(sb) {
2829                 free(sb);
2830                 sb=NULL;
2831         }
2832         
2833         if(bg) {
2834                 for(i=0;i<no_blockgroup;i++) {
2835                         if(bg[i]) {
2836                                 free(bg[i]);
2837                                 bg[i]=NULL;
2838                         }
2839                 }
2840                 free(bg);
2841                 bg=NULL;
2842         }
2843
2844         if(inode_bmaps) {
2845                 for(i=0;i<no_blockgroup;i++) {
2846                         if(inode_bmaps[i]) {
2847                                 free(inode_bmaps[i]);
2848                                 inode_bmaps[i]=NULL;
2849                         }
2850                 }
2851                 free(inode_bmaps);
2852                 inode_bmaps=NULL;
2853         }
2854
2855         if(gd_table) {
2856                 free(gd_table);
2857                 gd_table=NULL;
2858         }
2859         gd=NULL;
2860
2861         /* Reinit global variables */
2862         ext4fs_indir1_block = NULL;
2863         ext4fs_indir1_size = 0;
2864         ext4fs_indir1_blkno = -1;
2865         ext4fs_indir2_block = NULL;
2866         ext4fs_indir2_size = 0;
2867         ext4fs_indir2_blkno = -1;
2868         ext4fs_indir3_block = NULL;
2869         ext4fs_indir3_size = 0;
2870         ext4fs_indir3_blkno = -1;
2871
2872         /* Reinitiliazed the global inode and block bitmap first execution check variables */
2873         first_execution_inode = 0;
2874         first_execution = 0;
2875         inode_no=0;
2876         j_blkindex = 1;
2877         return;
2878 }
2879
2880 /* This function stores the backup copy of meta data in RAM
2881 *  journal_buffer -- Buffer containing meta data
2882 *  blknr -- Block number on disk of the meta data buffer
2883 */
2884 void log_journal(char *journal_buffer,unsigned int blknr)
2885 {
2886         int i = 0;
2887         for(i =0;i < MAX_JOURNAL_ENTRIES; i++) {
2888                 if(journal_ptr[i]->blknr == -1)
2889                         break;
2890                 if(journal_ptr[i]->blknr == blknr)
2891                         return;
2892         }
2893         if(!journal_buffer)
2894                 return ;
2895         journal_ptr[gindex]->buf = (char *)xzalloc(blocksize);
2896         if(!journal_ptr[gindex]->buf)
2897                 return ;
2898         memcpy(journal_ptr[gindex]->buf,journal_buffer,blocksize);
2899         journal_ptr[gindex++]->blknr = blknr;
2900 }
2901
2902 /* This function stores the modified meta data in RAM
2903 *  metadata_buffer -- Buffer containing meta data
2904 *  blknr -- Block number on disk of the meta data buffer
2905 */
2906 void put_metadata(char *metadata_buffer,unsigned int blknr)
2907 {
2908         if(!metadata_buffer)
2909                 return ;
2910         dirty_block_ptr[gd_index]->buf = (char *)xzalloc(blocksize);
2911         if(!dirty_block_ptr[gd_index]->buf)
2912                 return ;
2913         memcpy(dirty_block_ptr[gd_index]->buf,metadata_buffer,blocksize);
2914         dirty_block_ptr[gd_index++]->blknr = blknr;
2915 }
2916
2917 /*------------------------------------*/
2918 /*Revoke block handling functions*/
2919
2920 typedef struct journal_revoke_header_s
2921 {
2922         journal_header_t r_header;
2923         int              r_count;       /* Count of bytes used in the block */
2924 } journal_revoke_header_t;
2925
2926 typedef struct  _revoke_blk_list
2927 {
2928         char *content;/*revoke block itself*/
2929         struct _revoke_blk_list  *next;
2930 }revoke_blk_list;
2931
2932 #define TRUE 1
2933 #define FALSE 0
2934 revoke_blk_list *revk_blk_list=NULL;
2935 revoke_blk_list *prev_node=NULL;
2936 static int first_node=TRUE;
2937 #define RECOVER 1
2938 #define SCAN 0
2939
2940
2941 void print_revoke_blks(char *revk_blk)
2942 {
2943         journal_revoke_header_t *header;
2944         int offset, max;
2945         unsigned int blocknr;
2946         
2947         if(revk_blk==NULL)
2948                 return;
2949
2950         /*decode revoke block*/
2951         header = (journal_revoke_header_t *) revk_blk;
2952         offset = sizeof(journal_revoke_header_t);
2953         max = be_le(header->r_count);
2954         printf("total bytes %d\n",max);
2955
2956         while (offset < max) {
2957                 blocknr = be_le(*((unsigned int*)(revk_blk+offset)));                           
2958                 printf("revoke blknr is %u\n",blocknr);
2959                 offset += 4;
2960         }
2961         return;
2962 }
2963 static revoke_blk_list *
2964 _get_node(void)
2965 {
2966         revoke_blk_list *tmp_node;
2967         tmp_node=(revoke_blk_list *)
2968                 memalign(ARCH_DMA_MINALIGN, sizeof(revoke_blk_list));
2969         if(tmp_node==NULL) {
2970                 return NULL;
2971         }
2972         tmp_node->content=NULL;
2973         tmp_node->next=NULL;
2974         return tmp_node;
2975 }
2976
2977         
2978 void 
2979 push_revoke_blk (char * buffer)
2980 {
2981         revoke_blk_list *node;
2982         
2983         if(buffer==NULL) {
2984                 printf("buffer ptr is NULL\n");
2985                 return;
2986         }
2987         
2988         /*get the node*/
2989         if(!(node=_get_node())){
2990                 printf("_get_node: malloc failed\n");
2991                 return;
2992         }
2993         
2994         /*fill the node*/
2995         node->content = (char*) memalign(ARCH_DMA_MINALIGN, blocksize);
2996         memcpy(node->content,buffer,blocksize);
2997         
2998         if(first_node==TRUE) {
2999                 revk_blk_list=node;
3000                 prev_node=node;
3001                 first_node=FALSE; /*not enter again*/
3002         }
3003         else     {
3004                 prev_node->next=node;
3005                 prev_node=node;
3006         }
3007         return;
3008 }
3009
3010 void
3011 free_revoke_blks()
3012 {
3013         revoke_blk_list *tmp_node=revk_blk_list;
3014         revoke_blk_list *next_node=NULL;
3015                 
3016         while(tmp_node !=NULL) {
3017                 if (tmp_node->content)
3018                 free(tmp_node->content);
3019                 tmp_node=tmp_node->next;
3020         }
3021         
3022         tmp_node=revk_blk_list;
3023         while(tmp_node !=NULL) {
3024                 next_node=tmp_node->next;
3025                 free(tmp_node);
3026                 tmp_node=next_node;
3027         }
3028         
3029         revk_blk_list=NULL;
3030         prev_node=NULL;
3031         first_node=TRUE;
3032         return;
3033 }
3034
3035 int check_blknr_for_revoke(unsigned int blknr,int sequence_no)
3036 {
3037         journal_revoke_header_t *header;
3038         int offset, max;
3039         unsigned int blocknr;
3040         char *revk_blk;
3041         revoke_blk_list *tmp_revk_node=revk_blk_list;
3042         while (tmp_revk_node!=NULL) {
3043                 revk_blk=tmp_revk_node->content;
3044                 
3045                 /*decode revoke block*/
3046                 header = (journal_revoke_header_t *) revk_blk;
3047                 if (sequence_no < be_le(header->r_header.h_sequence)) {
3048                         offset = sizeof(journal_revoke_header_t);
3049                         max = be_le(header->r_count);
3050                         
3051                         while (offset < max) {
3052                                 blocknr = be_le(*((unsigned int*)(revk_blk+offset)));                           
3053                                 if(blocknr==blknr)
3054                                 { 
3055                                         goto found;
3056                                 }
3057                                 offset += 4;
3058                         }
3059                 }
3060                 tmp_revk_node=tmp_revk_node->next;
3061         }
3062         return -1;
3063         
3064         found:
3065                 return 0;
3066 }
3067 /*------------------------------------*/
3068 /* This function parses the journal blocks and replays the suceessful transactions
3069 *  A transaction is successful if commit block is found for a descriptor block
3070 *  The tags in descriptor block contain the disk block numbers of the metadata
3071 *  to be replayed
3072 */
3073 void recover_transaction(block_dev_desc_t *dev_desc,int prev_desc_logical_no)
3074 {
3075                 struct ext2_inode inode_journal;
3076                 journal_header_t *jdb;
3077                 unsigned int blknr;
3078                 char * p_jdb;
3079                 int ofs, flags;
3080                 int i;
3081                 struct ext3_journal_block_tag *tag;
3082                 unsigned char *temp_buff = (char *)xzalloc(blocksize);
3083                 unsigned char *metadata_buff = (char *)xzalloc(blocksize);
3084                 i = prev_desc_logical_no;
3085                 ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO,&inode_journal);
3086                 blknr = ext4fs_read_allocated_block (&inode_journal, i);
3087                 ext2fs_devread(blknr * sector_per_block, 0, blocksize, temp_buff);
3088                 p_jdb=(char *)temp_buff;
3089                 jdb=(journal_header_t *)temp_buff;
3090                 ofs = sizeof(journal_header_t);
3091
3092                 do {
3093                  tag = (struct ext3_journal_block_tag *)&p_jdb[ofs];
3094                  ofs += sizeof (struct ext3_journal_block_tag);
3095
3096                  if (ofs > blocksize)
3097                    break;
3098
3099                  flags = be_le (tag->flags);
3100                  if (! (flags & EXT3_JOURNAL_FLAG_SAME_UUID))
3101                    ofs += 16;
3102
3103                  i++;
3104 #ifdef DEBUG_LOG
3105                  printf("\t\ttag %u\n",be_le(tag->block));
3106 #endif
3107                  if(revk_blk_list!=NULL)  {
3108                         if(check_blknr_for_revoke(be_le(tag->block),be_le(jdb->h_sequence))==0)  {
3109                                 //printf("blknr %u  this should be ignored\n",be_le(tag->block));
3110                                 continue;
3111                         }
3112                  } 
3113
3114                  blknr = ext4fs_read_allocated_block (&inode_journal, i);
3115                  ext2fs_devread(blknr * sector_per_block, 0, blocksize, metadata_buff);
3116                  put_ext4(dev_desc,(uint64_t)(be_le(tag->block) * blocksize),
3117                                                                                 metadata_buff,(uint32_t)blocksize);
3118                 }
3119                 while (! (flags & EXT3_JOURNAL_FLAG_LAST_TAG));
3120                 if(temp_buff)
3121                         free(temp_buff);
3122                 if(metadata_buff)
3123                         free(metadata_buff);
3124 }
3125
3126
3127 int print_jrnl_status(int recovery_flag)
3128 {
3129         /*
3130         *if this function is called  scanning/recovery 
3131         *of journal must be  stoped.
3132         */
3133         if(recovery_flag==RECOVER) {
3134                 printf("Journal Recovery Completed\n");
3135         }
3136         else {
3137                 printf("Journal Scan Completed\n");
3138         }
3139         return 0;
3140 }
3141
3142
3143 int check_journal_state(block_dev_desc_t *dev_desc,int recovery_flag)
3144 {
3145                 struct ext2_inode inode_journal;
3146                 journal_superblock_t *jsb;
3147                 journal_header_t *jdb;
3148                 char * p_jdb;
3149                 int i;
3150                 int DB_FOUND = NO;
3151                 unsigned int blknr;
3152                 char *temp_buff = (char *)xzalloc(blocksize);
3153                 char *temp_buff1 = (char *)xzalloc(blocksize);
3154
3155                 int transaction_state=TRANSACTION_COMPLETE;
3156                 int prev_desc_logical_no =0;
3157                 int curr_desc_logical_no =0;
3158
3159                 int ofs, flags;
3160                 struct ext3_journal_block_tag *tag;
3161
3162                 ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO,&inode_journal);
3163                 blknr = ext4fs_read_allocated_block (&inode_journal, EXT2_JOURNAL_SUPERBLOCK);
3164                 ext2fs_devread(blknr * sector_per_block, 0, blocksize, temp_buff);
3165                 jsb=(journal_superblock_t*)temp_buff;
3166
3167                 if(sb->feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) {
3168                         if(recovery_flag==RECOVER)
3169                         printf("umount didn't happened :recovery required \n");
3170                 }
3171                 else {
3172                         if(recovery_flag==RECOVER)
3173                         printf("File System is consistent \n");
3174                         goto END;
3175                 }
3176
3177                 if(be_le(jsb->s_start)==0){
3178                         goto END;
3179                 }
3180
3181                 if(jsb->s_feature_compat & le_be(JBD2_FEATURE_COMPAT_CHECKSUM)){
3182                         //printf("checksum set journal \n");
3183                 }
3184                 else {
3185                         jsb->s_feature_compat |= le_be(JBD2_FEATURE_COMPAT_CHECKSUM);
3186                 }
3187
3188 #ifdef DEBUG_LOG
3189                 if(be_le(jsb->s_header.h_blocktype)==EXT3_JOURNAL_SUPERBLOCK_V1 ||
3190                                                         be_le(jsb->s_header.h_blocktype)==EXT3_JOURNAL_SUPERBLOCK_V2 )
3191                 {
3192                         printf("journal superblock info:\n");
3193                         printf("errno is %u\n",be_le(jsb->s_errno));
3194                         printf("start is %u\n",be_le(jsb->s_start));
3195                         printf("header sequence is %u\n",be_le(jsb->s_header.h_sequence));
3196                         printf("header magic is %u\n",be_le(jsb->s_header.h_magic));
3197                         printf("sequence is %u\n",be_le(jsb->s_sequence));
3198                         printf("first block of log is %u\n",be_le(jsb->s_first));
3199                         printf("total block of journal is %u\n",be_le(jsb->s_maxlen));
3200                         printf("s_feature_compat is %u\n",be_le(jsb->s_feature_compat));
3201                         printf("s_feature_incompat is %u\n",be_le(jsb->s_feature_incompat));
3202                         printf("s_feature_ro_compat is %u\n",be_le(jsb->s_feature_ro_compat));
3203                         printf("s_nr_users is %u\n",be_le(jsb->s_nr_users));
3204                         printf("total block of journal is %u\n",be_le(jsb->s_dynsuper));
3205                         printf("----------------------\n");
3206                 }
3207 #endif
3208                         i = be_le(jsb->s_first);
3209                         while(1){
3210                                 blknr = ext4fs_read_allocated_block (&inode_journal, i);
3211                                 memset(temp_buff1,'\0',blocksize);
3212                                 ext2fs_devread(blknr * sector_per_block, 0, blocksize, temp_buff1);
3213                                 jdb=(journal_header_t*)temp_buff1;
3214
3215                                 if(be_le(jdb->h_blocktype)==EXT3_JOURNAL_DESCRIPTOR_BLOCK)/*descriptor block*/
3216                                 {
3217 #ifdef DEBUG_LOG
3218                                         printf("Descriptor block \n");
3219 #endif
3220                                         if(be_le(jdb->h_sequence)!=be_le(jsb->s_sequence)){
3221                                                 print_jrnl_status(recovery_flag);
3222                                                 break;
3223                                         }
3224
3225                                         curr_desc_logical_no = i;
3226                                         if(transaction_state==TRANSACTION_COMPLETE)
3227                                                 transaction_state=TRANSACTION_RUNNING;
3228                                         else{
3229                                                 //printf("recovery required\n");
3230                                                 return -1;
3231                                         }
3232                                         p_jdb=(char *)temp_buff1;
3233 #ifdef DEBUG_LOG
3234                                         printf("\tIts Descriptor block: %u\n",blknr);
3235                                         printf("\t\tsequence no is %u\n",be_le(jdb->h_sequence));
3236                                         printf("\t\tmagic   no is %u\n",be_le(jdb->h_magic));
3237 #endif
3238                                         ofs = sizeof(journal_header_t);
3239                                         do {
3240                                                 tag = (struct ext3_journal_block_tag *)&p_jdb[ofs];
3241                                                 ofs += sizeof (struct ext3_journal_block_tag);
3242
3243                                                 if (ofs > blocksize)
3244                                                 break;
3245
3246                                                 flags = be_le (tag->flags);
3247                                                 if (! (flags & EXT3_JOURNAL_FLAG_SAME_UUID))
3248                                                         ofs += 16;
3249
3250                                                         i++;
3251 #ifdef DEBUG_LOG
3252                                                  printf("\t\ttag %u\n",be_le(tag->block));
3253 #endif
3254                                         }
3255                                         while (! (flags & EXT3_JOURNAL_FLAG_LAST_TAG));
3256                                         i++;
3257                                         DB_FOUND = YES;
3258                                 }
3259                                 else if(be_le(jdb->h_blocktype)==EXT3_JOURNAL_COMMIT_BLOCK){
3260 #ifdef DEBUG_LOG
3261                                         printf("Commit block\n");
3262 #endif
3263                                         if ((be_le(jdb->h_sequence) !=
3264                                                  be_le(jsb->s_sequence))) {
3265                                                 print_jrnl_status(recovery_flag);
3266                                                 break;
3267                                         }
3268
3269                                         if ((transaction_state ==
3270                                                 TRANSACTION_RUNNING) ||
3271                                                         (DB_FOUND == NO)) {
3272                                                 transaction_state=TRANSACTION_COMPLETE;
3273                                                 i++;
3274                                                 jsb->s_sequence = le_be(be_le(jsb->s_sequence)+1);
3275                                         }
3276 #ifdef DEBUG_LOG
3277                                         printf("\tIts Commit block: %u\n",blknr);
3278                                         printf("\t\tsequence no is %u\n",be_le(jdb->h_sequence));
3279                                         printf("\t\tmagic   no is %u\n",be_le(jdb->h_magic));
3280                                         printf("---------------------------\n");
3281 #endif
3282                                         prev_desc_logical_no = curr_desc_logical_no;
3283                                         if ((recovery_flag == RECOVER) &&
3284                                                          (DB_FOUND == YES))
3285                                                 recover_transaction(dev_desc,prev_desc_logical_no);
3286                                         DB_FOUND = NO;
3287                                 }
3288                                 else if (be_le(jdb->h_blocktype)==EXT3_JOURNAL_REVOKE_BLOCK){
3289                                         if(be_le(jdb->h_sequence)!=be_le(jsb->s_sequence)) {
3290                                                 print_jrnl_status(recovery_flag);
3291                                                 break;
3292                                         }
3293 #ifdef DEBUG_LOG
3294                                         printf("\tIts Revoke block: %u\n",blknr);
3295                                         printf("\t\tsequence no is %u\n",be_le(jdb->h_sequence));
3296                                         printf("\t\tmagic   no is %u\n",be_le(jdb->h_magic));
3297                                         printf("---------------------------\n");
3298 #endif
3299                                         if(recovery_flag==SCAN) {
3300                                                 push_revoke_blk(jdb);
3301                                         }
3302                                         i++;
3303                                 }
3304                                 else {
3305 #ifdef DEBUG_LOG
3306                                         printf("Else Case \n");
3307 #endif
3308                                         if(be_le(jdb->h_sequence)!=be_le(jsb->s_sequence)) {
3309                                                 print_jrnl_status(recovery_flag);
3310                                         break;
3311                                         }
3312                                 }
3313                 }
3314
3315 END:
3316                         if(recovery_flag==RECOVER)  {
3317                                 jsb->s_start= le_be(1);
3318                                 jsb->s_sequence = le_be(be_le(jsb->s_sequence)+1);
3319                                 /*get the superblock*/
3320                                 ext2fs_devread (SUPERBLOCK_SECTOR, 0, SUPERBLOCK_SIZE, sb);
3321                                 sb->feature_incompat |= EXT3_FEATURE_INCOMPAT_RECOVER;
3322
3323                                 /*Update the super block*/
3324                                 put_ext4(dev_desc,(uint64_t)(SUPERBLOCK_SIZE),(struct ext2_sblock*)sb,(uint32_t)SUPERBLOCK_SIZE);
3325                                 ext2fs_devread (SUPERBLOCK_SECTOR, 0, SUPERBLOCK_SIZE, sb);
3326
3327                                 blknr = ext4fs_read_allocated_block (&inode_journal, EXT2_JOURNAL_SUPERBLOCK);
3328                                 put_ext4(dev_desc,(uint64_t)(blknr * blocksize),
3329                                                 (struct journal_superblock_t*)temp_buff,(uint32_t)blocksize);
3330                                 free_revoke_blks();
3331                         }
3332
3333                                 if(temp_buff){
3334                                         free(temp_buff);
3335                                         temp_buff =NULL;
3336                                 }
3337
3338                                 if(temp_buff1){
3339                                         free(temp_buff1);
3340                                         temp_buff1 =NULL;
3341                                 }
3342                                 return 0;
3343 }
3344
3345 int ext4fs_init(block_dev_desc_t *dev_desc )
3346 {
3347         int status;
3348         int i;
3349         char *temp = NULL;
3350         unsigned int real_free_blocks=0;
3351         
3352         /*get the blocksize inode sector per block of the filesystem*/
3353         blocksize=EXT2_BLOCK_SIZE(ext4fs_root);
3354         inodesize=INODE_SIZE_FILESYSTEM(ext4fs_root);
3355         sector_per_block=blocksize/SECTOR_SIZE;
3356         
3357         /*get the superblock*/
3358         sb=(struct ext2_sblock *)xzalloc(SUPERBLOCK_SIZE);
3359         status = ext2fs_devread (SUPERBLOCK_SECTOR, 0, SUPERBLOCK_SIZE, sb);
3360         if(status==0)
3361         {
3362                 goto fail;
3363         }
3364
3365         for(i=0; i< MAX_JOURNAL_ENTRIES; i++){
3366                 journal_ptr[i] = (struct journal_log *)xzalloc(sizeof(struct journal_log));
3367                 if(!journal_ptr[i])
3368                         goto fail;
3369                 dirty_block_ptr[i] = (struct journal_log *)xzalloc(sizeof(struct dirty_blocks));
3370                 if(!dirty_block_ptr[i])
3371                         goto fail;
3372                 journal_ptr[i]->buf = NULL;
3373                 journal_ptr[i]->blknr = -1;
3374
3375                 dirty_block_ptr[i]->buf = NULL;
3376                 dirty_block_ptr[i]->blknr = -1;
3377         }
3378
3379         if(blocksize == 4096) {
3380                 temp = (char *)xzalloc(blocksize);
3381                 if(!temp)
3382                         goto fail;
3383                 journal_ptr[gindex]->buf = (char *)xzalloc(blocksize);
3384                 if(!journal_ptr[gindex]->buf)
3385                         goto fail;
3386                 ext2fs_devread (0, 0, blocksize, temp);
3387                 memcpy(temp + SUPERBLOCK_SIZE, sb,SUPERBLOCK_SIZE);
3388                 memcpy(journal_ptr[gindex]->buf,temp,blocksize);
3389                 journal_ptr[gindex++]->blknr = 0;
3390                 free(temp);
3391         }
3392         else {
3393                 journal_ptr[gindex]->buf = (char *)xzalloc(blocksize);
3394                 if(!journal_ptr[gindex]->buf)
3395                         goto fail;
3396                 memcpy(journal_ptr[gindex]->buf,sb,SUPERBLOCK_SIZE);
3397                 journal_ptr[gindex++]->blknr = 1;
3398         }
3399
3400         if(check_journal_state(dev_desc,SCAN))
3401                 goto fail;
3402         /* Check the file system state using journal super block */
3403         if(check_journal_state(dev_desc,RECOVER))
3404                 goto fail;
3405
3406         /*get the no of blockgroups*/
3407         no_blockgroup = (uint32_t)ext4fs_div_roundup((uint32_t)(ext4fs_root->sblock.total_blocks
3408                                 - ext4fs_root->sblock.first_data_block),(uint32_t)ext4fs_root->sblock.blocks_per_group);
3409
3410         /*get the block group descriptor table*/
3411         gd_table_block_no=((EXT2_MIN_BLOCK_SIZE == blocksize)+1);
3412         if(ext4fs_get_bgdtable()== -1)
3413         {
3414                 printf("***Eror in getting the block group descriptor table\n");
3415                 goto fail;
3416         }
3417         else
3418         {
3419                 gd=(struct ext2_block_group*)gd_table;
3420         }
3421
3422         /*load all the available bitmap block of the partition*/
3423         bg = (unsigned char **) memalign(ARCH_DMA_MINALIGN,
3424                                  no_blockgroup * sizeof(unsigned char *));
3425         for(i=0;i<no_blockgroup;i++)
3426         {
3427                 bg[i]=(unsigned char*)xzalloc(blocksize);
3428                 if(!bg[i])
3429                         goto fail;
3430         }
3431
3432         for(i=0;i<no_blockgroup;i++)
3433         {
3434                 status = ext2fs_devread (gd[i].block_id*sector_per_block, 0, blocksize, (unsigned char*)bg[i]);
3435                 if(status==0)
3436                 {
3437                         goto fail;
3438                 }
3439         }
3440
3441         /*load all the available inode bitmap of the partition*/
3442         inode_bmaps = (unsigned char **) memalign(ARCH_DMA_MINALIGN,
3443                                        no_blockgroup * sizeof(unsigned char *));
3444         for(i=0;i<no_blockgroup;i++)
3445         {
3446                 inode_bmaps[i]=(unsigned char*)xzalloc(blocksize);
3447                 if(!inode_bmaps[i])
3448                         goto fail;
3449         }
3450
3451         for(i=0;i<no_blockgroup;i++)
3452         {
3453                 status = ext2fs_devread (gd[i].inode_id*sector_per_block, 0, blocksize,
3454                                                                         (unsigned char*)inode_bmaps[i]);
3455                 if(status==0)
3456                 {
3457                         goto fail;
3458                 }
3459         }
3460
3461         /*
3462         *check filesystem consistency with free blocks of file system
3463         *some time we observed that superblock freeblocks does not match
3464         *with the  blockgroups freeblocks when improper reboot of a linux kernel
3465         */
3466         for(i=0;i<no_blockgroup;i++)
3467         {
3468                 real_free_blocks=real_free_blocks + gd[i].free_blocks;
3469         }
3470         if(real_free_blocks!=sb->free_blocks)
3471         {
3472                 sb->free_blocks=real_free_blocks;
3473         }
3474
3475 #ifdef DEBUG_LOG
3476         printf("-----------------------------\n");
3477         printf("inode size: %d\n",inodesize);
3478         printf("block size: %d\n",blocksize);
3479         printf("blocks per group: %d\n",ext4fs_root->sblock.blocks_per_group);
3480         printf("no of groups in this partition: %d\n",no_blockgroup);
3481         printf("block group descriptor blockno: %d\n",gd_table_block_no);
3482         printf("sector size is %d\n",SECTOR_SIZE);
3483         printf("size of inode structure is %d\n",sizeof(struct ext2_inode));
3484         printf("-----------------------------\n");
3485 #endif
3486
3487 #ifdef DEBUG_LOG
3488         //ext4fs_dump_the_inode_group_before_writing();
3489         ext4fs_dump_the_block_group_before_writing();
3490
3491 #endif
3492
3493         return 0;
3494 fail:
3495         ext4fs_deinit(dev_desc);
3496         return -1;
3497 }
3498
3499 #ifndef offsetof
3500 #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
3501 #endif
3502
3503 int ext4fs_checksum_update(unsigned int i)
3504 {
3505         struct ext2_block_group *desc;
3506         __u16 crc = 0;
3507
3508         desc = (struct ext2_block_group *)&gd[i];
3509
3510         if (sb->feature_ro_compat & EXT4_FEATURE_RO_COMPAT_GDT_CSUM) {
3511                 int offset = offsetof(struct ext2_block_group, bg_checksum);
3512
3513                 crc = ext2fs_crc16(~0, sb->unique_id,
3514                                    sizeof(sb->unique_id));
3515                 crc = ext2fs_crc16(crc, &i, sizeof(i));
3516                 crc = ext2fs_crc16(crc, desc, offset);
3517                 offset += sizeof(desc->bg_checksum); /* skip checksum */
3518                 assert(offset == sizeof(*desc));
3519         }
3520         return crc;
3521 }
3522
3523 int update_descriptor_block(block_dev_desc_t *dev_desc, unsigned int blknr)
3524 {
3525         journal_header_t jdb;
3526         struct ext3_journal_block_tag tag;
3527         struct ext2_inode inode_journal;
3528         journal_superblock_t *jsb;
3529         unsigned int jsb_blknr;
3530         char *buf =NULL, *temp = NULL;
3531         int  i;
3532         char *temp_buff = (char *)xzalloc(blocksize);
3533
3534         ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO,&inode_journal);
3535         jsb_blknr = ext4fs_read_allocated_block (&inode_journal, EXT2_JOURNAL_SUPERBLOCK);
3536         ext2fs_devread(jsb_blknr * sector_per_block, 0, blocksize, temp_buff);
3537         jsb=(journal_superblock_t*)temp_buff;
3538
3539         jdb.h_blocktype = le_be(EXT3_JOURNAL_DESCRIPTOR_BLOCK);
3540         jdb.h_magic = le_be(EXT3_JOURNAL_MAGIC_NUMBER); 
3541         jdb.h_sequence = jsb->s_sequence;
3542         buf = (char *)xzalloc(blocksize);
3543         temp = buf;
3544         memcpy(buf,&jdb, sizeof(journal_header_t));
3545         temp += sizeof(journal_header_t);
3546
3547         for(i =0;i < MAX_JOURNAL_ENTRIES; i++) {
3548                 if(journal_ptr[i]->blknr == -1)
3549                         break;
3550
3551                 tag.block = le_be(journal_ptr[i]->blknr);
3552                 tag.flags = le_be(EXT3_JOURNAL_FLAG_SAME_UUID);
3553                 memcpy(temp,&tag, sizeof (struct ext3_journal_block_tag));
3554                 temp = temp + sizeof (struct ext3_journal_block_tag);
3555         }
3556
3557         tag.block = le_be(journal_ptr[--i]->blknr);
3558         tag.flags = le_be(EXT3_JOURNAL_FLAG_LAST_TAG);
3559         memcpy(temp - sizeof (struct ext3_journal_block_tag) ,&tag, sizeof (struct ext3_journal_block_tag));
3560         put_ext4(dev_desc,(uint64_t)(blknr*blocksize),buf,(uint32_t)blocksize);
3561
3562         if(temp_buff){
3563                 free(temp_buff);
3564                 temp_buff =NULL;
3565         }
3566         if(buf){
3567                 free(buf);
3568                 buf =NULL;
3569         }
3570         return 0;
3571 }
3572
3573 int update_commit_block(block_dev_desc_t *dev_desc ,unsigned int blknr)
3574 {
3575         journal_header_t jdb;
3576         char *buf = NULL;
3577         struct ext2_inode inode_journal;
3578         journal_superblock_t *jsb;
3579         unsigned int jsb_blknr;
3580         char *temp_buff = (char *)xzalloc(blocksize);
3581
3582         ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO,&inode_journal);
3583         jsb_blknr = ext4fs_read_allocated_block (&inode_journal, EXT2_JOURNAL_SUPERBLOCK);
3584         ext2fs_devread(jsb_blknr * sector_per_block, 0, blocksize, temp_buff);
3585         jsb=(journal_superblock_t*)temp_buff;
3586
3587         jdb.h_blocktype = le_be(EXT3_JOURNAL_COMMIT_BLOCK);
3588         jdb.h_magic = le_be(EXT3_JOURNAL_MAGIC_NUMBER);
3589         jdb.h_sequence = jsb->s_sequence;
3590         buf = (char *)xzalloc(blocksize);
3591         memcpy(buf,&jdb, sizeof(journal_header_t));
3592         put_ext4(dev_desc,(uint64_t)(blknr*blocksize),buf,(uint32_t)blocksize);
3593
3594         if(temp_buff){
3595                 free(temp_buff);
3596                 temp_buff =NULL;
3597         }
3598         if(buf){
3599                 free(buf);
3600                 buf =NULL;
3601         }
3602         return 0;
3603 }
3604
3605 int update_journal(block_dev_desc_t *dev_desc)
3606 {
3607         struct ext2_inode inode_journal;
3608         unsigned int blknr;
3609         int i;
3610         unsigned char *metadata_buff = (unsigned char *)xzalloc(blocksize);
3611         ext4fs_read_inode(ext4fs_root, EXT2_JOURNAL_INO,&inode_journal);
3612         blknr = ext4fs_read_allocated_block (&inode_journal, j_blkindex++);
3613         update_descriptor_block(dev_desc ,blknr);
3614         for(i=0 ;i < MAX_JOURNAL_ENTRIES; i++ ) {
3615                 if(journal_ptr[i]->blknr == -1)
3616                 break;
3617                 blknr = ext4fs_read_allocated_block (&inode_journal, j_blkindex++);
3618                 put_ext4(dev_desc,(uint64_t)(blknr*blocksize),journal_ptr[i]->buf,(uint32_t)blocksize);
3619         }
3620         blknr = ext4fs_read_allocated_block (&inode_journal, j_blkindex++);
3621         update_commit_block(dev_desc ,blknr);
3622         printf("update journal finished \n");
3623         if(metadata_buff){
3624                 free(metadata_buff);
3625                 metadata_buff = NULL;
3626         }
3627         return 0;
3628 }
3629
3630 void ext4fs_update(block_dev_desc_t *dev_desc)
3631 {
3632         unsigned int i;
3633         update_journal(dev_desc);
3634         /*Update the super block*/
3635         put_ext4(dev_desc,(uint64_t)(SUPERBLOCK_SIZE),(struct ext2_sblock*)sb,(uint32_t)SUPERBLOCK_SIZE);
3636
3637         /*update the block group*/
3638         for(i=0;i<no_blockgroup;i++)
3639         {
3640                 gd[i].bg_checksum = ext4fs_checksum_update(i);
3641                 put_ext4(dev_desc,(uint64_t)(gd[i].block_id*blocksize),bg[i],(uint32_t)blocksize);
3642         }
3643
3644         /*update the inode table group*/
3645         for(i=0;i<no_blockgroup;i++)
3646         {
3647                 put_ext4(dev_desc,(uint64_t)(gd[i].inode_id*blocksize),inode_bmaps[i],(uint32_t)blocksize);
3648         }
3649
3650         /*update the block group descriptor table*/
3651         put_ext4(dev_desc,(uint64_t)(gd_table_block_no*blocksize),(struct ext2_block_group*)gd_table,
3652                                         (uint32_t)(blocksize * no_blk_req_per_gdt));
3653
3654         for(i =0;i < MAX_JOURNAL_ENTRIES; i++) {
3655                 if(dirty_block_ptr[i]->blknr == -1)
3656                         break;
3657                 put_ext4(dev_desc,(uint64_t)(dirty_block_ptr[i]->blknr * blocksize),dirty_block_ptr[i]->buf,
3658                                                         (uint32_t)blocksize);
3659                 free(dirty_block_ptr[i]->buf);
3660         }
3661
3662         for(i =0;i < MAX_JOURNAL_ENTRIES; i++) {
3663                 if(journal_ptr[i]->blknr == -1)
3664                         break;
3665                 free(journal_ptr[i]->buf);
3666         }
3667
3668         for(i=0; i< MAX_JOURNAL_ENTRIES; i++){
3669                 free(journal_ptr[i]);
3670                 free(dirty_block_ptr[i]);
3671         }
3672
3673         gindex = 0;
3674         gd_index = 0;
3675 }
3676
3677 static int check_void_in_dentry(struct ext2_dirent *dir,char *filename)
3678 {
3679         int dentry_length = 0;
3680         short int padding_factor = 0;
3681         int sizeof_void_space = 0;
3682         int new_entry_byte_reqd = 0;
3683         
3684         if(dir->namelen % 4 != 0) {
3685                 padding_factor = 4 - (dir->namelen % 4);/*for null storage*/
3686         }
3687         dentry_length = sizeof(struct ext2_dirent) + dir->namelen + padding_factor;
3688         sizeof_void_space = dir->direntlen - dentry_length;
3689         if(sizeof_void_space == 0) {
3690                 return 0;
3691         }
3692         else {
3693                 padding_factor = 0;
3694                 if(strlen(filename) % 4 != 0) {
3695                         padding_factor = 4 - (strlen(filename) % 4);
3696                 }
3697                 new_entry_byte_reqd = strlen(filename) + sizeof(struct ext2_dirent) + padding_factor;
3698                 if(sizeof_void_space >= new_entry_byte_reqd) {
3699                         dir->direntlen = dentry_length;
3700                         return sizeof_void_space;
3701                 }
3702                 else    {
3703                         return 0;
3704                 }
3705         }
3706 }
3707 int ext4fs_write(block_dev_desc_t *dev_desc, int part_no,char *fname,
3708                                 unsigned char* buffer,unsigned long sizebytes)
3709 {
3710         unsigned char *root_first_block_buffer = NULL;
3711         unsigned int i,j,k;
3712         int status,ret = 0;
3713         
3714         /*inode*/
3715         struct ext2_inode *file_inode = NULL;
3716         unsigned char *inode_buffer = NULL;
3717         unsigned int parent_inodeno;
3718         unsigned int inodeno;
3719         time_t timestamp = NULL;
3720         unsigned int first_block_no_of_root;
3721
3722         /*directory entry*/
3723         struct ext2_dirent *dir = NULL;
3724         int templength = 0;
3725         int totalbytes = 0;
3726         short int padding_factor = 0;
3727
3728         /*filesize*/
3729         uint64_t total_no_of_bytes_for_file;
3730         unsigned int total_no_of_block_for_file;
3731         unsigned int total_remaining_blocks;
3732
3733         /*final actual data block*/
3734         unsigned int    actual_block_no;
3735
3736         /*direct*/
3737         unsigned int    direct_blockno;
3738
3739         /*single indirect*/
3740         unsigned int    *single_indirect_buffer = NULL;
3741         unsigned int    single_indirect_blockno;
3742         unsigned int    *single_indirect_start_address = NULL;
3743
3744         /*double indirect*/
3745         unsigned int    double_indirect_blockno_parent;
3746         unsigned int    double_indirect_blockno_child;
3747         unsigned int    *double_indirect_buffer_parent = NULL;
3748         unsigned int    *double_indirect_buffer_child = NULL;
3749         unsigned int    *double_indirect_block_startaddress = NULL;
3750         unsigned int    *double_indirect_buffer_child_start = NULL;
3751
3752         /*Triple Indirect*/
3753         unsigned int triple_indirect_blockno_grand_parent;
3754         unsigned int triple_indirect_blockno_parent;
3755         unsigned int triple_indirect_blockno_child;
3756         unsigned int *triple_indirect_buffer_grand_parent = NULL;
3757         unsigned int *triple_indirect_buffer_parent = NULL;
3758         unsigned int *triple_indirect_buffer_child = NULL;
3759         unsigned int *triple_indirect_buffer_grand_parent_startaddress = NULL;
3760         unsigned int *triple_indirect_buffer_parent_startaddress = NULL;
3761         unsigned int *triple_indirect_buffer_child_startaddress = NULL;
3762
3763         unsigned int    existing_file_inodeno;
3764         unsigned int new_entry_byte_reqd;
3765         unsigned int last_entry_dirlen;
3766         int direct_blk_idx;
3767         unsigned int root_blknr;
3768
3769         unsigned char *ptr = NULL;
3770         struct ext2_dirent *temp_dir = NULL;
3771         ALLOC_CACHE_ALIGN_BUFFER(char, filename, EXT_MAX_FILE_LEN);
3772         memset(filename, 0x00, EXT_MAX_FILE_LEN);
3773
3774         unsigned int previous_blknr = -1;
3775         unsigned int *zero_buffer = NULL;
3776
3777
3778         char * temp_ptr = NULL;
3779         unsigned int itable_blkno, parent_itable_blkno,blkoff;
3780         struct ext2_sblock *sblock = &(ext4fs_root->sblock);
3781         unsigned int inodes_per_block;
3782         unsigned int inode_bitmap_index;
3783         int sizeof_void_space = 0;
3784         g_parent_inode = (struct ext2_inode *)xzalloc(sizeof(struct ext2_inode));
3785         if(!g_parent_inode)
3786                 goto fail;
3787
3788         if(ext4fs_init(dev_desc)!=0)
3789         {
3790                 printf("error in File System init\n");
3791                 return -1;
3792         }
3793         inodes_per_block = blocksize / inodesize;
3794         parent_inodeno = get_parent_inode_num_write(dev_desc,fname,filename);
3795         if(parent_inodeno==-1) {
3796                 goto fail;
3797         }
3798
3799         if(iget(parent_inodeno,g_parent_inode))
3800                 goto fail;
3801
3802         /*check if the filename is already present in root*/
3803         existing_file_inodeno= ext4fs_existing_filename_check(dev_desc,filename);
3804         if(existing_file_inodeno!=-1)/*file is exist having the same name as filename*/
3805         {
3806                 inodeno = existing_file_inodeno;
3807                 ret = ext4fs_delete_file(dev_desc,existing_file_inodeno);
3808                 first_execution=0;
3809                 blockno=0;
3810
3811                 first_execution_inode=0;
3812                 inode_no=0;
3813                 if(ret)
3814                         goto fail;
3815         }
3816
3817         /*calucalate how many blocks required*/
3818         total_no_of_bytes_for_file = sizebytes;
3819         total_no_of_block_for_file = lldiv(total_no_of_bytes_for_file, blocksize);
3820         
3821         if(do_div(total_no_of_bytes_for_file, blocksize) != 0)
3822         {
3823                 total_no_of_block_for_file++;
3824         }
3825         total_remaining_blocks=total_no_of_block_for_file;
3826
3827 #ifdef DEBUG_LOG
3828         printf("total_no_of_block_for_file %d\n",total_no_of_block_for_file);
3829         printf("superblock freebloks:%u\n",sb->free_blocks);
3830 #endif
3831
3832         /*Test for available space in partition*/
3833         if(sb->free_blocks < total_no_of_block_for_file)
3834         {
3835                 printf("Not enough space on partition !!!\n");
3836                 goto fail;
3837         }
3838
3839         /*############START: Update the root directory entry block of root inode ##############*/
3840         /*since we are populating this file under  root
3841         *directory take the root inode and its first block
3842         *currently we are looking only in first block of root
3843         *inode*/
3844
3845         zero_buffer = xzalloc(blocksize);
3846         if(!zero_buffer)
3847                 goto fail;
3848         root_first_block_buffer=memalign(ARCH_DMA_MINALIGN, blocksize);
3849 RESTART:
3850
3851         /*read the block no allocated to a file*/
3852         for(direct_blk_idx=0;direct_blk_idx<INDIRECT_BLOCKS;direct_blk_idx++)
3853         {
3854                         root_blknr=ext4fs_read_allocated_block(g_parent_inode, direct_blk_idx);
3855                         if(root_blknr==0)
3856                         {
3857                                 first_block_no_of_root=previous_blknr;
3858                                 break;
3859                         }
3860                         previous_blknr=root_blknr;
3861         }
3862 #ifdef DEBUG_LOG
3863         printf("previous blk no =%u \n",previous_blknr);
3864         printf("first_block_no_of_root =%u \n",first_block_no_of_root);
3865 #endif
3866
3867         status = ext2fs_devread (first_block_no_of_root*sector_per_block, 0, blocksize,
3868                                 (char *)root_first_block_buffer);
3869         if (status == 0)
3870         {
3871                 goto fail;
3872         }
3873         else
3874         {
3875                 log_journal(root_first_block_buffer,first_block_no_of_root);
3876                 dir=(struct ext2_dirent *) root_first_block_buffer;
3877                 ptr=(unsigned char*)dir;
3878                 totalbytes=0;
3879                 while(dir->direntlen>0)
3880                 {
3881 #ifdef DEBUG_LOG
3882                         printf("------------------------------------\n");
3883                         printf("current inode no is %d\n",dir->inode);
3884                         printf("current directory entry length is %d\n",dir->direntlen);
3885                         printf("current name length is %d\n",dir->namelen);
3886                         printf("current fileltype is %d\n",dir->filetype);
3887                         printf("total bytes is %d\n",totalbytes);
3888                         printf("dir->name is %s\n",ptr+sizeof(struct ext2_dirent));
3889                         printf("-------------------------------------\n");
3890 #endif
3891
3892                         /*blocksize-totalbytes because last directory length i.e.,
3893                         *dir->direntlen is free availble space in the block that means
3894                         *it is a last entry of directory entry
3895                         */
3896
3897                         /*traversing the each directory entry*/
3898                         if(blocksize-totalbytes==dir->direntlen)
3899                         {
3900                                 if(strlen(filename)%4!=0)
3901                                 {
3902                                         padding_factor=4-(strlen(filename)%4);
3903                                 }
3904                                 new_entry_byte_reqd = strlen(filename) + sizeof(struct ext2_dirent)+padding_factor;
3905                                 padding_factor = 0;
3906                                 /*update last directory entry length to its length because
3907                                 *we are creating new directory entry*/
3908                                 if(dir->namelen%4!=0)
3909                                 {
3910                                         padding_factor=4-(dir->namelen%4);/*for null storage*/
3911                                 }
3912                                 last_entry_dirlen= dir->namelen+sizeof(struct ext2_dirent)+padding_factor;
3913                                 if((blocksize-totalbytes -last_entry_dirlen) < new_entry_byte_reqd)
3914                                 {
3915 #ifdef DEBUG_LOG
3916                                         printf("Storage capcity of 1st Block over allocating new block\n");
3917 #endif
3918                                         if (direct_blk_idx==INDIRECT_BLOCKS-1)
3919                                         {
3920                                                 printf("Directory capacity exceeds the limit\n");
3921                                                 goto fail;
3922                                         }
3923                                         g_parent_inode->b.blocks.dir_blocks[direct_blk_idx]= 
3924                                                                         ext4fs_get_next_available_block_no(dev_desc,part_no);
3925                                         if(g_parent_inode->b.blocks.dir_blocks[direct_blk_idx] == -1)
3926                                         {
3927                                                 printf("no block left to assign\n");
3928                                                 goto fail;
3929                                         }
3930                                         put_ext4(dev_desc,((uint64_t)(g_parent_inode->b.blocks.dir_blocks[direct_blk_idx] * blocksize)),
3931                                                                         zero_buffer, blocksize);
3932                                         g_parent_inode->size = g_parent_inode->size + blocksize;
3933                                         g_parent_inode->blockcnt= g_parent_inode->blockcnt + sector_per_block;
3934                                         put_metadata(root_first_block_buffer,first_block_no_of_root);
3935                                         goto RESTART;
3936                                 }
3937                                 dir->direntlen=last_entry_dirlen;
3938                                 break;
3939                         }
3940
3941                         templength=dir->direntlen;
3942                         totalbytes=totalbytes+templength;
3943                         if(sizeof_void_space = check_void_in_dentry(dir,filename)) {
3944                                 break;
3945                         }
3946                         dir=(unsigned char*)dir;
3947                         dir=(unsigned char*)dir+templength;
3948                         dir=(struct ext2_dirent*)dir;
3949                         ptr=dir;
3950                 }
3951
3952                 /*make a pointer ready for creating next directory entry*/
3953                 templength=dir->direntlen;
3954                 totalbytes=totalbytes+templength;
3955                 dir=(unsigned char*)dir;
3956                 dir=(unsigned char*)dir+templength;
3957                 dir=(struct ext2_dirent*)dir;
3958                 ptr=dir;
3959
3960 #if DEBUG_LOG
3961                 printf("------------------------------------\n");
3962                 printf("JUST BEFORE ADDING NAME\n");
3963                 printf("------------------------------------\n");
3964                 printf("current inode no is %u\n",dir->inode);
3965                 printf("current directory entry length is %d\n",dir->direntlen);
3966                 printf("current name length is %d\n",dir->namelen);
3967                 printf("current fileltype is %d\n",dir->filetype);
3968                 printf("total bytes is %d\n",totalbytes);
3969                 printf("dir->name is %s\n",ptr+sizeof(struct ext2_dirent));
3970                 printf("-------------------------------------\n");
3971 #endif
3972         /*get the next available inode number*/
3973         inodeno=ext4fs_get_next_available_inode_no(dev_desc,part_no);
3974         if(inodeno==-1)
3975         {
3976                 printf("no inode left to assign\n");
3977                 goto fail;
3978         }
3979 #ifdef DEBUG_LOG
3980                 printf("New Inode Assignment :%d\n",inodeno);
3981 #endif
3982                 dir->inode=inodeno;
3983                 if(sizeof_void_space)
3984                         dir->direntlen = sizeof_void_space;
3985                 else
3986                         dir->direntlen = blocksize - totalbytes;
3987                 dir->namelen=strlen(filename);
3988                 dir->filetype=FILETYPE_REG; /*regular file*/
3989                 temp_dir=dir;
3990                 dir=(unsigned char*)dir;
3991                 dir=(unsigned char*)dir+sizeof(struct ext2_dirent);
3992                 memcpy(dir,filename,strlen(filename));
3993 #if DEBUG_LOG
3994                 dir=(struct ext2_dirent*)temp_dir;
3995
3996                 printf("------------------------------------\n");
3997                 printf("JUST AFTER ADDING NAME\n");
3998                 printf("------------------------------------\n");
3999                 printf("current inode no is %u\n",dir->inode);
4000                 printf("current directory entry length is %d\n",dir->direntlen);
4001                 printf("current name length is %d\n",dir->namelen);
4002                 printf("current fileltype is %d\n",dir->filetype);
4003                 printf("total bytes is %d\n",totalbytes);
4004                 printf("dir->name is %s\n",ptr+sizeof(struct ext2_dirent));
4005                 printf("-------------------------------------\n");
4006 #endif
4007         }
4008
4009         /*update or write  the 1st block of root inode*/
4010         put_metadata(root_first_block_buffer,first_block_no_of_root);
4011         
4012         if(root_first_block_buffer)
4013                 free(root_first_block_buffer);
4014
4015         /*############END: Update the root directory entry block of root inode ##############*/
4016
4017         /*prepare file inode*/
4018         inode_buffer = xmalloc(inodesize);
4019         memset(inode_buffer, '\0', inodesize);
4020         file_inode = (struct ext2_inode *)inode_buffer;
4021         file_inode->mode= S_IFREG | S_IRWXU | S_IRGRP | S_IROTH | S_IXGRP | S_IXOTH;
4022         /* ToDo: Update correct time*/
4023         file_inode->mtime= timestamp;
4024         file_inode->atime= timestamp;
4025         file_inode->ctime= timestamp;
4026         file_inode->nlinks= 1;
4027         file_inode->size = sizebytes;
4028
4029         /*----------------------------START:Allocation of Blocks to Inode---------------------------- */
4030         /*allocation of direct blocks*/
4031         for(i=0;i<INDIRECT_BLOCKS;i++)
4032         {
4033                 direct_blockno=ext4fs_get_next_available_block_no(dev_desc,part_no);
4034                 if(direct_blockno==-1)
4035                 {
4036                         printf("no block left to assign\n");
4037                         goto fail;
4038                 }
4039                 file_inode->b.blocks.dir_blocks[i]=direct_blockno;
4040 #ifdef DEBUG_LOG
4041                 printf("DB %d: %d\n",direct_blockno,total_remaining_blocks);
4042 #endif
4043                 total_remaining_blocks--;
4044                 if(total_remaining_blocks==0)
4045                 break;
4046         }
4047
4048         /*allocation of single indirect blocks*/
4049         if(total_remaining_blocks!=0)
4050         {
4051                 single_indirect_buffer=memalign(ARCH_DMA_MINALIGN, blocksize);
4052                 single_indirect_start_address=single_indirect_buffer;
4053                 single_indirect_blockno=ext4fs_get_next_available_block_no(dev_desc,part_no);
4054                 if(single_indirect_blockno==-1)
4055                 {
4056                         printf("no block left to assign\n");
4057                         goto fail;
4058                 }
4059                 total_no_of_block_for_file++;
4060 #ifdef DEBUG_LOG
4061                 printf("SIPB %d: %d\n",single_indirect_blockno,total_remaining_blocks);
4062 #endif
4063                 status = ext2fs_devread (single_indirect_blockno*sector_per_block, 0, blocksize,
4064                                         (unsigned int *)single_indirect_buffer);
4065                 memset(single_indirect_buffer,'\0',blocksize);
4066                 if (status == 0)
4067                 {
4068                         goto fail;
4069                 }
4070
4071                 for(i=0;i<(blocksize/sizeof(unsigned int));i++)
4072                 {
4073                         actual_block_no=ext4fs_get_next_available_block_no(dev_desc,part_no);
4074                         if(actual_block_no==-1)
4075                         {
4076                                 printf("no block left to assign\n");
4077                                 goto fail;
4078                         }
4079                         *single_indirect_buffer=actual_block_no;
4080 #ifdef DEBUG_LOG
4081                         printf("SIAB %d: %d\n",*single_indirect_buffer,total_remaining_blocks);
4082 #endif
4083                         single_indirect_buffer++;
4084                         total_remaining_blocks--;
4085                         if(total_remaining_blocks==0)
4086                         break;
4087                 }
4088
4089                 /*write the block to disk*/
4090                 put_ext4(dev_desc,((uint64_t)(single_indirect_blockno * blocksize)),
4091                                                 single_indirect_start_address, blocksize);
4092                 file_inode->b.blocks.indir_block=single_indirect_blockno;
4093                 if(single_indirect_start_address)
4094                         free(single_indirect_start_address);
4095         }
4096
4097         /*allocation of double indirect blocks*/
4098         if(total_remaining_blocks!=0)
4099         {
4100                 /*double indirect parent block connecting to inode*/
4101                 double_indirect_blockno_parent=ext4fs_get_next_available_block_no(dev_desc,part_no);
4102                 if(double_indirect_blockno_parent==-1)
4103                 {
4104                                 printf("no block left to assign\n");
4105                                 goto fail;
4106                 }
4107                 double_indirect_buffer_parent=xzalloc (blocksize);
4108                 if(!double_indirect_buffer_parent)
4109                 goto fail;
4110
4111                 double_indirect_block_startaddress=double_indirect_buffer_parent;
4112                 total_no_of_block_for_file++;
4113 #ifdef DEBUG_LOG
4114                 printf("DIPB %d: %d\n",double_indirect_blockno_parent,total_remaining_blocks);
4115 #endif
4116                 status = ext2fs_devread (double_indirect_blockno_parent*sector_per_block, 0,
4117                                         blocksize,(unsigned int *)double_indirect_buffer_parent);
4118                 memset(double_indirect_buffer_parent,'\0',blocksize);
4119
4120                 /*START: for each double indirect parent block create one more block*/
4121                 for(i=0;i<(blocksize/sizeof(unsigned int));i++)
4122                 {
4123                         double_indirect_blockno_child=ext4fs_get_next_available_block_no(dev_desc,part_no);
4124                         if(double_indirect_blockno_child==-1)
4125                         {
4126                                 printf("no block left to assign\n");
4127                                 goto fail;
4128                         }
4129                         double_indirect_buffer_child=xzalloc (blocksize);
4130                         if(!double_indirect_buffer_child)
4131                         goto fail;
4132
4133                         double_indirect_buffer_child_start=double_indirect_buffer_child;
4134                         *double_indirect_buffer_parent=double_indirect_blockno_child;
4135                         double_indirect_buffer_parent++;
4136                         total_no_of_block_for_file++;
4137 #ifdef DEBUG_LOG
4138                         printf("DICB %d: %d\n",double_indirect_blockno_child,total_remaining_blocks);
4139 #endif
4140                         status = ext2fs_devread (double_indirect_blockno_child*sector_per_block, 0,
4141                                                 blocksize,(unsigned int *)double_indirect_buffer_child);
4142                         memset(double_indirect_buffer_child,'\0',blocksize);
4143                         /*END: for each double indirect parent block create one more block*/
4144
4145                         /*filling of actual datablocks for each child*/
4146                         for(j=0;j<(blocksize/sizeof(unsigned int));j++)
4147                         {
4148                                 actual_block_no=ext4fs_get_next_available_block_no(dev_desc,part_no);
4149                                 if(actual_block_no==-1)
4150                                 {
4151                                         printf("no block left to assign\n");
4152                                         goto fail;
4153                                 }
4154                                 *double_indirect_buffer_child=actual_block_no;
4155 #ifdef DEBUG_LOG
4156                                 printf("DIAB %d: %d\n",actual_block_no,total_remaining_blocks);
4157 #endif
4158                                 double_indirect_buffer_child++;
4159                                 total_remaining_blocks--;
4160                                 if(total_remaining_blocks==0)
4161                                 break;
4162                         }
4163                         /*write the block  table*/
4164                         put_ext4(dev_desc,((uint64_t)(double_indirect_blockno_child * blocksize)),
4165                                         double_indirect_buffer_child_start, blocksize);
4166                         if(double_indirect_buffer_child_start)
4167                                 free(double_indirect_buffer_child_start);
4168
4169                         if(total_remaining_blocks==0)
4170                                 break;
4171                 }
4172                 put_ext4(dev_desc,((uint64_t)(double_indirect_blockno_parent * blocksize)),
4173                                         double_indirect_block_startaddress, blocksize);
4174                 if(double_indirect_block_startaddress)
4175                         free(double_indirect_block_startaddress);
4176                 file_inode->b.blocks.double_indir_block=double_indirect_blockno_parent;
4177         }
4178
4179         /*Triple Indirection */
4180
4181         /*allocation of triple indirect blocks*/
4182         if(total_remaining_blocks!=0)
4183         {
4184                 /*triple indirect grand parent block connecting to inode*/
4185                 triple_indirect_blockno_grand_parent=ext4fs_get_next_available_block_no(dev_desc,part_no);
4186                 if(triple_indirect_blockno_grand_parent==-1)
4187                 {
4188                                 printf("no block left to assign\n");
4189                                 goto fail;
4190                 }
4191                 triple_indirect_buffer_grand_parent=xzalloc (blocksize);
4192                 if(!triple_indirect_buffer_grand_parent)
4193                         goto fail;
4194
4195                 triple_indirect_buffer_grand_parent_startaddress=triple_indirect_buffer_grand_parent;
4196                 total_no_of_block_for_file++;
4197 #ifdef DEBUG_LOG
4198                 printf("TIGPB %d: %d\n",triple_indirect_blockno_grand_parent,total_remaining_blocks);
4199 #endif
4200
4201                 /* for each 4 byte grand parent entry create one more block*/
4202                 for(i=0;i<(blocksize/sizeof(unsigned int));i++)
4203                 {
4204                         triple_indirect_blockno_parent=ext4fs_get_next_available_block_no(dev_desc,part_no);
4205                         if(triple_indirect_blockno_parent==-1)
4206                         {
4207                                 printf("no block left to assign\n");
4208                                 goto fail;
4209                         }
4210                         triple_indirect_buffer_parent=xzalloc (blocksize);
4211                         if(!triple_indirect_buffer_parent)
4212                                 goto fail;
4213
4214                         triple_indirect_buffer_parent_startaddress=triple_indirect_buffer_parent;
4215                         *triple_indirect_buffer_grand_parent=triple_indirect_blockno_parent;
4216                         triple_indirect_buffer_grand_parent++;
4217                         total_no_of_block_for_file++;
4218 #ifdef DEBUG_LOG
4219                         printf("TIPB %d: %d\n",triple_indirect_blockno_parent,total_remaining_blocks);
4220 #endif
4221                         /*for each 4 byte entry parent  create one more block*/
4222                                 for(j=0;j<(blocksize/sizeof(unsigned int));j++)
4223                                 {
4224                                         triple_indirect_blockno_child=ext4fs_get_next_available_block_no(dev_desc,part_no);
4225                                         if(triple_indirect_blockno_child==-1)
4226                                         {
4227                                                 printf("no block left to assign\n");
4228                                                 goto fail;
4229                                         }
4230                                         triple_indirect_buffer_child=xzalloc (blocksize);
4231                                         if(!triple_indirect_buffer_child)
4232                                                 goto fail;
4233
4234                                         triple_indirect_buffer_child_startaddress=triple_indirect_buffer_child;
4235                                         *triple_indirect_buffer_parent=triple_indirect_blockno_child;
4236                                         triple_indirect_buffer_parent++;
4237                                         total_no_of_block_for_file++;
4238 #ifdef DEBUG_LOG
4239                         printf("TICB %d: %d\n",triple_indirect_blockno_parent,total_remaining_blocks);
4240 #endif
4241                                                 /*filling of actual datablocks for each child*/
4242                                                 for(k=0;k<(blocksize/sizeof(unsigned int));k++)
4243                                                 {
4244                                                         actual_block_no=ext4fs_get_next_available_block_no(dev_desc,part_no);
4245                                                         if(actual_block_no==-1)
4246                                                         {
4247                                                                 printf("no block left to assign\n");
4248                                                                 goto fail;
4249                                                         }
4250                                                         *triple_indirect_buffer_child=actual_block_no;
4251 #ifdef DEBUG_LOG
4252                                 printf("TIAB %d: %d\n",actual_block_no,total_remaining_blocks);
4253 #endif
4254                                                         triple_indirect_buffer_child++;
4255                                                         total_remaining_blocks--;
4256                                                         if(total_remaining_blocks==0)
4257                                                                 break;
4258                                                 }
4259                                                 /*write the child block */
4260                                                 put_ext4(dev_desc,((uint64_t)(triple_indirect_blockno_child * blocksize)),
4261                                                                 triple_indirect_buffer_child_startaddress, blocksize);
4262                                                 if(triple_indirect_buffer_child_startaddress)
4263                                                         free(triple_indirect_buffer_child_startaddress);
4264
4265                                                 if(total_remaining_blocks==0)
4266                                                         break;
4267                                 }
4268                                 /*write the parent block */
4269                                 put_ext4(dev_desc,((uint64_t)(triple_indirect_blockno_parent * blocksize)),
4270                                 triple_indirect_buffer_parent_startaddress, blocksize);
4271                                 if(triple_indirect_buffer_parent_startaddress)
4272                                         free(triple_indirect_buffer_parent_startaddress);
4273
4274                         if(total_remaining_blocks==0)
4275                                 break;
4276                 }
4277                 /*write the grand parent block */
4278                 put_ext4(dev_desc,((uint64_t)(triple_indirect_blockno_grand_parent * blocksize)),
4279                                         triple_indirect_buffer_grand_parent_startaddress, blocksize);
4280                 if(triple_indirect_buffer_grand_parent_startaddress)
4281                         free(triple_indirect_buffer_grand_parent_startaddress);
4282                 file_inode->b.blocks.tripple_indir_block=triple_indirect_blockno_grand_parent;
4283         }
4284         /*----------------------------END:Allocation of Blocks to Inode---------------------------- */
4285
4286         /*
4287         *write the inode to inode table after last filled inode in inode table
4288         *we are using hardcoded  gd[0].inode_table_id becuase 0th blockgroup
4289         *is suffcient to create more than 1000 file.TODO exapnd the logic to
4290         *all blockgroup
4291         */
4292         file_inode->blockcnt= (total_no_of_block_for_file*blocksize)/SECTOR_SIZE;
4293
4294         temp_ptr = (char *)xzalloc(blocksize);
4295         if(!temp_ptr)
4296                 goto fail;
4297         inode_bitmap_index = inodeno/(uint32_t)ext4fs_root->sblock.inodes_per_group;
4298         inodeno--;
4299         itable_blkno = __le32_to_cpu (gd[inode_bitmap_index].inode_table_id) +
4300                 (inodeno % __le32_to_cpu (sblock->inodes_per_group))
4301                 / inodes_per_block;
4302         blkoff = (inodeno % inodes_per_block) * inodesize;
4303         ext2fs_devread (itable_blkno*sector_per_block, 0, blocksize,temp_ptr);
4304         log_journal(temp_ptr,itable_blkno);
4305
4306         memcpy(temp_ptr + blkoff,inode_buffer,inodesize);
4307         put_metadata(temp_ptr,itable_blkno);
4308
4309         /*Copy the file content into data blocks*/
4310         ext4fs_write_file(dev_desc,file_inode,0,sizebytes,buffer);
4311 #ifdef DEBUG_LOG
4312         //ext4fs_dump_the_inode_group_after_writing();
4313         ext4fs_dump_the_block_group_after_writing();
4314 #endif
4315         inode_bitmap_index = parent_inodeno/(uint32_t)ext4fs_root->sblock.inodes_per_group;
4316         parent_inodeno--;
4317         parent_itable_blkno = __le32_to_cpu (gd[inode_bitmap_index].inode_table_id) +
4318                 (parent_inodeno % __le32_to_cpu (sblock->inodes_per_group))/ inodes_per_block;
4319         blkoff = (parent_inodeno % inodes_per_block) * inodesize;
4320         if(parent_itable_blkno != itable_blkno) {
4321                 memset(temp_ptr,'\0',blocksize);
4322                 ext2fs_devread (parent_itable_blkno*sector_per_block, 0, blocksize,temp_ptr);
4323                 log_journal(temp_ptr,parent_itable_blkno);
4324
4325                 memcpy(temp_ptr + blkoff,g_parent_inode,sizeof(struct ext2_inode));
4326                 put_metadata(temp_ptr,parent_itable_blkno);
4327                 free(temp_ptr);
4328         }
4329         else {
4330                 /* If parent and child fall in same inode table block both should be kept in 1 buffer*/
4331                 memcpy(temp_ptr + blkoff,g_parent_inode,sizeof(struct ext2_inode));
4332                 gd_index--;
4333                 put_metadata(temp_ptr,itable_blkno);
4334                 free(temp_ptr);
4335         }
4336         ext4fs_update(dev_desc);
4337
4338 #ifdef DEBUG_LOG
4339         /*print the block no allocated to a file*/
4340         unsigned int blknr;
4341         total_no_of_block_for_file=lldiv(total_no_of_bytes_for_file, blocksize);
4342         if(do_div(total_no_of_bytes_for_file, blocksize) !=0)
4343         {
4344                 total_no_of_block_for_file++;
4345         }
4346         printf("Total no of blocks for File: %u\n",total_no_of_block_for_file);
4347         for(i=0;i<total_no_of_block_for_file;i++)
4348         {
4349                 blknr = ext4fs_read_allocated_block (file_inode, i);
4350                 printf("Actual Data Blocks Allocated to File: %u\n",blknr);
4351         }
4352 #endif
4353         ext4fs_deinit(dev_desc);
4354         first_execution=0;
4355         blockno=0;
4356
4357         first_execution_inode=0;
4358         inode_no=0;
4359         if(inode_buffer)
4360                 free(inode_buffer);
4361         if(g_parent_inode){
4362                 free(g_parent_inode);
4363                 g_parent_inode=NULL;
4364         }
4365
4366 return 0;
4367
4368 fail:
4369         ext4fs_deinit(dev_desc);
4370         if(inode_buffer)
4371                 free(inode_buffer);
4372         if(zero_buffer)
4373                 free(zero_buffer);
4374         if(g_parent_inode){
4375                 free(g_parent_inode);
4376                 g_parent_inode=NULL;
4377         }
4378         return -1;
4379 }
4380
4381 static int search_dir(block_dev_desc_t *dev_desc,struct ext2_inode *parent_inode,unsigned char *dirname)
4382 {
4383         unsigned char *block_buffer;
4384         int blocksize;
4385         int sector_per_block;
4386         struct ext2_dirent *dir;
4387         struct ext2_dirent *previous_dir = NULL;
4388         int totalbytes = 0;
4389         int templength = 0;
4390         int status;
4391         int found = 0;
4392         unsigned char *ptr;
4393         int inodeno;
4394         int direct_blk_idx;
4395         unsigned int blknr;
4396         unsigned int previous_blknr;
4397
4398         /*get the blocksize of the filesystem*/
4399         blocksize=EXT2_BLOCK_SIZE(ext4fs_root);
4400
4401         /*calucalate sector per block*/
4402         sector_per_block=blocksize/SECTOR_SIZE;
4403
4404         /*get the first block of root*/
4405         /*read the block no allocated to a file*/
4406         for(direct_blk_idx=0;direct_blk_idx<INDIRECT_BLOCKS;direct_blk_idx++)
4407         {
4408                 blknr=ext4fs_read_allocated_block(parent_inode, direct_blk_idx);
4409                 if(blknr==0)
4410                 {
4411                         goto fail;
4412                 }
4413
4414                 /*read the blocks of parenet inode*/
4415                 block_buffer=xzalloc (blocksize);
4416                 if(!block_buffer)
4417                         goto fail;
4418
4419                 status = ext2fs_devread (blknr*sector_per_block, 0, blocksize,(char *)block_buffer);
4420                 if (status == 0) 
4421                 {
4422                         goto fail;
4423                 }
4424                 else
4425                 {
4426                         dir=(struct ext2_dirent *) block_buffer;
4427                         ptr=(unsigned char*)dir;
4428                         totalbytes=0;
4429                         while(dir->direntlen>=0)
4430                         {
4431                         /*blocksize-totalbytes because last directory length i.e.,
4432                         *dir->direntlen is free availble space in the block that means
4433                         *it is a last entry of directory entry
4434                         */
4435 #if DEBUG_LOG
4436                         printf("---------------------------\n");
4437                         printf("dirname is %s\n",dirname);
4438                         printf("current inode no is %d\n",dir->inode);
4439                         printf("current directory entry length is %d\n",dir->direntlen);
4440                         printf("current name length is %d\n",dir->namelen);
4441                         printf("current fileltype is %d\n",dir->filetype);
4442                         printf("dir->name is %s\n",ptr+sizeof(struct ext2_dirent));
4443                         printf("-------------------------------------\n");
4444 #endif
4445
4446                         if(strlen(dirname)==dir->namelen)
4447                         {
4448                                 if(strncmp(dirname,ptr+sizeof(struct ext2_dirent),dir->namelen)==0)
4449                                 {
4450                                         previous_dir->direntlen+=dir->direntlen;
4451                                         inodeno=dir->inode;
4452                                         dir->inode=0;
4453                                         found=1;
4454                                         break;
4455                                 }
4456                         }
4457
4458                         if(blocksize-totalbytes==dir->direntlen)
4459                         {
4460                                 break;
4461                         }
4462                         /*traversing the each directory entry*/
4463                         templength=dir->direntlen;
4464                         totalbytes=totalbytes+templength;
4465                         previous_dir=dir;
4466                         dir=(unsigned char*)dir;
4467                         dir=(unsigned char*)dir+templength;
4468                         dir=(struct ext2_dirent*)dir;
4469                         ptr=dir;
4470                 }
4471         }
4472
4473         if(found==1) {
4474                 if(block_buffer) {
4475                         free(block_buffer);
4476                         block_buffer = NULL;
4477                 }
4478                 return inodeno;
4479         }
4480
4481                 if(block_buffer){
4482                         free(block_buffer);
4483                         block_buffer = NULL;
4484                 }
4485         }
4486
4487 fail:
4488         if(block_buffer){
4489                 free(block_buffer);
4490                 block_buffer = NULL;
4491         }
4492         return -1;
4493 }
4494
4495 static int find_dir_depth(char *dirname)
4496 {
4497         char *token = strtok(dirname, "/");
4498         int count=0;
4499         while(token != NULL) {
4500                 token = strtok(NULL,"/");
4501                 count++;
4502         }
4503         return count;
4504 }
4505
4506 static int      parse_path(char **arr,char *dirname)
4507 {
4508         char *token = strtok(dirname, "/");
4509         int i=0;
4510
4511         /*add root*/
4512         arr[i] = xzalloc(strlen("/")+1);
4513         if(!arr[i])
4514                 return -1;
4515
4516         arr[i++] = "/";
4517
4518         /*add each path entry after root*/
4519         while(token != NULL) {
4520                 arr[i] = xzalloc(strlen(token)+1);
4521                 if(!arr[i])
4522                         return -1;
4523                 memcpy(arr[i++],token,strlen(token));
4524                 token = strtok(NULL,"/");
4525         }
4526
4527         arr[i]=NULL;
4528         /*success*/
4529         return 0;
4530 }
4531
4532 int  iget(unsigned int inode_no,struct ext2_inode* inode)
4533 {
4534         if( ext4fs_read_inode (ext4fs_root,inode_no,inode)==0)
4535                 return -1;
4536         else
4537                 return 0;
4538 }
4539
4540 /*
4541 * Function:get_parent_inode_num
4542 * Return Value: inode Number of the parent directory of  file/Directory to be created
4543 * dev_desc : Input parameter, device descriptor
4544 * dirname : Input parmater, input path name of the file/directory to be created
4545 * dname : Output parameter, to be filled with the name of the directory extracted from dirname
4546 */
4547 int get_parent_inode_num(block_dev_desc_t *dev_desc,char *dirname, char *dname)
4548 {
4549         char **ptr = NULL;
4550         int i,depth = 0;
4551         char *depth_dirname = NULL;
4552         char *parse_dirname = NULL;
4553         struct ext2_inode *parent_inode = NULL;
4554         struct ext2_inode *first_inode = NULL;
4555         unsigned int matched_inode_no;
4556         unsigned int result_inode_no = -1;
4557
4558         if(*dirname!='/')       {
4559                 printf("Please supply Absolute path\n");
4560                 return -1;
4561         }
4562
4563         /*TODO: input validation make equivalent to linux*/
4564         /*get the memory size*/
4565         depth_dirname = (char *)xzalloc(strlen(dirname)+1);
4566         if(!depth_dirname)
4567                 return -1;
4568
4569         memcpy(depth_dirname,dirname,strlen(dirname));
4570         depth=find_dir_depth(depth_dirname);
4571         parse_dirname = (char *)xzalloc(strlen(dirname)+1);
4572         if(!parse_dirname)
4573                 goto fail;
4574         memcpy(parse_dirname,dirname,strlen(dirname));
4575
4576         /*allocate memory for each directory level*/
4577         ptr=(char**)xzalloc((depth)* sizeof(char *));
4578         if(!ptr)
4579                 goto fail;
4580         parse_path(ptr,parse_dirname);
4581         parent_inode=(struct ext2_inode*)xzalloc(sizeof(struct ext2_inode));
4582         if(!parent_inode)
4583                 goto fail;
4584         first_inode=(struct ext2_inode*)xzalloc(sizeof(struct ext2_inode));
4585         if(!first_inode)
4586                 goto fail;
4587         memcpy(parent_inode,ext4fs_root->inode,sizeof(struct ext2_inode));
4588         memcpy(first_inode, parent_inode, sizeof(struct ext2_inode));
4589
4590         for(i=1;i<depth;i++) {
4591                 matched_inode_no=search_dir(dev_desc,parent_inode,ptr[i]);
4592                 if(matched_inode_no == -1) {
4593                         if(ptr[i+1] == NULL && i==1) {
4594                                 result_inode_no = EXT2_ROOT_INO;
4595                                 goto END;
4596                         }
4597                         else {
4598                                 if(ptr[i+1] == NULL)
4599                                         break;
4600                                 printf("Invalid path :(mkdir -p) Not Supported\n");
4601                                 result_inode_no = -1;
4602                                 goto fail;
4603                         }
4604                 }
4605                 else {
4606                         if(ptr[i+1] != NULL){
4607                         memset(parent_inode,'\0',sizeof(struct ext2_inode));
4608                         if(iget(matched_inode_no,parent_inode)) {
4609                                 result_inode_no = -1;
4610                                 goto fail;
4611                         }
4612                         result_inode_no=matched_inode_no;
4613                         }
4614                         else
4615                                 break;
4616                 }
4617         }
4618
4619 END:
4620         if(i==1)
4621                 matched_inode_no=search_dir(dev_desc,first_inode,ptr[i]);
4622         else
4623                 matched_inode_no=search_dir(dev_desc,parent_inode,ptr[i]);
4624
4625         if(matched_inode_no != -1) {
4626                 printf("file/Directory already present\n");
4627                 return -1;
4628         }
4629
4630         if(strlen(ptr[i])> 256) {
4631                 result_inode_no = -1;
4632                 goto fail;
4633         }
4634         memcpy(dname, ptr[i],strlen(ptr[i]));
4635
4636 fail:
4637         if(depth_dirname)
4638                 free(depth_dirname);
4639         if(parse_dirname)
4640                 free(parse_dirname);
4641         if(ptr)
4642                 free(ptr);
4643         if(parent_inode)
4644                 free(parent_inode);
4645         if(first_inode)
4646                 free(first_inode);
4647
4648         return result_inode_no;
4649 }
4650
4651 static int create_dir(block_dev_desc_t *dev_desc, unsigned int parent_inode_num,
4652                                         struct ext2_inode *parent_inode,char *dirname)
4653 {
4654         unsigned int direct_blk_idx;
4655         unsigned int parent_blknr;
4656         unsigned int previous_blknr = -1;
4657         int partno = 1;
4658         unsigned int inodeno;
4659         unsigned int working_block_no_of_parent = 0;
4660         unsigned char *working_block_buffer_for_parent = NULL;
4661         unsigned int inode_bitmap_index;
4662         unsigned char *buf = NULL;
4663         short create_dir_status = 0;
4664
4665         /*directory entry*/
4666         struct ext2_dirent *dir = NULL;
4667         struct ext4_dir *dir_entry = NULL;
4668
4669         int templength = 0;
4670         int totalbytes = 0;
4671         short int padding_factor = 0;
4672         unsigned int new_entry_byte_reqd;
4673         unsigned int last_entry_dirlen;
4674         int status;
4675
4676         unsigned char *ptr = NULL;
4677         struct ext2_dirent *temp_dir = NULL;
4678
4679         char * temp_ptr = NULL;
4680         unsigned int parent_itable_blkno,itable_blkno,blkoff;
4681         struct ext2_sblock *sblock = &(ext4fs_root->sblock);
4682         unsigned int inodes_per_block = blocksize / inodesize;
4683
4684         /*inode*/
4685         struct ext2_inode *file_inode = NULL;
4686         unsigned char *inode_buffer = NULL;
4687         unsigned char *zero_buffer = (unsigned char *)xzalloc(blocksize);
4688         if(!zero_buffer)
4689                 return -1;
4690         working_block_buffer_for_parent = (unsigned char *)xzalloc(blocksize);
4691
4692 RESTART:
4693         /*read the block no allocated to a file*/
4694         for(direct_blk_idx=0;direct_blk_idx<INDIRECT_BLOCKS;direct_blk_idx++) {
4695                 parent_blknr=ext4fs_read_allocated_block(parent_inode, direct_blk_idx);
4696                 if(parent_blknr==0) {
4697                         working_block_no_of_parent=previous_blknr;
4698                         break;
4699                 }
4700                 previous_blknr=parent_blknr;
4701         }
4702
4703 #ifdef DEBUG_LOG
4704                 printf("previous blk no =%u \n",previous_blknr);
4705                 printf("first_block_no_of_root =%u \n",working_block_no_of_parent);
4706 #endif
4707
4708                 status = ext2fs_devread (working_block_no_of_parent*sector_per_block, 0, blocksize,
4709                                         (char *)working_block_buffer_for_parent);
4710                 if (status == 0) {
4711                         goto fail;
4712                 }
4713                 else {
4714                         log_journal(working_block_buffer_for_parent,working_block_no_of_parent);
4715                         dir=(struct ext2_dirent *) working_block_buffer_for_parent;
4716                         ptr=(unsigned char*)dir;
4717                         totalbytes=0;
4718                         while(dir->direntlen>0) {
4719 #ifdef DEBUG_LOG
4720                                 printf("------------------------------------\n");
4721                                 printf("current inode no is %d\n",dir->inode);
4722                                 printf("current directory entry length is %d\n",dir->direntlen);
4723                                 printf("current name length is %d\n",dir->namelen);
4724                                 printf("current fileltype is %d\n",dir->filetype);
4725                                 printf("total bytes is %d\n",totalbytes);
4726                                 printf("dir->name is %s\n",ptr+sizeof(struct ext2_dirent));
4727                                 printf("-------------------------------------\n");
4728 #endif
4729                                 /*blocksize-totalbytes because last directory length i.e.,
4730                                 *dir->direntlen is free availble space in the block that means
4731                                 *it is a last entry of directory entry
4732                                 */
4733
4734                                 /*traversing the each directory entry*/
4735                                 if(blocksize-totalbytes==dir->direntlen)
4736                                 {
4737                                         if(strlen(dirname)%4!=0)
4738                                         {
4739                                                 padding_factor=4-(strlen(dirname)%4);
4740                                         }
4741                                         new_entry_byte_reqd = strlen(dirname) + sizeof(struct ext2_dirent)+padding_factor;
4742                                         padding_factor = 0;
4743                                         /*update last directory entry length to its length because
4744                                         *we are creating new directory entry*/
4745                                         if(dir->namelen%4!=0)
4746                                         {
4747                                                 padding_factor=4-(dir->namelen%4);/*for null storage*/
4748                                         }
4749                                         last_entry_dirlen= dir->namelen+sizeof(struct ext2_dirent)+padding_factor;
4750                                         if((blocksize-totalbytes -last_entry_dirlen) < new_entry_byte_reqd)
4751                                         {
4752 #ifdef DEBUG_LOG
4753                                                 printf("Storage capcity of 1st Block over allocating new block\n");
4754 #endif
4755                                                 if (direct_blk_idx==INDIRECT_BLOCKS-1)
4756                                                 {
4757                                                         printf("Directory capacity exceeds the limit\n");
4758                                                         goto fail;
4759                                                 }
4760                                                 parent_inode->b.blocks.dir_blocks[direct_blk_idx]= 
4761                                                                                 ext4fs_get_next_available_block_no(dev_desc,partno);
4762                                                 if(parent_inode->b.blocks.dir_blocks[direct_blk_idx] == -1)
4763                                                 {
4764                                                         printf("no block left to assign\n");
4765                                                         goto fail;
4766                                                 }
4767                                                 put_ext4(dev_desc,((uint64_t)(parent_inode->b.blocks.dir_blocks[direct_blk_idx] * blocksize)),
4768                                                                                 zero_buffer, blocksize);
4769                                                 parent_inode->size = parent_inode->size + blocksize;
4770                                                 parent_inode->blockcnt= parent_inode->blockcnt + sector_per_block;
4771                                                 put_metadata(working_block_buffer_for_parent,working_block_no_of_parent);
4772                                                 goto RESTART;
4773                                         }
4774                                         dir->direntlen=last_entry_dirlen;
4775                                         break;
4776                                 }
4777
4778                                 templength=dir->direntlen;
4779                                 totalbytes=totalbytes+templength;
4780                                 dir=(unsigned char*)dir;
4781                                 dir=(unsigned char*)dir+templength;
4782                                 dir=(struct ext2_dirent*)dir;
4783                                 ptr=dir;
4784                         }
4785
4786                         /*make a pointer ready for creating next directory entry*/
4787                         templength=dir->direntlen;
4788                         totalbytes=totalbytes+templength;
4789                         dir=(unsigned char*)dir;
4790                         dir=(unsigned char*)dir+templength;
4791                         dir=(struct ext2_dirent*)dir;
4792                         ptr=dir;
4793
4794 #if DEBUG_LOG
4795                         printf("------------------------------------\n");
4796                         printf("JUST BEFORE ADDING NAME\n");
4797                         printf("------------------------------------\n");
4798                         printf("current inode no is %u\n",dir->inode);
4799                         printf("current directory entry length is %d\n",dir->direntlen);
4800                         printf("current name length is %d\n",dir->namelen);
4801                         printf("current fileltype is %d\n",dir->filetype);
4802                         printf("total bytes is %d\n",totalbytes);
4803                         printf("dir->name is %s\n",ptr+sizeof(struct ext2_dirent));
4804                         printf("-------------------------------------\n");
4805 #endif
4806                 /*get the next available inode number*/
4807                 inodeno=ext4fs_get_next_available_inode_no(dev_desc,partno);
4808                 if(inodeno==-1)
4809                 {
4810                         printf("no inode left to assign\n");
4811                         goto fail;
4812                 }
4813 #ifdef DEBUG_LOG
4814                         printf("New Inode Assignment :%d\n",inodeno);
4815 #endif
4816                         dir->inode=inodeno;
4817                         dir->direntlen=blocksize-totalbytes;
4818                         dir->namelen=strlen(dirname);
4819                         dir->filetype=FILETYPE_DIRECTORY;
4820                         temp_dir=dir;
4821                         dir=(unsigned char*)dir;
4822                         dir=(unsigned char*)dir+sizeof(struct ext2_dirent);
4823                         memcpy(dir,dirname,strlen(dirname));
4824 #if DEBUG_LOG
4825                         dir=(struct ext2_dirent*)temp_dir;
4826
4827                         printf("------------------------------------\n");
4828                         printf("JUST AFTER ADDING NAME\n");
4829                         printf("------------------------------------\n");
4830                         printf("current inode no is %u\n",dir->inode);
4831                         printf("current directory entry length is %d\n",dir->direntlen);
4832                         printf("current name length is %d\n",dir->namelen);
4833                         printf("current fileltype is %d\n",dir->filetype);
4834                         printf("total bytes is %d\n",totalbytes);
4835                         printf("dir->name is %s\n",ptr+sizeof(struct ext2_dirent));
4836                         printf("-------------------------------------\n");
4837 #endif
4838                 }
4839                 put_metadata(working_block_buffer_for_parent,working_block_no_of_parent);
4840
4841                 /*Increase the Link count and write the parent inode
4842                  *journal backup of parent inode block */
4843                 temp_ptr = (char *)xzalloc(blocksize);
4844                 if(!temp_ptr)
4845                         goto fail;
4846                 inode_bitmap_index=parent_inode_num/(uint32_t)ext4fs_root->sblock.inodes_per_group;
4847                 parent_inode_num--;
4848                 parent_itable_blkno = __le32_to_cpu (gd[inode_bitmap_index].inode_table_id) +
4849                         (parent_inode_num % __le32_to_cpu (sblock->inodes_per_group))/ inodes_per_block;
4850                 blkoff = (parent_inode_num % inodes_per_block) * inodesize;
4851                 ext2fs_devread (parent_itable_blkno*sector_per_block, 0, blocksize,temp_ptr);
4852
4853                 log_journal(temp_ptr,parent_itable_blkno);
4854                 parent_inode_num++;
4855                 parent_inode->nlinks++;
4856                 memcpy(temp_ptr + blkoff,parent_inode,sizeof(struct ext2_inode));
4857                 put_metadata(temp_ptr,parent_itable_blkno);
4858
4859                 /* Update the group descriptor directory count*/
4860                 inode_bitmap_index=inodeno/(uint32_t)ext4fs_root->sblock.inodes_per_group;
4861                 gd[inode_bitmap_index].used_dir_cnt++;
4862
4863                 /*prepare the inode for the directory to be created*/
4864                 inode_buffer = xmalloc(inodesize);
4865                 memset(inode_buffer, '\0', inodesize);
4866                 file_inode = (struct ext2_inode *)inode_buffer;
4867                 file_inode->mode= S_IFDIR | S_IRWXU | S_IRGRP | S_IROTH | S_IXGRP | S_IXOTH;
4868                 /* ToDo: Update correct time*/
4869                 file_inode->mtime= NULL;
4870                 file_inode->atime= NULL;
4871                 file_inode->ctime= NULL;
4872                 file_inode->nlinks= 2;
4873                 file_inode->size = blocksize;
4874                 file_inode->blockcnt= blocksize/SECTOR_SIZE;
4875                 file_inode->b.blocks.dir_blocks[0] = ext4fs_get_next_available_block_no(dev_desc,partno);
4876
4877                 inodeno--;
4878                 itable_blkno = __le32_to_cpu (gd[inode_bitmap_index].inode_table_id) +
4879                 (inodeno % __le32_to_cpu (sblock->inodes_per_group))/ inodes_per_block;
4880                 blkoff = (inodeno % inodes_per_block) * inodesize;
4881                 if(parent_itable_blkno != itable_blkno) {
4882                         memset(temp_ptr,'\0',blocksize);
4883                         ext2fs_devread (itable_blkno*sector_per_block, 0, blocksize,temp_ptr);
4884                         log_journal(temp_ptr,itable_blkno);
4885                         memcpy(temp_ptr + blkoff,inode_buffer,inodesize);
4886                         put_metadata(temp_ptr,itable_blkno);
4887                         free(temp_ptr);
4888                 }
4889                 else {
4890                         /* If parent and child fall in same inode table block both should be kept in 1 buffer*/
4891                         memcpy(temp_ptr + blkoff,inode_buffer,inodesize);
4892                         gd_index--;
4893                         put_metadata(temp_ptr,itable_blkno);
4894                         free(temp_ptr);
4895                 }
4896                 inodeno++;
4897
4898                 /*create . and ../ for  new directory*/
4899                 buf = xzalloc(blocksize);
4900                 memset(buf, 0, blocksize);
4901                 dir_entry = (struct ext4_dir *)buf;
4902                 dir_entry->inode1 = inodeno;
4903                 dir_entry->rec_len1 = 12;
4904                 dir_entry->name_len1 = 1;
4905                 dir_entry->file_type1 = EXT2_FT_DIR;
4906                 dir_entry->name1[0] = '.';
4907                 dir_entry->inode2 = parent_inode_num;
4908                 dir_entry->rec_len2 = (blocksize - 12);
4909                 dir_entry->name_len2 = 2;
4910                 dir_entry->file_type2 = EXT2_FT_DIR;
4911                 dir_entry->name2[0] = '.'; dir_entry->name2[1] = '.';
4912                 put_ext4(dev_desc,(uint64_t)(file_inode->b.blocks.dir_blocks[0] * blocksize), buf, blocksize);
4913                 create_dir_status= SUCCESS;
4914
4915 fail:
4916         if(working_block_buffer_for_parent){
4917                 free(working_block_buffer_for_parent);
4918                 working_block_buffer_for_parent=NULL;
4919         }
4920         if(buf){
4921                 free(buf);
4922                 buf=NULL;
4923         }
4924         if(zero_buffer){
4925                 free(zero_buffer);
4926                 zero_buffer=NULL;
4927         }
4928         if(create_dir_status)
4929                 return 0;
4930         else
4931                 return -1;
4932 }
4933
4934 int ext4fs_create_dir (block_dev_desc_t *dev_desc, char *dirname)
4935 {
4936         unsigned int inodeno;
4937         int retval = 0;
4938         struct ext2_inode parent_inode;
4939         char dname[256] = {0,};
4940
4941         /*get the blocksize inode sector per block of the filesystem*/
4942         if(ext4fs_init(dev_desc)!=0) {
4943                 printf("error in File System init\n");
4944                 return -1;
4945         }
4946         inodeno= get_parent_inode_num(dev_desc,dirname,dname);
4947         if(inodeno==-1) {
4948                 retval = -1;
4949                 goto fail;
4950         }
4951         if(iget(inodeno,&parent_inode)){
4952                 retval = -1;
4953                 goto fail;
4954         }
4955         retval = create_dir(dev_desc,inodeno,&parent_inode,dname);
4956         if(retval){
4957                 printf("Failed to create directory\n");
4958                 goto fail;
4959         }
4960         ext4fs_update(dev_desc);
4961         printf("Done !!!\n");
4962 fail:
4963         ext4fs_deinit(dev_desc);
4964         return  retval;
4965 }
4966
4967 static int create_symlink(block_dev_desc_t *dev_desc,int link_type,unsigned int src_inodeno,
4968                 unsigned int parent_inode_num,struct ext2_inode *parent_inode,char *src_path, char *linkname)
4969 {
4970         unsigned int direct_blk_idx;
4971         unsigned int parent_blknr;
4972         unsigned int previous_blknr = -1;
4973         int partno = 1;
4974         unsigned int inodeno = 0;
4975         unsigned int working_block_no_of_parent = 0;
4976         unsigned char *working_block_buffer_for_parent = NULL;
4977         unsigned int inode_bitmap_index;
4978         unsigned char *buf = NULL;
4979         short create_dir_status = 1;
4980
4981         /*directory entry*/
4982         struct ext2_dirent *dir = NULL;
4983         struct ext4_dir *dir_entry = NULL;
4984         struct ext2_dirent *temp_dir = NULL;
4985         int templength = 0;
4986         int totalbytes = 0;
4987         short int padding_factor = 0;
4988         unsigned int new_entry_byte_reqd;
4989         unsigned int last_entry_dirlen;
4990         int status;
4991         unsigned char *ptr;
4992         char * temp_ptr = (char *)xzalloc(blocksize);
4993         unsigned int temp_blkno, blkoff;
4994         struct ext2_sblock *sblock = &(ext4fs_root->sblock);
4995         unsigned int inodes_per_block = blocksize / inodesize;
4996
4997         /*inode*/
4998         struct ext2_inode *file_inode = NULL;
4999         unsigned char *inode_buffer = NULL;
5000         unsigned int *zero_buffer = (unsigned char *)xzalloc(blocksize);
5001         if(!zero_buffer)
5002                 return -1;
5003         working_block_buffer_for_parent = (unsigned char *)xzalloc(blocksize);
5004
5005 RESTART:
5006         /*read the block no allocated to a file*/
5007         for(direct_blk_idx=0;direct_blk_idx<INDIRECT_BLOCKS;direct_blk_idx++){
5008                 parent_blknr=ext4fs_read_allocated_block(parent_inode, direct_blk_idx);
5009                 if(parent_blknr==0) {
5010                         working_block_no_of_parent=previous_blknr;
5011                         break;
5012                 }
5013                 previous_blknr=parent_blknr;
5014         }
5015
5016 #ifdef DEBUG_LOG
5017                 printf("previous blk no =%u \n",previous_blknr);
5018                 printf("first_block_no_of_root =%u \n",working_block_no_of_parent);
5019 #endif
5020                 status = ext2fs_devread (working_block_no_of_parent*sector_per_block, 0, blocksize,
5021                                         (char *)working_block_buffer_for_parent);
5022                 if (status == 0){
5023                         goto fail;
5024                 }
5025                 else {
5026                         log_journal(working_block_buffer_for_parent,working_block_no_of_parent);
5027                         dir=(struct ext2_dirent *) working_block_buffer_for_parent;
5028                         ptr=(unsigned char*)dir;
5029                         totalbytes=0;
5030                         while(dir->direntlen>0){
5031 #ifdef DEBUG_LOG
5032                                 printf("------------------------------------\n");
5033                                 printf("current inode no is %d\n",dir->inode);
5034                                 printf("current directory entry length is %d\n",dir->direntlen);
5035                                 printf("current name length is %d\n",dir->namelen);
5036                                 printf("current fileltype is %d\n",dir->filetype);
5037                                 printf("total bytes is %d\n",totalbytes);
5038                                 printf("dir->name is %s\n",ptr+sizeof(struct ext2_dirent));
5039                                 printf("-------------------------------------\n");
5040 #endif
5041                                 /*blocksize-totalbytes because last directory length i.e.,
5042                                 *dir->direntlen is free availble space in the block that means
5043                                 *it is a last entry of directory entry
5044                                 */
5045
5046                                 /*traversing the each directory entry*/
5047
5048                                 if(blocksize-totalbytes==dir->direntlen)
5049                                 {
5050                                         if(strlen(linkname)%4!=0)
5051                                         {
5052                                                 padding_factor=4-(strlen(linkname)%4);
5053                                         }
5054                                         new_entry_byte_reqd = strlen(linkname) + sizeof(struct ext2_dirent)+padding_factor;
5055                                         padding_factor = 0;
5056                                         /*update last directory entry length to its length because
5057                                         *we are creating new directory entry*/
5058                                         if(dir->namelen%4!=0)
5059                                         {
5060                                                 padding_factor=4-(dir->namelen%4);/*for null storage*/
5061                                         }
5062                                         last_entry_dirlen= dir->namelen+sizeof(struct ext2_dirent)+padding_factor;
5063                                         if((blocksize-totalbytes -last_entry_dirlen) < new_entry_byte_reqd)
5064                                         {
5065 #ifdef DEBUG_LOG
5066                                                 printf("Storage capacity of 1st Block over allocating new block\n");
5067 #endif
5068                                                 if (direct_blk_idx==INDIRECT_BLOCKS-1)
5069                                                 {
5070                                                         printf("Directory capacity exceeds the limit\n");
5071                                                         goto fail;
5072                                                 }
5073                                                 parent_inode->b.blocks.dir_blocks[direct_blk_idx]= 
5074                                                                                 ext4fs_get_next_available_block_no(dev_desc,partno);
5075                                                 if(parent_inode->b.blocks.dir_blocks[direct_blk_idx] == -1)
5076                                                 {
5077                                                         printf("no block left to assign\n");
5078                                                         goto fail;
5079                                                 }
5080                                                 put_ext4(dev_desc,((uint64_t)(parent_inode->b.blocks.dir_blocks[direct_blk_idx] * blocksize)),
5081                                                                                 zero_buffer, blocksize);
5082                                                 parent_inode->size = parent_inode->size + blocksize;
5083                                                 parent_inode->blockcnt= parent_inode->blockcnt + sector_per_block;
5084                                                 put_metadata(working_block_buffer_for_parent,working_block_no_of_parent);
5085                                                 goto RESTART;
5086                                         }
5087                                         dir->direntlen=last_entry_dirlen;
5088                                         break;
5089                                 }
5090                                 templength=dir->direntlen;
5091                                 totalbytes=totalbytes+templength;
5092                                 dir=(unsigned char*)dir;
5093                                 dir=(unsigned char*)dir+templength;
5094                                 dir=(struct ext2_dirent*)dir;
5095                                 ptr=dir;
5096                         }
5097
5098                         /*make a pointer ready for creating next directory entry*/
5099                         templength=dir->direntlen;
5100                         totalbytes=totalbytes+templength;
5101                         dir=(unsigned char*)dir;
5102                         dir=(unsigned char*)dir+templength;
5103                         dir=(struct ext2_dirent*)dir;
5104                         ptr=dir;
5105
5106 #if DEBUG_LOG
5107                         printf("------------------------------------\n");
5108                         printf("JUST BEFORE ADDING NAME\n");
5109                         printf("------------------------------------\n");
5110                         printf("current inode no is %u\n",dir->inode);
5111                         printf("current directory entry length is %d\n",dir->direntlen);
5112                         printf("current name length is %d\n",dir->namelen);
5113                         printf("current fileltype is %d\n",dir->filetype);
5114                         printf("total bytes is %d\n",totalbytes);
5115                         printf("dir->name is %s\n",ptr+sizeof(struct ext2_dirent));
5116                         printf("-------------------------------------\n");
5117 #endif
5118                 if(link_type == SOFT_LINK){
5119                 /*get the next available inode number*/
5120                 inodeno=ext4fs_get_next_available_inode_no(dev_desc,partno);
5121                 if(inodeno==-1)
5122                 {
5123                         printf("no inode left to assign\n");
5124                         goto fail;
5125                 }
5126 #ifdef DEBUG_LOG
5127                         printf("New Inode Assignment :%d\n",inodeno);
5128 #endif
5129                         dir->inode=inodeno;
5130                         }
5131                 else
5132                         dir->inode=src_inodeno;
5133
5134                         dir->direntlen=blocksize-totalbytes;
5135                         dir->namelen=strlen(linkname);
5136                         if(link_type == SOFT_LINK)
5137                         dir->filetype=FILETYPE_SYMLINK;
5138                         else
5139                                 dir->filetype=FILETYPE_REG;
5140                         temp_dir=dir;
5141                         dir=(unsigned char*)dir;
5142                         dir=(unsigned char*)dir+sizeof(struct ext2_dirent);
5143                         memcpy(dir,linkname,strlen(linkname));
5144 #if DEBUG_LOG
5145                         dir=(struct ext2_dirent*)temp_dir;
5146
5147                         printf("------------------------------------\n");
5148                         printf("JUST AFTER ADDING NAME\n");
5149                         printf("------------------------------------\n");
5150                         printf("current inode no is %u\n",dir->inode);
5151                         printf("current directory entry length is %d\n",dir->direntlen);
5152                         printf("current name length is %d\n",dir->namelen);
5153                         printf("current fileltype is %d\n",dir->filetype);
5154                         printf("total bytes is %d\n",totalbytes);
5155                         printf("dir->name is %s\n",ptr+sizeof(struct ext2_dirent));
5156                         printf("-------------------------------------\n");
5157 #endif
5158                 }
5159                 /*update  the directory entry block of parent inode for new directory*/
5160                 put_metadata(working_block_buffer_for_parent,working_block_no_of_parent);
5161
5162                 if(link_type == SOFT_LINK){
5163                         /*prepare the inode for the symlink to be created*/
5164                         inode_buffer = xmalloc(inodesize);
5165                         memset(inode_buffer, '\0', inodesize);
5166                         file_inode = (struct ext2_inode *)inode_buffer;
5167                         file_inode->mode= S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO;
5168                         /* ToDo: Update correct time*/
5169                         file_inode->mtime= NULL;
5170                         file_inode->atime= NULL;
5171                         file_inode->ctime= NULL;
5172                         file_inode->nlinks= 1;
5173                         file_inode->size = strlen(src_path);
5174                         file_inode->blockcnt= 0;
5175                         memcpy(file_inode->b.symlink,src_path, strlen(src_path));
5176
5177                         inode_bitmap_index=inodeno/(uint32_t)ext4fs_root->sblock.inodes_per_group;
5178                         inodeno--;
5179                         temp_blkno = __le32_to_cpu (gd[inode_bitmap_index].inode_table_id) +
5180                                 (inodeno % __le32_to_cpu (sblock->inodes_per_group))/ inodes_per_block;
5181                         blkoff = (inodeno % inodes_per_block) * inodesize;
5182                         ext2fs_devread (temp_blkno*sector_per_block, 0, blocksize,temp_ptr);
5183                         log_journal(temp_ptr,temp_blkno);
5184
5185                         memcpy(temp_ptr + blkoff,inode_buffer,inodesize);
5186                         put_metadata(temp_ptr,temp_blkno);
5187                         free(temp_ptr);
5188                 }
5189
5190 fail:
5191         if(working_block_buffer_for_parent){
5192                 free(working_block_buffer_for_parent);
5193                 working_block_buffer_for_parent=NULL;
5194         }
5195         if(buf){
5196                 free(buf);
5197                 buf=NULL;
5198         }
5199         if(zero_buffer){
5200                 free(zero_buffer);
5201                 zero_buffer=NULL;
5202         }
5203         if(create_dir_status)
5204                 return 0;
5205         else
5206                 return -1;
5207 }
5208
5209 /*
5210 * Function:get_parent_inode_num_write
5211 * Return Value: inode Number of the parent directory of  file/Directory to be created
5212 * dev_desc : Input parameter, device descriptor
5213 * dirname : Input parmater, input path name of the file/directory to be created
5214 * dname : Output parameter, to be filled with the name of the directory extracted from dirname
5215 */
5216 int get_parent_inode_num_write(block_dev_desc_t *dev_desc,char *dirname, char *dname)
5217 {
5218         char **ptr = NULL;
5219         int i,depth = 0;
5220         char *depth_dirname = NULL;
5221         char *parse_dirname = NULL;
5222         struct ext2_inode *parent_inode = NULL;
5223         struct ext2_inode *first_inode = NULL;
5224         unsigned int matched_inode_no;
5225         unsigned int result_inode_no;
5226         if(*dirname!='/') {
5227                 printf("Please supply Absolute path\n");
5228                 return -1;
5229         }
5230
5231         /*TODO: input validation make equivalent to linux*/
5232
5233         /*get the memory size*/
5234         depth_dirname = (char *)xzalloc(strlen(dirname)+1);
5235         memcpy(depth_dirname,dirname,strlen(dirname));
5236         depth=find_dir_depth(depth_dirname);
5237         parse_dirname = (char *)xzalloc(strlen(dirname)+1);
5238         memcpy(parse_dirname,dirname,strlen(dirname));
5239
5240         /*
5241          * NOTE:
5242          *
5243          * According to the code at parse_path we need two extra pointers
5244          * (+2 at xzalloc) to accomodate "/" pointer to root directory and extra
5245          * NULL pointer as a sentinel.
5246          *
5247          * However this path parsing shall be regarded as an overkill, since we
5248          * only store plain files at root "/" directory (e.g. /modem.bin
5249          * /uImage. etc.)
5250          *
5251          */
5252         ptr = (char**)xzalloc((depth + 2)* sizeof(char *));
5253         parse_path(ptr,parse_dirname);
5254
5255         parent_inode=(struct ext2_inode*)xzalloc(sizeof(struct ext2_inode));
5256         first_inode=(struct ext2_inode*)xzalloc(sizeof(struct ext2_inode));
5257         memcpy(parent_inode,ext4fs_root->inode,sizeof(struct ext2_inode));
5258         memcpy(first_inode, parent_inode, sizeof(struct ext2_inode));
5259
5260         result_inode_no = EXT2_ROOT_INO;
5261         for(i=1;i<depth;i++) {
5262                 matched_inode_no=search_dir(dev_desc,parent_inode,ptr[i]);
5263                 if(matched_inode_no == -1) {
5264                         if(ptr[i+1] == NULL && i==1) {
5265                                 result_inode_no = EXT2_ROOT_INO;
5266                                 goto END;
5267                         }
5268                         else {
5269                                 if(ptr[i+1] == NULL)
5270                                 break;
5271                                 printf("Invalid path \n");
5272                                 return -1;
5273                         }
5274                 }
5275                 else {
5276                         if(ptr[i+1] != NULL){
5277                         memset(parent_inode,'\0',sizeof(struct ext2_inode));
5278                         if(iget(matched_inode_no,parent_inode))
5279                                 return -1;
5280
5281                         result_inode_no=matched_inode_no;
5282                         }
5283                         else
5284                                 break;
5285                 }
5286         }
5287
5288 END:
5289         memcpy(dname, ptr[i],strlen(ptr[i])); 
5290
5291         if(depth_dirname)
5292                 free(depth_dirname);
5293         if(parse_dirname)
5294                 free(parse_dirname);
5295         if(ptr)
5296                 free(ptr);
5297         if(parent_inode)
5298                 free(parent_inode);
5299         if(first_inode)
5300                 free(first_inode);
5301
5302         return result_inode_no;
5303 }
5304
5305 int namei(block_dev_desc_t *dev_desc,char *dirname,char *dname)
5306 {
5307         char **ptr = NULL;
5308         int i,depth = 0;
5309         char *depth_dirname = NULL;
5310         char *parse_dirname = NULL;
5311         struct ext2_inode *parent_inode = NULL;
5312         struct ext2_inode *first_inode = NULL;
5313         unsigned int matched_inode_no;
5314         unsigned int result_inode_no;
5315
5316         if(*dirname!='/') {
5317                 printf("Please supply Absolute path\n");
5318                 return -1;
5319         }
5320
5321         /*TODO: input validation make equivalent to linux*/
5322
5323         /*get the memory size*/
5324         depth_dirname = (char *)xzalloc(strlen(dirname)+1);
5325         memcpy(depth_dirname,dirname,strlen(dirname));
5326         depth=find_dir_depth(depth_dirname);
5327         parse_dirname = (char *)xzalloc(strlen(dirname)+1);
5328         memcpy(parse_dirname,dirname,strlen(dirname));
5329
5330         /*allocate memory for each directory level*/
5331         ptr=(char**)xzalloc((depth)* sizeof(char *));
5332         parse_path(ptr,parse_dirname);
5333
5334         parent_inode=(struct ext2_inode*)xzalloc(sizeof(struct ext2_inode));
5335         first_inode=(struct ext2_inode*)xzalloc(sizeof(struct ext2_inode));
5336         memcpy(parent_inode,ext4fs_root->inode,sizeof(struct ext2_inode));
5337         memcpy(first_inode, parent_inode, sizeof(struct ext2_inode));
5338
5339         for(i=1;i<depth;i++) {
5340                 matched_inode_no=search_dir(dev_desc,parent_inode,ptr[i]);
5341                 if(matched_inode_no == -1) {
5342                         if(ptr[i+1] == NULL && i==1) {
5343                                 result_inode_no = EXT2_ROOT_INO;
5344                                 goto END;
5345                         }
5346                         else {
5347                                 if(ptr[i+1] == NULL)
5348                                         break;
5349                                 printf("Invalid Source Path\n");
5350                                 return -1;
5351                         }
5352                 }
5353                 else {
5354                         if(ptr[i+1] != NULL){
5355                         memset(parent_inode,'\0',sizeof(struct ext2_inode));
5356                         if(iget(matched_inode_no,parent_inode))
5357                                 return -1;
5358
5359                         result_inode_no=matched_inode_no;
5360                         }
5361                         else
5362                                 break;
5363                 }
5364         }
5365
5366 END:
5367         if(i==1)
5368                 matched_inode_no=search_dir(dev_desc,first_inode,ptr[i]);
5369         else
5370                 matched_inode_no=search_dir(dev_desc,parent_inode,ptr[i]);
5371
5372         if(matched_inode_no != -1) {
5373                 result_inode_no=matched_inode_no;
5374         }
5375         else
5376                 result_inode_no = -1;
5377         memcpy(dname, ptr[i],strlen(ptr[i]));
5378
5379         if(depth_dirname)
5380                 free(depth_dirname);
5381         if(parse_dirname)
5382                 free(parse_dirname);
5383         if(ptr)
5384                 free(ptr);
5385         if(parent_inode)
5386                 free(parent_inode);
5387         if(first_inode)
5388                 free(first_inode);
5389
5390         return result_inode_no;
5391 }
5392
5393 int ext4fs_create_symlink (block_dev_desc_t *dev_desc, int link_type,char *src_path, char *target_path)
5394 {
5395         unsigned int target_parent_inodeno;
5396         struct ext2_inode target_parent_inode;
5397         unsigned int src_inodeno = 0;
5398         struct ext2_inode src_inode;
5399         int inode_bitmap_index;
5400         char dname_src[256] = {0,};
5401         char dname_target[256] = {0,};
5402         int retval = 0;
5403         struct ext2_sblock *sblock = &(ext4fs_root->sblock);
5404         unsigned int inodes_per_block;
5405         unsigned int temp_blkno, blkoff;
5406         char *ptr = NULL;
5407
5408         /*get the blocksize inode sector per block of the filesystem*/
5409         if(ext4fs_init(dev_desc)!=0)
5410         {
5411                 printf("error in File System init\n");
5412                 return -1;
5413         }
5414         inodes_per_block = blocksize / inodesize;
5415         target_parent_inodeno= get_parent_inode_num(dev_desc,target_path,dname_target);
5416         if(target_parent_inodeno==-1) {
5417                 retval = -1;
5418                 goto FAIL;
5419         }
5420         if(iget(target_parent_inodeno,&target_parent_inode)){
5421                 retval = -1;
5422                 goto FAIL;
5423         }
5424         if(link_type==HARD_LINK){
5425         src_inodeno = namei(dev_desc,src_path,dname_src);
5426         if(src_inodeno==-1) {
5427                 printf("File Does Not exist\n");
5428                 retval = -1;
5429                 goto FAIL;
5430         }
5431         if(iget(src_inodeno,&src_inode)){
5432                 retval = -1;
5433                 goto FAIL;
5434         }
5435         ptr = (char *)xzalloc(blocksize);
5436         if(!ptr) {
5437                 retval = -1;
5438                 goto FAIL;
5439         }
5440         inode_bitmap_index=src_inodeno/(uint32_t)ext4fs_root->sblock.inodes_per_group;
5441         src_inodeno--;
5442         temp_blkno = __le32_to_cpu (gd[inode_bitmap_index].inode_table_id) +
5443                 (src_inodeno % __le32_to_cpu (sblock->inodes_per_group))/ inodes_per_block;     
5444         ext2fs_devread (temp_blkno*sector_per_block, 0, blocksize,ptr);
5445         log_journal(ptr,temp_blkno);
5446         src_inodeno++;
5447         free(ptr);
5448
5449         src_inode.nlinks++;
5450         if(src_inode.mode & S_IFDIR){
5451                 printf("Hard Link not allowed for a directory \n");
5452                 retval = -1;
5453                 goto FAIL;
5454         }
5455
5456         /*update the inode table entry for the new directory created*/
5457         /* Update the group descriptor directory count*/
5458         inode_bitmap_index=src_inodeno/(uint32_t)ext4fs_root->sblock.inodes_per_group;
5459         }
5460
5461         retval = create_symlink(dev_desc,link_type,src_inodeno,target_parent_inodeno,&target_parent_inode,
5462                                                                 src_path,dname_target);
5463         if(retval){
5464                 printf("Failed to create Link\n");
5465                 retval = -1;
5466                 goto FAIL;
5467         }
5468         else{
5469                 if(link_type==HARD_LINK){
5470                         ptr = (char *)xzalloc(blocksize);
5471                         if(!ptr) {
5472                                 retval = -1;
5473                                 goto FAIL;
5474                         }
5475                         inode_bitmap_index=src_inodeno/(uint32_t)ext4fs_root->sblock.inodes_per_group;
5476                         src_inodeno--;
5477                         temp_blkno = __le32_to_cpu (gd[inode_bitmap_index].inode_table_id) +
5478                         (src_inodeno % __le32_to_cpu (sblock->inodes_per_group))/ inodes_per_block;
5479                         blkoff = (src_inodeno % inodes_per_block) * inodesize;
5480                         ext2fs_devread (temp_blkno*sector_per_block, 0, blocksize,ptr);
5481                         memcpy(ptr + blkoff,&src_inode,sizeof(struct ext2_inode));
5482                         put_metadata(ptr,temp_blkno);
5483                         free(ptr);
5484                         }
5485         }
5486         ext4fs_update(dev_desc);
5487         printf("Done !!!\n");
5488 FAIL:
5489         ext4fs_deinit(dev_desc);
5490         return  retval;
5491 }
5492
5493 int ext4fs_ls (const char *dirname)
5494 {
5495         ext2fs_node_t dirnode;
5496         int status;
5497
5498         if (dirname== NULL)
5499                 return (0);
5500
5501         status = ext4fs_find_file (dirname, &ext4fs_root->diropen, &dirnode,
5502                 FILETYPE_DIRECTORY);
5503         if (status != 1) {
5504                 printf ("** Can not find directory. **\n");
5505                 return (1);
5506         }
5507
5508         ext4fs_iterate_dir (dirnode, NULL, NULL, NULL);
5509         ext4fs_free_node (dirnode, &ext4fs_root->diropen);
5510         return (0);
5511 }
5512
5513 int ext4fs_open (const char *filename)
5514 {
5515         ext2fs_node_t fdiro = NULL;
5516         int status;
5517         int len;
5518
5519         if (ext4fs_root == NULL)
5520                 return (-1);
5521
5522         ext4fs_file = NULL;
5523         status = ext4fs_find_file (filename, &ext4fs_root->diropen, &fdiro,
5524                 FILETYPE_REG);
5525         if (status == 0)
5526                 goto fail;
5527
5528         if (!fdiro->inode_read) {
5529                 status = ext4fs_read_inode (fdiro->data, fdiro->ino,
5530                         &fdiro->inode);
5531                 if (status == 0)
5532                         goto fail;
5533         }
5534         len = __le32_to_cpu (fdiro->inode.size);
5535         ext4fs_file = fdiro;
5536         return (len);
5537
5538 fail:
5539         ext4fs_free_node (fdiro, &ext4fs_root->diropen);
5540         return (-1);
5541 }
5542
5543 int ext4fs_close (void)
5544 {
5545         if ((ext4fs_file != NULL) && (ext4fs_root != NULL)) {
5546                 ext4fs_free_node (ext4fs_file, &ext4fs_root->diropen);
5547                 ext4fs_file = NULL;
5548         }
5549         if (ext4fs_root != NULL) {
5550                 free (ext4fs_root);
5551                 ext4fs_root = NULL;
5552         }
5553         if (ext4fs_indir1_block != NULL) {
5554                 free (ext4fs_indir1_block);
5555                 ext4fs_indir1_block = NULL;
5556                 ext4fs_indir1_size = 0;
5557                 ext4fs_indir1_blkno = -1;
5558         }
5559         if (ext4fs_indir2_block != NULL) {
5560                 free (ext4fs_indir2_block);
5561                 ext4fs_indir2_block = NULL;
5562                 ext4fs_indir2_size = 0;
5563                 ext4fs_indir2_blkno = -1;
5564         }
5565         return (0);
5566 }
5567
5568 int ext4fs_read (char *buf, unsigned len)
5569 {
5570         int status;
5571
5572         if (ext4fs_root == NULL) {
5573                 return (0);
5574         }
5575
5576         if (ext4fs_file == NULL) {
5577                 return (0);
5578         }
5579
5580         status = ext4fs_read_file (ext4fs_file, 0, len, buf);
5581         return (status);
5582 }
5583
5584 int ext4fs_mount (unsigned part_length)
5585 {
5586         struct ext2_data *data;
5587         int status;
5588
5589         data = memalign(ARCH_DMA_MINALIGN, sizeof (struct ext2_data));
5590         if (!data) {
5591                 return (0);
5592         }
5593         /* Read the superblock.  */
5594         status = ext2fs_devread (1 * 2, 0, sizeof (struct ext2_sblock),
5595                 (char *) &data->sblock);
5596
5597         if (status == 0)
5598                 goto fail;
5599
5600         /* Make sure this is an ext2 filesystem.  */
5601         if (__le16_to_cpu (data->sblock.magic) != EXT2_MAGIC) {
5602                 goto fail;
5603         }
5604         if (__le32_to_cpu(data->sblock.revision_level == 0)) {
5605                 inode_size = 128;
5606         } else {
5607                 inode_size = __le16_to_cpu(data->sblock.inode_size);
5608         }
5609 #ifdef DEBUG
5610         printf("EXT2 rev %d, inode_size %d\n",
5611                 __le32_to_cpu(data->sblock.revision_level), inode_size);
5612 #endif
5613         data->diropen.data = data;
5614         data->diropen.ino = 2;
5615         data->diropen.inode_read = 1;
5616         data->inode = &data->diropen.inode;
5617
5618         status = ext4fs_read_inode (data, 2, data->inode);
5619         if (status == 0)
5620                 goto fail;
5621
5622         ext4fs_root = data;
5623
5624         return (1);
5625
5626 fail:
5627         printf("Failed to mount ext2 filesystem...\n");
5628         free (data);
5629         ext4fs_root = NULL;
5630         return (0);
5631 }