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