ext2: Factor inode-group deserialization out
diff --git a/src/filo-fs-ext2.adb b/src/filo-fs-ext2.adb
index d7ee599..a69730e 100644
--- a/src/filo-fs-ext2.adb
+++ b/src/filo-fs-ext2.adb
@@ -118,22 +118,22 @@
declare
S_Desc_Size : constant Unsigned_16 := Read_LE16 (Super_Block, 63 * 4 + 2);
begin
- if Natural (S_Desc_Size) in Desc_Size and
+ if Natural (S_Desc_Size) in Group_Desc_Size and
Natural (S_Desc_Size) <= Static.Block_Size and
Is_Power_Of_2 (S_Desc_Size)
then
- Static.Desc_Size := Desc_Size (S_Desc_Size);
+ Static.Group_Desc_Size := Group_Desc_Size (S_Desc_Size);
else
Success := False;
return;
end if;
- pragma Assert (Static.Block_Size / Static.Desc_Size <= Natural (Group_In_Block_Count'Last));
+ pragma Assert (Static.Block_Size / Static.Group_Desc_Size <= Natural (Group_In_Block_Count'Last));
end;
- Static.Feature_64Bit := Static.Feature_64Bit and Static.Desc_Size >= 64;
+ Static.Feature_64Bit := Static.Feature_64Bit and Static.Group_Desc_Size >= 64;
else
- Static.Desc_Size := Desc_Size'First;
+ Static.Group_Desc_Size := Group_Desc_Size'First;
end if;
- Static.Desc_Per_Block := Group_In_Block_Count (Static.Block_Size / Static.Desc_Size);
+ Static.Group_Desc_Per_Block := Group_In_Block_Count (Static.Block_Size / Static.Group_Desc_Size);
end;
pragma Assert_And_Cut (Success);
@@ -606,6 +606,34 @@
end if;
end Extent_Block_Map;
+ procedure Parse_Group
+ (Static : in Mount_State;
+ Table_Start : out FSBlock_Offset;
+ Buf : in Buffer_Type;
+ Success : out Boolean)
+ with
+ Pre =>
+ Buf'Length >= Group_Desc_Size'First and
+ (if Static.Feature_64Bit then Buf'Length >= 64)
+ is
+ Inode_Table_Block : constant Unsigned_64 :=
+ (if Static.Feature_64Bit
+ then Shift_Left (Unsigned_64 (Read_LE32 (Buf, 40)), 32)
+ else 0)
+ or
+ Unsigned_64 (Read_LE32 (Buf, 8));
+ begin
+ if Inode_Table_Block >= Unsigned_64 (Static.First_Data_Block) and
+ Inode_Table_Block <= Unsigned_64 (FSBlock_Offset'Last)
+ then
+ Table_Start := FSBlock_Offset (Inode_Table_Block);
+ Success := True;
+ else
+ Table_Start := 0;
+ Success := False;
+ end if;
+ end Parse_Group;
+
procedure Parse_Inode
(Static : in Mount_State;
Inode : in out Inode_Info;
@@ -669,34 +697,20 @@
Static : Mount_State renames State.Static;
Cache : Cache_Buffer renames State.Cache.Buffer;
- ------------------------
- -- Group deserialization
-
- subtype Group_Off is Natural range 0 .. Desc_Size'Last;
- function Group_Byte_Offset (Idx : Desc_In_Block_Index; Off : Group_Off) return Natural
- is
- (Natural (Idx) * Static.Desc_Size + Off);
-
- function Group_Inode_Table (Buf : Buffer_Type; Idx : Desc_In_Block_Index) return Unsigned_64
- is
- ((if Static.Feature_64Bit
- then Shift_Left (Unsigned_64 (Read_LE32 (Buf, Group_Byte_Offset (Idx, 40))), 32)
- else 0)
- or
- Unsigned_64 (Read_LE32 (Buf, Group_Byte_Offset (Idx, 8))))
- with
- Pre => Buf'Length >= Group_Byte_Offset (Idx, (if Static.Feature_64Bit then 44 else 12));
-
Group : constant Group_Index := Group_Index ((Inode - 1) / Static.Inodes_Per_Group);
- Desc_Block : constant FSBlock_Offset :=
- 1 + FSBlock_Offset (Static.First_Data_Block) + FSBlock_Offset (Group / Static.Desc_Per_Block);
+ Group_Block : constant FSBlock_Offset :=
+ 1 + FSBlock_Offset (Static.First_Data_Block) + FSBlock_Offset (Group / Static.Group_Desc_Per_Block);
+ Group_In_Block : constant Group_In_Block_Index := Group_In_Block_Index (Group mod Static.Group_Desc_Per_Block);
+ Group_In_Block_Offset : constant Natural := Natural (Group_In_Block) * Static.Group_Desc_Size;
+
Cache_Start, Cache_End : Max_Block_Index;
+ First_Table_Block : FSBlock_Offset;
begin
Cache_FSBlock
(Static => Static,
Cache => State.Cache,
- Phys => Desc_Block,
- Level => Natural (Group_Index'Min (Group / Static.Desc_Per_Block,
+ Phys => Group_Block,
+ Level => Natural (Group_Index'Min (Group / Static.Group_Desc_Per_Block,
Group_Index (Block_Cache_Index'Last))),
Cache_Start => Cache_Start,
Cache_End => Cache_End,
@@ -706,31 +720,37 @@
end if;
pragma Assert_And_Cut (Cache_End = Cache_Start + Static.Block_Size - 1);
+ Parse_Group
+ (Static => Static,
+ Table_Start => First_Table_Block,
+ Buf => Cache (Cache_Start + Group_In_Block_Offset ..
+ Cache_Start + Group_In_Block_Offset + Static.Group_Desc_Size - 1),
+ Success => Success);
+ if not Success then
+ return;
+ end if;
+ pragma Assert_And_Cut (Boolean'(True));
+
declare
- Desc : constant Desc_In_Block_Index := Desc_In_Block_Index (Group mod Static.Desc_Per_Block);
Inode_In_Group : constant Inode_In_Group_Index :=
Inode_In_Group_Index ((Inode - 1) mod Static.Inodes_Per_Group);
- First_Table_Block : constant Unsigned_64 := Group_Inode_Table (Cache (Cache_Start .. Cache_End), Desc);
- Block_Offset : constant Unsigned_64 := Unsigned_64 (Inode_In_Group / Static.Inodes_Per_Block);
+ Inode_Block : constant FSBlock_Offset := FSBlock_Offset (Inode_In_Group / Static.Inodes_Per_Block);
Inode_In_Block : constant Inode_In_Block_Index :=
Inode_In_Block_Index (Inode_In_Group mod Static.Inodes_Per_Block);
Inode_In_Block_Offset : constant Natural :=
Natural (Inode_In_Block) * Static.Inode_Size;
begin
- if First_Table_Block < Unsigned_64 (Static.First_Data_Block) or
- First_Table_Block > Unsigned_64 (FSBlock_Offset'Last) - Block_Offset
- then
+ if First_Table_Block > FSBlock_Offset'Last - Inode_Block then
Success := False;
return;
end if;
- pragma Assert_And_Cut
- (First_Table_Block + Block_Offset in 0 .. Unsigned_64 (FSBlock_Offset'Last));
+ pragma Assert_And_Cut (First_Table_Block + Inode_Block in FSBlock_Offset);
Cache_FSBlock
(Static => Static,
Cache => State.Cache,
- Phys => FSBlock_Offset (First_Table_Block + Block_Offset),
+ Phys => FSBlock_Offset (First_Table_Block + Inode_Block),
Level => Block_Cache_Index'Last,
Cache_Start => Cache_Start,
Cache_End => Cache_End,