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,