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>
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.
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.
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.
25 #include <asm/byteorder.h>
26 #include <linux/stat.h>
27 #include <linux/time.h>
28 #include "../ext4/crc16.h"
34 /* Maximum entries in 1 journal transaction */
35 #define MAX_JOURNAL_ENTRIES 80
49 struct journal_log *journal_ptr[MAX_JOURNAL_ENTRIES];
50 struct dirty_blocks *dirty_block_ptr[MAX_JOURNAL_ENTRIES];
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);
56 #define EXT2_JOURNAL_INO 8 /* Journal inode */
57 #define EXT2_JOURNAL_SUPERBLOCK 0 /* Journal Superblock number */
58 #define S_IFLNK 0120000 /* symbolic link */
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
76 * Standard header for all descriptor blocks:
78 typedef struct journal_header_s
86 * The journal superblock. All fields are in big-endian byte order.
88 typedef struct journal_superblock_s
91 journal_header_t s_header;
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 */
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 */
105 /* Error value, as set by journal_abort(). */
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 */
114 __u8 s_uuid[16]; /* 128-bit uuid for journal */
117 __u32 s_nr_users; /* Nr of filesystems sharing log */
119 __u32 s_dynsuper; /* Blocknr of dynamic superblock copy*/
122 __u32 s_max_transaction; /* Limit of journal blocks per trans.*/
123 __u32 s_max_trans_data; /* Limit of data blocks per trans. */
129 __u8 s_users[16*48]; /* ids of all fs'es sharing the log */
131 } journal_superblock_t;
133 /* To convert big endian journal superblock entries to little endian */
134 unsigned int be_le(unsigned int num)
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
145 unsigned int le_be(unsigned int num)
147 return((num&0xff)<<24)+((num&0xff00)<<8)+((num&0xff0000)>>8)+((num>>24)&0xff);
150 struct ext3_journal_block_tag
156 extern int ext2fs_devread(int sector, int byte_offset, int byte_len, char *buf);
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
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
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 */
180 /* Bits used as offset in sector */
181 #define DISK_SECTOR_BITS 9
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)
186 /* Log2 size of ext2 block in bytes. */
187 #define LOG2_BLOCK_SIZE(data) (__le32_to_cpu (data->sblock.log2_block_size) + 10)
189 /* The size of an ext2 block in bytes. */
190 #define EXT2_BLOCK_SIZE(data) (1 << LOG2_BLOCK_SIZE(data))
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
196 #define EXT2_FT_DIR 2
199 #define EXT_MAX_FILE_LEN 256
200 // All fields are little-endian
219 /* The ext2 superblock. */
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;
235 uint16_t max_mnt_count;
238 uint16_t error_handling;
239 uint16_t minor_revision_level;
241 uint32_t checkinterval;
243 uint32_t revision_level;
244 uint16_t uid_reserved;
245 uint16_t gid_reserved;
246 uint32_t first_inode;
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;
258 struct ext2_block_group
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 */
267 __u32 bg_reserved[2];
268 __u16 bg_itable_unused; /* Unused inodes count */
269 __u16 bg_checksum; /* crc16(s_uuid+grouo_num+group_desc)*/
272 /* The ext2 inode. */
283 uint32_t blockcnt; /* Blocks of 512 bytes!! */
288 uint32_t dir_blocks[INDIRECT_BLOCKS];
289 uint32_t indir_block;
290 uint32_t double_indir_block;
291 uint32_t tripple_indir_block;
298 uint32_t fragment_addr;
302 /* The header of an ext2 directory entry. */
311 struct ext2_data *data;
312 struct ext2_inode inode;
317 struct ext4_extent_header {
332 struct ext4_extent_idx {
339 /* Information about a "mounted" ext2 filesystem. */
341 struct ext2_sblock sblock;
342 struct ext2_inode *inode;
343 struct ext2fs_node diropen;
346 typedef struct ext2fs_node *ext2fs_node_t;
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;
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;
363 #define BLOCK_NO_ONE 1
364 #define SUPERBLOCK_SECTOR 2
365 #define SUPERBLOCK_SIZE 1024
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;
379 static struct ext2_sblock *sb = NULL;
380 /*blockgroup bitmaps*/
381 static unsigned char **bg = NULL;
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;
390 * Macro-instructions used to manage several block sizes
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)
397 #define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001
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 */
403 #define EXT4_FEATURE_RO_COMPAT_GDT_CSUM 0x0010
404 #define EXT4_FEATURE_INCOMPAT_EXTENTS 0x0040 /* extents support */
407 #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
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);
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)
417 // Overflow-resistant
418 uint32_t res = size / n;
425 void ext4fs_dump_the_block_group_before_writing()
429 blocksize=EXT2_BLOCK_SIZE(ext4fs_root);
430 for(i=0;i<no_blockgroup;i++)
432 printf("\n-----------------\n");
433 printf("[BEFORE WRITING ]block group %d\n",i);
434 printf("-----------------\n");
435 for(j=0;j<blocksize;j++)
437 printf("%u",*(bg[i]+j));
442 void ext4fs_dump_the_block_group_after_writing()
446 blocksize=EXT2_BLOCK_SIZE(ext4fs_root);
447 for(i=0;i<no_blockgroup;i++)
449 printf("\n-----------------\n");
450 printf("[AFTER WRITING]block group %d\n",i);
451 printf("-----------------\n");
452 for(j=0;j<blocksize;j++)
454 printf("%u",*(bg[i]+j));
459 void ext4fs_dump_the_inode_group_before_writing()
463 blocksize=EXT2_BLOCK_SIZE(ext4fs_root);
464 for(i=0;i<no_blockgroup;i++)
466 printf("\n-----------------\n");
467 printf("[BEFORE WRITING ]block group %d\n",i);
468 printf("-----------------\n");
469 for(j=0;j<blocksize;j++)
471 printf("%u",*(inode_bmaps[i]+j));
476 void ext4fs_dump_the_inode_group_after_writing()
480 blocksize=EXT2_BLOCK_SIZE(ext4fs_root);
481 for(i=0;i<no_blockgroup;i++)
483 printf("\n-----------------\n");
484 printf("[AFTER WRITING]block group %d\n",i);
485 printf("-----------------\n");
486 for(j=0;j<blocksize;j++)
488 printf("%u",*(inode_bmaps[i]+j));
494 static int ext4fs_blockgroup
495 (struct ext2_data *data, int group, struct ext2_block_group *blkgrp)
499 unsigned int desc_per_blk;
501 desc_per_blk = EXT2_BLOCK_SIZE(data) / sizeof(struct ext2_block_group);
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);
507 printf ("ext4fs read %d group descriptor (blkno %d blkoff %d)\n",
508 group, blkno, blkoff);
510 return (ext2fs_devread (blkno << LOG2_EXT2_BLOCK_SIZE(data),
511 blkoff, sizeof(struct ext2_block_group), (char *)blkgrp));
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)
517 struct ext4_extent_idx *index;
524 index = (struct ext4_extent_idx *) (ext_block + 1);
526 if (le32_to_cpu(ext_block->magic) != EXT4_EXT_MAGIC)
529 if (ext_block->depth == 0)
532 for (i = 0; i < le32_to_cpu (ext_block->entries); i++) {
533 if (fileblock < le32_to_cpu(index[i].block))
540 block = le32_to_cpu (index[i].leaf_hi);
541 block = (block << 32) + le32_to_cpu (index[i].leaf);
543 if (ext2fs_devread (block << LOG2_EXT2_BLOCK_SIZE (data),
544 0, EXT2_BLOCK_SIZE(data), buf))
546 ext_block = (struct ext4_extent_header *) buf;
554 static int ext4fs_read_inode
555 (struct ext2_data *data, int ino, struct ext2_inode *inode)
557 struct ext2_block_group blkgrp;
558 struct ext2_sblock *sblock = &data->sblock;
559 int inodes_per_block;
566 printf ("ext4fs read inode %d, inode_size %d\n", ino, inode_size);
568 /* It is easier to calculate if the first inode is 0. */
570 status = ext4fs_blockgroup (data, ino / __le32_to_cpu
571 (sblock->inodes_per_group), &blkgrp);
576 inodes_per_block = EXT2_BLOCK_SIZE(data) / inode_size;
578 blkno = __le32_to_cpu (blkgrp.inode_table_id) +
579 (ino % __le32_to_cpu (sblock->inodes_per_group))
581 blkoff = (ino % inodes_per_block) * inode_size;
583 printf ("ext4fs read inode blkno %d blkoff %d\n", blkno, blkoff);
585 /* Read the inode. */
586 status = ext2fs_devread (blkno << LOG2_EXT2_BLOCK_SIZE (data), blkoff,
587 sizeof (struct ext2_inode), (char *) inode);
594 void ext4fs_free_node (ext2fs_node_t node, ext2fs_node_t currroot)
596 if ((node != &ext4fs_root->diropen) && (node != currroot))
600 int ext4fs_read_allocated_block(struct ext2_inode *inode, int fileblock)
607 unsigned int perblock;
608 unsigned int perblock_parent;
609 unsigned int perblock_child;
611 /*get the blocksize of the filesystem*/
612 blksz=EXT2_BLOCK_SIZE(ext4fs_root);
613 log2_blksz = LOG2_EXT2_BLOCK_SIZE (ext4fs_root);
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;
621 leaf = ext4fs_find_leaf (ext4fs_root, buf,
622 (struct ext4_extent_header *) inode->b.blocks.dir_blocks,
625 printf ("invalid extent \n");
629 ext = (struct ext4_extent *) (leaf + 1);
631 for (i = 0; i < le32_to_cpu (leaf->entries); i++) {
632 if (fileblock < le32_to_cpu (ext[i].block))
637 fileblock -= le32_to_cpu (ext[i].block);
638 if (fileblock >= le32_to_cpu (ext[i].len)) {
642 start = le32_to_cpu (ext[i].start_hi);
643 start = (start << 32) + le32_to_cpu (ext[i].start);
644 return fileblock + start;
647 printf("something wrong with extent \n");
653 if (fileblock < INDIRECT_BLOCKS) {
654 blknr = __le32_to_cpu (inode->b.blocks.dir_blocks[fileblock]);
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");
664 ext4fs_indir1_size = blksz;
665 ext4fs_indir1_blkno = -1;
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");
677 ext4fs_indir1_size = blksz;
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,
683 (char *) ext4fs_indir1_block);
685 printf ("** SI ext2fs read block (indir 1) failed. **\n");
688 ext4fs_indir1_blkno =
689 __le32_to_cpu (inode->b.blocks.
690 indir_block) << log2_blksz;
692 blknr = __le32_to_cpu (ext4fs_indir1_block
693 [fileblock - INDIRECT_BLOCKS]);
695 /* Double indirect. */
697 (INDIRECT_BLOCKS + (blksz / 4 * (blksz / 4 + 1)))) {
699 unsigned int perblock = blksz / 4;
700 unsigned int rblock = fileblock - (INDIRECT_BLOCKS
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");
709 ext4fs_indir1_size = blksz;
710 ext4fs_indir1_blkno = -1;
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");
722 ext4fs_indir1_size = blksz;
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,
728 (char *) ext4fs_indir1_block);
730 printf ("** DI ext2fs read block (indir 2 1) failed. **\n");
733 ext4fs_indir1_blkno =
734 __le32_to_cpu (inode->b.blocks.double_indir_block) << log2_blksz;
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");
743 ext4fs_indir2_size = blksz;
744 ext4fs_indir2_blkno = -1;
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");
756 ext4fs_indir2_size = blksz;
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,
762 (char *) ext4fs_indir2_block);
764 printf ("** DI ext2fs read block (indir 2 2) failed. **\n");
767 ext4fs_indir2_blkno =
768 __le32_to_cpu (ext4fs_indir1_block[rblock / perblock]) << log2_blksz;
770 blknr = __le32_to_cpu (ext4fs_indir2_block[rblock % perblock]);
772 /* Tripple indirect. */
774 rblock = fileblock - (INDIRECT_BLOCKS + blksz / 4 + (blksz / 4 * blksz / 4));
775 perblock_child = blksz / 4;
776 perblock_parent = ((blksz / 4) * (blksz / 4));
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");
784 ext4fs_indir1_size = blksz;
785 ext4fs_indir1_blkno = -1;
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");
797 ext4fs_indir1_size = blksz;
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,
804 (char *) ext4fs_indir1_block);
806 printf ("** TI ext2fs read block (indir 2 1) failed. **\n");
809 ext4fs_indir1_blkno =
810 __le32_to_cpu (inode->b.blocks.tripple_indir_block) << log2_blksz;
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");
819 ext4fs_indir2_size = blksz;
820 ext4fs_indir2_blkno = -1;
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");
832 ext4fs_indir2_size = blksz;
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,
838 (char *) ext4fs_indir2_block);
840 printf ("** TI ext2fs read block (indir 2 2) failed. **\n");
843 ext4fs_indir2_blkno =
844 __le32_to_cpu (ext4fs_indir1_block[rblock / perblock_parent]) << log2_blksz;
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");
853 ext4fs_indir3_size = blksz;
854 ext4fs_indir3_blkno = -1;
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");
866 ext4fs_indir3_size = blksz;
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);
874 printf ("** TI ext2fs read block (indir 2 2) failed. **\n");
877 ext4fs_indir3_blkno =
878 __le32_to_cpu (ext4fs_indir2_block[(rblock / perblock_child)%(blksz/4)]) << log2_blksz;
881 blknr = __le32_to_cpu (ext4fs_indir3_block[rblock % perblock_child]);
884 printf ("ext4fs_read_block %08x\n", blknr);
889 static int ext4fs_read_block (ext2fs_node_t node, int fileblock)
891 struct ext2_data *data = node->data;
892 struct ext2_inode *inode = &node->inode;
894 int blksz = EXT2_BLOCK_SIZE (data);
895 int log2_blksz = LOG2_EXT2_BLOCK_SIZE (data);
898 unsigned int perblock;
899 unsigned int perblock_parent;
900 unsigned int perblock_child;
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;
908 leaf = ext4fs_find_leaf (data, buf,
909 (struct ext4_extent_header *) inode->b.blocks.dir_blocks,
912 printf ("invalid extent \n");
916 ext = (struct ext4_extent *) (leaf + 1);
918 for (i = 0; i < le32_to_cpu (leaf->entries); i++) {
919 if (fileblock < le32_to_cpu (ext[i].block))
924 fileblock -= le32_to_cpu (ext[i].block);
925 if (fileblock >= le32_to_cpu (ext[i].len)) {
930 start = le32_to_cpu (ext[i].start_hi);
931 start = (start << 32) + le32_to_cpu (ext[i].start);
933 return fileblock + start;
936 printf("something wrong with extent \n");
942 if (fileblock < INDIRECT_BLOCKS) {
943 blknr = __le32_to_cpu (inode->b.blocks.dir_blocks[fileblock]);
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");
954 ext4fs_indir1_size = blksz;
955 ext4fs_indir1_blkno = -1;
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");
967 ext4fs_indir1_size = blksz;
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);
974 printf ("** SI ext2fs read block (indir 1) failed. **\n");
977 ext4fs_indir1_blkno = __le32_to_cpu (inode->b.blocks.
978 indir_block) << log2_blksz;
980 blknr = __le32_to_cpu (ext4fs_indir1_block[fileblock - INDIRECT_BLOCKS]);
982 /* Double indirect. */
985 (INDIRECT_BLOCKS + (blksz / 4 * (blksz / 4 + 1)))) {
986 perblock = blksz / 4;
987 rblock = fileblock - (INDIRECT_BLOCKS + blksz / 4);
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");
995 ext4fs_indir1_size = blksz;
996 ext4fs_indir1_blkno = -1;
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");
1008 ext4fs_indir1_size = blksz;
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,
1015 (char *) ext4fs_indir1_block);
1017 printf ("** DI ext2fs read block (indir 2 1) failed. **\n");
1020 ext4fs_indir1_blkno =
1021 __le32_to_cpu (inode->b.blocks.double_indir_block) << log2_blksz;
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");
1030 ext4fs_indir2_size = blksz;
1031 ext4fs_indir2_blkno = -1;
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");
1043 ext4fs_indir2_size = blksz;
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,
1049 (char *) ext4fs_indir2_block);
1051 printf ("** DI ext2fs read block (indir 2 2) failed. **\n");
1054 ext4fs_indir2_blkno =
1055 __le32_to_cpu (ext4fs_indir1_block[rblock / perblock]) << log2_blksz;
1057 blknr = __le32_to_cpu (ext4fs_indir2_block[rblock % perblock]);
1059 /* Tripple indirect. */
1061 rblock = fileblock - (INDIRECT_BLOCKS + blksz / 4 + (blksz / 4 * blksz / 4));
1062 perblock_child = blksz / 4;
1063 perblock_parent = ((blksz / 4) * (blksz / 4));
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");
1071 ext4fs_indir1_size = blksz;
1072 ext4fs_indir1_blkno = -1;
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");
1084 ext4fs_indir1_size = blksz;
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,
1091 (char *) ext4fs_indir1_block);
1093 printf ("** TI ext2fs read block (indir 2 1) failed. **\n");
1096 ext4fs_indir1_blkno =
1097 __le32_to_cpu (inode->b.blocks.tripple_indir_block) << log2_blksz;
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");
1106 ext4fs_indir2_size = blksz;
1107 ext4fs_indir2_blkno = -1;
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");
1119 ext4fs_indir2_size = blksz;
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);
1126 printf ("** TI ext2fs read block (indir 2 2) failed. **\n");
1129 ext4fs_indir2_blkno =
1130 __le32_to_cpu (ext4fs_indir1_block[rblock / perblock_parent]) << log2_blksz;
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");
1139 ext4fs_indir3_size = blksz;
1140 ext4fs_indir3_blkno = -1;
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");
1152 ext4fs_indir3_size = blksz;
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);
1159 printf ("** TI ext2fs read block (indir 2 2) failed. **\n");
1162 ext4fs_indir3_blkno =
1163 __le32_to_cpu (ext4fs_indir2_block[(rblock / perblock_child)%(blksz/4)]) << log2_blksz;
1166 blknr = __le32_to_cpu (ext4fs_indir3_block[rblock % perblock_child]);
1169 printf ("ext4fs_read_block %08x\n", blknr);
1174 int ext4fs_read_file
1175 (ext2fs_node_t node, int pos, unsigned int len, char *buf) {
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;
1190 /* Adjust len so it we can't read past the end of the file. */
1194 blockcnt = ((len + pos) + blocksize - 1) / blocksize;
1196 for (i = pos / blocksize; i < blockcnt; i++) {
1198 int blockoff = pos % blocksize;
1199 int blockend = blocksize;
1201 blknr = ext4fs_read_block (node, i);
1205 blknr = blknr << log2blocksize;
1208 if (i == blockcnt - 1) {
1209 blockend = (len + pos) % blocksize;
1211 /* The last portion is exactly blocksize. */
1213 blockend = blocksize;
1217 if (i == pos / blocksize) {
1218 skipfirst = blockoff;
1219 blockend -= skipfirst;
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,
1234 previous_block_number = blknr;
1235 delayed_start = blknr;
1236 delayed_extent = blockend;
1237 delayed_skipfirst = skipfirst;
1239 delayed_next = blknr +
1240 (blockend >> SECTOR_BITS);
1243 previous_block_number = blknr;
1244 delayed_start = blknr;
1245 delayed_extent = blockend;
1246 delayed_skipfirst = skipfirst;
1248 delayed_next = blknr + (blockend >> SECTOR_BITS);
1251 if (previous_block_number != -1) {
1253 status = ext2fs_devread(delayed_start,
1254 delayed_skipfirst, delayed_extent,
1258 previous_block_number = -1;
1260 memset(buf, 0, blocksize - skipfirst);
1262 buf += blocksize - skipfirst;
1264 if (previous_block_number != -1) {
1266 status = ext2fs_devread(delayed_start,
1267 delayed_skipfirst, delayed_extent, delayed_buf);
1270 previous_block_number = -1;
1275 int ext4fs_write_file
1276 (block_dev_desc_t *dev_desc, struct ext2_inode *file_inode, int pos, unsigned int len, char *buf) {
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;
1288 /* Adjust len so it we can't read past the end of the file. */
1292 blockcnt = ((len + pos) + blocksize - 1) / blocksize;
1294 for (i = pos / blocksize; i < blockcnt; i++) {
1296 int blockend = blocksize;
1298 blknr = ext4fs_read_allocated_block (file_inode, i);
1302 blknr = blknr << log2blocksize;
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;
1316 delayed_next = blknr +
1317 (blockend >> SECTOR_BITS);
1320 previous_block_number = blknr;
1321 delayed_start = blknr;
1322 delayed_extent = blockend;
1324 delayed_next = blknr + (blockend >> SECTOR_BITS);
1327 if (previous_block_number != -1) {
1329 put_ext4(dev_desc,(uint64_t)(delayed_start*SECTOR_SIZE), delayed_buf,
1330 (uint32_t)delayed_extent);
1332 previous_block_number = -1;
1334 memset(buf, 0, blocksize - skipfirst);
1336 buf += blocksize - skipfirst;
1338 if (previous_block_number != -1) {
1340 put_ext4(dev_desc,(uint64_t)(delayed_start*SECTOR_SIZE), delayed_buf, (uint32_t)delayed_extent);
1342 previous_block_number = -1;
1347 static int ext4fs_iterate_dir (ext2fs_node_t dir, char *name, ext2fs_node_t * fnode, int *ftype)
1349 unsigned int fpos = 0;
1351 struct ext2fs_node *diro = (struct ext2fs_node *) dir;
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,
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),
1372 if (dirent.namelen != 0) {
1373 char filename[dirent.namelen + 1];
1374 ext2fs_node_t fdiro;
1375 int type = FILETYPE_UNKNOWN;
1377 status = ext4fs_read_file (diro,
1378 fpos + sizeof (struct ext2_dirent),
1379 dirent.namelen, filename);
1383 fdiro = memalign(ARCH_DMA_MINALIGN, sizeof (struct ext2fs_node));
1388 fdiro->data = diro->data;
1389 fdiro->ino = __le32_to_cpu (dirent.inode);
1391 filename[dirent.namelen] = '\0';
1393 if (dirent.filetype != FILETYPE_UNKNOWN) {
1394 fdiro->inode_read = 0;
1396 if (dirent.filetype == FILETYPE_DIRECTORY) {
1397 type = FILETYPE_DIRECTORY;
1398 } else if (dirent.filetype ==
1400 type = FILETYPE_SYMLINK;
1401 } else if (dirent.filetype == FILETYPE_REG) {
1402 type = FILETYPE_REG;
1405 /* The filetype can not be read from the dirent, get it from inode */
1407 status = ext4fs_read_inode (diro->data,
1408 __le32_to_cpu(dirent.inode),
1414 fdiro->inode_read = 1;
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) ==
1426 type = FILETYPE_REG;
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) {
1440 if (fdiro->inode_read == 0) {
1441 status = ext4fs_read_inode (diro->data,
1442 __le32_to_cpu (dirent.inode),
1448 fdiro->inode_read = 1;
1451 case FILETYPE_DIRECTORY:
1454 case FILETYPE_SYMLINK:
1464 printf ("%10d %s\n",
1465 __le32_to_cpu (fdiro->inode.size),
1470 fpos += __le16_to_cpu (dirent.direntlen);
1475 static char *ext4fs_read_symlink (ext2fs_node_t node)
1478 struct ext2fs_node *diro = node;
1481 if (!diro->inode_read) {
1482 status = ext4fs_read_inode (diro->data, diro->ino,
1487 symlink = memalign(ARCH_DMA_MINALIGN, __le32_to_cpu (diro->inode.size) + 1);
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));
1498 status = ext4fs_read_file (diro, 0,
1499 __le32_to_cpu (diro->inode.size), symlink);
1505 symlink[__le32_to_cpu (diro->inode.size)] = '\0';
1509 int ext4fs_find_file1
1510 (const char *currpath,
1511 ext2fs_node_t currroot, ext2fs_node_t * currfound, int *foundtype)
1513 char fpath[strlen (currpath) + 1];
1517 int type = FILETYPE_DIRECTORY;
1518 ext2fs_node_t currnode = currroot;
1519 ext2fs_node_t oldnode = currroot;
1521 strncpy (fpath, currpath, strlen (currpath) + 1);
1523 /* Remove all leading slashes. */
1524 while (*name == '/') {
1528 *currfound = currnode;
1535 /* Extract the actual part from the pathname. */
1536 next = strchr (name, '/');
1538 /* Remove all leading slashes. */
1539 while (*next == '/') {
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);
1553 /* Iterate over the directory. */
1554 found = ext4fs_iterate_dir (currnode, name, &currnode, &type);
1560 /* Read in the symlink and follow it. */
1561 if (type == FILETYPE_SYMLINK) {
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);
1571 symlink = ext4fs_read_symlink (currnode);
1572 ext4fs_free_node (currnode, currroot);
1575 ext4fs_free_node (oldnode, currroot);
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;
1587 /* Lookup the node the symlink points to. */
1588 status = ext4fs_find_file1 (symlink, oldnode,
1594 ext4fs_free_node (oldnode, currroot);
1599 ext4fs_free_node (oldnode, currroot);
1601 /* Found the node! */
1602 if (!next || *next == '\0') {
1603 *currfound = currnode;
1612 int ext4fs_find_file
1614 ext2fs_node_t rootnode, ext2fs_node_t * foundnode, int expecttype)
1617 int foundtype = FILETYPE_DIRECTORY;
1619 ext4fs_symlinknest = 0;
1623 status = ext4fs_find_file1 (path, rootnode, foundnode, &foundtype);
1627 /* Check if the node that was found was of the expected type. */
1628 if ((expecttype == FILETYPE_REG) && (foundtype != expecttype)) {
1630 } else if ((expecttype == FILETYPE_DIRECTORY)
1631 && (foundtype != expecttype)) {
1637 int ext4fs_get_inode_no_from_inodebitmap(unsigned char *buffer)
1640 unsigned char input;
1645 /*get the blocksize of the filesystem*/
1646 unsigned char *ptr=buffer;
1651 if(count>(uint32_t)ext4fs_root->sblock.inodes_per_group)
1655 for(j=0;j<blocksize;j++)
1662 status = input & operand;
1679 int ext4fs_get_block_no_from_blockbitmap(unsigned char *buffer)
1682 unsigned char input;
1688 /*get the blocksize of the filesystem*/
1689 blocksize=EXT2_BLOCK_SIZE(ext4fs_root);
1690 unsigned char *ptr=buffer;
1700 if(count==(blocksize *8))
1704 for(j=0;j<blocksize;j++)
1711 status = input & operand;
1728 int ext4fs_update_bmap_with_one(unsigned long blockno, unsigned char * buffer, int index)
1731 unsigned int remainder;
1732 unsigned char *ptr=buffer;
1733 unsigned char operand;
1737 remainder=blockno%8;
1739 /*get the blocksize of the filesystem*/
1740 blocksize=EXT2_BLOCK_SIZE(ext4fs_root);
1741 i=i-(index * blocksize);
1745 operand=1<<remainder;
1746 status=*ptr & operand;
1767 operand=(1<<(remainder-1));
1769 status=*ptr & operand;
1782 int ext4fs_update_bmap_with_zero(unsigned long blockno, unsigned char * buffer, int index)
1785 unsigned int remainder;
1786 unsigned char *ptr=buffer;
1787 unsigned char operand;
1790 remainder=blockno%8;
1793 /*get the blocksize of the filesystem*/
1794 blocksize=EXT2_BLOCK_SIZE(ext4fs_root);
1795 i=i-(index * blocksize);
1799 operand=(1<<remainder);
1800 status=*ptr & operand;
1803 *ptr=*ptr & ~(operand);
1821 operand=(1<<(remainder-1));
1823 status=*ptr & operand;
1826 *ptr=*ptr & ~(operand);
1837 int ext4fs_update_inode_bmap_with_one(unsigned long inode_no, unsigned char * buffer, int index)
1840 unsigned int remainder;
1841 unsigned char *ptr=buffer;
1842 unsigned char operand;
1845 inode_no -= (index * (uint32_t)ext4fs_root->sblock.inodes_per_group);
1848 remainder=inode_no%8;
1857 operand=(1<<(remainder-1));
1859 status=*ptr & operand;
1871 int ext4fs_update_inode_bmap_with_zero(unsigned long inode_no, unsigned char * buffer,int index)
1874 unsigned int remainder;
1875 unsigned char *ptr=buffer;
1876 unsigned char operand;
1879 inode_no -= (index * (uint32_t)ext4fs_root->sblock.inodes_per_group);
1881 remainder=inode_no%8;
1890 operand=(1<<(remainder-1));
1892 status=*ptr & operand;
1895 *ptr=*ptr & ~(operand);
1904 unsigned long ext4fs_get_next_available_block_no(block_dev_desc_t *dev_desc,int part_no)
1909 int sector_per_block;
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;
1916 /*get the blocksize of the filesystem*/
1917 blocksize=EXT2_BLOCK_SIZE(ext4fs_root);
1919 /*calucalate sector per block*/
1920 sector_per_block=blocksize/SECTOR_SIZE;
1921 struct ext2_block_group *gd=(struct ext2_block_group*)gd_table;
1923 if(first_execution==0)
1925 for(i=0;i<no_blockgroup;i++)
1927 if(gd[i].free_blocks)
1930 printf("Block group reading is %d\n",i);
1932 if(gd[i].bg_flags & EXT4_BG_BLOCK_UNINIT)
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);
1946 blockno=ext4fs_get_block_no_from_blockbitmap(bg[i]);
1947 if(blockno==-1) /*if block bitmap is completely fill*/
1951 blockno=blockno +(i*blocksize*8);
1953 printf("every first block no getting is %d\n",blockno);
1956 gd[i].free_blocks--;
1959 journal_buffer = (unsigned char *)xzalloc(blocksize);
1960 status = ext2fs_devread (gd[i].block_id*sector_per_block, 0, blocksize,journal_buffer);
1962 free(journal_buffer);
1965 log_journal(journal_buffer,gd[i].block_id);
1966 free(journal_buffer);
1972 printf("no space left on the block group %d \n",i);
1982 /*get the blockbitmap index respective to blockno */
1985 bg_bitmap_index=blockno/(uint32_t)ext4fs_root->sblock.blocks_per_group;
1989 bg_bitmap_index=blockno/(uint32_t)ext4fs_root->sblock.blocks_per_group;
1990 remainder = blockno%(uint32_t)ext4fs_root->sblock.blocks_per_group;
1995 /*To skip completely filled block group bitmaps : Optimize the block allocation*/
1996 if(bg_bitmap_index >= no_blockgroup)
1999 if(gd[bg_bitmap_index].free_blocks==0)
2002 printf("block group %d is full. Skipping\n",bg_bitmap_index);
2004 blockno= blockno + ext4fs_root->sblock.blocks_per_group;
2009 if(gd[bg_bitmap_index].bg_flags & EXT4_BG_BLOCK_UNINIT)
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;
2023 if(ext4fs_update_bmap_with_one(blockno,bg[bg_bitmap_index],bg_bitmap_index)!=0)
2026 printf("going for restart for the block no %u %d\n",blockno,bg_bitmap_index);
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);
2037 free(journal_buffer);
2040 log_journal(journal_buffer,gd[bg_bitmap_index].block_id);
2041 prev_bg_bitmap_index = bg_bitmap_index;
2042 free(journal_buffer);
2044 gd[bg_bitmap_index].free_blocks--;
2050 unsigned long ext4fs_get_next_available_inode_no(block_dev_desc_t *dev_desc,int part_no)
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;
2059 struct ext2_block_group *gd=(struct ext2_block_group*)gd_table;
2061 if(first_execution_inode==0)
2063 for(i=0;i<no_blockgroup;i++)
2065 if(gd[i].free_inodes)
2068 printf("Block group reading is %d\n",i);
2070 if (gd[i].bg_itable_unused !=
2072 gd[i].bg_itable_unused =
2074 if(gd[i].bg_flags & EXT4_BG_INODE_UNINIT)
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);
2087 inode_no=ext4fs_get_inode_no_from_inodebitmap(inode_bmaps[i]);
2088 if(inode_no==-1) /*if block bitmap is completely fill*/
2092 inode_no=inode_no +(i*ext4fs_root->sblock.inodes_per_group);
2094 printf("every first inode no getting is %d\n",inode_no);
2096 first_execution_inode++;
2097 gd[i].free_inodes--;
2098 gd[i].bg_itable_unused--;
2101 journal_buffer = (unsigned char *)xzalloc(blocksize);
2102 status = ext2fs_devread (gd[i].inode_id*sector_per_block, 0, blocksize,journal_buffer);
2105 free(journal_buffer);
2108 log_journal(journal_buffer,gd[i].inode_id);
2109 free(journal_buffer);
2115 printf("no inode left on the block group %d \n",i);
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)
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);
2141 if(ext4fs_update_inode_bmap_with_one(inode_no,inode_bmaps[inode_bitmap_index],inode_bitmap_index)!=0)
2144 printf("going for restart for the block no %u %d\n",inode_no,inode_bitmap_index);
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);
2155 free(journal_buffer);
2158 log_journal(journal_buffer,gd[inode_bitmap_index].inode_id);
2159 prev_inode_bitmap_index = inode_bitmap_index;
2160 free(journal_buffer);
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--;
2173 int ext4fs_existing_filename_check(block_dev_desc_t *dev_desc,char *filename)
2175 unsigned int direct_blk_idx=0;
2176 unsigned int blknr=-1;
2179 /*read the block no allocated to a file*/
2180 for(direct_blk_idx=0;direct_blk_idx<INDIRECT_BLOCKS;direct_blk_idx++)
2182 blknr=ext4fs_read_allocated_block(g_parent_inode, direct_blk_idx);
2187 inodeno= ext4fs_if_filename_exists_in_root(dev_desc,filename,blknr);
2196 int ext4fs_if_filename_exists_in_root(block_dev_desc_t *dev_desc,char *filename, unsigned int blknr)
2198 unsigned char *root_first_block_buffer;
2199 unsigned char *root_first_block_addr;
2200 unsigned int first_block_no_of_root;
2202 int sector_per_block;
2203 struct ext2_dirent *dir = NULL;
2204 struct ext2_dirent *previous_dir = NULL;
2212 /*get the blocksize of the filesystem*/
2213 blocksize=EXT2_BLOCK_SIZE(ext4fs_root);
2215 /*get the first block of root*/
2216 first_block_no_of_root=blknr;
2218 /*calucalate sector per block*/
2219 sector_per_block=blocksize/SECTOR_SIZE;
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);
2232 dir=(struct ext2_dirent *) root_first_block_buffer;
2233 ptr=(unsigned char*)dir;
2235 while(dir->direntlen>=0)
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
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");
2251 if(strlen(filename)==dir->namelen)
2253 if(strncmp(filename,ptr+sizeof(struct ext2_dirent),dir->namelen)==0)
2255 printf("file found deleting\n");
2256 previous_dir->direntlen+=dir->direntlen;
2258 memset(ptr+sizeof(struct ext2_dirent),'\0',dir->namelen);
2265 if(blocksize-totalbytes==dir->direntlen)
2269 /*traversing the each directory entry*/
2270 templength=dir->direntlen;
2271 totalbytes=totalbytes+templength;
2273 dir=(unsigned char*)dir;
2274 dir=(unsigned char*)dir+templength;
2275 dir=(struct ext2_dirent*)dir;
2282 put_metadata(root_first_block_addr,first_block_no_of_root);
2283 if(root_first_block_addr)
2284 free(root_first_block_addr);
2293 if(root_first_block_addr)
2294 free(root_first_block_addr);
2298 int ext4fs_delete_file(block_dev_desc_t *dev_desc, unsigned int inodeno)
2300 struct ext2_data *diro=ext4fs_root;
2301 struct ext2_inode inode;
2305 int sector_per_block;
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;
2321 static int prev_bg_bitmap_index = -1;
2322 unsigned char *journal_buffer=NULL;
2323 unsigned int inodes_per_block;
2325 unsigned int blkoff;
2326 struct ext2_inode *inode_buffer;
2328 /*get the block group descriptor table*/
2329 gd=(struct ext2_block_group*)gd_table;
2330 status = ext4fs_read_inode (diro,inodeno,&inode);
2336 /*calucalate sector per block*/
2337 sector_per_block=blocksize/SECTOR_SIZE;
2339 /*read the block no allocated to a file*/
2340 no_blocks= inode.size/blocksize;
2341 if(inode.size%blocksize)
2344 if (le32_to_cpu(inode.flags) & EXT4_EXTENTS_FLAG)
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));
2352 for(i=0;i<no_blocks;i++)
2354 blknr=ext4fs_read_block(node_inode, i);
2357 bg_bitmap_index=blknr/(uint32_t)ext4fs_root->sblock.blocks_per_group;
2361 bg_bitmap_index=blknr/(uint32_t)ext4fs_root->sblock.blocks_per_group;
2362 remainder = blknr%(uint32_t)ext4fs_root->sblock.blocks_per_group;
2366 ext4fs_update_bmap_with_zero(blknr,bg[bg_bitmap_index],bg_bitmap_index);
2368 printf("EXT4_EXTENTS Block releasing %u: %d\n",blknr,bg_bitmap_index);
2370 gd[bg_bitmap_index].free_blocks++;
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);
2379 free(journal_buffer);
2382 log_journal(journal_buffer,gd[bg_bitmap_index].block_id);
2383 prev_bg_bitmap_index = bg_bitmap_index;
2384 free(journal_buffer);
2395 /*deleting the single indirect block associated with inode*/
2396 if(inode.b.blocks.indir_block!=0)
2399 printf("SIPB releasing %d\n",inode.b.blocks.indir_block);
2401 blknr=inode.b.blocks.indir_block;
2404 bg_bitmap_index=blknr/(uint32_t)ext4fs_root->sblock.blocks_per_group;
2408 bg_bitmap_index=blknr/(uint32_t)ext4fs_root->sblock.blocks_per_group;
2409 remainder = blknr%(uint32_t)ext4fs_root->sblock.blocks_per_group;
2413 ext4fs_update_bmap_with_zero(blknr,bg[bg_bitmap_index],bg_bitmap_index);
2414 gd[bg_bitmap_index].free_blocks++;
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);
2422 free(journal_buffer);
2425 log_journal(journal_buffer,gd[bg_bitmap_index].block_id);
2426 prev_bg_bitmap_index = bg_bitmap_index;
2427 free(journal_buffer);
2431 /*deleting the double indirect blocks */
2432 if(inode.b.blocks.double_indir_block!=0)
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++)
2441 if(*double_indirect_buffer==0)
2444 printf("DICB releasing %d\n",*double_indirect_buffer);
2448 bg_bitmap_index=(*double_indirect_buffer)/(uint32_t)ext4fs_root->sblock.blocks_per_group;
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;
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++;
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);
2467 free(journal_buffer);
2470 log_journal(journal_buffer,gd[bg_bitmap_index].block_id);
2471 prev_bg_bitmap_index = bg_bitmap_index;
2472 free(journal_buffer);
2476 /*removing the parent double indirect block*/
2477 /*find the bitmap index*/
2478 blknr=inode.b.blocks.double_indir_block;
2481 bg_bitmap_index=blknr/(uint32_t)ext4fs_root->sblock.blocks_per_group;
2485 bg_bitmap_index=blknr/(uint32_t)ext4fs_root->sblock.blocks_per_group;
2486 remainder = blknr%(uint32_t)ext4fs_root->sblock.blocks_per_group;
2490 ext4fs_update_bmap_with_zero(blknr,bg[bg_bitmap_index],bg_bitmap_index);
2491 gd[bg_bitmap_index].free_blocks++;
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);
2499 free(journal_buffer);
2502 log_journal(journal_buffer,gd[bg_bitmap_index].block_id);
2503 prev_bg_bitmap_index = bg_bitmap_index;
2504 free(journal_buffer);
2507 printf("DIPB releasing %d\n",blknr);
2510 free(DIB_start_addr);
2513 /*deleting the triple indirect blocks */
2514 if(inode.b.blocks.tripple_indir_block!=0)
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++)
2523 if(*triple_indirect_grand_parent_buffer==0)
2526 printf("TIGPB releasing %d\n",*triple_indirect_grand_parent_buffer);
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++)
2534 if(*triple_indirect_parent_buffer==0)
2539 bg_bitmap_index=(*triple_indirect_parent_buffer)/
2540 (uint32_t)ext4fs_root->sblock.blocks_per_group;
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;
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++;
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);
2563 free(journal_buffer);
2566 log_journal(journal_buffer,gd[bg_bitmap_index].block_id);
2567 prev_bg_bitmap_index = bg_bitmap_index;
2568 free(journal_buffer);
2572 free(TIPB_start_addr);
2574 /*removing the grand parent blocks which is connected to inode*/
2577 bg_bitmap_index=(*triple_indirect_grand_parent_buffer)/
2578 (uint32_t)ext4fs_root->sblock.blocks_per_group;
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;
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++;
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);
2600 free(journal_buffer);
2603 log_journal(journal_buffer,gd[bg_bitmap_index].block_id);
2604 prev_bg_bitmap_index = bg_bitmap_index;
2605 free(journal_buffer);
2609 /*removing the grand parent triple indirect block*/
2610 /*find the bitmap index*/
2611 blknr=inode.b.blocks.tripple_indir_block;
2614 bg_bitmap_index=blknr/(uint32_t)ext4fs_root->sblock.blocks_per_group;
2618 bg_bitmap_index=blknr/(uint32_t)ext4fs_root->sblock.blocks_per_group;
2619 remainder = blknr%(uint32_t)ext4fs_root->sblock.blocks_per_group;
2623 ext4fs_update_bmap_with_zero(blknr,bg[bg_bitmap_index],bg_bitmap_index);
2624 gd[bg_bitmap_index].free_blocks++;
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);
2632 free(journal_buffer);
2635 log_journal(journal_buffer,gd[bg_bitmap_index].block_id);
2636 prev_bg_bitmap_index = bg_bitmap_index;
2637 free(journal_buffer);
2640 printf("TIGPB iteself releasing %d\n",blknr);
2643 free(TIB_start_addr);
2646 /*read the block no allocated to a file*/
2647 no_blocks= inode.size/blocksize;
2648 if(inode.size%blocksize)
2650 for(i=0;i<no_blocks;i++)
2652 blknr = ext4fs_read_allocated_block(&inode, i);
2655 bg_bitmap_index=blknr/(uint32_t)ext4fs_root->sblock.blocks_per_group;
2659 bg_bitmap_index=blknr/(uint32_t)ext4fs_root->sblock.blocks_per_group;
2660 remainder = blknr%(uint32_t)ext4fs_root->sblock.blocks_per_group;
2664 ext4fs_update_bmap_with_zero(blknr,bg[bg_bitmap_index],bg_bitmap_index);
2666 printf("ActualB releasing %d: %d\n",blknr,bg_bitmap_index);
2668 gd[bg_bitmap_index].free_blocks++;
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);
2676 free(journal_buffer);
2679 log_journal(journal_buffer,gd[bg_bitmap_index].block_id);
2680 prev_bg_bitmap_index = bg_bitmap_index;
2681 free(journal_buffer);
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;
2690 /*get the block no*/
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;
2695 /*get the offset of the inode*/
2696 blkoff = ((inodeno) % inodes_per_block) * inode_size;
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);
2705 log_journal(read_buffer,blkno);
2707 read_buffer = read_buffer+blkoff;
2708 inode_buffer = (struct ext2_inode*)read_buffer;
2709 memset(inode_buffer,'\0',sizeof(struct ext2_inode));
2711 /*write the inode to original position in inode table*/
2712 put_metadata(start_block_address,blkno);
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++;
2720 journal_buffer = (unsigned char *)xzalloc(blocksize);
2721 status = ext2fs_devread (gd[inode_bitmap_index].inode_id*sector_per_block, 0, blocksize,journal_buffer);
2723 free(journal_buffer);
2726 log_journal(journal_buffer,gd[inode_bitmap_index].inode_id);
2727 free(journal_buffer);
2729 ext4fs_update(dev_desc);
2730 ext4fs_deinit(dev_desc);
2732 if(ext4fs_init(dev_desc) != 0) {
2733 printf("error in File System init\n");
2738 if(start_block_address)
2739 free(start_block_address);
2744 free(DIB_start_addr);
2745 if(start_block_address)
2746 free(start_block_address);
2750 int ext4fs_get_bgdtable(void )
2753 int sector_per_block;
2756 unsigned char *temp;
2757 unsigned int var = gd_table_block_no;
2759 /*get the blocksize of the filesystem*/
2760 blocksize=EXT2_BLOCK_SIZE(ext4fs_root);
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++;
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);
2776 /*allocate mem for gdtable*/
2777 gd_table= (char *)xzalloc(blocksize * no_blk_req_per_gdt);
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);
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);
2791 journal_ptr[gindex++]->blknr = var++;
2803 void ext4fs_deinit(block_dev_desc_t *dev_desc)
2806 struct ext2_inode inode_journal;
2807 journal_superblock_t *jsb;
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;
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);
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);
2834 for(i=0;i<no_blockgroup;i++) {
2845 for(i=0;i<no_blockgroup;i++) {
2846 if(inode_bmaps[i]) {
2847 free(inode_bmaps[i]);
2848 inode_bmaps[i]=NULL;
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;
2872 /* Reinitiliazed the global inode and block bitmap first execution check variables */
2873 first_execution_inode = 0;
2874 first_execution = 0;
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
2884 void log_journal(char *journal_buffer,unsigned int blknr)
2887 for(i =0;i < MAX_JOURNAL_ENTRIES; i++) {
2888 if(journal_ptr[i]->blknr == -1)
2890 if(journal_ptr[i]->blknr == blknr)
2895 journal_ptr[gindex]->buf = (char *)xzalloc(blocksize);
2896 if(!journal_ptr[gindex]->buf)
2898 memcpy(journal_ptr[gindex]->buf,journal_buffer,blocksize);
2899 journal_ptr[gindex++]->blknr = blknr;
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
2906 void put_metadata(char *metadata_buffer,unsigned int blknr)
2908 if(!metadata_buffer)
2910 dirty_block_ptr[gd_index]->buf = (char *)xzalloc(blocksize);
2911 if(!dirty_block_ptr[gd_index]->buf)
2913 memcpy(dirty_block_ptr[gd_index]->buf,metadata_buffer,blocksize);
2914 dirty_block_ptr[gd_index++]->blknr = blknr;
2917 /*------------------------------------*/
2918 /*Revoke block handling functions*/
2920 typedef struct journal_revoke_header_s
2922 journal_header_t r_header;
2923 int r_count; /* Count of bytes used in the block */
2924 } journal_revoke_header_t;
2926 typedef struct _revoke_blk_list
2928 char *content;/*revoke block itself*/
2929 struct _revoke_blk_list *next;
2934 revoke_blk_list *revk_blk_list=NULL;
2935 revoke_blk_list *prev_node=NULL;
2936 static int first_node=TRUE;
2941 void print_revoke_blks(char *revk_blk)
2943 journal_revoke_header_t *header;
2945 unsigned int blocknr;
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);
2956 while (offset < max) {
2957 blocknr = be_le(*((unsigned int*)(revk_blk+offset)));
2958 printf("revoke blknr is %u\n",blocknr);
2963 static revoke_blk_list *
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) {
2972 tmp_node->content=NULL;
2973 tmp_node->next=NULL;
2979 push_revoke_blk (char * buffer)
2981 revoke_blk_list *node;
2984 printf("buffer ptr is NULL\n");
2989 if(!(node=_get_node())){
2990 printf("_get_node: malloc failed\n");
2995 node->content = (char*) memalign(ARCH_DMA_MINALIGN, blocksize);
2996 memcpy(node->content,buffer,blocksize);
2998 if(first_node==TRUE) {
3001 first_node=FALSE; /*not enter again*/
3004 prev_node->next=node;
3013 revoke_blk_list *tmp_node=revk_blk_list;
3014 revoke_blk_list *next_node=NULL;
3016 while(tmp_node !=NULL) {
3017 if (tmp_node->content)
3018 free(tmp_node->content);
3019 tmp_node=tmp_node->next;
3022 tmp_node=revk_blk_list;
3023 while(tmp_node !=NULL) {
3024 next_node=tmp_node->next;
3035 int check_blknr_for_revoke(unsigned int blknr,int sequence_no)
3037 journal_revoke_header_t *header;
3039 unsigned int blocknr;
3041 revoke_blk_list *tmp_revk_node=revk_blk_list;
3042 while (tmp_revk_node!=NULL) {
3043 revk_blk=tmp_revk_node->content;
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);
3051 while (offset < max) {
3052 blocknr = be_le(*((unsigned int*)(revk_blk+offset)));
3060 tmp_revk_node=tmp_revk_node->next;
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
3073 void recover_transaction(block_dev_desc_t *dev_desc,int prev_desc_logical_no)
3075 struct ext2_inode inode_journal;
3076 journal_header_t *jdb;
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);
3093 tag = (struct ext3_journal_block_tag *)&p_jdb[ofs];
3094 ofs += sizeof (struct ext3_journal_block_tag);
3096 if (ofs > blocksize)
3099 flags = be_le (tag->flags);
3100 if (! (flags & EXT3_JOURNAL_FLAG_SAME_UUID))
3105 printf("\t\ttag %u\n",be_le(tag->block));
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));
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);
3119 while (! (flags & EXT3_JOURNAL_FLAG_LAST_TAG));
3123 free(metadata_buff);
3127 int print_jrnl_status(int recovery_flag)
3130 *if this function is called scanning/recovery
3131 *of journal must be stoped.
3133 if(recovery_flag==RECOVER) {
3134 printf("Journal Recovery Completed\n");
3137 printf("Journal Scan Completed\n");
3143 int check_journal_state(block_dev_desc_t *dev_desc,int recovery_flag)
3145 struct ext2_inode inode_journal;
3146 journal_superblock_t *jsb;
3147 journal_header_t *jdb;
3152 char *temp_buff = (char *)xzalloc(blocksize);
3153 char *temp_buff1 = (char *)xzalloc(blocksize);
3155 int transaction_state=TRANSACTION_COMPLETE;
3156 int prev_desc_logical_no =0;
3157 int curr_desc_logical_no =0;
3160 struct ext3_journal_block_tag *tag;
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;
3167 if(sb->feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) {
3168 if(recovery_flag==RECOVER)
3169 printf("umount didn't happened :recovery required \n");
3172 if(recovery_flag==RECOVER)
3173 printf("File System is consistent \n");
3177 if(be_le(jsb->s_start)==0){
3181 if(jsb->s_feature_compat & le_be(JBD2_FEATURE_COMPAT_CHECKSUM)){
3182 //printf("checksum set journal \n");
3185 jsb->s_feature_compat |= le_be(JBD2_FEATURE_COMPAT_CHECKSUM);
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 )
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");
3208 i = be_le(jsb->s_first);
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;
3215 if(be_le(jdb->h_blocktype)==EXT3_JOURNAL_DESCRIPTOR_BLOCK)/*descriptor block*/
3218 printf("Descriptor block \n");
3220 if(be_le(jdb->h_sequence)!=be_le(jsb->s_sequence)){
3221 print_jrnl_status(recovery_flag);
3225 curr_desc_logical_no = i;
3226 if(transaction_state==TRANSACTION_COMPLETE)
3227 transaction_state=TRANSACTION_RUNNING;
3229 //printf("recovery required\n");
3232 p_jdb=(char *)temp_buff1;
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));
3238 ofs = sizeof(journal_header_t);
3240 tag = (struct ext3_journal_block_tag *)&p_jdb[ofs];
3241 ofs += sizeof (struct ext3_journal_block_tag);
3243 if (ofs > blocksize)
3246 flags = be_le (tag->flags);
3247 if (! (flags & EXT3_JOURNAL_FLAG_SAME_UUID))
3252 printf("\t\ttag %u\n",be_le(tag->block));
3255 while (! (flags & EXT3_JOURNAL_FLAG_LAST_TAG));
3259 else if(be_le(jdb->h_blocktype)==EXT3_JOURNAL_COMMIT_BLOCK){
3261 printf("Commit block\n");
3263 if ((be_le(jdb->h_sequence) !=
3264 be_le(jsb->s_sequence))) {
3265 print_jrnl_status(recovery_flag);
3269 if ((transaction_state ==
3270 TRANSACTION_RUNNING) ||
3272 transaction_state=TRANSACTION_COMPLETE;
3274 jsb->s_sequence = le_be(be_le(jsb->s_sequence)+1);
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");
3282 prev_desc_logical_no = curr_desc_logical_no;
3283 if ((recovery_flag == RECOVER) &&
3285 recover_transaction(dev_desc,prev_desc_logical_no);
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);
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");
3299 if(recovery_flag==SCAN) {
3300 push_revoke_blk(jdb);
3306 printf("Else Case \n");
3308 if(be_le(jdb->h_sequence)!=be_le(jsb->s_sequence)) {
3309 print_jrnl_status(recovery_flag);
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;
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);
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);
3345 int ext4fs_init(block_dev_desc_t *dev_desc )
3350 unsigned int real_free_blocks=0;
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;
3357 /*get the superblock*/
3358 sb=(struct ext2_sblock *)xzalloc(SUPERBLOCK_SIZE);
3359 status = ext2fs_devread (SUPERBLOCK_SECTOR, 0, SUPERBLOCK_SIZE, sb);
3365 for(i=0; i< MAX_JOURNAL_ENTRIES; i++){
3366 journal_ptr[i] = (struct journal_log *)xzalloc(sizeof(struct journal_log));
3369 dirty_block_ptr[i] = (struct journal_log *)xzalloc(sizeof(struct dirty_blocks));
3370 if(!dirty_block_ptr[i])
3372 journal_ptr[i]->buf = NULL;
3373 journal_ptr[i]->blknr = -1;
3375 dirty_block_ptr[i]->buf = NULL;
3376 dirty_block_ptr[i]->blknr = -1;
3379 if(blocksize == 4096) {
3380 temp = (char *)xzalloc(blocksize);
3383 journal_ptr[gindex]->buf = (char *)xzalloc(blocksize);
3384 if(!journal_ptr[gindex]->buf)
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;
3393 journal_ptr[gindex]->buf = (char *)xzalloc(blocksize);
3394 if(!journal_ptr[gindex]->buf)
3396 memcpy(journal_ptr[gindex]->buf,sb,SUPERBLOCK_SIZE);
3397 journal_ptr[gindex++]->blknr = 1;
3400 if(check_journal_state(dev_desc,SCAN))
3402 /* Check the file system state using journal super block */
3403 if(check_journal_state(dev_desc,RECOVER))
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);
3410 /*get the block group descriptor table*/
3411 gd_table_block_no=((EXT2_MIN_BLOCK_SIZE == blocksize)+1);
3412 if(ext4fs_get_bgdtable()== -1)
3414 printf("***Eror in getting the block group descriptor table\n");
3419 gd=(struct ext2_block_group*)gd_table;
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++)
3427 bg[i]=(unsigned char*)xzalloc(blocksize);
3432 for(i=0;i<no_blockgroup;i++)
3434 status = ext2fs_devread (gd[i].block_id*sector_per_block, 0, blocksize, (unsigned char*)bg[i]);
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++)
3446 inode_bmaps[i]=(unsigned char*)xzalloc(blocksize);
3451 for(i=0;i<no_blockgroup;i++)
3453 status = ext2fs_devread (gd[i].inode_id*sector_per_block, 0, blocksize,
3454 (unsigned char*)inode_bmaps[i]);
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
3466 for(i=0;i<no_blockgroup;i++)
3468 real_free_blocks=real_free_blocks + gd[i].free_blocks;
3470 if(real_free_blocks!=sb->free_blocks)
3472 sb->free_blocks=real_free_blocks;
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");
3488 //ext4fs_dump_the_inode_group_before_writing();
3489 ext4fs_dump_the_block_group_before_writing();
3495 ext4fs_deinit(dev_desc);
3500 #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
3503 int ext4fs_checksum_update(unsigned int i)
3505 struct ext2_block_group *desc;
3508 desc = (struct ext2_block_group *)&gd[i];
3510 if (sb->feature_ro_compat & EXT4_FEATURE_RO_COMPAT_GDT_CSUM) {
3511 int offset = offsetof(struct ext2_block_group, bg_checksum);
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));
3523 int update_descriptor_block(block_dev_desc_t *dev_desc, unsigned int blknr)
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;
3532 char *temp_buff = (char *)xzalloc(blocksize);
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;
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);
3544 memcpy(buf,&jdb, sizeof(journal_header_t));
3545 temp += sizeof(journal_header_t);
3547 for(i =0;i < MAX_JOURNAL_ENTRIES; i++) {
3548 if(journal_ptr[i]->blknr == -1)
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);
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);
3573 int update_commit_block(block_dev_desc_t *dev_desc ,unsigned int blknr)
3575 journal_header_t jdb;
3577 struct ext2_inode inode_journal;
3578 journal_superblock_t *jsb;
3579 unsigned int jsb_blknr;
3580 char *temp_buff = (char *)xzalloc(blocksize);
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;
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);
3605 int update_journal(block_dev_desc_t *dev_desc)
3607 struct ext2_inode inode_journal;
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)
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);
3620 blknr = ext4fs_read_allocated_block (&inode_journal, j_blkindex++);
3621 update_commit_block(dev_desc ,blknr);
3622 printf("update journal finished \n");
3624 free(metadata_buff);
3625 metadata_buff = NULL;
3630 void ext4fs_update(block_dev_desc_t *dev_desc)
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);
3637 /*update the block group*/
3638 for(i=0;i<no_blockgroup;i++)
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);
3644 /*update the inode table group*/
3645 for(i=0;i<no_blockgroup;i++)
3647 put_ext4(dev_desc,(uint64_t)(gd[i].inode_id*blocksize),inode_bmaps[i],(uint32_t)blocksize);
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));
3654 for(i =0;i < MAX_JOURNAL_ENTRIES; i++) {
3655 if(dirty_block_ptr[i]->blknr == -1)
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);
3662 for(i =0;i < MAX_JOURNAL_ENTRIES; i++) {
3663 if(journal_ptr[i]->blknr == -1)
3665 free(journal_ptr[i]->buf);
3668 for(i=0; i< MAX_JOURNAL_ENTRIES; i++){
3669 free(journal_ptr[i]);
3670 free(dirty_block_ptr[i]);
3677 static int check_void_in_dentry(struct ext2_dirent *dir,char *filename)
3679 int dentry_length = 0;
3680 short int padding_factor = 0;
3681 int sizeof_void_space = 0;
3682 int new_entry_byte_reqd = 0;
3684 if(dir->namelen % 4 != 0) {
3685 padding_factor = 4 - (dir->namelen % 4);/*for null storage*/
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) {
3694 if(strlen(filename) % 4 != 0) {
3695 padding_factor = 4 - (strlen(filename) % 4);
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;
3707 int ext4fs_write(block_dev_desc_t *dev_desc, int part_no,char *fname,
3708 unsigned char* buffer,unsigned long sizebytes)
3710 unsigned char *root_first_block_buffer = NULL;
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;
3723 struct ext2_dirent *dir = NULL;
3726 short int padding_factor = 0;
3729 uint64_t total_no_of_bytes_for_file;
3730 unsigned int total_no_of_block_for_file;
3731 unsigned int total_remaining_blocks;
3733 /*final actual data block*/
3734 unsigned int actual_block_no;
3737 unsigned int direct_blockno;
3740 unsigned int *single_indirect_buffer = NULL;
3741 unsigned int single_indirect_blockno;
3742 unsigned int *single_indirect_start_address = NULL;
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;
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;
3763 unsigned int existing_file_inodeno;
3764 unsigned int new_entry_byte_reqd;
3765 unsigned int last_entry_dirlen;
3767 unsigned int root_blknr;
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);
3774 unsigned int previous_blknr = -1;
3775 unsigned int *zero_buffer = NULL;
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));
3788 if(ext4fs_init(dev_desc)!=0)
3790 printf("error in File System init\n");
3793 inodes_per_block = blocksize / inodesize;
3794 parent_inodeno = get_parent_inode_num_write(dev_desc,fname,filename);
3795 if(parent_inodeno==-1) {
3799 if(iget(parent_inodeno,g_parent_inode))
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*/
3806 inodeno = existing_file_inodeno;
3807 ret = ext4fs_delete_file(dev_desc,existing_file_inodeno);
3811 first_execution_inode=0;
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);
3821 if(do_div(total_no_of_bytes_for_file, blocksize) != 0)
3823 total_no_of_block_for_file++;
3825 total_remaining_blocks=total_no_of_block_for_file;
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);
3832 /*Test for available space in partition*/
3833 if(sb->free_blocks < total_no_of_block_for_file)
3835 printf("Not enough space on partition !!!\n");
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
3845 zero_buffer = xzalloc(blocksize);
3848 root_first_block_buffer=memalign(ARCH_DMA_MINALIGN, blocksize);
3851 /*read the block no allocated to a file*/
3852 for(direct_blk_idx=0;direct_blk_idx<INDIRECT_BLOCKS;direct_blk_idx++)
3854 root_blknr=ext4fs_read_allocated_block(g_parent_inode, direct_blk_idx);
3857 first_block_no_of_root=previous_blknr;
3860 previous_blknr=root_blknr;
3863 printf("previous blk no =%u \n",previous_blknr);
3864 printf("first_block_no_of_root =%u \n",first_block_no_of_root);
3867 status = ext2fs_devread (first_block_no_of_root*sector_per_block, 0, blocksize,
3868 (char *)root_first_block_buffer);
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;
3879 while(dir->direntlen>0)
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");
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
3897 /*traversing the each directory entry*/
3898 if(blocksize-totalbytes==dir->direntlen)
3900 if(strlen(filename)%4!=0)
3902 padding_factor=4-(strlen(filename)%4);
3904 new_entry_byte_reqd = strlen(filename) + sizeof(struct ext2_dirent)+padding_factor;
3906 /*update last directory entry length to its length because
3907 *we are creating new directory entry*/
3908 if(dir->namelen%4!=0)
3910 padding_factor=4-(dir->namelen%4);/*for null storage*/
3912 last_entry_dirlen= dir->namelen+sizeof(struct ext2_dirent)+padding_factor;
3913 if((blocksize-totalbytes -last_entry_dirlen) < new_entry_byte_reqd)
3916 printf("Storage capcity of 1st Block over allocating new block\n");
3918 if (direct_blk_idx==INDIRECT_BLOCKS-1)
3920 printf("Directory capacity exceeds the limit\n");
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)
3927 printf("no block left to assign\n");
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);
3937 dir->direntlen=last_entry_dirlen;
3941 templength=dir->direntlen;
3942 totalbytes=totalbytes+templength;
3943 if(sizeof_void_space = check_void_in_dentry(dir,filename)) {
3946 dir=(unsigned char*)dir;
3947 dir=(unsigned char*)dir+templength;
3948 dir=(struct ext2_dirent*)dir;
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;
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");
3972 /*get the next available inode number*/
3973 inodeno=ext4fs_get_next_available_inode_no(dev_desc,part_no);
3976 printf("no inode left to assign\n");
3980 printf("New Inode Assignment :%d\n",inodeno);
3983 if(sizeof_void_space)
3984 dir->direntlen = sizeof_void_space;
3986 dir->direntlen = blocksize - totalbytes;
3987 dir->namelen=strlen(filename);
3988 dir->filetype=FILETYPE_REG; /*regular file*/
3990 dir=(unsigned char*)dir;
3991 dir=(unsigned char*)dir+sizeof(struct ext2_dirent);
3992 memcpy(dir,filename,strlen(filename));
3994 dir=(struct ext2_dirent*)temp_dir;
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");
4009 /*update or write the 1st block of root inode*/
4010 put_metadata(root_first_block_buffer,first_block_no_of_root);
4012 if(root_first_block_buffer)
4013 free(root_first_block_buffer);
4015 /*############END: Update the root directory entry block of root inode ##############*/
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;
4029 /*----------------------------START:Allocation of Blocks to Inode---------------------------- */
4030 /*allocation of direct blocks*/
4031 for(i=0;i<INDIRECT_BLOCKS;i++)
4033 direct_blockno=ext4fs_get_next_available_block_no(dev_desc,part_no);
4034 if(direct_blockno==-1)
4036 printf("no block left to assign\n");
4039 file_inode->b.blocks.dir_blocks[i]=direct_blockno;
4041 printf("DB %d: %d\n",direct_blockno,total_remaining_blocks);
4043 total_remaining_blocks--;
4044 if(total_remaining_blocks==0)
4048 /*allocation of single indirect blocks*/
4049 if(total_remaining_blocks!=0)
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)
4056 printf("no block left to assign\n");
4059 total_no_of_block_for_file++;
4061 printf("SIPB %d: %d\n",single_indirect_blockno,total_remaining_blocks);
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);
4071 for(i=0;i<(blocksize/sizeof(unsigned int));i++)
4073 actual_block_no=ext4fs_get_next_available_block_no(dev_desc,part_no);
4074 if(actual_block_no==-1)
4076 printf("no block left to assign\n");
4079 *single_indirect_buffer=actual_block_no;
4081 printf("SIAB %d: %d\n",*single_indirect_buffer,total_remaining_blocks);
4083 single_indirect_buffer++;
4084 total_remaining_blocks--;
4085 if(total_remaining_blocks==0)
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);
4097 /*allocation of double indirect blocks*/
4098 if(total_remaining_blocks!=0)
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)
4104 printf("no block left to assign\n");
4107 double_indirect_buffer_parent=xzalloc (blocksize);
4108 if(!double_indirect_buffer_parent)
4111 double_indirect_block_startaddress=double_indirect_buffer_parent;
4112 total_no_of_block_for_file++;
4114 printf("DIPB %d: %d\n",double_indirect_blockno_parent,total_remaining_blocks);
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);
4120 /*START: for each double indirect parent block create one more block*/
4121 for(i=0;i<(blocksize/sizeof(unsigned int));i++)
4123 double_indirect_blockno_child=ext4fs_get_next_available_block_no(dev_desc,part_no);
4124 if(double_indirect_blockno_child==-1)
4126 printf("no block left to assign\n");
4129 double_indirect_buffer_child=xzalloc (blocksize);
4130 if(!double_indirect_buffer_child)
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++;
4138 printf("DICB %d: %d\n",double_indirect_blockno_child,total_remaining_blocks);
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*/
4145 /*filling of actual datablocks for each child*/
4146 for(j=0;j<(blocksize/sizeof(unsigned int));j++)
4148 actual_block_no=ext4fs_get_next_available_block_no(dev_desc,part_no);
4149 if(actual_block_no==-1)
4151 printf("no block left to assign\n");
4154 *double_indirect_buffer_child=actual_block_no;
4156 printf("DIAB %d: %d\n",actual_block_no,total_remaining_blocks);
4158 double_indirect_buffer_child++;
4159 total_remaining_blocks--;
4160 if(total_remaining_blocks==0)
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);
4169 if(total_remaining_blocks==0)
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;
4179 /*Triple Indirection */
4181 /*allocation of triple indirect blocks*/
4182 if(total_remaining_blocks!=0)
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)
4188 printf("no block left to assign\n");
4191 triple_indirect_buffer_grand_parent=xzalloc (blocksize);
4192 if(!triple_indirect_buffer_grand_parent)
4195 triple_indirect_buffer_grand_parent_startaddress=triple_indirect_buffer_grand_parent;
4196 total_no_of_block_for_file++;
4198 printf("TIGPB %d: %d\n",triple_indirect_blockno_grand_parent,total_remaining_blocks);
4201 /* for each 4 byte grand parent entry create one more block*/
4202 for(i=0;i<(blocksize/sizeof(unsigned int));i++)
4204 triple_indirect_blockno_parent=ext4fs_get_next_available_block_no(dev_desc,part_no);
4205 if(triple_indirect_blockno_parent==-1)
4207 printf("no block left to assign\n");
4210 triple_indirect_buffer_parent=xzalloc (blocksize);
4211 if(!triple_indirect_buffer_parent)
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++;
4219 printf("TIPB %d: %d\n",triple_indirect_blockno_parent,total_remaining_blocks);
4221 /*for each 4 byte entry parent create one more block*/
4222 for(j=0;j<(blocksize/sizeof(unsigned int));j++)
4224 triple_indirect_blockno_child=ext4fs_get_next_available_block_no(dev_desc,part_no);
4225 if(triple_indirect_blockno_child==-1)
4227 printf("no block left to assign\n");
4230 triple_indirect_buffer_child=xzalloc (blocksize);
4231 if(!triple_indirect_buffer_child)
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++;
4239 printf("TICB %d: %d\n",triple_indirect_blockno_parent,total_remaining_blocks);
4241 /*filling of actual datablocks for each child*/
4242 for(k=0;k<(blocksize/sizeof(unsigned int));k++)
4244 actual_block_no=ext4fs_get_next_available_block_no(dev_desc,part_no);
4245 if(actual_block_no==-1)
4247 printf("no block left to assign\n");
4250 *triple_indirect_buffer_child=actual_block_no;
4252 printf("TIAB %d: %d\n",actual_block_no,total_remaining_blocks);
4254 triple_indirect_buffer_child++;
4255 total_remaining_blocks--;
4256 if(total_remaining_blocks==0)
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);
4265 if(total_remaining_blocks==0)
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);
4274 if(total_remaining_blocks==0)
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;
4284 /*----------------------------END:Allocation of Blocks to Inode---------------------------- */
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
4292 file_inode->blockcnt= (total_no_of_block_for_file*blocksize)/SECTOR_SIZE;
4294 temp_ptr = (char *)xzalloc(blocksize);
4297 inode_bitmap_index = inodeno/(uint32_t)ext4fs_root->sblock.inodes_per_group;
4299 itable_blkno = __le32_to_cpu (gd[inode_bitmap_index].inode_table_id) +
4300 (inodeno % __le32_to_cpu (sblock->inodes_per_group))
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);
4306 memcpy(temp_ptr + blkoff,inode_buffer,inodesize);
4307 put_metadata(temp_ptr,itable_blkno);
4309 /*Copy the file content into data blocks*/
4310 ext4fs_write_file(dev_desc,file_inode,0,sizebytes,buffer);
4312 //ext4fs_dump_the_inode_group_after_writing();
4313 ext4fs_dump_the_block_group_after_writing();
4315 inode_bitmap_index = parent_inodeno/(uint32_t)ext4fs_root->sblock.inodes_per_group;
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);
4325 memcpy(temp_ptr + blkoff,g_parent_inode,sizeof(struct ext2_inode));
4326 put_metadata(temp_ptr,parent_itable_blkno);
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));
4333 put_metadata(temp_ptr,itable_blkno);
4336 ext4fs_update(dev_desc);
4339 /*print the block no allocated to a file*/
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)
4344 total_no_of_block_for_file++;
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++)
4349 blknr = ext4fs_read_allocated_block (file_inode, i);
4350 printf("Actual Data Blocks Allocated to File: %u\n",blknr);
4353 ext4fs_deinit(dev_desc);
4357 first_execution_inode=0;
4362 free(g_parent_inode);
4363 g_parent_inode=NULL;
4369 ext4fs_deinit(dev_desc);
4375 free(g_parent_inode);
4376 g_parent_inode=NULL;
4381 static int search_dir(block_dev_desc_t *dev_desc,struct ext2_inode *parent_inode,unsigned char *dirname)
4383 unsigned char *block_buffer;
4385 int sector_per_block;
4386 struct ext2_dirent *dir;
4387 struct ext2_dirent *previous_dir = NULL;
4396 unsigned int previous_blknr;
4398 /*get the blocksize of the filesystem*/
4399 blocksize=EXT2_BLOCK_SIZE(ext4fs_root);
4401 /*calucalate sector per block*/
4402 sector_per_block=blocksize/SECTOR_SIZE;
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++)
4408 blknr=ext4fs_read_allocated_block(parent_inode, direct_blk_idx);
4414 /*read the blocks of parenet inode*/
4415 block_buffer=xzalloc (blocksize);
4419 status = ext2fs_devread (blknr*sector_per_block, 0, blocksize,(char *)block_buffer);
4426 dir=(struct ext2_dirent *) block_buffer;
4427 ptr=(unsigned char*)dir;
4429 while(dir->direntlen>=0)
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
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");
4446 if(strlen(dirname)==dir->namelen)
4448 if(strncmp(dirname,ptr+sizeof(struct ext2_dirent),dir->namelen)==0)
4450 previous_dir->direntlen+=dir->direntlen;
4458 if(blocksize-totalbytes==dir->direntlen)
4462 /*traversing the each directory entry*/
4463 templength=dir->direntlen;
4464 totalbytes=totalbytes+templength;
4466 dir=(unsigned char*)dir;
4467 dir=(unsigned char*)dir+templength;
4468 dir=(struct ext2_dirent*)dir;
4476 block_buffer = NULL;
4483 block_buffer = NULL;
4490 block_buffer = NULL;
4495 static int find_dir_depth(char *dirname)
4497 char *token = strtok(dirname, "/");
4499 while(token != NULL) {
4500 token = strtok(NULL,"/");
4506 static int parse_path(char **arr,char *dirname)
4508 char *token = strtok(dirname, "/");
4512 arr[i] = xzalloc(strlen("/")+1);
4518 /*add each path entry after root*/
4519 while(token != NULL) {
4520 arr[i] = xzalloc(strlen(token)+1);
4523 memcpy(arr[i++],token,strlen(token));
4524 token = strtok(NULL,"/");
4532 int iget(unsigned int inode_no,struct ext2_inode* inode)
4534 if( ext4fs_read_inode (ext4fs_root,inode_no,inode)==0)
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
4547 int get_parent_inode_num(block_dev_desc_t *dev_desc,char *dirname, char *dname)
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;
4559 printf("Please supply Absolute path\n");
4563 /*TODO: input validation make equivalent to linux*/
4564 /*get the memory size*/
4565 depth_dirname = (char *)xzalloc(strlen(dirname)+1);
4569 memcpy(depth_dirname,dirname,strlen(dirname));
4570 depth=find_dir_depth(depth_dirname);
4571 parse_dirname = (char *)xzalloc(strlen(dirname)+1);
4574 memcpy(parse_dirname,dirname,strlen(dirname));
4576 /*allocate memory for each directory level*/
4577 ptr=(char**)xzalloc((depth)* sizeof(char *));
4580 parse_path(ptr,parse_dirname);
4581 parent_inode=(struct ext2_inode*)xzalloc(sizeof(struct ext2_inode));
4584 first_inode=(struct ext2_inode*)xzalloc(sizeof(struct ext2_inode));
4587 memcpy(parent_inode,ext4fs_root->inode,sizeof(struct ext2_inode));
4588 memcpy(first_inode, parent_inode, sizeof(struct ext2_inode));
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;
4598 if(ptr[i+1] == NULL)
4600 printf("Invalid path :(mkdir -p) Not Supported\n");
4601 result_inode_no = -1;
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;
4612 result_inode_no=matched_inode_no;
4621 matched_inode_no=search_dir(dev_desc,first_inode,ptr[i]);
4623 matched_inode_no=search_dir(dev_desc,parent_inode,ptr[i]);
4625 if(matched_inode_no != -1) {
4626 printf("file/Directory already present\n");
4630 if(strlen(ptr[i])> 256) {
4631 result_inode_no = -1;
4634 memcpy(dname, ptr[i],strlen(ptr[i]));
4638 free(depth_dirname);
4640 free(parse_dirname);
4648 return result_inode_no;
4651 static int create_dir(block_dev_desc_t *dev_desc, unsigned int parent_inode_num,
4652 struct ext2_inode *parent_inode,char *dirname)
4654 unsigned int direct_blk_idx;
4655 unsigned int parent_blknr;
4656 unsigned int previous_blknr = -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;
4666 struct ext2_dirent *dir = NULL;
4667 struct ext4_dir *dir_entry = NULL;
4671 short int padding_factor = 0;
4672 unsigned int new_entry_byte_reqd;
4673 unsigned int last_entry_dirlen;
4676 unsigned char *ptr = NULL;
4677 struct ext2_dirent *temp_dir = NULL;
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;
4685 struct ext2_inode *file_inode = NULL;
4686 unsigned char *inode_buffer = NULL;
4687 unsigned char *zero_buffer = (unsigned char *)xzalloc(blocksize);
4690 working_block_buffer_for_parent = (unsigned char *)xzalloc(blocksize);
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;
4700 previous_blknr=parent_blknr;
4704 printf("previous blk no =%u \n",previous_blknr);
4705 printf("first_block_no_of_root =%u \n",working_block_no_of_parent);
4708 status = ext2fs_devread (working_block_no_of_parent*sector_per_block, 0, blocksize,
4709 (char *)working_block_buffer_for_parent);
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;
4718 while(dir->direntlen>0) {
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");
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
4734 /*traversing the each directory entry*/
4735 if(blocksize-totalbytes==dir->direntlen)
4737 if(strlen(dirname)%4!=0)
4739 padding_factor=4-(strlen(dirname)%4);
4741 new_entry_byte_reqd = strlen(dirname) + sizeof(struct ext2_dirent)+padding_factor;
4743 /*update last directory entry length to its length because
4744 *we are creating new directory entry*/
4745 if(dir->namelen%4!=0)
4747 padding_factor=4-(dir->namelen%4);/*for null storage*/
4749 last_entry_dirlen= dir->namelen+sizeof(struct ext2_dirent)+padding_factor;
4750 if((blocksize-totalbytes -last_entry_dirlen) < new_entry_byte_reqd)
4753 printf("Storage capcity of 1st Block over allocating new block\n");
4755 if (direct_blk_idx==INDIRECT_BLOCKS-1)
4757 printf("Directory capacity exceeds the limit\n");
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)
4764 printf("no block left to assign\n");
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);
4774 dir->direntlen=last_entry_dirlen;
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;
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;
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");
4806 /*get the next available inode number*/
4807 inodeno=ext4fs_get_next_available_inode_no(dev_desc,partno);
4810 printf("no inode left to assign\n");
4814 printf("New Inode Assignment :%d\n",inodeno);
4817 dir->direntlen=blocksize-totalbytes;
4818 dir->namelen=strlen(dirname);
4819 dir->filetype=FILETYPE_DIRECTORY;
4821 dir=(unsigned char*)dir;
4822 dir=(unsigned char*)dir+sizeof(struct ext2_dirent);
4823 memcpy(dir,dirname,strlen(dirname));
4825 dir=(struct ext2_dirent*)temp_dir;
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");
4839 put_metadata(working_block_buffer_for_parent,working_block_no_of_parent);
4841 /*Increase the Link count and write the parent inode
4842 *journal backup of parent inode block */
4843 temp_ptr = (char *)xzalloc(blocksize);
4846 inode_bitmap_index=parent_inode_num/(uint32_t)ext4fs_root->sblock.inodes_per_group;
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);
4853 log_journal(temp_ptr,parent_itable_blkno);
4855 parent_inode->nlinks++;
4856 memcpy(temp_ptr + blkoff,parent_inode,sizeof(struct ext2_inode));
4857 put_metadata(temp_ptr,parent_itable_blkno);
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++;
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);
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);
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);
4893 put_metadata(temp_ptr,itable_blkno);
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;
4916 if(working_block_buffer_for_parent){
4917 free(working_block_buffer_for_parent);
4918 working_block_buffer_for_parent=NULL;
4928 if(create_dir_status)
4934 int ext4fs_create_dir (block_dev_desc_t *dev_desc, char *dirname)
4936 unsigned int inodeno;
4938 struct ext2_inode parent_inode;
4939 char dname[256] = {0,};
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");
4946 inodeno= get_parent_inode_num(dev_desc,dirname,dname);
4951 if(iget(inodeno,&parent_inode)){
4955 retval = create_dir(dev_desc,inodeno,&parent_inode,dname);
4957 printf("Failed to create directory\n");
4960 ext4fs_update(dev_desc);
4961 printf("Done !!!\n");
4963 ext4fs_deinit(dev_desc);
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)
4970 unsigned int direct_blk_idx;
4971 unsigned int parent_blknr;
4972 unsigned int previous_blknr = -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;
4982 struct ext2_dirent *dir = NULL;
4983 struct ext4_dir *dir_entry = NULL;
4984 struct ext2_dirent *temp_dir = NULL;
4987 short int padding_factor = 0;
4988 unsigned int new_entry_byte_reqd;
4989 unsigned int last_entry_dirlen;
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;
4998 struct ext2_inode *file_inode = NULL;
4999 unsigned char *inode_buffer = NULL;
5000 unsigned int *zero_buffer = (unsigned char *)xzalloc(blocksize);
5003 working_block_buffer_for_parent = (unsigned char *)xzalloc(blocksize);
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;
5013 previous_blknr=parent_blknr;
5017 printf("previous blk no =%u \n",previous_blknr);
5018 printf("first_block_no_of_root =%u \n",working_block_no_of_parent);
5020 status = ext2fs_devread (working_block_no_of_parent*sector_per_block, 0, blocksize,
5021 (char *)working_block_buffer_for_parent);
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;
5030 while(dir->direntlen>0){
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");
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
5046 /*traversing the each directory entry*/
5048 if(blocksize-totalbytes==dir->direntlen)
5050 if(strlen(linkname)%4!=0)
5052 padding_factor=4-(strlen(linkname)%4);
5054 new_entry_byte_reqd = strlen(linkname) + sizeof(struct ext2_dirent)+padding_factor;
5056 /*update last directory entry length to its length because
5057 *we are creating new directory entry*/
5058 if(dir->namelen%4!=0)
5060 padding_factor=4-(dir->namelen%4);/*for null storage*/
5062 last_entry_dirlen= dir->namelen+sizeof(struct ext2_dirent)+padding_factor;
5063 if((blocksize-totalbytes -last_entry_dirlen) < new_entry_byte_reqd)
5066 printf("Storage capacity of 1st Block over allocating new block\n");
5068 if (direct_blk_idx==INDIRECT_BLOCKS-1)
5070 printf("Directory capacity exceeds the limit\n");
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)
5077 printf("no block left to assign\n");
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);
5087 dir->direntlen=last_entry_dirlen;
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;
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;
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");
5118 if(link_type == SOFT_LINK){
5119 /*get the next available inode number*/
5120 inodeno=ext4fs_get_next_available_inode_no(dev_desc,partno);
5123 printf("no inode left to assign\n");
5127 printf("New Inode Assignment :%d\n",inodeno);
5132 dir->inode=src_inodeno;
5134 dir->direntlen=blocksize-totalbytes;
5135 dir->namelen=strlen(linkname);
5136 if(link_type == SOFT_LINK)
5137 dir->filetype=FILETYPE_SYMLINK;
5139 dir->filetype=FILETYPE_REG;
5141 dir=(unsigned char*)dir;
5142 dir=(unsigned char*)dir+sizeof(struct ext2_dirent);
5143 memcpy(dir,linkname,strlen(linkname));
5145 dir=(struct ext2_dirent*)temp_dir;
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");
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);
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));
5177 inode_bitmap_index=inodeno/(uint32_t)ext4fs_root->sblock.inodes_per_group;
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);
5185 memcpy(temp_ptr + blkoff,inode_buffer,inodesize);
5186 put_metadata(temp_ptr,temp_blkno);
5191 if(working_block_buffer_for_parent){
5192 free(working_block_buffer_for_parent);
5193 working_block_buffer_for_parent=NULL;
5203 if(create_dir_status)
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
5216 int get_parent_inode_num_write(block_dev_desc_t *dev_desc,char *dirname, char *dname)
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;
5227 printf("Please supply Absolute path\n");
5231 /*TODO: input validation make equivalent to linux*/
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));
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.
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
5252 ptr = (char**)xzalloc((depth + 2)* sizeof(char *));
5253 parse_path(ptr,parse_dirname);
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));
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;
5269 if(ptr[i+1] == NULL)
5271 printf("Invalid path \n");
5276 if(ptr[i+1] != NULL){
5277 memset(parent_inode,'\0',sizeof(struct ext2_inode));
5278 if(iget(matched_inode_no,parent_inode))
5281 result_inode_no=matched_inode_no;
5289 memcpy(dname, ptr[i],strlen(ptr[i]));
5292 free(depth_dirname);
5294 free(parse_dirname);
5302 return result_inode_no;
5305 int namei(block_dev_desc_t *dev_desc,char *dirname,char *dname)
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;
5317 printf("Please supply Absolute path\n");
5321 /*TODO: input validation make equivalent to linux*/
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));
5330 /*allocate memory for each directory level*/
5331 ptr=(char**)xzalloc((depth)* sizeof(char *));
5332 parse_path(ptr,parse_dirname);
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));
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;
5347 if(ptr[i+1] == NULL)
5349 printf("Invalid Source Path\n");
5354 if(ptr[i+1] != NULL){
5355 memset(parent_inode,'\0',sizeof(struct ext2_inode));
5356 if(iget(matched_inode_no,parent_inode))
5359 result_inode_no=matched_inode_no;
5368 matched_inode_no=search_dir(dev_desc,first_inode,ptr[i]);
5370 matched_inode_no=search_dir(dev_desc,parent_inode,ptr[i]);
5372 if(matched_inode_no != -1) {
5373 result_inode_no=matched_inode_no;
5376 result_inode_no = -1;
5377 memcpy(dname, ptr[i],strlen(ptr[i]));
5380 free(depth_dirname);
5382 free(parse_dirname);
5390 return result_inode_no;
5393 int ext4fs_create_symlink (block_dev_desc_t *dev_desc, int link_type,char *src_path, char *target_path)
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,};
5403 struct ext2_sblock *sblock = &(ext4fs_root->sblock);
5404 unsigned int inodes_per_block;
5405 unsigned int temp_blkno, blkoff;
5408 /*get the blocksize inode sector per block of the filesystem*/
5409 if(ext4fs_init(dev_desc)!=0)
5411 printf("error in File System init\n");
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) {
5420 if(iget(target_parent_inodeno,&target_parent_inode)){
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");
5431 if(iget(src_inodeno,&src_inode)){
5435 ptr = (char *)xzalloc(blocksize);
5440 inode_bitmap_index=src_inodeno/(uint32_t)ext4fs_root->sblock.inodes_per_group;
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);
5450 if(src_inode.mode & S_IFDIR){
5451 printf("Hard Link not allowed for a directory \n");
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;
5461 retval = create_symlink(dev_desc,link_type,src_inodeno,target_parent_inodeno,&target_parent_inode,
5462 src_path,dname_target);
5464 printf("Failed to create Link\n");
5469 if(link_type==HARD_LINK){
5470 ptr = (char *)xzalloc(blocksize);
5475 inode_bitmap_index=src_inodeno/(uint32_t)ext4fs_root->sblock.inodes_per_group;
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);
5486 ext4fs_update(dev_desc);
5487 printf("Done !!!\n");
5489 ext4fs_deinit(dev_desc);
5493 int ext4fs_ls (const char *dirname)
5495 ext2fs_node_t dirnode;
5501 status = ext4fs_find_file (dirname, &ext4fs_root->diropen, &dirnode,
5502 FILETYPE_DIRECTORY);
5504 printf ("** Can not find directory. **\n");
5508 ext4fs_iterate_dir (dirnode, NULL, NULL, NULL);
5509 ext4fs_free_node (dirnode, &ext4fs_root->diropen);
5513 int ext4fs_open (const char *filename)
5515 ext2fs_node_t fdiro = NULL;
5519 if (ext4fs_root == NULL)
5523 status = ext4fs_find_file (filename, &ext4fs_root->diropen, &fdiro,
5528 if (!fdiro->inode_read) {
5529 status = ext4fs_read_inode (fdiro->data, fdiro->ino,
5534 len = __le32_to_cpu (fdiro->inode.size);
5535 ext4fs_file = fdiro;
5539 ext4fs_free_node (fdiro, &ext4fs_root->diropen);
5543 int ext4fs_close (void)
5545 if ((ext4fs_file != NULL) && (ext4fs_root != NULL)) {
5546 ext4fs_free_node (ext4fs_file, &ext4fs_root->diropen);
5549 if (ext4fs_root != NULL) {
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;
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;
5568 int ext4fs_read (char *buf, unsigned len)
5572 if (ext4fs_root == NULL) {
5576 if (ext4fs_file == NULL) {
5580 status = ext4fs_read_file (ext4fs_file, 0, len, buf);
5584 int ext4fs_mount (unsigned part_length)
5586 struct ext2_data *data;
5589 data = memalign(ARCH_DMA_MINALIGN, sizeof (struct ext2_data));
5593 /* Read the superblock. */
5594 status = ext2fs_devread (1 * 2, 0, sizeof (struct ext2_sblock),
5595 (char *) &data->sblock);
5600 /* Make sure this is an ext2 filesystem. */
5601 if (__le16_to_cpu (data->sblock.magic) != EXT2_MAGIC) {
5604 if (__le32_to_cpu(data->sblock.revision_level == 0)) {
5607 inode_size = __le16_to_cpu(data->sblock.inode_size);
5610 printf("EXT2 rev %d, inode_size %d\n",
5611 __le32_to_cpu(data->sblock.revision_level), inode_size);
5613 data->diropen.data = data;
5614 data->diropen.ino = 2;
5615 data->diropen.inode_read = 1;
5616 data->inode = &data->diropen.inode;
5618 status = ext4fs_read_inode (data, 2, data->inode);
5627 printf("Failed to mount ext2 filesystem...\n");