Nico Huber | cc960f2 | 2024-01-29 01:13:45 +0100 | [diff] [blame] | 1 | package FILO.FS.ISO9660 is |
| 2 | |
| 3 | type T is private; |
| 4 | |
| 5 | function Is_Mounted (State : T) return Boolean; |
| 6 | function Is_Open (State : T) return Boolean |
| 7 | with |
| 8 | Post => (if Is_Open'Result then Is_Mounted (State)); |
| 9 | |
| 10 | procedure Mount |
| 11 | (State : in out T; |
| 12 | Part_Len : in Partition_Length; |
| 13 | Success : out Boolean) |
| 14 | with |
| 15 | Pre => not Is_Mounted (State), |
| 16 | Post => Success = Is_Mounted (State); |
| 17 | |
| 18 | procedure Open |
| 19 | (State : in out T; |
| 20 | File_Len : out File_Length; |
| 21 | File_Type : out FS.File_Type; |
| 22 | File_Name : in String; |
| 23 | In_Root : in Boolean; |
| 24 | Success : out Boolean) |
| 25 | with |
Nico Huber | 8e4b9f8 | 2024-02-12 01:13:51 +0100 | [diff] [blame^] | 26 | Pre => Is_Mounted (State) and File_Name'Length <= Natural'Last - 3, |
Nico Huber | cc960f2 | 2024-01-29 01:13:45 +0100 | [diff] [blame] | 27 | Post => (if Success then Is_Open (State) else Is_Mounted (State)); |
| 28 | |
| 29 | procedure Close (State : in out T) |
| 30 | with |
| 31 | Pre => Is_Open (State), |
| 32 | Post => Is_Mounted (State); |
| 33 | |
Nico Huber | 4210fcc | 2024-01-29 16:33:47 +0100 | [diff] [blame] | 34 | pragma Warnings |
| 35 | (GNATprove, Off, """State"" is not modified*", |
| 36 | Reason => "It's `in out' to fulfill common interface."); |
Nico Huber | cc960f2 | 2024-01-29 01:13:45 +0100 | [diff] [blame] | 37 | procedure Read |
| 38 | (State : in out T; |
| 39 | File_Pos : in out File_Offset; |
| 40 | Buf : out Buffer_Type; |
| 41 | Len : out Natural) |
| 42 | with |
Nico Huber | 4210fcc | 2024-01-29 16:33:47 +0100 | [diff] [blame] | 43 | Relaxed_Initialization => Buf, |
Nico Huber | cc960f2 | 2024-01-29 01:13:45 +0100 | [diff] [blame] | 44 | Pre => Is_Open (State) and Buf'Length > 0, |
Nico Huber | 4210fcc | 2024-01-29 16:33:47 +0100 | [diff] [blame] | 45 | Post => Is_Open (State) and Buf'Initialized; |
| 46 | pragma Warnings (GNATprove, On, """State"" is not modified*"); |
Nico Huber | cc960f2 | 2024-01-29 01:13:45 +0100 | [diff] [blame] | 47 | |
| 48 | private |
| 49 | type State is (Unmounted, Mounted, File_Opened); |
| 50 | |
| 51 | FSBlock_Size : constant := 2048; |
Nico Huber | 666da67 | 2024-02-08 15:30:20 +0100 | [diff] [blame] | 52 | subtype FSBlock_Length is Index_Type range 0 .. FSBlock_Size; |
Nico Huber | cc960f2 | 2024-01-29 01:13:45 +0100 | [diff] [blame] | 53 | subtype FSBlock_Index is Index_Type range 0 .. FSBlock_Size - 1; |
| 54 | |
| 55 | type FSBlock_Count is range 0 .. 2 ** 32 - 1; |
| 56 | subtype FSBlock is FSBlock_Count range 0 .. FSBlock_Count'Last - 1; |
| 57 | type FSBlock_Logical is new FSBlock; |
| 58 | |
Nico Huber | 666da67 | 2024-02-08 15:30:20 +0100 | [diff] [blame] | 59 | type FS_Record is record |
| 60 | Block : FSBlock := 0; |
| 61 | Offset : FSBlock_Length := 0; |
| 62 | Size : FSBlock_Length := 0; |
| 63 | end record |
| 64 | with |
| 65 | Dynamic_Predicate => |
| 66 | Size <= FSBlock_Size - Offset; |
| 67 | |
Nico Huber | cc960f2 | 2024-01-29 01:13:45 +0100 | [diff] [blame] | 68 | subtype Directory_Record_Range is Index_Type range 0 .. 32; |
| 69 | subtype Directory_Record is Buffer_Type (Directory_Record_Range); |
Nico Huber | 4210fcc | 2024-01-29 16:33:47 +0100 | [diff] [blame] | 70 | subtype Directory_Record_Offset is FSBlock_Index |
| 71 | range 0 .. FSBlock_Size - Directory_Record'Length; |
Nico Huber | cc960f2 | 2024-01-29 01:13:45 +0100 | [diff] [blame] | 72 | |
| 73 | -- We'll use the absolute position of the dir record |
Nico Huber | 666da67 | 2024-02-08 15:30:20 +0100 | [diff] [blame] | 74 | subtype Inode_Index is FS_Record |
| 75 | with |
Nico Huber | 8e4b9f8 | 2024-02-12 01:13:51 +0100 | [diff] [blame^] | 76 | Dynamic_Predicate => |
| 77 | Inode_Index.Size >= Directory_Record'Length; |
Nico Huber | cc960f2 | 2024-01-29 01:13:45 +0100 | [diff] [blame] | 78 | type Inode_Length is range 0 .. FSBlock_Count'Last * FSBlock_Size; |
| 79 | |
| 80 | type Mount_State is record |
| 81 | Part_Len : Partition_Length := 0; |
Nico Huber | 8e4b9f8 | 2024-02-12 01:13:51 +0100 | [diff] [blame^] | 82 | Root_Inode : Inode_Index := (Size => Directory_Record'Length, others => <>); |
Nico Huber | cc960f2 | 2024-01-29 01:13:45 +0100 | [diff] [blame] | 83 | end record; |
| 84 | |
| 85 | type Extent is record |
| 86 | Start : FSBlock := 0; |
| 87 | Count : FSBlock_Count := 0; |
Nico Huber | 8e4b9f8 | 2024-02-12 01:13:51 +0100 | [diff] [blame^] | 88 | end record |
| 89 | with |
| 90 | Dynamic_Predicate => |
| 91 | Start <= FSBlock_Count'Last - Count; |
Nico Huber | cc960f2 | 2024-01-29 01:13:45 +0100 | [diff] [blame] | 92 | |
| 93 | type Extent_Range is range 0 .. 0; -- Linux allows 100 "file sections" |
| 94 | type Extents is array (Extent_Range) of Extent; |
| 95 | |
| 96 | type Inode_Info is record |
Nico Huber | 8e4b9f8 | 2024-02-12 01:13:51 +0100 | [diff] [blame^] | 97 | I : Inode_Index := (Size => Directory_Record'Length, others => <>); |
Nico Huber | cc960f2 | 2024-01-29 01:13:45 +0100 | [diff] [blame] | 98 | Mode : File_Type := File_Type'First; |
| 99 | Size : Inode_Length := 0; |
| 100 | Extents : ISO9660.Extents := (Extent_Range => (others => <>)); |
| 101 | end record; |
| 102 | |
| 103 | type T is record |
| 104 | Static : Mount_State := (others => <>); |
| 105 | S : State; |
| 106 | Inode : Inode_Info := (others => <>); |
Nico Huber | 8e4b9f8 | 2024-02-12 01:13:51 +0100 | [diff] [blame^] | 107 | Cur_Dir : Inode_Index := (Size => Directory_Record'Length, others => <>); |
Nico Huber | cc960f2 | 2024-01-29 01:13:45 +0100 | [diff] [blame] | 108 | end record; |
| 109 | |
| 110 | end FILO.FS.ISO9660; |