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,
diff --git a/src/filo-fs-ext2.ads b/src/filo-fs-ext2.ads
index 6003198..5e6b641 100644
--- a/src/filo-fs-ext2.ads
+++ b/src/filo-fs-ext2.ads
@@ -74,7 +74,7 @@
type Inode_0_Index is new Unsigned_32;
subtype Inode_Index is Inode_0_Index range 2 .. Inode_0_Index'Last;
subtype Inode_Size is Positive range 128 .. Positive (Unsigned_16'Last);
- subtype Desc_Size is Positive range 32 .. 2 ** 15; -- power-of-2 that fits in 16 bits
+ subtype Group_Desc_Size is Positive range 32 .. 2 ** 15; -- power-of-2 that fits in 16 bits
type Inode_Type is (Dir, Regular, Link, Fast_Link);
type Inode_Length is range 0 .. 2 ** 46;
@@ -89,8 +89,8 @@
type Group_Index is new Inode_0_Index;
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);
+ range 1 .. Group_Index (Block_Size'Last / Group_Desc_Size'First);
+ type Group_In_Block_Index is new Natural range 0 .. Natural (Group_In_Block_Count'Last - 1);
subtype Inode_In_Group_Count is Inode_0_Index range 1 .. Inode_0_Index'Last;
type Inode_In_Group_Index is new Inode_0_Index range 0 .. Inode_In_Group_Count'Last - 1;
@@ -106,8 +106,8 @@
Inodes_Per_Group : Inode_In_Group_Count := Inode_In_Group_Count'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;
+ Group_Desc_Size : Ext2.Group_Desc_Size := Ext2.Group_Desc_Size'First;
+ Group_Desc_Per_Block : Group_In_Block_Count := Group_In_Block_Count'First;
Feature_Extents : Boolean := False;
Feature_64Bit : Boolean := False;
end record;