blob: 96bd10236ca636105b495bdc77a4d21996be9560 [file] [log] [blame]
Thomas Heijligen5c43abc2023-12-11 15:24:36 +00001package FILO.FS.Ext2 is
Nico Huber1d7727f2023-11-30 15:58:46 +01002
Nico Huber57d3a852023-12-04 15:42:40 +01003 type T is private;
Nico Huber1d7727f2023-11-30 15:58:46 +01004
Nico Huber57d3a852023-12-04 15:42:40 +01005 function Is_Mounted (State : T) return Boolean;
6 function Is_Open (State : T) return Boolean
Nico Huber1d7727f2023-11-30 15:58:46 +01007 with
Nico Huber57d3a852023-12-04 15:42:40 +01008 Post => (if Is_Open'Result then Is_Mounted (State));
Nico Huber1d7727f2023-11-30 15:58:46 +01009
Nico Huber57d3a852023-12-04 15:42:40 +010010 procedure Mount
11 (State : in out T;
12 Part_Len : in Partition_Length;
13 Success : out Boolean)
Nico Huber1d7727f2023-11-30 15:58:46 +010014 with
Nico Huber57d3a852023-12-04 15:42:40 +010015 Pre => not Is_Mounted (State),
16 Post => Success = Is_Mounted (State);
Nico Huber1d7727f2023-11-30 15:58:46 +010017
Nico Huber57d3a852023-12-04 15:42:40 +010018 procedure Open
19 (State : in out T;
20 File_Len : out File_Length;
21 File_Path : in String;
22 Success : out Boolean)
Nico Huber1d7727f2023-11-30 15:58:46 +010023 with
Nico Huber57d3a852023-12-04 15:42:40 +010024 Pre => Is_Mounted (State) and not Is_Open (State),
25 Post => Success = Is_Open (State);
26
27 procedure Close (State : in out T)
28 with
29 Pre => Is_Open (State),
30 Post => Is_Mounted (State);
31
32 procedure Read
33 (State : in out T;
34 File_Len : in File_Length;
35 File_Pos : in out File_Offset;
36 Buf : out Buffer_Type;
37 Len : out Natural)
38 with
39 Pre => Is_Open (State),
40 Post => Is_Open (State);
41
42private
43 type State is (Unmounted, Mounted, File_Opened);
44
Nico Huber26f71832023-12-05 16:26:56 +010045 -- maximum block size is 64KiB (2^16):
46 subtype Log_Block_Size is Positive range 10 .. 16;
Nico Huber6623c982023-12-12 16:35:46 +010047 subtype Max_Block_Index is Index_Type range 0 .. 2 ** Log_Block_Size'Last - 1;
48
49 -- Minimum ext2 block size is 1KiB (two 512B blocks)
50 type FSBlock_Offset is new Block_Offset range 0 .. Block_Offset'Last / 2;
51 type FSBlock_Logical is new Block_Offset range 0 .. Block_Offset'Last / 2;
52
53 -- We use a 64KiB cache.
54 -- * If that's the block size, only the `Any` entry is used.
55 -- * For a 32KiB block size, `Any` and `Last_Level` (for indirect block
56 -- lookups) are used.
57 -- * For smaller block sizes, the most common case, we cache four blocks.
58 -- For the `Any` entry, we note the logical block address (block offset
59 -- within a file). For the indirect entries, we note the *first* logical
60 -- block that they map.
61 type Block_Cache_Index is (Any, Last_Level, Second_Last_Level, First_Level);
62 type Block_Cache_Type is array (Block_Cache_Index) of FSBlock_Logical;
63
64 Direct_Blocks : constant := 12;
65 type Direct_Blocks_Array is array (Natural range 0 .. Direct_Blocks - 1) of Unsigned_32;
Nico Huber26f71832023-12-05 16:26:56 +010066
67 subtype Inode_Size is Positive range 128 .. Positive (Unsigned_16'Last);
68 subtype Desc_Size is Positive range 32 .. Positive (Unsigned_16'Last);
69
Nico Huber57d3a852023-12-04 15:42:40 +010070 type T is record
71 S : State;
Nico Huber26f71832023-12-05 16:26:56 +010072 Part_Len : Partition_Length := 0;
73 First_Data_Block : Block_Offset := 0;
74 Block_Size_Bits : Log_Block_Size := 10;
75 Inodes_Per_Group : Positive := 1;
76 Inode_Size : Ext2.Inode_Size := Ext2.Inode_Size'First;
77 Desc_Size : Ext2.Desc_Size := Ext2.Desc_Size'First;
78 Feature_Extents : Boolean := False;
79 Feature_64Bit : Boolean := False;
Nico Huber6623c982023-12-12 16:35:46 +010080 Direct_Blocks : Direct_Blocks_Array := (others => 0);
81 Indirect_Block : Unsigned_32 := 0;
82 Double_Indirect : Unsigned_32 := 0;
83 Triple_Indirect : Unsigned_32 := 0;
84 Block_Cache_Index : Block_Cache_Type := (others => 0);
85 Block_Cache : Buffer_Type (Max_Block_Index) := (others => 16#00#);
Nico Huber57d3a852023-12-04 15:42:40 +010086 end record;
Nico Huber1d7727f2023-11-30 15:58:46 +010087
Thomas Heijligen5c43abc2023-12-11 15:24:36 +000088end FILO.FS.Ext2;