Implement Ext2.Open()
diff --git a/src/filo-fs-ext2.adb b/src/filo-fs-ext2.adb
index 1d074d4..9cd9c7a 100644
--- a/src/filo-fs-ext2.adb
+++ b/src/filo-fs-ext2.adb
@@ -75,7 +75,7 @@
       declare
          S_Inodes_Per_Group : constant Unsigned_32 := Read_LE32 (Super_Block, 10 * 4);
       begin
-         if S_Inodes_Per_Group in 1 .. Unsigned_32'Last then
+         if S_Inodes_Per_Group in 2 .. Unsigned_32'Last then
             State.Inodes_Per_Group := Inode_Index (S_Inodes_Per_Group);
          else
             Success := False;
@@ -727,6 +727,7 @@
             end;
             State.Inode.Use_Extents := State.Feature_Extents and (I_Flags and EXT4_EXTENTS_FL) /= 0;
             State.Inode.Inline := State.Block_Cache (Cache_Start + 40 .. Cache_Start + 100 - 1);
+            State.Inode.I := Inode;
             Reset_Cache_Logical (State);
             State.S := File_Opened;
          end;
@@ -741,9 +742,112 @@
       In_Root     : in     Boolean;
       Success     : out    Boolean)
    is
+      File_Name_Max : constant := 255;
+      Root_Inode : constant := 2;
+
+      function Str_Buf_Equal (Str : String; Buf : Buffer_Type) return Boolean is
+      begin
+         for I in Str'Range loop
+            if Character'Pos (Str (I)) /= Buf (Buf'First + (I - Str'First)) then
+               return False;
+            end if;
+         end loop;
+         return True;
+      end Str_Buf_Equal;
+
+      File_Inode : Inode_Index;
+      File_Pos : File_Length;
    begin
       File_Len := 0;
+      File_Type := FS.File_Type'First;
+
+      if File_Name'Length > File_Name_Max then
+         Success := False;
+         return;
+      end if;
+
+      -- Ensure dir is opened:
+      --
+      if State.S = File_Opened then
+         if State.Cur_Dir /= State.Inode.I then
+            Success := False;
+            return;
+         end if;
+      else
+         if In_Root then
+            State.Cur_Dir := Root_Inode;
+         end if;
+         Open (State, State.Cur_Dir, Success);
+         if not Success then
+            return;
+         end if;
+      end if;
+
+      -- Lookup file in opened dir:
+      --
+      File_Pos := 0;
       Success := False;
+      while Unsigned_64 (File_Pos) < Unsigned_64 (State.Inode.Size) loop
+         declare
+            Dir_Entry_Header_Length : constant := 4 + 2 + 1 + 1;
+            subtype Dir_Entry_Index is Natural
+               range 0 .. Dir_Entry_Header_Length + File_Name_Max - 1;
+            Dir_Entry : Buffer_Type (Dir_Entry_Index);
+            Entry_File_Pos : File_Offset := File_Pos;
+            Len : Natural;
+         begin
+            Read
+              (State    => State,
+               File_Pos => Entry_File_Pos,
+               Buf      => Dir_Entry (0 .. 7),
+               Len      => Len);
+            if Len < Dir_Entry_Header_Length then
+               return;
+            end if;
+
+            -- Only check filenames of exact same length
+            if Read_LE32 (Dir_Entry, 0) > Root_Inode and then
+               File_Name'Length = Natural (Dir_Entry (6))
+            then
+               Read
+                 (State    => State,
+                  File_Pos => Entry_File_Pos,
+                  Buf      => Dir_Entry (8 .. 8 + File_Name'Length - 1),
+                  Len      => Len);
+               if Len < File_Name'Length then
+                  return;
+               end if;
+
+               File_Inode := Inode_Index (Read_LE32 (Dir_Entry, 0));
+               Success := Str_Buf_Equal (File_Name, Dir_Entry (8 .. 8 + File_Name'Length - 1));
+               exit when Success;
+            end if;
+
+            File_Pos := File_Pos + File_Length (Read_LE16 (Dir_Entry, 4));
+         end;
+      end loop;
+
+      if Success then
+         Open (State, File_Inode, Success);
+         if not Success then
+            return;
+         end if;
+
+         if State.Inode.Mode = Dir then
+            State.Cur_Dir := File_Inode;
+         end if;
+      end if;
+
+      Success := Unsigned_64 (State.Inode.Size) <= Unsigned_64 (File_Length'Last);
+      if Success then
+         File_Len := File_Length (State.Inode.Size);
+         File_Type := (case State.Inode.Mode is
+                        when Dir                => FS.Dir,
+                        when Regular            => FS.Regular,
+                        when Link .. Fast_Link  => FS.Link);
+      else
+         Close (State);
+      end if;
    end Open;
 
    procedure Close (State : in out T) is
diff --git a/src/filo-fs-ext2.ads b/src/filo-fs-ext2.ads
index 2c30e0a..0deefb6 100644
--- a/src/filo-fs-ext2.ads
+++ b/src/filo-fs-ext2.ads
@@ -66,7 +66,7 @@
    subtype Inode_Extents_Index is Natural range 0 .. 59;
    subtype Inode_Extents is Buffer_Type (Inode_Extents_Index);
 
-   type Inode_Index is new Unsigned_32 range 1 .. Unsigned_32'Last;
+   type Inode_Index is new Unsigned_32 range 2 .. Unsigned_32'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
 
@@ -74,6 +74,7 @@
    type Inode_Length is range 0 .. 2 ** 46;
 
    type Inode_Info is record
+      I           : Inode_Index;
       Mode        : Inode_Type := Inode_Type'First;
       Size        : Inode_Length := 0;
       Use_Extents : Boolean := False;
@@ -85,12 +86,13 @@
       Part_Len             : Partition_Length := 0;
       First_Data_Block     : FSBlock_Offset := 0;
       Block_Size_Bits      : Log_Block_Size := 10;
-      Inodes_Per_Group     : Inode_Index := 1;
+      Inodes_Per_Group     : Inode_Index := Inode_Index'First;
       Inode_Size           : Ext2.Inode_Size := Ext2.Inode_Size'First;
       Desc_Size            : Ext2.Desc_Size := Ext2.Desc_Size'First;
       Feature_Extents      : Boolean := False;
       Feature_64Bit        : Boolean := False;
       Inode                : Inode_Info := (others => <>);
+      Cur_Dir              : Inode_Index := Inode_Index'First;
       Block_Cache_Logical  : Cache_Label_Logical := (others => False);
       Block_Cache_Label    : Cache_Label_Array := (others => 0);
       Block_Cache          : Buffer_Type (Max_Block_Index) := (others => 16#00#);