4 * PROGRAMMER: Matt Wu <mattwu@163.com>
5 * HOMEPAGE: http://ext2.yeah.net
8 /* INCLUDES **************************************************************/
12 /* DEFINITIONS ***********************************************************/
14 extern char *device_name
;
16 /* FUNCTIONS *************************************************************/
19 bool ext2_get_inode_lba(PEXT2_FILESYS Ext2Sys
, ULONG no
, LONGLONG
*offset
)
22 PEXT2_SUPER_BLOCK pExt2Sb
= Ext2Sys
->ext2_sb
;
24 if (no
< 1 || no
> pExt2Sb
->s_inodes_count
)
26 KdPrint(("Mke2fs: Inode value %lu was out of range in load_inode.(1-%ld)\n",
27 no
, pExt2Sb
->s_inodes_count
));
32 loc
= (LONGLONG
)(Ext2Sys
->blocksize
) * Ext2Sys
->group_desc
[(no
- 1) / pExt2Sb
->s_inodes_per_group
].bg_inode_table
+
33 ((no
- 1) % pExt2Sb
->s_inodes_per_group
) * sizeof(EXT2_INODE
);
40 bool ext2_load_inode(PEXT2_FILESYS Ext2Sys
, ULONG no
, PEXT2_INODE pInode
)
45 if (ext2_get_inode_lba(Ext2Sys
, no
, &Offset
))
47 bRet
= NT_SUCCESS(Ext2ReadDisk(
51 (unsigned char *)pInode
));
58 bool ext2_save_inode(PEXT2_FILESYS Ext2Sys
, ULONG no
, PEXT2_INODE pInode
)
63 if (ext2_get_inode_lba(Ext2Sys
, no
, &offset
))
65 bRet
= NT_SUCCESS(Ext2WriteDisk(
69 (unsigned char *)pInode
));
77 * Right now, just search forward from the parent directory's block
78 * group to find the next free inode.
80 * Should have a special policy for directories.
83 bool ext2_new_inode(PEXT2_FILESYS fs
, ULONG dir
, int mode
,
84 PEXT2_INODE_BITMAP map
, ULONG
*ret
)
97 dir_group
= (dir
- 1) / EXT2_INODES_PER_GROUP(fs
->ext2_sb
);
99 start_inode
= (dir_group
* EXT2_INODES_PER_GROUP(fs
->ext2_sb
)) + 1;
101 if (start_inode
< EXT2_FIRST_INODE(fs
->ext2_sb
))
102 start_inode
= EXT2_FIRST_INODE(fs
->ext2_sb
);
108 if (!ext2_test_inode_bitmap(map
, i
))
113 if (i
> fs
->ext2_sb
->s_inodes_count
)
114 i
= EXT2_FIRST_INODE(fs
->ext2_sb
);
116 } while (i
!= start_inode
);
118 if (ext2_test_inode_bitmap(map
, i
))
127 bool ext2_expand_block( PEXT2_FILESYS Ext2Sys
, PEXT2_INODE Inode
,
128 ULONG dwContent
, ULONG Index
, int layer
,
129 ULONG newBlk
, ULONG
*dwRet
, ULONG
*off
)
132 ULONG i
= 0, j
= 0, temp
= 1;
134 ULONG dwNewBlk
= newBlk
;
139 PEXT2_SUPER_BLOCK pExt2Sb
= Ext2Sys
->ext2_sb
;
141 pData
= (ULONG
*)RtlAllocateHeap(GetProcessHeap(), 0, Ext2Sys
->blocksize
);
149 if (!ext2_read_block(Ext2Sys
, dwContent
, (void *)pData
))
159 pData
[Index
] = newBlk
;
165 temp
= 1 << ((10 + pExt2Sb
->s_log_block_size
- 2) * (layer
- 1));
174 if (ext2_alloc_block(Ext2Sys
, 0, &dwBlk
) )
179 Inode
->i_blocks
+= (Ext2Sys
->blocksize
/ SECTOR_SIZE
);
186 if (!ext2_expand_block(Ext2Sys
, Inode
, dwBlk
, j
, layer
- 1, bDirty
, &dwNewBlk
, &Offset
))
189 KdPrint(("Mke2fs: ext2_expand_block: ... error recuise...\n"));
196 bRet
= ext2_write_block(Ext2Sys
, dwContent
, (void *)pData
);
203 RtlFreeHeap(GetProcessHeap(), 0, pData
);
211 bool ext2_expand_inode( PEXT2_FILESYS Ext2Sys
,
215 ULONG dwSizes
[4] = {12, 1, 1, 1};
218 ULONG dwBlk
= 0, dwNewBlk
= 0, Offset
= 0;
219 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 KdPrint(("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
;
251 dwBlk
= Inode
->i_block
[(i
+ 12 - 1)];
255 if (ext2_alloc_block(Ext2Sys
, 0, &dwBlk
))
257 Inode
->i_block
[(i
+ 12 - 1)] = dwBlk
;
260 Inode
->i_blocks
+= (Ext2Sys
->blocksize
/ SECTOR_SIZE
);
269 bRet
= ext2_expand_block(
290 bool ext2_get_block(PEXT2_FILESYS Ext2Sys
, ULONG dwContent
, ULONG Index
, int layer
, ULONG
*dwRet
)
294 ULONG i
= 0, j
= 0, temp
= 1;
298 PEXT2_SUPER_BLOCK pExt2Sb
= Ext2Sys
->ext2_sb
;
300 Offset
= (LONGLONG
) dwContent
;
301 Offset
= Offset
* Ext2Sys
->blocksize
;
303 pData
= (ULONG
*)RtlAllocateHeap(GetProcessHeap(), 0, Ext2Sys
->blocksize
);
309 memset(pData
, 0, Ext2Sys
->blocksize
);
318 if (!ext2_read_block(Ext2Sys
, dwContent
, (void *)pData
))
324 temp
= 1 << ((10 + pExt2Sb
->s_log_block_size
- 2) * (layer
- 1));
329 if (!ext2_get_block(Ext2Sys
, pData
[i
], j
, layer
- 1, &dwBlk
))
332 KdPrint(("Mke2fs: ext2_get_block: ... error recuise...\n"));
340 RtlFreeHeap(GetProcessHeap(), 0, pData
);
348 bool ext2_block_map(PEXT2_FILESYS Ext2Sys
, PEXT2_INODE inode
, ULONG block
, ULONG
*dwRet
)
350 ULONG dwSizes
[4] = {12, 1, 1, 1};
353 PEXT2_SUPER_BLOCK pExt2Sb
= Ext2Sys
->ext2_sb
;
359 for (i
= 0; i
< 4; i
++)
361 dwSizes
[i
] = dwSizes
[i
] << ((10 + pExt2Sb
->s_log_block_size
- 2) * i
);
364 if (Index
>= inode
->i_blocks
/ (Ext2Sys
->blocksize
/ SECTOR_SIZE
))
366 KdPrint(("Mke2fs: ext2_block_map: beyond the size of the inode.\n"));
370 for (i
= 0; i
< 4; i
++)
372 if (Index
< dwSizes
[i
])
374 dwBlk
= inode
->i_block
[i
==0 ? (Index
):(i
+ 12 - 1)];
376 bRet
= ext2_get_block(Ext2Sys
, dwBlk
, Index
, i
, &dwBlk
);
394 ULONG
ext2_build_bdl(PEXT2_FILESYS Ext2Sys
,
395 PEXT2_INODE ext2_inode
,
398 OUT PEXT2_BDL
*ext2_bdl
)
400 ULONG nBeg
, nEnd
, nBlocks
;
406 PEXT2_BDL ext2bdl
= NULL
;
410 if (offset
>= ext2_inode
->i_size
)
412 KdPrint(("Mke2fs: ext2_build_bdl: beyond the file range.\n"));
417 if (offset + size > ext2_inode->i_size)
419 size = ext2_inode->i_size - offset;
423 nBeg
= offset
/ Ext2Sys
->blocksize
;
424 nEnd
= (size
+ offset
+ Ext2Sys
->blocksize
- 1) / Ext2Sys
->blocksize
;
426 nBlocks
= nEnd
- nBeg
;
430 ext2bdl
= (PEXT2_BDL
)
431 RtlAllocateHeap(GetProcessHeap(), 0, sizeof(EXT2_BDL
) * nBlocks
);
436 memset(ext2bdl
, 0, sizeof(EXT2_BDL
) * nBlocks
);
438 for (i
= nBeg
; i
< nEnd
; i
++)
440 if (!ext2_block_map(Ext2Sys
, ext2_inode
, i
, &dwBlk
))
445 lba
= (LONGLONG
) dwBlk
;
446 lba
= lba
* Ext2Sys
->blocksize
;
448 if (nBlocks
== 1) // ie. (nBeg == nEnd - 1)
451 ext2bdl
[i
- nBeg
].Lba
= lba
+ (LONGLONG
)(offset
% (Ext2Sys
->blocksize
));
452 ext2bdl
[i
- nBeg
].Length
= dwBytes
;
453 ext2bdl
[i
- nBeg
].Offset
= 0;
459 dwBytes
= Ext2Sys
->blocksize
- (offset
% (Ext2Sys
->blocksize
));
460 ext2bdl
[i
- nBeg
].Lba
= lba
+ (LONGLONG
)(offset
% (Ext2Sys
->blocksize
));
461 ext2bdl
[i
- nBeg
].Length
= dwBytes
;
462 ext2bdl
[i
- nBeg
].Offset
= 0;
464 else if (i
== nEnd
- 1)
466 ext2bdl
[i
- nBeg
].Lba
= lba
;
467 ext2bdl
[i
- nBeg
].Length
= size
- dwBytes
;
468 ext2bdl
[i
- nBeg
].Offset
= dwBytes
;
473 ext2bdl
[i
- nBeg
].Lba
= lba
;
474 ext2bdl
[i
- nBeg
].Length
= Ext2Sys
->blocksize
;
475 ext2bdl
[i
- nBeg
].Offset
= dwBytes
;
476 dwBytes
+= Ext2Sys
->blocksize
;
489 RtlFreeHeap(GetProcessHeap(), 0, ext2bdl
);
496 bool ext2_read_inode(PEXT2_FILESYS Ext2Sys
,
503 PEXT2_BDL ext2_bdl
= NULL
;
506 EXT2_INODE ext2_inode
;
509 if (!ext2_load_inode(Ext2Sys
, ino
, &ext2_inode
))
514 blocks
= ext2_build_bdl(Ext2Sys
, &ext2_inode
, offset
, size
, &ext2_bdl
);
520 for(i
= 0; i
< blocks
; i
++)
522 bRet
= NT_SUCCESS(Ext2ReadDisk(
526 (PUCHAR
)Buffer
+ ext2_bdl
[i
].Offset
531 dwTotal
+= ext2_bdl
[i
].Length
;
537 RtlFreeHeap(GetProcessHeap(), 0, ext2_bdl
);
543 bool ext2_write_inode (PEXT2_FILESYS Ext2Sys
,
550 PEXT2_BDL ext2_bdl
= NULL
;
558 blocks
= (size
+ offset
+ Ext2Sys
->blocksize
- 1) / Ext2Sys
->blocksize
;
560 if (!ext2_load_inode(Ext2Sys
, ino
, &inode
))
565 TotalBlks
= inode
.i_blocks
/ (Ext2Sys
->blocksize
/ SECTOR_SIZE
);
566 TotalBlks
= Ext2DataBlocks(Ext2Sys
, TotalBlks
);
568 if (blocks
> TotalBlks
)
570 for (i
=0; i
< (blocks
- TotalBlks
); i
++)
572 if (ext2_alloc_block(Ext2Sys
, 0, &dwBlk
) )
574 ext2_expand_inode(Ext2Sys
, &inode
, dwBlk
);
575 inode
.i_blocks
+= (Ext2Sys
->blocksize
/SECTOR_SIZE
);
580 blocks
= ext2_build_bdl(Ext2Sys
, &inode
, offset
, size
, &ext2_bdl
);
585 for(i
= 0; i
< blocks
; i
++)
587 bRet
= NT_SUCCESS(Ext2WriteDisk(
591 (PUCHAR
)Buffer
+ ext2_bdl
[i
].Offset
599 dwTotal
+= ext2_bdl
[i
].Length
;
604 if (size
+ offset
> inode
.i_size
)
606 inode
.i_size
= size
+ offset
;
609 ext2_save_inode(Ext2Sys
, ino
, &inode
);
615 RtlFreeHeap(GetProcessHeap(), 0, ext2_bdl
);
621 ext2_add_entry( PEXT2_FILESYS Ext2Sys
,
622 ULONG parent
, ULONG inode
,
623 int filetype
, char *name
)
625 PEXT2_DIR_ENTRY2 dir
= NULL
, newdir
= NULL
;
626 EXT2_INODE parent_inode
;
632 rec_len
= EXT2_DIR_REC_LEN(strlen(name
));
634 if (!ext2_load_inode(Ext2Sys
, parent
, &parent_inode
))
639 buf
= (char *)RtlAllocateHeap(GetProcessHeap(), 0, parent_inode
.i_size
);
641 if (!ext2_read_inode(Ext2Sys
, parent
, 0, buf
, parent_inode
.i_size
, &dwRet
))
646 dir
= (PEXT2_DIR_ENTRY2
) buf
;
648 while ((char *)dir
< buf
+ parent_inode
.i_size
)
650 if ((dir
->inode
== 0 && dir
->rec_len
>= rec_len
) ||
651 (dir
->rec_len
>= dir
->name_len
+ rec_len
) )
655 newdir
= (PEXT2_DIR_ENTRY2
) ((PUCHAR
)dir
+ EXT2_DIR_REC_LEN(dir
->name_len
));
656 newdir
->rec_len
= dir
->rec_len
- EXT2_DIR_REC_LEN(dir
->name_len
);
658 dir
->rec_len
= EXT2_DIR_REC_LEN(dir
->name_len
);
663 dir
->file_type
= filetype
;
665 dir
->name_len
= strlen(name
);
666 memcpy(dir
->name
, name
, strlen(name
));
672 dir
= (PEXT2_DIR_ENTRY2
) (dir
->rec_len
+ (PUCHAR
) dir
);
677 return ext2_write_inode(Ext2Sys
, parent
, 0, buf
, parent_inode
.i_size
, &dwRet
);
683 bool ext2_reserve_inodes(PEXT2_FILESYS fs
)
688 for (i
= EXT2_ROOT_INO
+ 1; i
< EXT2_FIRST_INODE(fs
->ext2_sb
); i
++)
690 ext2_mark_inode_bitmap(fs
->inode_map
, i
);
691 group
= ext2_group_of_ino(fs
, i
);
692 fs
->group_desc
[group
].bg_free_inodes_count
--;
693 fs
->ext2_sb
->s_free_inodes_count
--;