gnatcoll_24.0.0_11c512d1/src/os/gnatcoll-os-dir.ads

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
------------------------------------------------------------------------------
--                              G N A T C O L L                             --
--                                                                          --
--                       Copyright (C) 2021-2022, AdaCore                   --
--                                                                          --
-- This library is free software;  you can redistribute it and/or modify it --
-- under terms of the  GNU General Public License  as published by the Free --
-- Software  Foundation;  either version 3,  or (at your  option) any later --
-- version. This library is distributed in the hope that it will be useful, --
-- but WITHOUT ANY WARRANTY;  without even the implied warranty of MERCHAN- --
-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE.                            --
--                                                                          --
-- As a special exception under Section 7 of GPL version 3, you are granted --
-- additional permissions described in the GCC Runtime Library Exception,   --
-- version 3.1, as published by the Free Software Foundation.               --
--                                                                          --
-- You should have received a copy of the GNU General Public License and    --
-- a copy of the GCC Runtime Library Exception along with this program;     --
-- see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see    --
-- <http://www.gnu.org/licenses/>.                                          --
--                                                                          --
------------------------------------------------------------------------------

--  Provides a low-level portable API to iterate on directories content. The
--  main advantage of this implementation over the default one in the GNAT
--  runtime is that it returns both the filename and the "stat" information
--  for each entry in a given directory. On systems such as Windows this
--  reduce significantly the cost of file system operations as the Win32 API
--  can achieve this with one system call (the equivalent to readdir).

with Ada.Strings.UTF_Encoding;
with GNATCOLL.OS.Stat;
with GNATCOLL.OS.Dir_Types;
with Ada.Calendar; use Ada.Calendar;

package GNATCOLL.OS.Dir is

   package UTF8 renames Ada.Strings.UTF_Encoding;
   package Stat renames GNATCOLL.OS.Stat;

   type Dir_Handle is private;
   --  Handle on a directory

   type Dir_Entry is private;
   --  Directory entry

   function Open (Path : UTF8.UTF_8_String) return Dir_Handle;
   --  Open a directory at path Path. In case of error OS_Error exception is
   --  raised.

   procedure Close (Handle : in out Dir_Handle);
   --  Close a directory. In case of error OS_Error is raised.

   function Is_Opened (Handle : Dir_Handle) return Boolean;
   --  Return True of the handle is opened.

   function Read
      (Handle          : Dir_Handle;
       Follow_Symlinks : Boolean := True)
      return Dir_Entry;
   --  Read next entry in directory Handle. In case of error OS_Error is
   --  raised. When reaching the end of the entry list a special Dir_Entry E
   --  is returned for which End_Of_Iteration (E) is True. If Follow_Symlinks
   --  is set to True, the stat information stored is the Dir_Entry is the
   --  stat information of the file targeted by the link. Otherwise the stat
   --  information of the link itself is returned.

   function Path (Handle : Dir_Handle) return UTF8.UTF_8_String;
   --  Returned path associated with the handle. If Handle is not opened then
   --  OS_Error is raised.

   function End_Of_Iteration (Self : Dir_Entry) return Boolean;
   --  Return True if the entry represent the end of the iteration. Note that
   --  the entry for which En_Of_Iteration returns True is not a valid entry.
   --  (no name and no attributes are set).

   function Name (Self : Dir_Entry) return UTF8.UTF_8_String;
   --  Return the filename for Self (note that this is just the basename)

   function Path (Dir : Dir_Handle; Self : Dir_Entry) return UTF8.UTF_8_String;
   --  Return the full path for a given entry

   function Attributes (Self : Dir_Entry) return Stat.File_Attributes;
   --  Return the file attributes for Self

   function Is_File (Self : Dir_Entry) return Boolean;
   --  Return True if the file is a regular file

   function Is_Directory (Self : Dir_Entry) return Boolean;
   --  Return True if the file is a directory

   function Is_Symbolic_Link (Self : Dir_Entry) return Boolean;
   --  Return True if the file is a symbolic link

   function Is_Executable (Self : Dir_Entry) return Boolean;
   --  Return True if the file is executable

   function Is_Readable (Self : Dir_Entry) return Boolean;
   --  Return True if the file is readable

   function Is_Writable (Self : Dir_Entry) return Boolean;
   --  Return True if the file is writable

   function Is_Executable_File (Self : Dir_Entry) return Boolean;
   --  Return True if the file is a regular file and is executable

   function Modification_Time (Self : Dir_Entry) return Time;
   --  Return file modification time

   type Process_File is access
      procedure (Dir : Dir_Handle; Element : Dir_Entry);
   --  Function called on each file except directories found by Walk

   type Process_Directory is access
      function (Dir : Dir_Handle; Element : Dir_Entry) return Boolean;
   --  Function called on each directory found by Walk. If the handler returns
   --  True then the directory is also explored. If False then the directory
   --  is skipped.

   type Walk_Error is (OPEN_DIR_ERROR, OTHER_ERROR);

   type Process_Error is access
      procedure (Dir     : Dir_Handle;
                 Element : Dir_Entry;
                 Error   : Walk_Error;
                 Msg     : String);
   --  Function called in case an error occurs during a call to walk

   procedure Raise_Exception_On_Error
      (Dir     : Dir_Handle;
       Element : Dir_Entry;
       Error   : Walk_Error;
       Msg     : String);
   --  Raise exception in case of error

   Ignore         : constant Process_Error := null;
   Raise_OS_Error : constant Process_Error := Raise_Exception_On_Error'Access;

   procedure Walk
      (Path            : UTF8.UTF_8_String;
       File_Handler    : Process_File;
       Dir_Handler     : Process_Directory := null;
       Max_Depth       : Positive          := 256;
       On_Error        : Process_Error     := Ignore;
       Follow_Symlinks : Boolean           := False);
   --  Explore recursively a directory Path. For each entry found, call
   --  Dir_Handler if the entry is a directory and File_Handler otherwise.
   --  if a call to Dir_Handler returns True then Walk explores that
   --  subdirectory. Otherwise the subdirectory is skipped. Note that if a null
   --  Dir_Handler is passed then Walk behaves as if Dir_Handler always returns
   --  True (and thus explore all subdirectories).
   --
   --  Max_Depth limits the depth of the exploration. For example a Max_Depth
   --  of 1 is equivalent to a non recursive call as it returns only direct
   --  entries of Path.
   --
   --  On_Error handler is called on each error during the exploration of Path.
   --  Two default handlers are already implemented: Ignore and Raise_OS_Error.
   --
   --  If Follow_Symlinks is True, each time a symbolic link is encountered the
   --  target of the link is returned. If False, the link itself is returned.
   --  Note that setting Follow_Symlink to True might lead in theory to
   --  infinite loop. In our case the Max_Depth parameter provides a limit.

private

   PATH_MAX : constant Integer := 4096;
   NAME_MAX : constant Integer := 1024;

   type Dir_Handle is record
      Handle    : GNATCOLL.OS.Dir_Types.OS_Dir_Handle;
      Is_Opened : Boolean := False;
      Path_Last : Integer;
      Path      : UTF8.UTF_8_String (1 .. PATH_MAX);
   end record;

   type Dir_Entry is record
      Info        : Stat.File_Attributes;
      Name_Last   : Integer;
      Name_Buffer : UTF8.UTF_8_String (1 .. NAME_MAX);
   end record;

end GNATCOLL.OS.Dir;