ext2: Pre-compute Inodes_Per_Block & Desc_Per_Block
Eases proving that they are in range.
diff --git a/src/filo-fs-ext2.adb b/src/filo-fs-ext2.adb
index 3d6c0eb..c7ea867 100644
--- a/src/filo-fs-ext2.adb
+++ b/src/filo-fs-ext2.adb
@@ -71,6 +71,7 @@
return;
end if;
end;
+ pragma Assert_And_Cut (Success);
declare
S_Inodes_Per_Group : constant Unsigned_32 := Read_LE32 (Super_Block, 10 * 4);
@@ -82,6 +83,7 @@
return;
end if;
end;
+ pragma Assert_And_Cut (Success);
declare
S_Rev_Level : constant Unsigned_32 := Read_LE32 (Super_Block, 19 * 4);
@@ -90,17 +92,22 @@
declare
S_Inode_Size : constant Unsigned_16 := Read_LE16 (Super_Block, 22 * 4);
begin
- if Natural (S_Inode_Size) in Inode_Size then
+ if Natural (S_Inode_Size) in Inode_Size and then
+ Natural (S_Inode_Size) <= Static.Block_Size
+ then
Static.Inode_Size := Inode_Size (S_Inode_Size);
else
Success := False;
return;
end if;
+ pragma Assert (Static.Block_Size / Static.Inode_Size <= Natural (Inode_In_Block_Count'Last));
end;
else
Static.Inode_Size := Inode_Size'First;
end if;
+ Static.Inodes_Per_Block := Inode_In_Block_Count (Static.Block_Size / Static.Inode_Size);
end;
+ pragma Assert_And_Cut (Success);
declare
S_Feature_Incompat : constant Unsigned_32 := Read_LE32 (Super_Block, 24 * 4);
@@ -125,7 +132,9 @@
else
Static.Desc_Size := Desc_Size'First;
end if;
+ Static.Desc_Per_Block := Group_Index (Static.Block_Size / Static.Desc_Size);
end;
+ pragma Assert_And_Cut (Success);
State.S := Mounted;
end Mount;
@@ -607,13 +616,6 @@
Static : Mount_State renames State.Static;
Cache : Cache_Buffer renames State.Cache.Buffer;
- type Group_Index is new Natural;
- subtype Desc_In_Block_Index is Group_Index
- range 0 .. Group_Index (2 ** Log_Block_Size'Last / Desc_Size'First - 1);
-
- Inodes_Per_Block : constant Inode_Index := Inode_Index (Static.Block_Size / Static.Inode_Size);
- Desc_Per_Block : constant Group_Index := Group_Index (Static.Block_Size / Static.Desc_Size);
-
------------------------
-- Group deserialization
@@ -676,14 +678,14 @@
Group : constant Group_Index := Group_Index ((Inode - 1) / Static.Inodes_Per_Group);
Desc_Block : constant FSBlock_Offset :=
- 1 + Static.First_Data_Block + FSBlock_Offset (Group / Desc_Per_Block);
+ 1 + Static.First_Data_Block + FSBlock_Offset (Group / Static.Desc_Per_Block);
Cache_Start, Cache_End : Max_Block_Index;
begin
Cache_FSBlock
(Static => Static,
Cache => State.Cache,
Phys => Desc_Block,
- Level => Natural'Min (Natural (Group / Desc_Per_Block), Block_Cache_Index'Last),
+ Level => Natural'Min (Natural (Group / Static.Desc_Per_Block), Block_Cache_Index'Last),
Cache_Start => Cache_Start,
Cache_End => Cache_End,
Success => Success);
@@ -692,11 +694,12 @@
end if;
declare
- Desc : constant Desc_In_Block_Index := Group mod Desc_Per_Block;
- Inode_In_Group : constant Inode_Index := (Inode - 1) mod Static.Inodes_Per_Group;
+ 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);
Inode_Block : constant FSBlock_Offset :=
Group_Inode_Table (Cache (Cache_Start .. Cache_End), Group) +
- FSBlock_Offset (Inode_In_Group / Inodes_Per_Block);
+ FSBlock_Offset (Inode_In_Group / Static.Inodes_Per_Block);
begin
Cache_FSBlock
(Static => Static,
@@ -716,7 +719,7 @@
S_IFREG : constant := 8#100000#;
S_IFLNK : constant := 8#120000#;
- Inode_In_Block : constant Inode_Index := Inode_In_Group mod Inodes_Per_Block;
+ Inode_In_Block : constant Inode_Index := Inode_Index (Inode_In_Group mod Static.Inodes_Per_Block);
I_Mode : constant Unsigned_16 :=
Inode_Mode (Cache (Cache_Start .. Cache_End), Inode_In_Block);
I_Flags : constant Unsigned_32 :=
@@ -750,6 +753,7 @@
State.Inode.Size := Inode_Length (I_Size);
else
Success := False;
+ return;
end if;
end;
State.Inode.Use_Extents := Static.Feature_Extents and (I_Flags and EXT4_EXTENTS_FL) /= 0;
diff --git a/src/filo-fs-ext2.ads b/src/filo-fs-ext2.ads
index 7c1e467..5537507 100644
--- a/src/filo-fs-ext2.ads
+++ b/src/filo-fs-ext2.ads
@@ -86,6 +86,16 @@
Inline : Inode_Extents := (others => 16#00#);
end record;
+ type Group_Index is new Natural range 0 .. Natural (Inode_Index'Last / 2);
+ subtype Group_In_Block_Count is Group_Index
+ range 1 .. Group_Index (Block_Size'Last / Desc_Size'First);
+ type Desc_In_Block_Index is new Natural range 0 .. Natural (Group_In_Block_Count'Last - 1);
+
+ type Inode_In_Group_Index is new Natural range 0 .. Natural (Inode_Index'Last / 2);
+ subtype Inode_In_Block_Count is Inode_In_Group_Index
+ range 1 .. Inode_In_Group_Index (Block_Size'Last / Inode_Size'First);
+ type Inode_In_Block_Index is new Natural range 0 .. Natural (Inode_In_Block_Count'Last - 1);
+
type Mount_State is record
Part_Len : Partition_Length := 0;
First_Data_Block : FSBlock_Offset := 0;
@@ -93,7 +103,9 @@
Block_Size : Ext2.Block_Size := Ext2.Block_Size'First;
Inodes_Per_Group : Inode_Index := Inode_Index'First;
Inode_Size : Ext2.Inode_Size := Ext2.Inode_Size'First;
+ Inodes_Per_Block : Inode_In_Block_Count := Inode_In_Block_Count'First;
Desc_Size : Ext2.Desc_Size := Ext2.Desc_Size'First;
+ Desc_Per_Block : Group_In_Block_Count := Group_In_Block_Count'First;
Feature_Extents : Boolean := False;
Feature_64Bit : Boolean := False;
end record;