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
;
225 TotalBlocks
= Inode
->i_blocks
/ (Ext2Sys
->blocksize
/ SECTOR_SIZE
);
226 Index
= Ext2DataBlocks(Ext2Sys
, TotalBlocks
);
228 for (i
= 0; i
< 4; i
++)
230 dwSizes
[i
] = dwSizes
[i
] << ((10 + pExt2Sb
->s_log_block_size
- 2) * i
);
231 dwTotal
+= dwSizes
[i
];
234 if (Index
>= dwTotal
)
236 DPRINT1("Mke2fs: ext2_expand_inode: beyond the maxinum size of an inode.\n");
240 for (i
= 0; i
< 4; i
++)
242 if (Index
< dwSizes
[i
])
246 Inode
->i_block
[Index
] = newBlk
;
250 dwBlk
= Inode
->i_block
[(i
+ 12 - 1)];
254 if (ext2_alloc_block(Ext2Sys
, 0, &dwBlk
))
256 Inode
->i_block
[(i
+ 12 - 1)] = dwBlk
;
258 Inode
->i_blocks
+= (Ext2Sys
->blocksize
/ SECTOR_SIZE
);
267 bRet
= ext2_expand_block(
288 bool ext2_get_block(PEXT2_FILESYS Ext2Sys
, ULONG dwContent
, ULONG Index
, int layer
, ULONG
*dwRet
)
292 ULONG i
= 0, j
= 0, temp
= 1;
296 PEXT2_SUPER_BLOCK pExt2Sb
= Ext2Sys
->ext2_sb
;
298 Offset
= (LONGLONG
) dwContent
;
299 Offset
= Offset
* Ext2Sys
->blocksize
;
301 pData
= (ULONG
*)RtlAllocateHeap(RtlGetProcessHeap(), 0, Ext2Sys
->blocksize
);
307 memset(pData
, 0, Ext2Sys
->blocksize
);
316 if (!ext2_read_block(Ext2Sys
, dwContent
, (void *)pData
))
322 temp
= 1 << ((10 + pExt2Sb
->s_log_block_size
- 2) * (layer
- 1));
327 if (!ext2_get_block(Ext2Sys
, pData
[i
], j
, layer
- 1, &dwBlk
))
330 DPRINT1("Mke2fs: ext2_get_block: ... error recuise...\n");
338 RtlFreeHeap(RtlGetProcessHeap(), 0, pData
);
346 bool ext2_block_map(PEXT2_FILESYS Ext2Sys
, PEXT2_INODE inode
, ULONG block
, ULONG
*dwRet
)
348 ULONG dwSizes
[4] = { 12, 1, 1, 1 };
351 PEXT2_SUPER_BLOCK pExt2Sb
= Ext2Sys
->ext2_sb
;
357 for (i
= 0; i
< 4; i
++)
359 dwSizes
[i
] = dwSizes
[i
] << ((10 + pExt2Sb
->s_log_block_size
- 2) * i
);
362 if (Index
>= inode
->i_blocks
/ (Ext2Sys
->blocksize
/ SECTOR_SIZE
))
364 DPRINT1("Mke2fs: ext2_block_map: beyond the size of the inode.\n");
368 for (i
= 0; i
< 4; i
++)
370 if (Index
< dwSizes
[i
])
372 dwBlk
= inode
->i_block
[i
==0 ? (Index
):(i
+ 12 - 1)];
374 bRet
= ext2_get_block(Ext2Sys
, dwBlk
, Index
, i
, &dwBlk
);
392 ULONG
ext2_build_bdl(PEXT2_FILESYS Ext2Sys
,
393 PEXT2_INODE ext2_inode
,
396 OUT PEXT2_BDL
*ext2_bdl
)
398 ULONG nBeg
, nEnd
, nBlocks
;
404 PEXT2_BDL ext2bdl
= NULL
;
408 if (offset
>= ext2_inode
->i_size
)
410 DPRINT1("Mke2fs: ext2_build_bdl: beyond the file range.\n");
415 if (offset + size > ext2_inode->i_size)
417 size = ext2_inode->i_size - offset;
421 nBeg
= offset
/ Ext2Sys
->blocksize
;
422 nEnd
= (size
+ offset
+ Ext2Sys
->blocksize
- 1) / Ext2Sys
->blocksize
;
424 nBlocks
= nEnd
- nBeg
;
428 ext2bdl
= (PEXT2_BDL
)
429 RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(EXT2_BDL
) * nBlocks
);
434 memset(ext2bdl
, 0, sizeof(EXT2_BDL
) * nBlocks
);
436 for (i
= nBeg
; i
< nEnd
; i
++)
438 if (!ext2_block_map(Ext2Sys
, ext2_inode
, i
, &dwBlk
))
443 lba
= (LONGLONG
) dwBlk
;
444 lba
= lba
* Ext2Sys
->blocksize
;
446 if (nBlocks
== 1) // ie. (nBeg == nEnd - 1)
449 ext2bdl
[i
- nBeg
].Lba
= lba
+ (LONGLONG
)(offset
% (Ext2Sys
->blocksize
));
450 ext2bdl
[i
- nBeg
].Length
= dwBytes
;
451 ext2bdl
[i
- nBeg
].Offset
= 0;
457 dwBytes
= Ext2Sys
->blocksize
- (offset
% (Ext2Sys
->blocksize
));
458 ext2bdl
[i
- nBeg
].Lba
= lba
+ (LONGLONG
)(offset
% (Ext2Sys
->blocksize
));
459 ext2bdl
[i
- nBeg
].Length
= dwBytes
;
460 ext2bdl
[i
- nBeg
].Offset
= 0;
462 else if (i
== nEnd
- 1)
464 ext2bdl
[i
- nBeg
].Lba
= lba
;
465 ext2bdl
[i
- nBeg
].Length
= size
- dwBytes
;
466 ext2bdl
[i
- nBeg
].Offset
= dwBytes
;
471 ext2bdl
[i
- nBeg
].Lba
= lba
;
472 ext2bdl
[i
- nBeg
].Length
= Ext2Sys
->blocksize
;
473 ext2bdl
[i
- nBeg
].Offset
= dwBytes
;
474 dwBytes
+= Ext2Sys
->blocksize
;
487 RtlFreeHeap(RtlGetProcessHeap(), 0, ext2bdl
);
494 bool ext2_read_inode(PEXT2_FILESYS Ext2Sys
,
501 PEXT2_BDL ext2_bdl
= NULL
;
504 EXT2_INODE ext2_inode
;
507 if (!ext2_load_inode(Ext2Sys
, ino
, &ext2_inode
))
512 blocks
= ext2_build_bdl(Ext2Sys
, &ext2_inode
, offset
, size
, &ext2_bdl
);
518 for(i
= 0; i
< blocks
; i
++)
520 bRet
= NT_SUCCESS(Ext2ReadDisk(
524 (PUCHAR
)Buffer
+ ext2_bdl
[i
].Offset
529 dwTotal
+= ext2_bdl
[i
].Length
;
535 RtlFreeHeap(RtlGetProcessHeap(), 0, ext2_bdl
);
541 bool ext2_write_inode (PEXT2_FILESYS Ext2Sys
,
548 PEXT2_BDL ext2_bdl
= NULL
;
556 blocks
= (size
+ offset
+ Ext2Sys
->blocksize
- 1) / Ext2Sys
->blocksize
;
558 if (!ext2_load_inode(Ext2Sys
, ino
, &inode
))
563 TotalBlks
= inode
.i_blocks
/ (Ext2Sys
->blocksize
/ SECTOR_SIZE
);
564 TotalBlks
= Ext2DataBlocks(Ext2Sys
, TotalBlks
);
566 if (blocks
> TotalBlks
)
568 for (i
=0; i
< (blocks
- TotalBlks
); i
++)
570 if (ext2_alloc_block(Ext2Sys
, 0, &dwBlk
) )
572 ext2_expand_inode(Ext2Sys
, &inode
, dwBlk
);
573 inode
.i_blocks
+= (Ext2Sys
->blocksize
/SECTOR_SIZE
);
578 blocks
= ext2_build_bdl(Ext2Sys
, &inode
, offset
, size
, &ext2_bdl
);
583 for(i
= 0; i
< blocks
; i
++)
585 bRet
= NT_SUCCESS(Ext2WriteDisk(
589 (PUCHAR
)Buffer
+ ext2_bdl
[i
].Offset
597 dwTotal
+= ext2_bdl
[i
].Length
;
602 if (size
+ offset
> inode
.i_size
)
604 inode
.i_size
= size
+ offset
;
607 ext2_save_inode(Ext2Sys
, ino
, &inode
);
613 RtlFreeHeap(RtlGetProcessHeap(), 0, ext2_bdl
);
619 ext2_add_entry( PEXT2_FILESYS Ext2Sys
,
620 ULONG parent
, ULONG inode
,
621 int filetype
, char *name
)
623 PEXT2_DIR_ENTRY2 dir
= NULL
, newdir
= NULL
;
624 EXT2_INODE parent_inode
;
630 rec_len
= EXT2_DIR_REC_LEN(strlen(name
));
632 if (!ext2_load_inode(Ext2Sys
, parent
, &parent_inode
))
637 buf
= (char *)RtlAllocateHeap(RtlGetProcessHeap(), 0, parent_inode
.i_size
);
639 if (!ext2_read_inode(Ext2Sys
, parent
, 0, buf
, parent_inode
.i_size
, &dwRet
))
644 dir
= (PEXT2_DIR_ENTRY2
) buf
;
646 while ((char *)dir
< buf
+ parent_inode
.i_size
)
648 if ((dir
->inode
== 0 && dir
->rec_len
>= rec_len
) ||
649 (dir
->rec_len
>= dir
->name_len
+ rec_len
) )
653 newdir
= (PEXT2_DIR_ENTRY2
) ((PUCHAR
)dir
+ EXT2_DIR_REC_LEN(dir
->name_len
));
654 newdir
->rec_len
= dir
->rec_len
- EXT2_DIR_REC_LEN(dir
->name_len
);
656 dir
->rec_len
= EXT2_DIR_REC_LEN(dir
->name_len
);
661 dir
->file_type
= filetype
;
663 dir
->name_len
= strlen(name
);
664 memcpy(dir
->name
, name
, strlen(name
));
670 dir
= (PEXT2_DIR_ENTRY2
) (dir
->rec_len
+ (PUCHAR
) dir
);
675 return ext2_write_inode(Ext2Sys
, parent
, 0, buf
, parent_inode
.i_size
, &dwRet
);
681 bool ext2_reserve_inodes(PEXT2_FILESYS fs
)
686 for (i
= EXT2_ROOT_INO
+ 1; i
< EXT2_FIRST_INODE(fs
->ext2_sb
); i
++)
688 ext2_mark_inode_bitmap(fs
->inode_map
, i
);
689 group
= ext2_group_of_ino(fs
, i
);
690 fs
->group_desc
[group
].bg_free_inodes_count
--;
691 fs
->ext2_sb
->s_free_inodes_count
--;