2 * (C) Copyright 2011 - 2012 Samsung Electronics
3 * EXT4 filesystem implementation in Uboot by
4 * Uma Shankar <uma.shankar@samsung.com>
5 * Manjunatha C Achar <a.manjunatha@samsung.com>
7 * ext4ls and ext4load : Based on ext2 ls load support in Uboot.
10 * esd gmbh <www.esd-electronics.com>
11 * Reinhard Arlt <reinhard.arlt@esd-electronics.com>
13 * based on code from grub2 fs/ext2.c and fs/fshelp.c by
14 * GRUB -- GRand Unified Bootloader
15 * Copyright (C) 2003, 2004 Free Software Foundation, Inc.
17 * ext4write : Based on generic ext4 protocol.
19 * This program is free software; you can redistribute it and/or modify
20 * it under the terms of the GNU General Public License as published by
21 * the Free Software Foundation; either version 2 of the License, or
22 * (at your option) any later version.
24 * This program is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU General Public License for more details.
29 * You should have received a copy of the GNU General Public License
30 * along with this program; if not, write to the Free Software
31 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
35 #include <ext_common.h>
39 #include <linux/stat.h>
40 #include <linux/time.h>
41 #include <asm/byteorder.h>
42 #include "ext4_common.h"
44 struct ext2_data
*ext4fs_root
;
45 struct ext2fs_node
*ext4fs_file
;
46 uint32_t *ext4fs_indir1_block
;
47 int ext4fs_indir1_size
;
48 int ext4fs_indir1_blkno
= -1;
49 uint32_t *ext4fs_indir2_block
;
50 int ext4fs_indir2_size
;
51 int ext4fs_indir2_blkno
= -1;
53 uint32_t *ext4fs_indir3_block
;
54 int ext4fs_indir3_size
;
55 int ext4fs_indir3_blkno
= -1;
56 struct ext2_inode
*g_parent_inode
;
57 static int symlinknest
;
59 #if defined(CONFIG_EXT4_WRITE)
60 uint32_t ext4fs_div_roundup(uint32_t size
, uint32_t n
)
62 uint32_t res
= size
/ n
;
69 void put_ext4(uint64_t off
, void *buf
, uint32_t size
)
73 unsigned char *temp_ptr
= NULL
;
74 struct ext_filesystem
*fs
= get_fs();
75 int log2blksz
= fs
->dev_desc
->log2blksz
;
76 ALLOC_CACHE_ALIGN_BUFFER(unsigned char, sec_buf
, fs
->dev_desc
->blksz
);
78 startblock
= off
>> log2blksz
;
79 startblock
+= part_offset
;
80 remainder
= off
& (uint64_t)(fs
->dev_desc
->blksz
- 1);
82 if (fs
->dev_desc
== NULL
)
85 if ((startblock
+ (size
>> log2blksz
)) >
86 (part_offset
+ fs
->total_sect
)) {
87 printf("part_offset is " LBAFU
"\n", part_offset
);
88 printf("total_sector is %llu\n", fs
->total_sect
);
89 printf("error: overflow occurs\n");
94 if (fs
->dev_desc
->block_read
) {
95 fs
->dev_desc
->block_read(fs
->dev_desc
->dev
,
96 startblock
, 1, sec_buf
);
98 memcpy((temp_ptr
+ remainder
),
99 (unsigned char *)buf
, size
);
100 fs
->dev_desc
->block_write(fs
->dev_desc
->dev
,
101 startblock
, 1, sec_buf
);
104 if (size
>> log2blksz
!= 0) {
105 fs
->dev_desc
->block_write(fs
->dev_desc
->dev
,
108 (unsigned long *)buf
);
110 fs
->dev_desc
->block_read(fs
->dev_desc
->dev
,
111 startblock
, 1, sec_buf
);
113 memcpy(temp_ptr
, buf
, size
);
114 fs
->dev_desc
->block_write(fs
->dev_desc
->dev
,
116 (unsigned long *)sec_buf
);
121 static int _get_new_inode_no(unsigned char *buffer
)
123 struct ext_filesystem
*fs
= get_fs();
129 /* get the blocksize of the filesystem */
130 unsigned char *ptr
= buffer
;
131 while (*ptr
== 255) {
134 if (count
> ext4fs_root
->sblock
.inodes_per_group
)
138 for (j
= 0; j
< fs
->blksz
; j
++) {
143 status
= input
& operand
;
158 static int _get_new_blk_no(unsigned char *buffer
)
164 unsigned char *ptr
= buffer
;
165 struct ext_filesystem
*fs
= get_fs();
167 if (fs
->blksz
!= 1024)
172 while (*ptr
== 255) {
175 if (count
== (fs
->blksz
* 8))
179 for (j
= 0; j
< fs
->blksz
; j
++) {
184 status
= input
& operand
;
199 int ext4fs_set_block_bmap(long int blockno
, unsigned char *buffer
, int index
)
201 int i
, remainder
, status
;
202 unsigned char *ptr
= buffer
;
203 unsigned char operand
;
205 remainder
= blockno
% 8;
206 int blocksize
= EXT2_BLOCK_SIZE(ext4fs_root
);
208 i
= i
- (index
* blocksize
);
209 if (blocksize
!= 1024) {
211 operand
= 1 << remainder
;
212 status
= *ptr
& operand
;
216 *ptr
= *ptr
| operand
;
219 if (remainder
== 0) {
224 operand
= (1 << (remainder
- 1));
226 status
= *ptr
& operand
;
230 *ptr
= *ptr
| operand
;
235 void ext4fs_reset_block_bmap(long int blockno
, unsigned char *buffer
, int index
)
237 int i
, remainder
, status
;
238 unsigned char *ptr
= buffer
;
239 unsigned char operand
;
241 remainder
= blockno
% 8;
242 int blocksize
= EXT2_BLOCK_SIZE(ext4fs_root
);
244 i
= i
- (index
* blocksize
);
245 if (blocksize
!= 1024) {
247 operand
= (1 << remainder
);
248 status
= *ptr
& operand
;
250 *ptr
= *ptr
& ~(operand
);
252 if (remainder
== 0) {
257 operand
= (1 << (remainder
- 1));
259 status
= *ptr
& operand
;
261 *ptr
= *ptr
& ~(operand
);
265 int ext4fs_set_inode_bmap(int inode_no
, unsigned char *buffer
, int index
)
267 int i
, remainder
, status
;
268 unsigned char *ptr
= buffer
;
269 unsigned char operand
;
271 inode_no
-= (index
* ext4fs_root
->sblock
.inodes_per_group
);
273 remainder
= inode_no
% 8;
274 if (remainder
== 0) {
279 operand
= (1 << (remainder
- 1));
281 status
= *ptr
& operand
;
285 *ptr
= *ptr
| operand
;
290 void ext4fs_reset_inode_bmap(int inode_no
, unsigned char *buffer
, int index
)
292 int i
, remainder
, status
;
293 unsigned char *ptr
= buffer
;
294 unsigned char operand
;
296 inode_no
-= (index
* ext4fs_root
->sblock
.inodes_per_group
);
298 remainder
= inode_no
% 8;
299 if (remainder
== 0) {
304 operand
= (1 << (remainder
- 1));
306 status
= *ptr
& operand
;
308 *ptr
= *ptr
& ~(operand
);
311 int ext4fs_checksum_update(unsigned int i
)
313 struct ext2_block_group
*desc
;
314 struct ext_filesystem
*fs
= get_fs();
317 desc
= (struct ext2_block_group
*)&fs
->bgd
[i
];
318 if (fs
->sb
->feature_ro_compat
& EXT4_FEATURE_RO_COMPAT_GDT_CSUM
) {
319 int offset
= offsetof(struct ext2_block_group
, bg_checksum
);
321 crc
= ext2fs_crc16(~0, fs
->sb
->unique_id
,
322 sizeof(fs
->sb
->unique_id
));
323 crc
= ext2fs_crc16(crc
, &i
, sizeof(i
));
324 crc
= ext2fs_crc16(crc
, desc
, offset
);
325 offset
+= sizeof(desc
->bg_checksum
); /* skip checksum */
326 assert(offset
== sizeof(*desc
));
332 static int check_void_in_dentry(struct ext2_dirent
*dir
, char *filename
)
335 int sizeof_void_space
;
336 int new_entry_byte_reqd
;
337 short padding_factor
= 0;
339 if (dir
->namelen
% 4 != 0)
340 padding_factor
= 4 - (dir
->namelen
% 4);
342 dentry_length
= sizeof(struct ext2_dirent
) +
343 dir
->namelen
+ padding_factor
;
344 sizeof_void_space
= dir
->direntlen
- dentry_length
;
345 if (sizeof_void_space
== 0)
349 if (strlen(filename
) % 4 != 0)
350 padding_factor
= 4 - (strlen(filename
) % 4);
352 new_entry_byte_reqd
= strlen(filename
) +
353 sizeof(struct ext2_dirent
) + padding_factor
;
354 if (sizeof_void_space
>= new_entry_byte_reqd
) {
355 dir
->direntlen
= dentry_length
;
356 return sizeof_void_space
;
362 void ext4fs_update_parent_dentry(char *filename
, int *p_ino
, int file_type
)
364 unsigned int *zero_buffer
= NULL
;
365 char *root_first_block_buffer
= NULL
;
368 long int first_block_no_of_root
= 0;
369 long int previous_blknr
= -1;
371 short int padding_factor
= 0;
372 unsigned int new_entry_byte_reqd
;
373 unsigned int last_entry_dirlen
;
374 int sizeof_void_space
= 0;
378 struct ext_filesystem
*fs
= get_fs();
379 /* directory entry */
380 struct ext2_dirent
*dir
;
381 char *temp_dir
= NULL
;
383 zero_buffer
= zalloc(fs
->blksz
);
385 printf("No Memory\n");
388 root_first_block_buffer
= zalloc(fs
->blksz
);
389 if (!root_first_block_buffer
) {
391 printf("No Memory\n");
396 /* read the block no allocated to a file */
397 for (direct_blk_idx
= 0; direct_blk_idx
< INDIRECT_BLOCKS
;
399 root_blknr
= read_allocated_block(g_parent_inode
,
401 if (root_blknr
== 0) {
402 first_block_no_of_root
= previous_blknr
;
405 previous_blknr
= root_blknr
;
408 status
= ext4fs_devread((lbaint_t
)first_block_no_of_root
410 0, fs
->blksz
, root_first_block_buffer
);
414 if (ext4fs_log_journal(root_first_block_buffer
, first_block_no_of_root
))
416 dir
= (struct ext2_dirent
*)root_first_block_buffer
;
418 while (dir
->direntlen
> 0) {
420 * blocksize-totalbytes because last directory length
421 * i.e. dir->direntlen is free availble space in the
422 * block that means it is a last entry of directory
426 /* traversing the each directory entry */
427 if (fs
->blksz
- totalbytes
== dir
->direntlen
) {
428 if (strlen(filename
) % 4 != 0)
429 padding_factor
= 4 - (strlen(filename
) % 4);
431 new_entry_byte_reqd
= strlen(filename
) +
432 sizeof(struct ext2_dirent
) + padding_factor
;
435 * update last directory entry length to its
436 * length because we are creating new directory
439 if (dir
->namelen
% 4 != 0)
440 padding_factor
= 4 - (dir
->namelen
% 4);
442 last_entry_dirlen
= dir
->namelen
+
443 sizeof(struct ext2_dirent
) + padding_factor
;
444 if ((fs
->blksz
- totalbytes
- last_entry_dirlen
) <
445 new_entry_byte_reqd
) {
446 printf("1st Block Full:Allocate new block\n");
448 if (direct_blk_idx
== INDIRECT_BLOCKS
- 1) {
449 printf("Directory exceeds limit\n");
452 g_parent_inode
->b
.blocks
.dir_blocks
453 [direct_blk_idx
] = ext4fs_get_new_blk_no();
454 if (g_parent_inode
->b
.blocks
.dir_blocks
455 [direct_blk_idx
] == -1) {
456 printf("no block left to assign\n");
461 blocks
.dir_blocks
[direct_blk_idx
] *
462 fs
->blksz
)), zero_buffer
, fs
->blksz
);
463 g_parent_inode
->size
=
464 g_parent_inode
->size
+ fs
->blksz
;
465 g_parent_inode
->blockcnt
=
466 g_parent_inode
->blockcnt
+ fs
->sect_perblk
;
467 if (ext4fs_put_metadata
468 (root_first_block_buffer
,
469 first_block_no_of_root
))
473 dir
->direntlen
= last_entry_dirlen
;
477 templength
= dir
->direntlen
;
478 totalbytes
= totalbytes
+ templength
;
479 sizeof_void_space
= check_void_in_dentry(dir
, filename
);
480 if (sizeof_void_space
)
483 dir
= (struct ext2_dirent
*)((char *)dir
+ templength
);
486 /* make a pointer ready for creating next directory entry */
487 templength
= dir
->direntlen
;
488 totalbytes
= totalbytes
+ templength
;
489 dir
= (struct ext2_dirent
*)((char *)dir
+ templength
);
491 /* get the next available inode number */
492 inodeno
= ext4fs_get_new_inode_no();
494 printf("no inode left to assign\n");
497 dir
->inode
= inodeno
;
498 if (sizeof_void_space
)
499 dir
->direntlen
= sizeof_void_space
;
501 dir
->direntlen
= fs
->blksz
- totalbytes
;
503 dir
->namelen
= strlen(filename
);
504 dir
->filetype
= FILETYPE_REG
; /* regular file */
505 temp_dir
= (char *)dir
;
506 temp_dir
= temp_dir
+ sizeof(struct ext2_dirent
);
507 memcpy(temp_dir
, filename
, strlen(filename
));
511 /* update or write the 1st block of root inode */
512 if (ext4fs_put_metadata(root_first_block_buffer
,
513 first_block_no_of_root
))
518 free(root_first_block_buffer
);
521 static int search_dir(struct ext2_inode
*parent_inode
, char *dirname
)
531 unsigned char *block_buffer
= NULL
;
532 struct ext2_dirent
*dir
= NULL
;
533 struct ext2_dirent
*previous_dir
= NULL
;
534 struct ext_filesystem
*fs
= get_fs();
536 /* read the block no allocated to a file */
537 for (direct_blk_idx
= 0; direct_blk_idx
< INDIRECT_BLOCKS
;
539 blknr
= read_allocated_block(parent_inode
, direct_blk_idx
);
543 /* read the blocks of parenet inode */
544 block_buffer
= zalloc(fs
->blksz
);
548 status
= ext4fs_devread((lbaint_t
)blknr
* fs
->sect_perblk
,
549 0, fs
->blksz
, (char *)block_buffer
);
553 dir
= (struct ext2_dirent
*)block_buffer
;
556 while (dir
->direntlen
>= 0) {
558 * blocksize-totalbytes because last directory
559 * length i.e.,*dir->direntlen is free availble
560 * space in the block that means
561 * it is a last entry of directory entry
563 if (strlen(dirname
) == dir
->namelen
) {
564 if (strncmp(dirname
, ptr
+
565 sizeof(struct ext2_dirent
),
566 dir
->namelen
) == 0) {
567 previous_dir
->direntlen
+=
569 inodeno
= dir
->inode
;
576 if (fs
->blksz
- totalbytes
== dir
->direntlen
)
579 /* traversing the each directory entry */
580 templength
= dir
->direntlen
;
581 totalbytes
= totalbytes
+ templength
;
583 dir
= (struct ext2_dirent
*)((char *)dir
+ templength
);
603 static int find_dir_depth(char *dirname
)
605 char *token
= strtok(dirname
, "/");
607 while (token
!= NULL
) {
608 token
= strtok(NULL
, "/");
611 return count
+ 1 + 1;
613 * for example for string /home/temp
614 * depth=home(1)+temp(1)+1 extra for NULL;
619 static int parse_path(char **arr
, char *dirname
)
621 char *token
= strtok(dirname
, "/");
625 arr
[i
] = zalloc(strlen("/") + 1);
631 /* add each path entry after root */
632 while (token
!= NULL
) {
633 arr
[i
] = zalloc(strlen(token
) + 1);
636 memcpy(arr
[i
++], token
, strlen(token
));
637 token
= strtok(NULL
, "/");
644 int ext4fs_iget(int inode_no
, struct ext2_inode
*inode
)
646 if (ext4fs_read_inode(ext4fs_root
, inode_no
, inode
) == 0)
653 * Function: ext4fs_get_parent_inode_num
654 * Return Value: inode Number of the parent directory of file/Directory to be
656 * dirname : Input parmater, input path name of the file/directory to be created
657 * dname : Output parameter, to be filled with the name of the directory
658 * extracted from dirname
660 int ext4fs_get_parent_inode_num(const char *dirname
, char *dname
, int flags
)
664 int matched_inode_no
;
665 int result_inode_no
= -1;
667 char *depth_dirname
= NULL
;
668 char *parse_dirname
= NULL
;
669 struct ext2_inode
*parent_inode
= NULL
;
670 struct ext2_inode
*first_inode
= NULL
;
671 struct ext2_inode temp_inode
;
673 if (*dirname
!= '/') {
674 printf("Please supply Absolute path\n");
678 /* TODO: input validation make equivalent to linux */
679 depth_dirname
= zalloc(strlen(dirname
) + 1);
683 memcpy(depth_dirname
, dirname
, strlen(dirname
));
684 depth
= find_dir_depth(depth_dirname
);
685 parse_dirname
= zalloc(strlen(dirname
) + 1);
688 memcpy(parse_dirname
, dirname
, strlen(dirname
));
690 /* allocate memory for each directory level */
691 ptr
= zalloc((depth
) * sizeof(char *));
694 if (parse_path(ptr
, parse_dirname
))
696 parent_inode
= zalloc(sizeof(struct ext2_inode
));
699 first_inode
= zalloc(sizeof(struct ext2_inode
));
702 memcpy(parent_inode
, ext4fs_root
->inode
, sizeof(struct ext2_inode
));
703 memcpy(first_inode
, parent_inode
, sizeof(struct ext2_inode
));
705 result_inode_no
= EXT2_ROOT_INO
;
706 for (i
= 1; i
< depth
; i
++) {
707 matched_inode_no
= search_dir(parent_inode
, ptr
[i
]);
708 if (matched_inode_no
== -1) {
709 if (ptr
[i
+ 1] == NULL
&& i
== 1) {
710 result_inode_no
= EXT2_ROOT_INO
;
713 if (ptr
[i
+ 1] == NULL
)
715 printf("Invalid path\n");
716 result_inode_no
= -1;
720 if (ptr
[i
+ 1] != NULL
) {
721 memset(parent_inode
, '\0',
722 sizeof(struct ext2_inode
));
723 if (ext4fs_iget(matched_inode_no
,
725 result_inode_no
= -1;
728 result_inode_no
= matched_inode_no
;
737 matched_inode_no
= search_dir(first_inode
, ptr
[i
]);
739 matched_inode_no
= search_dir(parent_inode
, ptr
[i
]);
741 if (matched_inode_no
!= -1) {
742 ext4fs_iget(matched_inode_no
, &temp_inode
);
743 if (temp_inode
.mode
& S_IFDIR
) {
744 printf("It is a Directory\n");
745 result_inode_no
= -1;
750 if (strlen(ptr
[i
]) > 256) {
751 result_inode_no
= -1;
754 memcpy(dname
, ptr
[i
], strlen(ptr
[i
]));
763 return result_inode_no
;
766 static int check_filename(char *filename
, unsigned int blknr
)
768 unsigned int first_block_no_of_root
;
773 char *root_first_block_buffer
= NULL
;
774 char *root_first_block_addr
= NULL
;
775 struct ext2_dirent
*dir
= NULL
;
776 struct ext2_dirent
*previous_dir
= NULL
;
778 struct ext_filesystem
*fs
= get_fs();
780 /* get the first block of root */
781 first_block_no_of_root
= blknr
;
782 root_first_block_buffer
= zalloc(fs
->blksz
);
783 if (!root_first_block_buffer
)
785 root_first_block_addr
= root_first_block_buffer
;
786 status
= ext4fs_devread((lbaint_t
)first_block_no_of_root
*
788 fs
->blksz
, root_first_block_buffer
);
792 if (ext4fs_log_journal(root_first_block_buffer
, first_block_no_of_root
))
794 dir
= (struct ext2_dirent
*)root_first_block_buffer
;
797 while (dir
->direntlen
>= 0) {
799 * blocksize-totalbytes because last
800 * directory length i.e., *dir->direntlen
801 * is free availble space in the block that
802 * means it is a last entry of directory entry
804 if (strlen(filename
) == dir
->namelen
) {
805 if (strncmp(filename
, ptr
+ sizeof(struct ext2_dirent
),
806 dir
->namelen
) == 0) {
807 printf("file found deleting\n");
808 previous_dir
->direntlen
+= dir
->direntlen
;
809 inodeno
= dir
->inode
;
816 if (fs
->blksz
- totalbytes
== dir
->direntlen
)
819 /* traversing the each directory entry */
820 templength
= dir
->direntlen
;
821 totalbytes
= totalbytes
+ templength
;
823 dir
= (struct ext2_dirent
*)((char *)dir
+ templength
);
829 if (ext4fs_put_metadata(root_first_block_addr
,
830 first_block_no_of_root
))
835 free(root_first_block_buffer
);
840 int ext4fs_filename_check(char *filename
)
842 short direct_blk_idx
= 0;
846 /* read the block no allocated to a file */
847 for (direct_blk_idx
= 0; direct_blk_idx
< INDIRECT_BLOCKS
;
849 blknr
= read_allocated_block(g_parent_inode
, direct_blk_idx
);
852 inodeno
= check_filename(filename
, blknr
);
860 long int ext4fs_get_new_blk_no(void)
866 static int prev_bg_bitmap_index
= -1;
867 unsigned int blk_per_grp
= ext4fs_root
->sblock
.blocks_per_group
;
868 struct ext_filesystem
*fs
= get_fs();
869 char *journal_buffer
= zalloc(fs
->blksz
);
870 char *zero_buffer
= zalloc(fs
->blksz
);
871 if (!journal_buffer
|| !zero_buffer
)
873 struct ext2_block_group
*bgd
= (struct ext2_block_group
*)fs
->gdtable
;
875 if (fs
->first_pass_bbmap
== 0) {
876 for (i
= 0; i
< fs
->no_blkgrp
; i
++) {
877 if (bgd
[i
].free_blocks
) {
878 if (bgd
[i
].bg_flags
& EXT4_BG_BLOCK_UNINIT
) {
879 put_ext4(((uint64_t) (bgd
[i
].block_id
*
881 zero_buffer
, fs
->blksz
);
884 bg_flags
& ~EXT4_BG_BLOCK_UNINIT
;
885 memcpy(fs
->blk_bmaps
[i
], zero_buffer
,
889 _get_new_blk_no(fs
->blk_bmaps
[i
]);
890 if (fs
->curr_blkno
== -1)
891 /* if block bitmap is completely fill */
893 fs
->curr_blkno
= fs
->curr_blkno
+
895 fs
->first_pass_bbmap
++;
896 bgd
[i
].free_blocks
--;
897 fs
->sb
->free_blocks
--;
898 status
= ext4fs_devread((lbaint_t
)
905 if (ext4fs_log_journal(journal_buffer
,
910 debug("no space left on block group %d\n", i
);
918 /* get the blockbitmap index respective to blockno */
919 if (fs
->blksz
!= 1024) {
920 bg_idx
= fs
->curr_blkno
/ blk_per_grp
;
922 bg_idx
= fs
->curr_blkno
/ blk_per_grp
;
923 remainder
= fs
->curr_blkno
% blk_per_grp
;
929 * To skip completely filled block group bitmaps
930 * Optimize the block allocation
932 if (bg_idx
>= fs
->no_blkgrp
)
935 if (bgd
[bg_idx
].free_blocks
== 0) {
936 debug("block group %u is full. Skipping\n", bg_idx
);
937 fs
->curr_blkno
= fs
->curr_blkno
+ blk_per_grp
;
942 if (bgd
[bg_idx
].bg_flags
& EXT4_BG_BLOCK_UNINIT
) {
943 memset(zero_buffer
, '\0', fs
->blksz
);
944 put_ext4(((uint64_t) (bgd
[bg_idx
].block_id
*
945 fs
->blksz
)), zero_buffer
, fs
->blksz
);
946 memcpy(fs
->blk_bmaps
[bg_idx
], zero_buffer
, fs
->blksz
);
947 bgd
[bg_idx
].bg_flags
= bgd
[bg_idx
].bg_flags
&
948 ~EXT4_BG_BLOCK_UNINIT
;
951 if (ext4fs_set_block_bmap(fs
->curr_blkno
, fs
->blk_bmaps
[bg_idx
],
953 debug("going for restart for the block no %ld %u\n",
954 fs
->curr_blkno
, bg_idx
);
959 if (prev_bg_bitmap_index
!= bg_idx
) {
960 memset(journal_buffer
, '\0', fs
->blksz
);
961 status
= ext4fs_devread((lbaint_t
)bgd
[bg_idx
].block_id
963 0, fs
->blksz
, journal_buffer
);
966 if (ext4fs_log_journal(journal_buffer
,
967 bgd
[bg_idx
].block_id
))
970 prev_bg_bitmap_index
= bg_idx
;
972 bgd
[bg_idx
].free_blocks
--;
973 fs
->sb
->free_blocks
--;
977 free(journal_buffer
);
980 return fs
->curr_blkno
;
982 free(journal_buffer
);
988 int ext4fs_get_new_inode_no(void)
992 unsigned int ibmap_idx
;
993 static int prev_inode_bitmap_index
= -1;
994 unsigned int inodes_per_grp
= ext4fs_root
->sblock
.inodes_per_group
;
995 struct ext_filesystem
*fs
= get_fs();
996 char *journal_buffer
= zalloc(fs
->blksz
);
997 char *zero_buffer
= zalloc(fs
->blksz
);
998 if (!journal_buffer
|| !zero_buffer
)
1000 struct ext2_block_group
*bgd
= (struct ext2_block_group
*)fs
->gdtable
;
1002 if (fs
->first_pass_ibmap
== 0) {
1003 for (i
= 0; i
< fs
->no_blkgrp
; i
++) {
1004 if (bgd
[i
].free_inodes
) {
1005 if (bgd
[i
].bg_itable_unused
!=
1007 bgd
[i
].bg_itable_unused
=
1009 if (bgd
[i
].bg_flags
& EXT4_BG_INODE_UNINIT
) {
1010 put_ext4(((uint64_t)
1013 zero_buffer
, fs
->blksz
);
1014 bgd
[i
].bg_flags
= bgd
[i
].bg_flags
&
1015 ~EXT4_BG_INODE_UNINIT
;
1016 memcpy(fs
->inode_bmaps
[i
],
1017 zero_buffer
, fs
->blksz
);
1020 _get_new_inode_no(fs
->inode_bmaps
[i
]);
1021 if (fs
->curr_inode_no
== -1)
1022 /* if block bitmap is completely fill */
1024 fs
->curr_inode_no
= fs
->curr_inode_no
+
1025 (i
* inodes_per_grp
);
1026 fs
->first_pass_ibmap
++;
1027 bgd
[i
].free_inodes
--;
1028 bgd
[i
].bg_itable_unused
--;
1029 fs
->sb
->free_inodes
--;
1030 status
= ext4fs_devread((lbaint_t
)
1037 if (ext4fs_log_journal(journal_buffer
,
1042 debug("no inode left on block group %d\n", i
);
1047 fs
->curr_inode_no
++;
1048 /* get the blockbitmap index respective to blockno */
1049 ibmap_idx
= fs
->curr_inode_no
/ inodes_per_grp
;
1050 if (bgd
[ibmap_idx
].bg_flags
& EXT4_BG_INODE_UNINIT
) {
1051 memset(zero_buffer
, '\0', fs
->blksz
);
1052 put_ext4(((uint64_t) (bgd
[ibmap_idx
].inode_id
*
1053 fs
->blksz
)), zero_buffer
,
1055 bgd
[ibmap_idx
].bg_flags
=
1056 bgd
[ibmap_idx
].bg_flags
& ~EXT4_BG_INODE_UNINIT
;
1057 memcpy(fs
->inode_bmaps
[ibmap_idx
], zero_buffer
,
1061 if (ext4fs_set_inode_bmap(fs
->curr_inode_no
,
1062 fs
->inode_bmaps
[ibmap_idx
],
1064 debug("going for restart for the block no %d %u\n",
1065 fs
->curr_inode_no
, ibmap_idx
);
1069 /* journal backup */
1070 if (prev_inode_bitmap_index
!= ibmap_idx
) {
1071 memset(journal_buffer
, '\0', fs
->blksz
);
1072 status
= ext4fs_devread((lbaint_t
)
1073 bgd
[ibmap_idx
].inode_id
1075 0, fs
->blksz
, journal_buffer
);
1078 if (ext4fs_log_journal(journal_buffer
,
1079 bgd
[ibmap_idx
].inode_id
))
1081 prev_inode_bitmap_index
= ibmap_idx
;
1083 if (bgd
[ibmap_idx
].bg_itable_unused
!=
1084 bgd
[ibmap_idx
].free_inodes
)
1085 bgd
[ibmap_idx
].bg_itable_unused
=
1086 bgd
[ibmap_idx
].free_inodes
;
1087 bgd
[ibmap_idx
].free_inodes
--;
1088 bgd
[ibmap_idx
].bg_itable_unused
--;
1089 fs
->sb
->free_inodes
--;
1094 free(journal_buffer
);
1097 return fs
->curr_inode_no
;
1099 free(journal_buffer
);
1107 static void alloc_single_indirect_block(struct ext2_inode
*file_inode
,
1108 unsigned int *total_remaining_blocks
,
1109 unsigned int *no_blks_reqd
)
1113 long int actual_block_no
;
1114 long int si_blockno
;
1115 /* si :single indirect */
1116 unsigned int *si_buffer
= NULL
;
1117 unsigned int *si_start_addr
= NULL
;
1118 struct ext_filesystem
*fs
= get_fs();
1120 if (*total_remaining_blocks
!= 0) {
1121 si_buffer
= zalloc(fs
->blksz
);
1123 printf("No Memory\n");
1126 si_start_addr
= si_buffer
;
1127 si_blockno
= ext4fs_get_new_blk_no();
1128 if (si_blockno
== -1) {
1129 printf("no block left to assign\n");
1133 debug("SIPB %ld: %u\n", si_blockno
, *total_remaining_blocks
);
1135 status
= ext4fs_devread((lbaint_t
)si_blockno
* fs
->sect_perblk
,
1136 0, fs
->blksz
, (char *)si_buffer
);
1137 memset(si_buffer
, '\0', fs
->blksz
);
1141 for (i
= 0; i
< (fs
->blksz
/ sizeof(int)); i
++) {
1142 actual_block_no
= ext4fs_get_new_blk_no();
1143 if (actual_block_no
== -1) {
1144 printf("no block left to assign\n");
1147 *si_buffer
= actual_block_no
;
1148 debug("SIAB %u: %u\n", *si_buffer
,
1149 *total_remaining_blocks
);
1152 (*total_remaining_blocks
)--;
1153 if (*total_remaining_blocks
== 0)
1157 /* write the block to disk */
1158 put_ext4(((uint64_t) (si_blockno
* fs
->blksz
)),
1159 si_start_addr
, fs
->blksz
);
1160 file_inode
->b
.blocks
.indir_block
= si_blockno
;
1163 free(si_start_addr
);
1166 static void alloc_double_indirect_block(struct ext2_inode
*file_inode
,
1167 unsigned int *total_remaining_blocks
,
1168 unsigned int *no_blks_reqd
)
1173 long int actual_block_no
;
1174 /* di:double indirect */
1175 long int di_blockno_parent
;
1176 long int di_blockno_child
;
1177 unsigned int *di_parent_buffer
= NULL
;
1178 unsigned int *di_child_buff
= NULL
;
1179 unsigned int *di_block_start_addr
= NULL
;
1180 unsigned int *di_child_buff_start
= NULL
;
1181 struct ext_filesystem
*fs
= get_fs();
1183 if (*total_remaining_blocks
!= 0) {
1184 /* double indirect parent block connecting to inode */
1185 di_blockno_parent
= ext4fs_get_new_blk_no();
1186 if (di_blockno_parent
== -1) {
1187 printf("no block left to assign\n");
1190 di_parent_buffer
= zalloc(fs
->blksz
);
1191 if (!di_parent_buffer
)
1194 di_block_start_addr
= di_parent_buffer
;
1196 debug("DIPB %ld: %u\n", di_blockno_parent
,
1197 *total_remaining_blocks
);
1199 status
= ext4fs_devread((lbaint_t
)di_blockno_parent
*
1201 fs
->blksz
, (char *)di_parent_buffer
);
1204 printf("%s: Device read error!\n", __func__
);
1207 memset(di_parent_buffer
, '\0', fs
->blksz
);
1210 * start:for each double indirect parent
1211 * block create one more block
1213 for (i
= 0; i
< (fs
->blksz
/ sizeof(int)); i
++) {
1214 di_blockno_child
= ext4fs_get_new_blk_no();
1215 if (di_blockno_child
== -1) {
1216 printf("no block left to assign\n");
1219 di_child_buff
= zalloc(fs
->blksz
);
1223 di_child_buff_start
= di_child_buff
;
1224 *di_parent_buffer
= di_blockno_child
;
1227 debug("DICB %ld: %u\n", di_blockno_child
,
1228 *total_remaining_blocks
);
1230 status
= ext4fs_devread((lbaint_t
)di_blockno_child
*
1233 (char *)di_child_buff
);
1236 printf("%s: Device read error!\n", __func__
);
1239 memset(di_child_buff
, '\0', fs
->blksz
);
1240 /* filling of actual datablocks for each child */
1241 for (j
= 0; j
< (fs
->blksz
/ sizeof(int)); j
++) {
1242 actual_block_no
= ext4fs_get_new_blk_no();
1243 if (actual_block_no
== -1) {
1244 printf("no block left to assign\n");
1247 *di_child_buff
= actual_block_no
;
1248 debug("DIAB %ld: %u\n", actual_block_no
,
1249 *total_remaining_blocks
);
1252 (*total_remaining_blocks
)--;
1253 if (*total_remaining_blocks
== 0)
1256 /* write the block table */
1257 put_ext4(((uint64_t) (di_blockno_child
* fs
->blksz
)),
1258 di_child_buff_start
, fs
->blksz
);
1259 free(di_child_buff_start
);
1260 di_child_buff_start
= NULL
;
1262 if (*total_remaining_blocks
== 0)
1265 put_ext4(((uint64_t) (di_blockno_parent
* fs
->blksz
)),
1266 di_block_start_addr
, fs
->blksz
);
1267 file_inode
->b
.blocks
.double_indir_block
= di_blockno_parent
;
1270 free(di_block_start_addr
);
1273 static void alloc_triple_indirect_block(struct ext2_inode
*file_inode
,
1274 unsigned int *total_remaining_blocks
,
1275 unsigned int *no_blks_reqd
)
1280 long int actual_block_no
;
1281 /* ti: Triple Indirect */
1282 long int ti_gp_blockno
;
1283 long int ti_parent_blockno
;
1284 long int ti_child_blockno
;
1285 unsigned int *ti_gp_buff
= NULL
;
1286 unsigned int *ti_parent_buff
= NULL
;
1287 unsigned int *ti_child_buff
= NULL
;
1288 unsigned int *ti_gp_buff_start_addr
= NULL
;
1289 unsigned int *ti_pbuff_start_addr
= NULL
;
1290 unsigned int *ti_cbuff_start_addr
= NULL
;
1291 struct ext_filesystem
*fs
= get_fs();
1292 if (*total_remaining_blocks
!= 0) {
1293 /* triple indirect grand parent block connecting to inode */
1294 ti_gp_blockno
= ext4fs_get_new_blk_no();
1295 if (ti_gp_blockno
== -1) {
1296 printf("no block left to assign\n");
1299 ti_gp_buff
= zalloc(fs
->blksz
);
1303 ti_gp_buff_start_addr
= ti_gp_buff
;
1305 debug("TIGPB %ld: %u\n", ti_gp_blockno
,
1306 *total_remaining_blocks
);
1308 /* for each 4 byte grand parent entry create one more block */
1309 for (i
= 0; i
< (fs
->blksz
/ sizeof(int)); i
++) {
1310 ti_parent_blockno
= ext4fs_get_new_blk_no();
1311 if (ti_parent_blockno
== -1) {
1312 printf("no block left to assign\n");
1315 ti_parent_buff
= zalloc(fs
->blksz
);
1316 if (!ti_parent_buff
)
1319 ti_pbuff_start_addr
= ti_parent_buff
;
1320 *ti_gp_buff
= ti_parent_blockno
;
1323 debug("TIPB %ld: %u\n", ti_parent_blockno
,
1324 *total_remaining_blocks
);
1326 /* for each 4 byte entry parent create one more block */
1327 for (j
= 0; j
< (fs
->blksz
/ sizeof(int)); j
++) {
1328 ti_child_blockno
= ext4fs_get_new_blk_no();
1329 if (ti_child_blockno
== -1) {
1330 printf("no block left assign\n");
1333 ti_child_buff
= zalloc(fs
->blksz
);
1337 ti_cbuff_start_addr
= ti_child_buff
;
1338 *ti_parent_buff
= ti_child_blockno
;
1341 debug("TICB %ld: %u\n", ti_parent_blockno
,
1342 *total_remaining_blocks
);
1344 /* fill actual datablocks for each child */
1345 for (k
= 0; k
< (fs
->blksz
/ sizeof(int));
1348 ext4fs_get_new_blk_no();
1349 if (actual_block_no
== -1) {
1350 printf("no block left\n");
1353 *ti_child_buff
= actual_block_no
;
1354 debug("TIAB %ld: %u\n", actual_block_no
,
1355 *total_remaining_blocks
);
1358 (*total_remaining_blocks
)--;
1359 if (*total_remaining_blocks
== 0)
1362 /* write the child block */
1363 put_ext4(((uint64_t) (ti_child_blockno
*
1365 ti_cbuff_start_addr
, fs
->blksz
);
1366 free(ti_cbuff_start_addr
);
1368 if (*total_remaining_blocks
== 0)
1371 /* write the parent block */
1372 put_ext4(((uint64_t) (ti_parent_blockno
* fs
->blksz
)),
1373 ti_pbuff_start_addr
, fs
->blksz
);
1374 free(ti_pbuff_start_addr
);
1376 if (*total_remaining_blocks
== 0)
1379 /* write the grand parent block */
1380 put_ext4(((uint64_t) (ti_gp_blockno
* fs
->blksz
)),
1381 ti_gp_buff_start_addr
, fs
->blksz
);
1382 file_inode
->b
.blocks
.triple_indir_block
= ti_gp_blockno
;
1385 free(ti_gp_buff_start_addr
);
1388 void ext4fs_allocate_blocks(struct ext2_inode
*file_inode
,
1389 unsigned int total_remaining_blocks
,
1390 unsigned int *total_no_of_block
)
1393 long int direct_blockno
;
1394 unsigned int no_blks_reqd
= 0;
1396 /* allocation of direct blocks */
1397 for (i
= 0; i
< INDIRECT_BLOCKS
; i
++) {
1398 direct_blockno
= ext4fs_get_new_blk_no();
1399 if (direct_blockno
== -1) {
1400 printf("no block left to assign\n");
1403 file_inode
->b
.blocks
.dir_blocks
[i
] = direct_blockno
;
1404 debug("DB %ld: %u\n", direct_blockno
, total_remaining_blocks
);
1406 total_remaining_blocks
--;
1407 if (total_remaining_blocks
== 0)
1411 alloc_single_indirect_block(file_inode
, &total_remaining_blocks
,
1413 alloc_double_indirect_block(file_inode
, &total_remaining_blocks
,
1415 alloc_triple_indirect_block(file_inode
, &total_remaining_blocks
,
1417 *total_no_of_block
+= no_blks_reqd
;
1422 static struct ext4_extent_header
*ext4fs_get_extent_block
1423 (struct ext2_data
*data
, char *buf
,
1424 struct ext4_extent_header
*ext_block
,
1425 uint32_t fileblock
, int log2_blksz
)
1427 struct ext4_extent_idx
*index
;
1428 unsigned long long block
;
1429 struct ext_filesystem
*fs
= get_fs();
1433 index
= (struct ext4_extent_idx
*)(ext_block
+ 1);
1435 if (le16_to_cpu(ext_block
->eh_magic
) != EXT4_EXT_MAGIC
)
1438 if (ext_block
->eh_depth
== 0)
1443 if (i
>= le16_to_cpu(ext_block
->eh_entries
))
1445 } while (fileblock
> le32_to_cpu(index
[i
].ei_block
));
1450 block
= le16_to_cpu(index
[i
].ei_leaf_hi
);
1451 block
= (block
<< 32) + le32_to_cpu(index
[i
].ei_leaf_lo
);
1453 if (ext4fs_devread((lbaint_t
)block
<< log2_blksz
, 0, fs
->blksz
,
1455 ext_block
= (struct ext4_extent_header
*)buf
;
1461 static int ext4fs_blockgroup
1462 (struct ext2_data
*data
, int group
, struct ext2_block_group
*blkgrp
)
1465 unsigned int blkoff
, desc_per_blk
;
1466 int log2blksz
= get_fs()->dev_desc
->log2blksz
;
1468 desc_per_blk
= EXT2_BLOCK_SIZE(data
) / sizeof(struct ext2_block_group
);
1470 blkno
= __le32_to_cpu(data
->sblock
.first_data_block
) + 1 +
1471 group
/ desc_per_blk
;
1472 blkoff
= (group
% desc_per_blk
) * sizeof(struct ext2_block_group
);
1474 debug("ext4fs read %d group descriptor (blkno %ld blkoff %u)\n",
1475 group
, blkno
, blkoff
);
1477 return ext4fs_devread((lbaint_t
)blkno
<<
1478 (LOG2_BLOCK_SIZE(data
) - log2blksz
),
1479 blkoff
, sizeof(struct ext2_block_group
),
1483 int ext4fs_read_inode(struct ext2_data
*data
, int ino
, struct ext2_inode
*inode
)
1485 struct ext2_block_group blkgrp
;
1486 struct ext2_sblock
*sblock
= &data
->sblock
;
1487 struct ext_filesystem
*fs
= get_fs();
1488 int log2blksz
= get_fs()->dev_desc
->log2blksz
;
1489 int inodes_per_block
, status
;
1491 unsigned int blkoff
;
1493 /* It is easier to calculate if the first inode is 0. */
1495 status
= ext4fs_blockgroup(data
, ino
/ __le32_to_cpu
1496 (sblock
->inodes_per_group
), &blkgrp
);
1500 inodes_per_block
= EXT2_BLOCK_SIZE(data
) / fs
->inodesz
;
1501 blkno
= __le32_to_cpu(blkgrp
.inode_table_id
) +
1502 (ino
% __le32_to_cpu(sblock
->inodes_per_group
)) / inodes_per_block
;
1503 blkoff
= (ino
% inodes_per_block
) * fs
->inodesz
;
1504 /* Read the inode. */
1505 status
= ext4fs_devread((lbaint_t
)blkno
<< (LOG2_BLOCK_SIZE(data
) -
1507 sizeof(struct ext2_inode
), (char *)inode
);
1514 long int read_allocated_block(struct ext2_inode
*inode
, int fileblock
)
1521 long int perblock_parent
;
1522 long int perblock_child
;
1523 unsigned long long start
;
1524 /* get the blocksize of the filesystem */
1525 blksz
= EXT2_BLOCK_SIZE(ext4fs_root
);
1526 log2_blksz
= LOG2_BLOCK_SIZE(ext4fs_root
)
1527 - get_fs()->dev_desc
->log2blksz
;
1529 if (le32_to_cpu(inode
->flags
) & EXT4_EXTENTS_FL
) {
1530 char *buf
= zalloc(blksz
);
1533 struct ext4_extent_header
*ext_block
;
1534 struct ext4_extent
*extent
;
1537 ext4fs_get_extent_block(ext4fs_root
, buf
,
1538 (struct ext4_extent_header
*)
1539 inode
->b
.blocks
.dir_blocks
,
1540 fileblock
, log2_blksz
);
1542 printf("invalid extent block\n");
1547 extent
= (struct ext4_extent
*)(ext_block
+ 1);
1551 if (i
>= le16_to_cpu(ext_block
->eh_entries
))
1553 } while (fileblock
>= le32_to_cpu(extent
[i
].ee_block
));
1555 fileblock
-= le32_to_cpu(extent
[i
].ee_block
);
1556 if (fileblock
>= le16_to_cpu(extent
[i
].ee_len
)) {
1561 start
= le16_to_cpu(extent
[i
].ee_start_hi
);
1562 start
= (start
<< 32) +
1563 le32_to_cpu(extent
[i
].ee_start_lo
);
1565 return fileblock
+ start
;
1568 printf("Extent Error\n");
1573 /* Direct blocks. */
1574 if (fileblock
< INDIRECT_BLOCKS
)
1575 blknr
= __le32_to_cpu(inode
->b
.blocks
.dir_blocks
[fileblock
]);
1578 else if (fileblock
< (INDIRECT_BLOCKS
+ (blksz
/ 4))) {
1579 if (ext4fs_indir1_block
== NULL
) {
1580 ext4fs_indir1_block
= zalloc(blksz
);
1581 if (ext4fs_indir1_block
== NULL
) {
1582 printf("** SI ext2fs read block (indir 1)"
1583 "malloc failed. **\n");
1586 ext4fs_indir1_size
= blksz
;
1587 ext4fs_indir1_blkno
= -1;
1589 if (blksz
!= ext4fs_indir1_size
) {
1590 free(ext4fs_indir1_block
);
1591 ext4fs_indir1_block
= NULL
;
1592 ext4fs_indir1_size
= 0;
1593 ext4fs_indir1_blkno
= -1;
1594 ext4fs_indir1_block
= zalloc(blksz
);
1595 if (ext4fs_indir1_block
== NULL
) {
1596 printf("** SI ext2fs read block (indir 1):"
1597 "malloc failed. **\n");
1600 ext4fs_indir1_size
= blksz
;
1602 if ((__le32_to_cpu(inode
->b
.blocks
.indir_block
) <<
1603 log2_blksz
) != ext4fs_indir1_blkno
) {
1605 ext4fs_devread((lbaint_t
)__le32_to_cpu
1607 indir_block
) << log2_blksz
, 0,
1608 blksz
, (char *)ext4fs_indir1_block
);
1610 printf("** SI ext2fs read block (indir 1)"
1614 ext4fs_indir1_blkno
=
1615 __le32_to_cpu(inode
->b
.blocks
.
1616 indir_block
) << log2_blksz
;
1618 blknr
= __le32_to_cpu(ext4fs_indir1_block
1619 [fileblock
- INDIRECT_BLOCKS
]);
1621 /* Double indirect. */
1622 else if (fileblock
< (INDIRECT_BLOCKS
+ (blksz
/ 4 *
1623 (blksz
/ 4 + 1)))) {
1625 long int perblock
= blksz
/ 4;
1626 long int rblock
= fileblock
- (INDIRECT_BLOCKS
+ blksz
/ 4);
1628 if (ext4fs_indir1_block
== NULL
) {
1629 ext4fs_indir1_block
= zalloc(blksz
);
1630 if (ext4fs_indir1_block
== NULL
) {
1631 printf("** DI ext2fs read block (indir 2 1)"
1632 "malloc failed. **\n");
1635 ext4fs_indir1_size
= blksz
;
1636 ext4fs_indir1_blkno
= -1;
1638 if (blksz
!= ext4fs_indir1_size
) {
1639 free(ext4fs_indir1_block
);
1640 ext4fs_indir1_block
= NULL
;
1641 ext4fs_indir1_size
= 0;
1642 ext4fs_indir1_blkno
= -1;
1643 ext4fs_indir1_block
= zalloc(blksz
);
1644 if (ext4fs_indir1_block
== NULL
) {
1645 printf("** DI ext2fs read block (indir 2 1)"
1646 "malloc failed. **\n");
1649 ext4fs_indir1_size
= blksz
;
1651 if ((__le32_to_cpu(inode
->b
.blocks
.double_indir_block
) <<
1652 log2_blksz
) != ext4fs_indir1_blkno
) {
1654 ext4fs_devread((lbaint_t
)__le32_to_cpu
1656 double_indir_block
) << log2_blksz
,
1658 (char *)ext4fs_indir1_block
);
1660 printf("** DI ext2fs read block (indir 2 1)"
1664 ext4fs_indir1_blkno
=
1665 __le32_to_cpu(inode
->b
.blocks
.double_indir_block
) <<
1669 if (ext4fs_indir2_block
== NULL
) {
1670 ext4fs_indir2_block
= zalloc(blksz
);
1671 if (ext4fs_indir2_block
== NULL
) {
1672 printf("** DI ext2fs read block (indir 2 2)"
1673 "malloc failed. **\n");
1676 ext4fs_indir2_size
= blksz
;
1677 ext4fs_indir2_blkno
= -1;
1679 if (blksz
!= ext4fs_indir2_size
) {
1680 free(ext4fs_indir2_block
);
1681 ext4fs_indir2_block
= NULL
;
1682 ext4fs_indir2_size
= 0;
1683 ext4fs_indir2_blkno
= -1;
1684 ext4fs_indir2_block
= zalloc(blksz
);
1685 if (ext4fs_indir2_block
== NULL
) {
1686 printf("** DI ext2fs read block (indir 2 2)"
1687 "malloc failed. **\n");
1690 ext4fs_indir2_size
= blksz
;
1692 if ((__le32_to_cpu(ext4fs_indir1_block
[rblock
/ perblock
]) <<
1693 log2_blksz
) != ext4fs_indir2_blkno
) {
1694 status
= ext4fs_devread((lbaint_t
)__le32_to_cpu
1695 (ext4fs_indir1_block
1697 perblock
]) << log2_blksz
, 0,
1699 (char *)ext4fs_indir2_block
);
1701 printf("** DI ext2fs read block (indir 2 2)"
1705 ext4fs_indir2_blkno
=
1706 __le32_to_cpu(ext4fs_indir1_block
[rblock
1711 blknr
= __le32_to_cpu(ext4fs_indir2_block
[rblock
% perblock
]);
1713 /* Tripple indirect. */
1715 rblock
= fileblock
- (INDIRECT_BLOCKS
+ blksz
/ 4 +
1716 (blksz
/ 4 * blksz
/ 4));
1717 perblock_child
= blksz
/ 4;
1718 perblock_parent
= ((blksz
/ 4) * (blksz
/ 4));
1720 if (ext4fs_indir1_block
== NULL
) {
1721 ext4fs_indir1_block
= zalloc(blksz
);
1722 if (ext4fs_indir1_block
== NULL
) {
1723 printf("** TI ext2fs read block (indir 2 1)"
1724 "malloc failed. **\n");
1727 ext4fs_indir1_size
= blksz
;
1728 ext4fs_indir1_blkno
= -1;
1730 if (blksz
!= ext4fs_indir1_size
) {
1731 free(ext4fs_indir1_block
);
1732 ext4fs_indir1_block
= NULL
;
1733 ext4fs_indir1_size
= 0;
1734 ext4fs_indir1_blkno
= -1;
1735 ext4fs_indir1_block
= zalloc(blksz
);
1736 if (ext4fs_indir1_block
== NULL
) {
1737 printf("** TI ext2fs read block (indir 2 1)"
1738 "malloc failed. **\n");
1741 ext4fs_indir1_size
= blksz
;
1743 if ((__le32_to_cpu(inode
->b
.blocks
.triple_indir_block
) <<
1744 log2_blksz
) != ext4fs_indir1_blkno
) {
1745 status
= ext4fs_devread
1747 __le32_to_cpu(inode
->b
.blocks
.triple_indir_block
)
1748 << log2_blksz
, 0, blksz
,
1749 (char *)ext4fs_indir1_block
);
1751 printf("** TI ext2fs read block (indir 2 1)"
1755 ext4fs_indir1_blkno
=
1756 __le32_to_cpu(inode
->b
.blocks
.triple_indir_block
) <<
1760 if (ext4fs_indir2_block
== NULL
) {
1761 ext4fs_indir2_block
= zalloc(blksz
);
1762 if (ext4fs_indir2_block
== NULL
) {
1763 printf("** TI ext2fs read block (indir 2 2)"
1764 "malloc failed. **\n");
1767 ext4fs_indir2_size
= blksz
;
1768 ext4fs_indir2_blkno
= -1;
1770 if (blksz
!= ext4fs_indir2_size
) {
1771 free(ext4fs_indir2_block
);
1772 ext4fs_indir2_block
= NULL
;
1773 ext4fs_indir2_size
= 0;
1774 ext4fs_indir2_blkno
= -1;
1775 ext4fs_indir2_block
= zalloc(blksz
);
1776 if (ext4fs_indir2_block
== NULL
) {
1777 printf("** TI ext2fs read block (indir 2 2)"
1778 "malloc failed. **\n");
1781 ext4fs_indir2_size
= blksz
;
1783 if ((__le32_to_cpu(ext4fs_indir1_block
[rblock
/
1784 perblock_parent
]) <<
1786 != ext4fs_indir2_blkno
) {
1787 status
= ext4fs_devread((lbaint_t
)__le32_to_cpu
1788 (ext4fs_indir1_block
1790 perblock_parent
]) <<
1791 log2_blksz
, 0, blksz
,
1792 (char *)ext4fs_indir2_block
);
1794 printf("** TI ext2fs read block (indir 2 2)"
1798 ext4fs_indir2_blkno
=
1799 __le32_to_cpu(ext4fs_indir1_block
[rblock
/
1804 if (ext4fs_indir3_block
== NULL
) {
1805 ext4fs_indir3_block
= zalloc(blksz
);
1806 if (ext4fs_indir3_block
== NULL
) {
1807 printf("** TI ext2fs read block (indir 2 2)"
1808 "malloc failed. **\n");
1811 ext4fs_indir3_size
= blksz
;
1812 ext4fs_indir3_blkno
= -1;
1814 if (blksz
!= ext4fs_indir3_size
) {
1815 free(ext4fs_indir3_block
);
1816 ext4fs_indir3_block
= NULL
;
1817 ext4fs_indir3_size
= 0;
1818 ext4fs_indir3_blkno
= -1;
1819 ext4fs_indir3_block
= zalloc(blksz
);
1820 if (ext4fs_indir3_block
== NULL
) {
1821 printf("** TI ext2fs read block (indir 2 2)"
1822 "malloc failed. **\n");
1825 ext4fs_indir3_size
= blksz
;
1827 if ((__le32_to_cpu(ext4fs_indir2_block
[rblock
1830 log2_blksz
) != ext4fs_indir3_blkno
) {
1832 ext4fs_devread((lbaint_t
)__le32_to_cpu
1833 (ext4fs_indir2_block
1834 [(rblock
/ perblock_child
)
1835 % (blksz
/ 4)]) << log2_blksz
, 0,
1836 blksz
, (char *)ext4fs_indir3_block
);
1838 printf("** TI ext2fs read block (indir 2 2)"
1842 ext4fs_indir3_blkno
=
1843 __le32_to_cpu(ext4fs_indir2_block
[(rblock
/
1850 blknr
= __le32_to_cpu(ext4fs_indir3_block
1851 [rblock
% perblock_child
]);
1853 debug("read_allocated_block %ld\n", blknr
);
1858 void ext4fs_close(void)
1860 if ((ext4fs_file
!= NULL
) && (ext4fs_root
!= NULL
)) {
1861 ext4fs_free_node(ext4fs_file
, &ext4fs_root
->diropen
);
1864 if (ext4fs_root
!= NULL
) {
1868 if (ext4fs_indir1_block
!= NULL
) {
1869 free(ext4fs_indir1_block
);
1870 ext4fs_indir1_block
= NULL
;
1871 ext4fs_indir1_size
= 0;
1872 ext4fs_indir1_blkno
= -1;
1874 if (ext4fs_indir2_block
!= NULL
) {
1875 free(ext4fs_indir2_block
);
1876 ext4fs_indir2_block
= NULL
;
1877 ext4fs_indir2_size
= 0;
1878 ext4fs_indir2_blkno
= -1;
1880 if (ext4fs_indir3_block
!= NULL
) {
1881 free(ext4fs_indir3_block
);
1882 ext4fs_indir3_block
= NULL
;
1883 ext4fs_indir3_size
= 0;
1884 ext4fs_indir3_blkno
= -1;
1888 int ext4fs_iterate_dir(struct ext2fs_node
*dir
, char *name
,
1889 struct ext2fs_node
**fnode
, int *ftype
)
1891 unsigned int fpos
= 0;
1893 struct ext2fs_node
*diro
= (struct ext2fs_node
*) dir
;
1897 printf("Iterate dir %s\n", name
);
1898 #endif /* of DEBUG */
1899 if (!diro
->inode_read
) {
1900 status
= ext4fs_read_inode(diro
->data
, diro
->ino
, &diro
->inode
);
1904 /* Search the file. */
1905 while (fpos
< __le32_to_cpu(diro
->inode
.size
)) {
1906 struct ext2_dirent dirent
;
1908 status
= ext4fs_read_file(diro
, fpos
,
1909 sizeof(struct ext2_dirent
),
1914 if (dirent
.namelen
!= 0) {
1915 char filename
[dirent
.namelen
+ 1];
1916 struct ext2fs_node
*fdiro
;
1917 int type
= FILETYPE_UNKNOWN
;
1919 status
= ext4fs_read_file(diro
,
1921 sizeof(struct ext2_dirent
),
1922 dirent
.namelen
, filename
);
1926 fdiro
= zalloc(sizeof(struct ext2fs_node
));
1930 fdiro
->data
= diro
->data
;
1931 fdiro
->ino
= __le32_to_cpu(dirent
.inode
);
1933 filename
[dirent
.namelen
] = '\0';
1935 if (dirent
.filetype
!= FILETYPE_UNKNOWN
) {
1936 fdiro
->inode_read
= 0;
1938 if (dirent
.filetype
== FILETYPE_DIRECTORY
)
1939 type
= FILETYPE_DIRECTORY
;
1940 else if (dirent
.filetype
== FILETYPE_SYMLINK
)
1941 type
= FILETYPE_SYMLINK
;
1942 else if (dirent
.filetype
== FILETYPE_REG
)
1943 type
= FILETYPE_REG
;
1945 status
= ext4fs_read_inode(diro
->data
,
1953 fdiro
->inode_read
= 1;
1955 if ((__le16_to_cpu(fdiro
->inode
.mode
) &
1956 FILETYPE_INO_MASK
) ==
1957 FILETYPE_INO_DIRECTORY
) {
1958 type
= FILETYPE_DIRECTORY
;
1959 } else if ((__le16_to_cpu(fdiro
->inode
.mode
)
1960 & FILETYPE_INO_MASK
) ==
1961 FILETYPE_INO_SYMLINK
) {
1962 type
= FILETYPE_SYMLINK
;
1963 } else if ((__le16_to_cpu(fdiro
->inode
.mode
)
1964 & FILETYPE_INO_MASK
) ==
1966 type
= FILETYPE_REG
;
1970 printf("iterate >%s<\n", filename
);
1971 #endif /* of DEBUG */
1972 if ((name
!= NULL
) && (fnode
!= NULL
)
1973 && (ftype
!= NULL
)) {
1974 if (strcmp(filename
, name
) == 0) {
1980 if (fdiro
->inode_read
== 0) {
1981 status
= ext4fs_read_inode(diro
->data
,
1989 fdiro
->inode_read
= 1;
1992 case FILETYPE_DIRECTORY
:
1995 case FILETYPE_SYMLINK
:
2006 __le32_to_cpu(fdiro
->inode
.size
),
2011 fpos
+= __le16_to_cpu(dirent
.direntlen
);
2016 static char *ext4fs_read_symlink(struct ext2fs_node
*node
)
2019 struct ext2fs_node
*diro
= node
;
2022 if (!diro
->inode_read
) {
2023 status
= ext4fs_read_inode(diro
->data
, diro
->ino
, &diro
->inode
);
2027 symlink
= zalloc(__le32_to_cpu(diro
->inode
.size
) + 1);
2031 if (__le32_to_cpu(diro
->inode
.size
) <= 60) {
2032 strncpy(symlink
, diro
->inode
.b
.symlink
,
2033 __le32_to_cpu(diro
->inode
.size
));
2035 status
= ext4fs_read_file(diro
, 0,
2036 __le32_to_cpu(diro
->inode
.size
),
2043 symlink
[__le32_to_cpu(diro
->inode
.size
)] = '\0';
2047 static int ext4fs_find_file1(const char *currpath
,
2048 struct ext2fs_node
*currroot
,
2049 struct ext2fs_node
**currfound
, int *foundtype
)
2051 char fpath
[strlen(currpath
) + 1];
2055 int type
= FILETYPE_DIRECTORY
;
2056 struct ext2fs_node
*currnode
= currroot
;
2057 struct ext2fs_node
*oldnode
= currroot
;
2059 strncpy(fpath
, currpath
, strlen(currpath
) + 1);
2061 /* Remove all leading slashes. */
2062 while (*name
== '/')
2066 *currfound
= currnode
;
2073 /* Extract the actual part from the pathname. */
2074 next
= strchr(name
, '/');
2076 /* Remove all leading slashes. */
2077 while (*next
== '/')
2081 if (type
!= FILETYPE_DIRECTORY
) {
2082 ext4fs_free_node(currnode
, currroot
);
2088 /* Iterate over the directory. */
2089 found
= ext4fs_iterate_dir(currnode
, name
, &currnode
, &type
);
2096 /* Read in the symlink and follow it. */
2097 if (type
== FILETYPE_SYMLINK
) {
2100 /* Test if the symlink does not loop. */
2101 if (++symlinknest
== 8) {
2102 ext4fs_free_node(currnode
, currroot
);
2103 ext4fs_free_node(oldnode
, currroot
);
2107 symlink
= ext4fs_read_symlink(currnode
);
2108 ext4fs_free_node(currnode
, currroot
);
2111 ext4fs_free_node(oldnode
, currroot
);
2115 debug("Got symlink >%s<\n", symlink
);
2117 if (symlink
[0] == '/') {
2118 ext4fs_free_node(oldnode
, currroot
);
2119 oldnode
= &ext4fs_root
->diropen
;
2122 /* Lookup the node the symlink points to. */
2123 status
= ext4fs_find_file1(symlink
, oldnode
,
2129 ext4fs_free_node(oldnode
, currroot
);
2134 ext4fs_free_node(oldnode
, currroot
);
2136 /* Found the node! */
2137 if (!next
|| *next
== '\0') {
2138 *currfound
= currnode
;
2147 int ext4fs_find_file(const char *path
, struct ext2fs_node
*rootnode
,
2148 struct ext2fs_node
**foundnode
, int expecttype
)
2151 int foundtype
= FILETYPE_DIRECTORY
;
2157 status
= ext4fs_find_file1(path
, rootnode
, foundnode
, &foundtype
);
2161 /* Check if the node that was found was of the expected type. */
2162 if ((expecttype
== FILETYPE_REG
) && (foundtype
!= expecttype
))
2164 else if ((expecttype
== FILETYPE_DIRECTORY
)
2165 && (foundtype
!= expecttype
))
2171 int ext4fs_open(const char *filename
)
2173 struct ext2fs_node
*fdiro
= NULL
;
2177 if (ext4fs_root
== NULL
)
2181 status
= ext4fs_find_file(filename
, &ext4fs_root
->diropen
, &fdiro
,
2186 if (!fdiro
->inode_read
) {
2187 status
= ext4fs_read_inode(fdiro
->data
, fdiro
->ino
,
2192 len
= __le32_to_cpu(fdiro
->inode
.size
);
2193 ext4fs_file
= fdiro
;
2197 ext4fs_free_node(fdiro
, &ext4fs_root
->diropen
);
2202 int ext4fs_mount(unsigned part_length
)
2204 struct ext2_data
*data
;
2206 struct ext_filesystem
*fs
= get_fs();
2207 data
= zalloc(SUPERBLOCK_SIZE
);
2211 /* Read the superblock. */
2212 status
= ext4_read_superblock((char *)&data
->sblock
);
2217 /* Make sure this is an ext2 filesystem. */
2218 if (__le16_to_cpu(data
->sblock
.magic
) != EXT2_MAGIC
)
2221 if (__le32_to_cpu(data
->sblock
.revision_level
== 0))
2224 fs
->inodesz
= __le16_to_cpu(data
->sblock
.inode_size
);
2226 debug("EXT2 rev %d, inode_size %d\n",
2227 __le32_to_cpu(data
->sblock
.revision_level
), fs
->inodesz
);
2229 data
->diropen
.data
= data
;
2230 data
->diropen
.ino
= 2;
2231 data
->diropen
.inode_read
= 1;
2232 data
->inode
= &data
->diropen
.inode
;
2234 status
= ext4fs_read_inode(data
, 2, data
->inode
);
2242 printf("Failed to mount ext2 filesystem...\n");