4 * PROGRAMMER: Matt Wu <mattwu@163.com>
5 * HOMEPAGE: http://ext2.yeah.net
8 /* INCLUDES **************************************************************/
13 /* DEFINITIONS ***********************************************************/
15 extern char *device_name
;
17 /* FUNCTIONS *************************************************************/
20 bool ext2_get_inode_lba(PEXT2_FILESYS Ext2Sys
, ULONG no
, LONGLONG
*offset
)
23 PEXT2_SUPER_BLOCK pExt2Sb
= Ext2Sys
->ext2_sb
;
25 if (no
< 1 || no
> pExt2Sb
->s_inodes_count
)
27 DPRINT1("Mke2fs: Inode value %lu was out of range in load_inode.(1-%ld)\n",
28 no
, pExt2Sb
->s_inodes_count
);
33 loc
= (LONGLONG
)(Ext2Sys
->blocksize
) * Ext2Sys
->group_desc
[(no
- 1) / pExt2Sb
->s_inodes_per_group
].bg_inode_table
+
34 ((no
- 1) % pExt2Sb
->s_inodes_per_group
) * sizeof(EXT2_INODE
);
41 bool ext2_load_inode(PEXT2_FILESYS Ext2Sys
, ULONG no
, PEXT2_INODE pInode
)
46 if (ext2_get_inode_lba(Ext2Sys
, no
, &Offset
))
48 bRet
= NT_SUCCESS(Ext2ReadDisk(
52 (unsigned char *)pInode
));
59 bool ext2_save_inode(PEXT2_FILESYS Ext2Sys
, ULONG no
, PEXT2_INODE pInode
)
64 if (ext2_get_inode_lba(Ext2Sys
, no
, &offset
))
66 bRet
= NT_SUCCESS(Ext2WriteDisk(
70 (unsigned char *)pInode
));
78 * Right now, just search forward from the parent directory's block
79 * group to find the next free inode.
81 * Should have a special policy for directories.
84 bool ext2_new_inode(PEXT2_FILESYS fs
, ULONG dir
, int mode
,
85 PEXT2_INODE_BITMAP map
, ULONG
*ret
)
98 dir_group
= (dir
- 1) / EXT2_INODES_PER_GROUP(fs
->ext2_sb
);
100 start_inode
= (dir_group
* EXT2_INODES_PER_GROUP(fs
->ext2_sb
)) + 1;
102 if (start_inode
< EXT2_FIRST_INODE(fs
->ext2_sb
))
103 start_inode
= EXT2_FIRST_INODE(fs
->ext2_sb
);
109 if (!ext2_test_inode_bitmap(map
, i
))
114 if (i
> fs
->ext2_sb
->s_inodes_count
)
115 i
= EXT2_FIRST_INODE(fs
->ext2_sb
);
117 } while (i
!= start_inode
);
119 if (ext2_test_inode_bitmap(map
, i
))
128 bool ext2_expand_block( PEXT2_FILESYS Ext2Sys
, PEXT2_INODE Inode
,
129 ULONG dwContent
, ULONG Index
, int layer
,
130 ULONG newBlk
, ULONG
*dwRet
, ULONG
*off
)
133 ULONG i
= 0, j
= 0, temp
= 1;
135 ULONG dwNewBlk
= newBlk
;
140 PEXT2_SUPER_BLOCK pExt2Sb
= Ext2Sys
->ext2_sb
;
142 pData
= (ULONG
*)RtlAllocateHeap(RtlGetProcessHeap(), 0, Ext2Sys
->blocksize
);
150 if (!ext2_read_block(Ext2Sys
, dwContent
, (void *)pData
))
160 pData
[Index
] = newBlk
;
166 temp
= 1 << ((10 + pExt2Sb
->s_log_block_size
- 2) * (layer
- 1));
175 if (ext2_alloc_block(Ext2Sys
, 0, &dwBlk
) )
180 Inode
->i_blocks
+= (Ext2Sys
->blocksize
/ SECTOR_SIZE
);
187 if (!ext2_expand_block(Ext2Sys
, Inode
, dwBlk
, j
, layer
- 1, bDirty
, &dwNewBlk
, &Offset
))
190 DPRINT1("Mke2fs: ext2_expand_block: ... error recuise...\n");
197 bRet
= ext2_write_block(Ext2Sys
, dwContent
, (void *)pData
);
204 RtlFreeHeap(RtlGetProcessHeap(), 0, pData
);
212 bool ext2_expand_inode( PEXT2_FILESYS Ext2Sys
,
216 ULONG dwSizes
[4] = {12, 1, 1, 1};
219 ULONG dwBlk
= 0, dwNewBlk
= 0, Offset
= 0;
220 PEXT2_SUPER_BLOCK pExt2Sb
= Ext2Sys
->ext2_sb
;
226 TotalBlocks
= Inode
->i_blocks
/ (Ext2Sys
->blocksize
/ SECTOR_SIZE
);
227 Index
= Ext2DataBlocks(Ext2Sys
, TotalBlocks
);
229 for (i
= 0; i
< 4; i
++)
231 dwSizes
[i
] = dwSizes
[i
] << ((10 + pExt2Sb
->s_log_block_size
- 2) * i
);
232 dwTotal
+= dwSizes
[i
];
235 if (Index
>= dwTotal
)
237 DPRINT1("Mke2fs: ext2_expand_inode: beyond the maxinum size of an inode.\n");
241 for (i
= 0; i
< 4; i
++)
243 if (Index
< dwSizes
[i
])
247 Inode
->i_block
[Index
] = newBlk
;
252 dwBlk
= Inode
->i_block
[(i
+ 12 - 1)];
256 if (ext2_alloc_block(Ext2Sys
, 0, &dwBlk
))
258 Inode
->i_block
[(i
+ 12 - 1)] = dwBlk
;
261 Inode
->i_blocks
+= (Ext2Sys
->blocksize
/ SECTOR_SIZE
);
270 bRet
= ext2_expand_block(
291 bool ext2_get_block(PEXT2_FILESYS Ext2Sys
, ULONG dwContent
, ULONG Index
, int layer
, ULONG
*dwRet
)
295 ULONG i
= 0, j
= 0, temp
= 1;
299 PEXT2_SUPER_BLOCK pExt2Sb
= Ext2Sys
->ext2_sb
;
301 Offset
= (LONGLONG
) dwContent
;
302 Offset
= Offset
* Ext2Sys
->blocksize
;
304 pData
= (ULONG
*)RtlAllocateHeap(RtlGetProcessHeap(), 0, Ext2Sys
->blocksize
);
310 memset(pData
, 0, Ext2Sys
->blocksize
);
319 if (!ext2_read_block(Ext2Sys
, dwContent
, (void *)pData
))
325 temp
= 1 << ((10 + pExt2Sb
->s_log_block_size
- 2) * (layer
- 1));
330 if (!ext2_get_block(Ext2Sys
, pData
[i
], j
, layer
- 1, &dwBlk
))
333 DPRINT1("Mke2fs: ext2_get_block: ... error recuise...\n");
341 RtlFreeHeap(RtlGetProcessHeap(), 0, pData
);
349 bool ext2_block_map(PEXT2_FILESYS Ext2Sys
, PEXT2_INODE inode
, ULONG block
, ULONG
*dwRet
)
351 ULONG dwSizes
[4] = { 12, 1, 1, 1 };
354 PEXT2_SUPER_BLOCK pExt2Sb
= Ext2Sys
->ext2_sb
;
360 for (i
= 0; i
< 4; i
++)
362 dwSizes
[i
] = dwSizes
[i
] << ((10 + pExt2Sb
->s_log_block_size
- 2) * i
);
365 if (Index
>= inode
->i_blocks
/ (Ext2Sys
->blocksize
/ SECTOR_SIZE
))
367 DPRINT1("Mke2fs: ext2_block_map: beyond the size of the inode.\n");
371 for (i
= 0; i
< 4; i
++)
373 if (Index
< dwSizes
[i
])
375 dwBlk
= inode
->i_block
[i
==0 ? (Index
):(i
+ 12 - 1)];
377 bRet
= ext2_get_block(Ext2Sys
, dwBlk
, Index
, i
, &dwBlk
);
395 ULONG
ext2_build_bdl(PEXT2_FILESYS Ext2Sys
,
396 PEXT2_INODE ext2_inode
,
399 OUT PEXT2_BDL
*ext2_bdl
)
401 ULONG nBeg
, nEnd
, nBlocks
;
407 PEXT2_BDL ext2bdl
= NULL
;
411 if (offset
>= ext2_inode
->i_size
)
413 DPRINT1("Mke2fs: ext2_build_bdl: beyond the file range.\n");
418 if (offset + size > ext2_inode->i_size)
420 size = ext2_inode->i_size - offset;
424 nBeg
= offset
/ Ext2Sys
->blocksize
;
425 nEnd
= (size
+ offset
+ Ext2Sys
->blocksize
- 1) / Ext2Sys
->blocksize
;
427 nBlocks
= nEnd
- nBeg
;
431 ext2bdl
= (PEXT2_BDL
)
432 RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(EXT2_BDL
) * nBlocks
);
437 memset(ext2bdl
, 0, sizeof(EXT2_BDL
) * nBlocks
);
439 for (i
= nBeg
; i
< nEnd
; i
++)
441 if (!ext2_block_map(Ext2Sys
, ext2_inode
, i
, &dwBlk
))
446 lba
= (LONGLONG
) dwBlk
;
447 lba
= lba
* Ext2Sys
->blocksize
;
449 if (nBlocks
== 1) // ie. (nBeg == nEnd - 1)
452 ext2bdl
[i
- nBeg
].Lba
= lba
+ (LONGLONG
)(offset
% (Ext2Sys
->blocksize
));
453 ext2bdl
[i
- nBeg
].Length
= dwBytes
;
454 ext2bdl
[i
- nBeg
].Offset
= 0;
460 dwBytes
= Ext2Sys
->blocksize
- (offset
% (Ext2Sys
->blocksize
));
461 ext2bdl
[i
- nBeg
].Lba
= lba
+ (LONGLONG
)(offset
% (Ext2Sys
->blocksize
));
462 ext2bdl
[i
- nBeg
].Length
= dwBytes
;
463 ext2bdl
[i
- nBeg
].Offset
= 0;
465 else if (i
== nEnd
- 1)
467 ext2bdl
[i
- nBeg
].Lba
= lba
;
468 ext2bdl
[i
- nBeg
].Length
= size
- dwBytes
;
469 ext2bdl
[i
- nBeg
].Offset
= dwBytes
;
474 ext2bdl
[i
- nBeg
].Lba
= lba
;
475 ext2bdl
[i
- nBeg
].Length
= Ext2Sys
->blocksize
;
476 ext2bdl
[i
- nBeg
].Offset
= dwBytes
;
477 dwBytes
+= Ext2Sys
->blocksize
;
490 RtlFreeHeap(RtlGetProcessHeap(), 0, ext2bdl
);
497 bool ext2_read_inode(PEXT2_FILESYS Ext2Sys
,
504 PEXT2_BDL ext2_bdl
= NULL
;
507 EXT2_INODE ext2_inode
;
510 if (!ext2_load_inode(Ext2Sys
, ino
, &ext2_inode
))
515 blocks
= ext2_build_bdl(Ext2Sys
, &ext2_inode
, offset
, size
, &ext2_bdl
);
521 for(i
= 0; i
< blocks
; i
++)
523 bRet
= NT_SUCCESS(Ext2ReadDisk(
527 (PUCHAR
)Buffer
+ ext2_bdl
[i
].Offset
532 dwTotal
+= ext2_bdl
[i
].Length
;
538 RtlFreeHeap(RtlGetProcessHeap(), 0, ext2_bdl
);
544 bool ext2_write_inode (PEXT2_FILESYS Ext2Sys
,
551 PEXT2_BDL ext2_bdl
= NULL
;
559 blocks
= (size
+ offset
+ Ext2Sys
->blocksize
- 1) / Ext2Sys
->blocksize
;
561 if (!ext2_load_inode(Ext2Sys
, ino
, &inode
))
566 TotalBlks
= inode
.i_blocks
/ (Ext2Sys
->blocksize
/ SECTOR_SIZE
);
567 TotalBlks
= Ext2DataBlocks(Ext2Sys
, TotalBlks
);
569 if (blocks
> TotalBlks
)
571 for (i
=0; i
< (blocks
- TotalBlks
); i
++)
573 if (ext2_alloc_block(Ext2Sys
, 0, &dwBlk
) )
575 ext2_expand_inode(Ext2Sys
, &inode
, dwBlk
);
576 inode
.i_blocks
+= (Ext2Sys
->blocksize
/SECTOR_SIZE
);
581 blocks
= ext2_build_bdl(Ext2Sys
, &inode
, offset
, size
, &ext2_bdl
);
586 for(i
= 0; i
< blocks
; i
++)
588 bRet
= NT_SUCCESS(Ext2WriteDisk(
592 (PUCHAR
)Buffer
+ ext2_bdl
[i
].Offset
600 dwTotal
+= ext2_bdl
[i
].Length
;
605 if (size
+ offset
> inode
.i_size
)
607 inode
.i_size
= size
+ offset
;
610 ext2_save_inode(Ext2Sys
, ino
, &inode
);
616 RtlFreeHeap(RtlGetProcessHeap(), 0, ext2_bdl
);
622 ext2_add_entry( PEXT2_FILESYS Ext2Sys
,
623 ULONG parent
, ULONG inode
,
624 int filetype
, char *name
)
626 PEXT2_DIR_ENTRY2 dir
= NULL
, newdir
= NULL
;
627 EXT2_INODE parent_inode
;
633 rec_len
= EXT2_DIR_REC_LEN(strlen(name
));
635 if (!ext2_load_inode(Ext2Sys
, parent
, &parent_inode
))
640 buf
= (char *)RtlAllocateHeap(RtlGetProcessHeap(), 0, parent_inode
.i_size
);
642 if (!ext2_read_inode(Ext2Sys
, parent
, 0, buf
, parent_inode
.i_size
, &dwRet
))
647 dir
= (PEXT2_DIR_ENTRY2
) buf
;
649 while ((char *)dir
< buf
+ parent_inode
.i_size
)
651 if ((dir
->inode
== 0 && dir
->rec_len
>= rec_len
) ||
652 (dir
->rec_len
>= dir
->name_len
+ rec_len
) )
656 newdir
= (PEXT2_DIR_ENTRY2
) ((PUCHAR
)dir
+ EXT2_DIR_REC_LEN(dir
->name_len
));
657 newdir
->rec_len
= dir
->rec_len
- EXT2_DIR_REC_LEN(dir
->name_len
);
659 dir
->rec_len
= EXT2_DIR_REC_LEN(dir
->name_len
);
664 dir
->file_type
= filetype
;
666 dir
->name_len
= strlen(name
);
667 memcpy(dir
->name
, name
, strlen(name
));
673 dir
= (PEXT2_DIR_ENTRY2
) (dir
->rec_len
+ (PUCHAR
) dir
);
678 return ext2_write_inode(Ext2Sys
, parent
, 0, buf
, parent_inode
.i_size
, &dwRet
);
684 bool ext2_reserve_inodes(PEXT2_FILESYS fs
)
689 for (i
= EXT2_ROOT_INO
+ 1; i
< EXT2_FIRST_INODE(fs
->ext2_sb
); i
++)
691 ext2_mark_inode_bitmap(fs
->inode_map
, i
);
692 group
= ext2_group_of_ino(fs
, i
);
693 fs
->group_desc
[group
].bg_free_inodes_count
--;
694 fs
->ext2_sb
->s_free_inodes_count
--;