ext2: Factor inode deserialization out
diff --git a/src/filo-fs-ext2.adb b/src/filo-fs-ext2.adb
index c0ced37..d7ee599 100644
--- a/src/filo-fs-ext2.adb
+++ b/src/filo-fs-ext2.adb
@@ -606,6 +606,58 @@
end if;
end Extent_Block_Map;
+ procedure Parse_Inode
+ (Static : in Mount_State;
+ Inode : in out Inode_Info;
+ Buf : in Buffer_Type;
+ Success : out Boolean)
+ with
+ Pre => Buf'Length >= Inode_Size'First
+ is
+ S_IFMT : constant := 8#170000#;
+ S_IFDIR : constant := 8#040000#;
+ S_IFREG : constant := 8#100000#;
+ S_IFLNK : constant := 8#120000#;
+
+ I_Mode : constant Unsigned_16 := Read_LE16 (Buf, 0);
+ I_Blocks : constant Unsigned_32 := Read_LE32 (Buf, 28);
+ I_Flags : constant Unsigned_32 := Read_LE32 (Buf, 32);
+ I_File_ACL : constant Unsigned_32 := Read_LE32 (Buf, 104);
+ begin
+ case I_Mode and S_IFMT is
+ when S_IFDIR => Inode.Mode := Dir;
+ when S_IFREG => Inode.Mode := Regular;
+ when S_IFLNK => Inode.Mode := Link;
+ when others => Success := False; return;
+ end case;
+
+ if Inode.Mode = Link and
+ ((I_File_ACL = 0 and I_Blocks = 0) or
+ (I_File_ACL /= 0 and I_Blocks = 2 ** (Static.Block_Size_Bits - 9)))
+ then
+ Inode.Mode := Fast_Link;
+ end if;
+
+ declare
+ I_Size : constant Unsigned_64 :=
+ (if Inode.Mode = Regular
+ then Shift_Left (Unsigned_64 (Read_LE32 (Buf, 108)), 32)
+ else 0) or
+ Unsigned_64 (Read_LE32 (Buf, 4));
+ begin
+ if I_Size > Unsigned_64 (Inode_Length'Last) then
+ Success := False;
+ return;
+ end if;
+ Inode.Size := Inode_Length (I_Size);
+ end;
+
+ Inode.Use_Extents := Static.Feature_Extents and (I_Flags and EXT4_EXTENTS_FL) /= 0;
+ Inode.Inline := Buf (Buf'First + 40 .. Buf'First + 100 - 1);
+
+ Success := True;
+ end Parse_Inode;
+
procedure Open
(State : in out T;
Inode : in Inode_Index;
@@ -635,47 +687,6 @@
with
Pre => Buf'Length >= Group_Byte_Offset (Idx, (if Static.Feature_64Bit then 44 else 12));
- ------------------------
- -- Inode deserialization
-
- subtype Inode_Off is Natural range 0 .. Inode_Size'Last;
- function Inode_Byte_Offset (Idx : Inode_In_Block_Index; Off : Inode_Off) return Natural
- is
- (Natural (Idx) * Static.Inode_Size + Off);
-
- function Inode_Mode (Buf : Buffer_Type; Idx : Inode_In_Block_Index) return Unsigned_16
- is
- (Read_LE16 (Buf, Inode_Byte_Offset (Idx, 0)))
- with
- Pre => Buf'Length >= Inode_Byte_Offset (Idx, 2);
-
- function Inode_Size (Buf : Buffer_Type; Idx : Inode_In_Block_Index; Mode : Inode_Type) return Unsigned_64
- is
- ((if Mode = Regular
- then Shift_Left (Unsigned_64 (Read_LE32 (Buf, Inode_Byte_Offset (Idx, 108))), 32)
- else 0) or
- Unsigned_64 (Read_LE32 (Buf, Inode_Byte_Offset (Idx, 4))))
- with
- Pre => Buf'Length >= Inode_Byte_Offset (Idx, 112);
-
- function Inode_Blocks (Buf : Buffer_Type; Idx : Inode_In_Block_Index) return Unsigned_32
- is
- (Read_LE32 (Buf, Inode_Byte_Offset (Idx, 28)))
- with
- Pre => Buf'Length >= Inode_Byte_Offset (Idx, 32);
-
- function Inode_Flags (Buf : Buffer_Type; Idx : Inode_In_Block_Index) return Unsigned_32
- is
- (Read_LE32 (Buf, Inode_Byte_Offset (Idx, 32)))
- with
- Pre => Buf'Length >= Inode_Byte_Offset (Idx, 36);
-
- function Inode_File_ACL (Buf : Buffer_Type; Idx : Inode_In_Block_Index) return Unsigned_32
- is
- (Read_LE32 (Buf, Inode_Byte_Offset (Idx, 104)))
- with
- Pre => Buf'Length >= Inode_Byte_Offset (Idx, 108);
-
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);
@@ -701,6 +712,11 @@
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_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
@@ -723,56 +739,18 @@
return;
end if;
- declare
- S_IFMT : constant := 8#170000#;
- S_IFDIR : constant := 8#040000#;
- S_IFREG : constant := 8#100000#;
- S_IFLNK : constant := 8#120000#;
+ Parse_Inode
+ (Static => State.Static,
+ Inode => State.Inode,
+ Buf => Cache (Cache_Start + Inode_In_Block_Offset ..
+ Cache_Start + Inode_In_Block_Offset + Static.Inode_Size - 1),
+ Success => Success);
- Inode_In_Block : constant Inode_In_Block_Index :=
- Inode_In_Block_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 :=
- Inode_Flags (Cache (Cache_Start .. Cache_End), Inode_In_Block);
- begin
- case I_Mode and S_IFMT is
- when S_IFDIR => State.Inode.Mode := Dir;
- when S_IFREG => State.Inode.Mode := Regular;
- when S_IFLNK => State.Inode.Mode := Link;
- when others => Success := False; return;
- end case;
- if State.Inode.Mode = Link then
- declare
- I_File_ACL : constant Unsigned_32 := Inode_File_ACL (
- Cache (Cache_Start .. Cache_End), Inode_In_Block);
- I_Blocks : constant Unsigned_32 := Inode_Blocks (
- Cache (Cache_Start .. Cache_End), Inode_In_Block);
- begin
- if (I_File_ACL = 0 and I_Blocks = 0) or
- (I_File_ACL /= 0 and I_Blocks = 2 ** (Static.Block_Size_Bits - 9))
- then
- State.Inode.Mode := Fast_Link;
- end if;
- end;
- end if;
- declare
- I_Size : constant Unsigned_64 := Inode_Size (
- Cache (Cache_Start .. Cache_End), Inode_In_Block, State.Inode.Mode);
- begin
- if I_Size <= Unsigned_64 (Inode_Length'Last) then
- 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;
- State.Inode.Inline := Cache (Cache_Start + 40 .. Cache_Start + 100 - 1);
+ if Success then
State.Inode.I := Inode;
Reset_Cache_Logical (State.Cache);
State.S := File_Opened;
- end;
+ end if;
end;
end Open;