annotate gcc/ada/libgnat/a-direct.adb @ 111:04ced10e8804

gcc 7
author kono
date Fri, 27 Oct 2017 22:46:09 +0900
parents
children 84e7813d76e9
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 ------------------------------------------------------------------------------
kono
parents:
diff changeset
2 -- --
kono
parents:
diff changeset
3 -- GNAT RUN-TIME COMPONENTS --
kono
parents:
diff changeset
4 -- --
kono
parents:
diff changeset
5 -- A D A . D I R E C T O R I E S --
kono
parents:
diff changeset
6 -- --
kono
parents:
diff changeset
7 -- B o d y --
kono
parents:
diff changeset
8 -- --
kono
parents:
diff changeset
9 -- Copyright (C) 2004-2017, Free Software Foundation, Inc. --
kono
parents:
diff changeset
10 -- --
kono
parents:
diff changeset
11 -- GNAT is free software; you can redistribute it and/or modify it under --
kono
parents:
diff changeset
12 -- terms of the GNU General Public License as published by the Free Soft- --
kono
parents:
diff changeset
13 -- ware Foundation; either version 3, or (at your option) any later ver- --
kono
parents:
diff changeset
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
kono
parents:
diff changeset
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
kono
parents:
diff changeset
16 -- or FITNESS FOR A PARTICULAR PURPOSE. --
kono
parents:
diff changeset
17 -- --
kono
parents:
diff changeset
18 -- As a special exception under Section 7 of GPL version 3, you are granted --
kono
parents:
diff changeset
19 -- additional permissions described in the GCC Runtime Library Exception, --
kono
parents:
diff changeset
20 -- version 3.1, as published by the Free Software Foundation. --
kono
parents:
diff changeset
21 -- --
kono
parents:
diff changeset
22 -- You should have received a copy of the GNU General Public License and --
kono
parents:
diff changeset
23 -- a copy of the GCC Runtime Library Exception along with this program; --
kono
parents:
diff changeset
24 -- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
kono
parents:
diff changeset
25 -- <http://www.gnu.org/licenses/>. --
kono
parents:
diff changeset
26 -- --
kono
parents:
diff changeset
27 -- GNAT was originally developed by the GNAT team at New York University. --
kono
parents:
diff changeset
28 -- Extensive contributions were provided by Ada Core Technologies Inc. --
kono
parents:
diff changeset
29 -- --
kono
parents:
diff changeset
30 ------------------------------------------------------------------------------
kono
parents:
diff changeset
31
kono
parents:
diff changeset
32 with Ada.Calendar; use Ada.Calendar;
kono
parents:
diff changeset
33 with Ada.Calendar.Formatting; use Ada.Calendar.Formatting;
kono
parents:
diff changeset
34 with Ada.Characters.Handling; use Ada.Characters.Handling;
kono
parents:
diff changeset
35 with Ada.Directories.Validity; use Ada.Directories.Validity;
kono
parents:
diff changeset
36 with Ada.Strings.Fixed;
kono
parents:
diff changeset
37 with Ada.Strings.Maps; use Ada.Strings.Maps;
kono
parents:
diff changeset
38 with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
kono
parents:
diff changeset
39 with Ada.Unchecked_Deallocation;
kono
parents:
diff changeset
40
kono
parents:
diff changeset
41 with System; use System;
kono
parents:
diff changeset
42 with System.CRTL; use System.CRTL;
kono
parents:
diff changeset
43 with System.File_Attributes; use System.File_Attributes;
kono
parents:
diff changeset
44 with System.File_IO; use System.File_IO;
kono
parents:
diff changeset
45 with System.OS_Constants; use System.OS_Constants;
kono
parents:
diff changeset
46 with System.OS_Lib; use System.OS_Lib;
kono
parents:
diff changeset
47 with System.Regexp; use System.Regexp;
kono
parents:
diff changeset
48
kono
parents:
diff changeset
49 package body Ada.Directories is
kono
parents:
diff changeset
50
kono
parents:
diff changeset
51 type Dir_Type_Value is new Address;
kono
parents:
diff changeset
52 -- This is the low-level address directory structure as returned by the C
kono
parents:
diff changeset
53 -- opendir routine.
kono
parents:
diff changeset
54
kono
parents:
diff changeset
55 No_Dir : constant Dir_Type_Value := Dir_Type_Value (Null_Address);
kono
parents:
diff changeset
56 -- Null directory value
kono
parents:
diff changeset
57
kono
parents:
diff changeset
58 Dir_Separator : constant Character;
kono
parents:
diff changeset
59 pragma Import (C, Dir_Separator, "__gnat_dir_separator");
kono
parents:
diff changeset
60 -- Running system default directory separator
kono
parents:
diff changeset
61
kono
parents:
diff changeset
62 Dir_Seps : constant Character_Set := Strings.Maps.To_Set ("/\");
kono
parents:
diff changeset
63 -- UNIX and DOS style directory separators
kono
parents:
diff changeset
64
kono
parents:
diff changeset
65 Max_Path : Integer;
kono
parents:
diff changeset
66 pragma Import (C, Max_Path, "__gnat_max_path_len");
kono
parents:
diff changeset
67 -- The maximum length of a path
kono
parents:
diff changeset
68
kono
parents:
diff changeset
69 type Search_Data is record
kono
parents:
diff changeset
70 Is_Valid : Boolean := False;
kono
parents:
diff changeset
71 Name : Unbounded_String;
kono
parents:
diff changeset
72 Pattern : Regexp;
kono
parents:
diff changeset
73 Filter : Filter_Type;
kono
parents:
diff changeset
74 Dir : Dir_Type_Value := No_Dir;
kono
parents:
diff changeset
75 Entry_Fetched : Boolean := False;
kono
parents:
diff changeset
76 Dir_Entry : Directory_Entry_Type;
kono
parents:
diff changeset
77 end record;
kono
parents:
diff changeset
78 -- The current state of a search
kono
parents:
diff changeset
79
kono
parents:
diff changeset
80 Empty_String : constant String := (1 .. 0 => ASCII.NUL);
kono
parents:
diff changeset
81 -- Empty string, returned by function Extension when there is no extension
kono
parents:
diff changeset
82
kono
parents:
diff changeset
83 procedure Free is new Ada.Unchecked_Deallocation (Search_Data, Search_Ptr);
kono
parents:
diff changeset
84
kono
parents:
diff changeset
85 procedure Close (Dir : Dir_Type_Value);
kono
parents:
diff changeset
86
kono
parents:
diff changeset
87 function File_Exists (Name : String) return Boolean;
kono
parents:
diff changeset
88 -- Returns True if the named file exists
kono
parents:
diff changeset
89
kono
parents:
diff changeset
90 procedure Fetch_Next_Entry (Search : Search_Type);
kono
parents:
diff changeset
91 -- Get the next entry in a directory, setting Entry_Fetched if successful
kono
parents:
diff changeset
92 -- or resetting Is_Valid if not.
kono
parents:
diff changeset
93
kono
parents:
diff changeset
94 ---------------
kono
parents:
diff changeset
95 -- Base_Name --
kono
parents:
diff changeset
96 ---------------
kono
parents:
diff changeset
97
kono
parents:
diff changeset
98 function Base_Name (Name : String) return String is
kono
parents:
diff changeset
99 Simple : constant String := Simple_Name (Name);
kono
parents:
diff changeset
100 -- Simple'First is guaranteed to be 1
kono
parents:
diff changeset
101
kono
parents:
diff changeset
102 begin
kono
parents:
diff changeset
103 -- Look for the last dot in the file name and return the part of the
kono
parents:
diff changeset
104 -- file name preceding this last dot. If the first dot is the first
kono
parents:
diff changeset
105 -- character of the file name, the base name is the empty string.
kono
parents:
diff changeset
106
kono
parents:
diff changeset
107 for Pos in reverse Simple'Range loop
kono
parents:
diff changeset
108 if Simple (Pos) = '.' then
kono
parents:
diff changeset
109 return Simple (1 .. Pos - 1);
kono
parents:
diff changeset
110 end if;
kono
parents:
diff changeset
111 end loop;
kono
parents:
diff changeset
112
kono
parents:
diff changeset
113 -- If there is no dot, return the complete file name
kono
parents:
diff changeset
114
kono
parents:
diff changeset
115 return Simple;
kono
parents:
diff changeset
116 end Base_Name;
kono
parents:
diff changeset
117
kono
parents:
diff changeset
118 -----------
kono
parents:
diff changeset
119 -- Close --
kono
parents:
diff changeset
120 -----------
kono
parents:
diff changeset
121
kono
parents:
diff changeset
122 procedure Close (Dir : Dir_Type_Value) is
kono
parents:
diff changeset
123 Discard : Integer;
kono
parents:
diff changeset
124 pragma Warnings (Off, Discard);
kono
parents:
diff changeset
125
kono
parents:
diff changeset
126 function closedir (directory : DIRs) return Integer;
kono
parents:
diff changeset
127 pragma Import (C, closedir, "__gnat_closedir");
kono
parents:
diff changeset
128
kono
parents:
diff changeset
129 begin
kono
parents:
diff changeset
130 Discard := closedir (DIRs (Dir));
kono
parents:
diff changeset
131 end Close;
kono
parents:
diff changeset
132
kono
parents:
diff changeset
133 -------------
kono
parents:
diff changeset
134 -- Compose --
kono
parents:
diff changeset
135 -------------
kono
parents:
diff changeset
136
kono
parents:
diff changeset
137 function Compose
kono
parents:
diff changeset
138 (Containing_Directory : String := "";
kono
parents:
diff changeset
139 Name : String;
kono
parents:
diff changeset
140 Extension : String := "") return String
kono
parents:
diff changeset
141 is
kono
parents:
diff changeset
142 Result : String (1 .. Containing_Directory'Length +
kono
parents:
diff changeset
143 Name'Length + Extension'Length + 2);
kono
parents:
diff changeset
144 Last : Natural;
kono
parents:
diff changeset
145
kono
parents:
diff changeset
146 begin
kono
parents:
diff changeset
147 -- First, deal with the invalid cases
kono
parents:
diff changeset
148
kono
parents:
diff changeset
149 if Containing_Directory /= ""
kono
parents:
diff changeset
150 and then not Is_Valid_Path_Name (Containing_Directory)
kono
parents:
diff changeset
151 then
kono
parents:
diff changeset
152 raise Name_Error with
kono
parents:
diff changeset
153 "invalid directory path name """ & Containing_Directory & '"';
kono
parents:
diff changeset
154
kono
parents:
diff changeset
155 elsif
kono
parents:
diff changeset
156 Extension'Length = 0 and then (not Is_Valid_Simple_Name (Name))
kono
parents:
diff changeset
157 then
kono
parents:
diff changeset
158 raise Name_Error with
kono
parents:
diff changeset
159 "invalid simple name """ & Name & '"';
kono
parents:
diff changeset
160
kono
parents:
diff changeset
161 elsif Extension'Length /= 0
kono
parents:
diff changeset
162 and then not Is_Valid_Simple_Name (Name & '.' & Extension)
kono
parents:
diff changeset
163 then
kono
parents:
diff changeset
164 raise Name_Error with
kono
parents:
diff changeset
165 "invalid file name """ & Name & '.' & Extension & '"';
kono
parents:
diff changeset
166
kono
parents:
diff changeset
167 -- This is not an invalid case so build the path name
kono
parents:
diff changeset
168
kono
parents:
diff changeset
169 else
kono
parents:
diff changeset
170 Last := Containing_Directory'Length;
kono
parents:
diff changeset
171 Result (1 .. Last) := Containing_Directory;
kono
parents:
diff changeset
172
kono
parents:
diff changeset
173 -- Add a directory separator if needed
kono
parents:
diff changeset
174
kono
parents:
diff changeset
175 if Last /= 0 and then not Is_In (Result (Last), Dir_Seps) then
kono
parents:
diff changeset
176 Last := Last + 1;
kono
parents:
diff changeset
177 Result (Last) := Dir_Separator;
kono
parents:
diff changeset
178 end if;
kono
parents:
diff changeset
179
kono
parents:
diff changeset
180 -- Add the file name
kono
parents:
diff changeset
181
kono
parents:
diff changeset
182 Result (Last + 1 .. Last + Name'Length) := Name;
kono
parents:
diff changeset
183 Last := Last + Name'Length;
kono
parents:
diff changeset
184
kono
parents:
diff changeset
185 -- If extension was specified, add dot followed by this extension
kono
parents:
diff changeset
186
kono
parents:
diff changeset
187 if Extension'Length /= 0 then
kono
parents:
diff changeset
188 Last := Last + 1;
kono
parents:
diff changeset
189 Result (Last) := '.';
kono
parents:
diff changeset
190 Result (Last + 1 .. Last + Extension'Length) := Extension;
kono
parents:
diff changeset
191 Last := Last + Extension'Length;
kono
parents:
diff changeset
192 end if;
kono
parents:
diff changeset
193
kono
parents:
diff changeset
194 return Result (1 .. Last);
kono
parents:
diff changeset
195 end if;
kono
parents:
diff changeset
196 end Compose;
kono
parents:
diff changeset
197
kono
parents:
diff changeset
198 --------------------------
kono
parents:
diff changeset
199 -- Containing_Directory --
kono
parents:
diff changeset
200 --------------------------
kono
parents:
diff changeset
201
kono
parents:
diff changeset
202 function Containing_Directory (Name : String) return String is
kono
parents:
diff changeset
203 begin
kono
parents:
diff changeset
204 -- First, the invalid case
kono
parents:
diff changeset
205
kono
parents:
diff changeset
206 if not Is_Valid_Path_Name (Name) then
kono
parents:
diff changeset
207 raise Name_Error with "invalid path name """ & Name & '"';
kono
parents:
diff changeset
208
kono
parents:
diff changeset
209 else
kono
parents:
diff changeset
210 declare
kono
parents:
diff changeset
211 Last_DS : constant Natural :=
kono
parents:
diff changeset
212 Strings.Fixed.Index (Name, Dir_Seps, Going => Strings.Backward);
kono
parents:
diff changeset
213
kono
parents:
diff changeset
214 begin
kono
parents:
diff changeset
215 if Last_DS = 0 then
kono
parents:
diff changeset
216
kono
parents:
diff changeset
217 -- There is no directory separator, returns "." representing
kono
parents:
diff changeset
218 -- the current working directory.
kono
parents:
diff changeset
219
kono
parents:
diff changeset
220 return ".";
kono
parents:
diff changeset
221
kono
parents:
diff changeset
222 -- If Name indicates a root directory, raise Use_Error, because
kono
parents:
diff changeset
223 -- it has no containing directory.
kono
parents:
diff changeset
224
kono
parents:
diff changeset
225 elsif Name = "/"
kono
parents:
diff changeset
226 or else
kono
parents:
diff changeset
227 (Windows
kono
parents:
diff changeset
228 and then
kono
parents:
diff changeset
229 (Name = "\"
kono
parents:
diff changeset
230 or else
kono
parents:
diff changeset
231 (Name'Length = 3
kono
parents:
diff changeset
232 and then Name (Name'Last - 1 .. Name'Last) = ":\"
kono
parents:
diff changeset
233 and then (Name (Name'First) in 'a' .. 'z'
kono
parents:
diff changeset
234 or else
kono
parents:
diff changeset
235 Name (Name'First) in 'A' .. 'Z'))))
kono
parents:
diff changeset
236 then
kono
parents:
diff changeset
237 raise Use_Error with
kono
parents:
diff changeset
238 "directory """ & Name & """ has no containing directory";
kono
parents:
diff changeset
239
kono
parents:
diff changeset
240 else
kono
parents:
diff changeset
241 declare
kono
parents:
diff changeset
242 Last : Positive := Last_DS - Name'First + 1;
kono
parents:
diff changeset
243 Result : String (1 .. Last);
kono
parents:
diff changeset
244
kono
parents:
diff changeset
245 begin
kono
parents:
diff changeset
246 Result := Name (Name'First .. Last_DS);
kono
parents:
diff changeset
247
kono
parents:
diff changeset
248 -- Remove any trailing directory separator, except as the
kono
parents:
diff changeset
249 -- first character or the first character following a drive
kono
parents:
diff changeset
250 -- number on Windows.
kono
parents:
diff changeset
251
kono
parents:
diff changeset
252 while Last > 1 loop
kono
parents:
diff changeset
253 exit when
kono
parents:
diff changeset
254 Result (Last) /= '/'
kono
parents:
diff changeset
255 and then
kono
parents:
diff changeset
256 Result (Last) /= Directory_Separator;
kono
parents:
diff changeset
257
kono
parents:
diff changeset
258 exit when Windows
kono
parents:
diff changeset
259 and then Last = 3
kono
parents:
diff changeset
260 and then Result (2) = ':'
kono
parents:
diff changeset
261 and then
kono
parents:
diff changeset
262 (Result (1) in 'A' .. 'Z'
kono
parents:
diff changeset
263 or else
kono
parents:
diff changeset
264 Result (1) in 'a' .. 'z');
kono
parents:
diff changeset
265
kono
parents:
diff changeset
266 Last := Last - 1;
kono
parents:
diff changeset
267 end loop;
kono
parents:
diff changeset
268
kono
parents:
diff changeset
269 -- Special case of "..": the current directory may be a root
kono
parents:
diff changeset
270 -- directory.
kono
parents:
diff changeset
271
kono
parents:
diff changeset
272 if Last = 2 and then Result (1 .. 2) = ".." then
kono
parents:
diff changeset
273 return Containing_Directory (Current_Directory);
kono
parents:
diff changeset
274
kono
parents:
diff changeset
275 else
kono
parents:
diff changeset
276 return Result (1 .. Last);
kono
parents:
diff changeset
277 end if;
kono
parents:
diff changeset
278 end;
kono
parents:
diff changeset
279 end if;
kono
parents:
diff changeset
280 end;
kono
parents:
diff changeset
281 end if;
kono
parents:
diff changeset
282 end Containing_Directory;
kono
parents:
diff changeset
283
kono
parents:
diff changeset
284 ---------------
kono
parents:
diff changeset
285 -- Copy_File --
kono
parents:
diff changeset
286 ---------------
kono
parents:
diff changeset
287
kono
parents:
diff changeset
288 procedure Copy_File
kono
parents:
diff changeset
289 (Source_Name : String;
kono
parents:
diff changeset
290 Target_Name : String;
kono
parents:
diff changeset
291 Form : String := "")
kono
parents:
diff changeset
292 is
kono
parents:
diff changeset
293 Success : Boolean;
kono
parents:
diff changeset
294 Mode : Copy_Mode := Overwrite;
kono
parents:
diff changeset
295 Preserve : Attribute := None;
kono
parents:
diff changeset
296
kono
parents:
diff changeset
297 begin
kono
parents:
diff changeset
298 -- First, the invalid cases
kono
parents:
diff changeset
299
kono
parents:
diff changeset
300 if not Is_Valid_Path_Name (Source_Name) then
kono
parents:
diff changeset
301 raise Name_Error with
kono
parents:
diff changeset
302 "invalid source path name """ & Source_Name & '"';
kono
parents:
diff changeset
303
kono
parents:
diff changeset
304 elsif not Is_Valid_Path_Name (Target_Name) then
kono
parents:
diff changeset
305 raise Name_Error with
kono
parents:
diff changeset
306 "invalid target path name """ & Target_Name & '"';
kono
parents:
diff changeset
307
kono
parents:
diff changeset
308 elsif not Is_Regular_File (Source_Name) then
kono
parents:
diff changeset
309 raise Name_Error with '"' & Source_Name & """ is not a file";
kono
parents:
diff changeset
310
kono
parents:
diff changeset
311 elsif Is_Directory (Target_Name) then
kono
parents:
diff changeset
312 raise Use_Error with "target """ & Target_Name & """ is a directory";
kono
parents:
diff changeset
313
kono
parents:
diff changeset
314 else
kono
parents:
diff changeset
315 if Form'Length > 0 then
kono
parents:
diff changeset
316 declare
kono
parents:
diff changeset
317 Formstr : String (1 .. Form'Length + 1);
kono
parents:
diff changeset
318 V1, V2 : Natural;
kono
parents:
diff changeset
319
kono
parents:
diff changeset
320 begin
kono
parents:
diff changeset
321 -- Acquire form string, setting required NUL terminator
kono
parents:
diff changeset
322
kono
parents:
diff changeset
323 Formstr (1 .. Form'Length) := Form;
kono
parents:
diff changeset
324 Formstr (Formstr'Last) := ASCII.NUL;
kono
parents:
diff changeset
325
kono
parents:
diff changeset
326 -- Convert form string to lower case
kono
parents:
diff changeset
327
kono
parents:
diff changeset
328 for J in Formstr'Range loop
kono
parents:
diff changeset
329 if Formstr (J) in 'A' .. 'Z' then
kono
parents:
diff changeset
330 Formstr (J) :=
kono
parents:
diff changeset
331 Character'Val (Character'Pos (Formstr (J)) + 32);
kono
parents:
diff changeset
332 end if;
kono
parents:
diff changeset
333 end loop;
kono
parents:
diff changeset
334
kono
parents:
diff changeset
335 -- Check Form
kono
parents:
diff changeset
336
kono
parents:
diff changeset
337 Form_Parameter (Formstr, "mode", V1, V2);
kono
parents:
diff changeset
338
kono
parents:
diff changeset
339 if V1 = 0 then
kono
parents:
diff changeset
340 Mode := Overwrite;
kono
parents:
diff changeset
341 elsif Formstr (V1 .. V2) = "copy" then
kono
parents:
diff changeset
342 Mode := Copy;
kono
parents:
diff changeset
343 elsif Formstr (V1 .. V2) = "overwrite" then
kono
parents:
diff changeset
344 Mode := Overwrite;
kono
parents:
diff changeset
345 elsif Formstr (V1 .. V2) = "append" then
kono
parents:
diff changeset
346 Mode := Append;
kono
parents:
diff changeset
347 else
kono
parents:
diff changeset
348 raise Use_Error with "invalid Form";
kono
parents:
diff changeset
349 end if;
kono
parents:
diff changeset
350
kono
parents:
diff changeset
351 Form_Parameter (Formstr, "preserve", V1, V2);
kono
parents:
diff changeset
352
kono
parents:
diff changeset
353 if V1 = 0 then
kono
parents:
diff changeset
354 Preserve := None;
kono
parents:
diff changeset
355 elsif Formstr (V1 .. V2) = "timestamps" then
kono
parents:
diff changeset
356 Preserve := Time_Stamps;
kono
parents:
diff changeset
357 elsif Formstr (V1 .. V2) = "all_attributes" then
kono
parents:
diff changeset
358 Preserve := Full;
kono
parents:
diff changeset
359 elsif Formstr (V1 .. V2) = "no_attributes" then
kono
parents:
diff changeset
360 Preserve := None;
kono
parents:
diff changeset
361 else
kono
parents:
diff changeset
362 raise Use_Error with "invalid Form";
kono
parents:
diff changeset
363 end if;
kono
parents:
diff changeset
364 end;
kono
parents:
diff changeset
365 end if;
kono
parents:
diff changeset
366
kono
parents:
diff changeset
367 -- Do actual copy using System.OS_Lib.Copy_File
kono
parents:
diff changeset
368
kono
parents:
diff changeset
369 Copy_File (Source_Name, Target_Name, Success, Mode, Preserve);
kono
parents:
diff changeset
370
kono
parents:
diff changeset
371 if not Success then
kono
parents:
diff changeset
372 raise Use_Error with "copy of """ & Source_Name & """ failed";
kono
parents:
diff changeset
373 end if;
kono
parents:
diff changeset
374 end if;
kono
parents:
diff changeset
375 end Copy_File;
kono
parents:
diff changeset
376
kono
parents:
diff changeset
377 ----------------------
kono
parents:
diff changeset
378 -- Create_Directory --
kono
parents:
diff changeset
379 ----------------------
kono
parents:
diff changeset
380
kono
parents:
diff changeset
381 procedure Create_Directory
kono
parents:
diff changeset
382 (New_Directory : String;
kono
parents:
diff changeset
383 Form : String := "")
kono
parents:
diff changeset
384 is
kono
parents:
diff changeset
385 C_Dir_Name : constant String := New_Directory & ASCII.NUL;
kono
parents:
diff changeset
386
kono
parents:
diff changeset
387 begin
kono
parents:
diff changeset
388 -- First, the invalid case
kono
parents:
diff changeset
389
kono
parents:
diff changeset
390 if not Is_Valid_Path_Name (New_Directory) then
kono
parents:
diff changeset
391 raise Name_Error with
kono
parents:
diff changeset
392 "invalid new directory path name """ & New_Directory & '"';
kono
parents:
diff changeset
393
kono
parents:
diff changeset
394 else
kono
parents:
diff changeset
395 -- Acquire setting of encoding parameter
kono
parents:
diff changeset
396
kono
parents:
diff changeset
397 declare
kono
parents:
diff changeset
398 Formstr : constant String := To_Lower (Form);
kono
parents:
diff changeset
399
kono
parents:
diff changeset
400 Encoding : CRTL.Filename_Encoding;
kono
parents:
diff changeset
401 -- Filename encoding specified into the form parameter
kono
parents:
diff changeset
402
kono
parents:
diff changeset
403 V1, V2 : Natural;
kono
parents:
diff changeset
404
kono
parents:
diff changeset
405 begin
kono
parents:
diff changeset
406 Form_Parameter (Formstr, "encoding", V1, V2);
kono
parents:
diff changeset
407
kono
parents:
diff changeset
408 if V1 = 0 then
kono
parents:
diff changeset
409 Encoding := CRTL.Unspecified;
kono
parents:
diff changeset
410 elsif Formstr (V1 .. V2) = "utf8" then
kono
parents:
diff changeset
411 Encoding := CRTL.UTF8;
kono
parents:
diff changeset
412 elsif Formstr (V1 .. V2) = "8bits" then
kono
parents:
diff changeset
413 Encoding := CRTL.ASCII_8bits;
kono
parents:
diff changeset
414 else
kono
parents:
diff changeset
415 raise Use_Error with "invalid Form";
kono
parents:
diff changeset
416 end if;
kono
parents:
diff changeset
417
kono
parents:
diff changeset
418 if CRTL.mkdir (C_Dir_Name, Encoding) /= 0 then
kono
parents:
diff changeset
419 raise Use_Error with
kono
parents:
diff changeset
420 "creation of new directory """ & New_Directory & """ failed";
kono
parents:
diff changeset
421 end if;
kono
parents:
diff changeset
422 end;
kono
parents:
diff changeset
423 end if;
kono
parents:
diff changeset
424 end Create_Directory;
kono
parents:
diff changeset
425
kono
parents:
diff changeset
426 -----------------
kono
parents:
diff changeset
427 -- Create_Path --
kono
parents:
diff changeset
428 -----------------
kono
parents:
diff changeset
429
kono
parents:
diff changeset
430 procedure Create_Path
kono
parents:
diff changeset
431 (New_Directory : String;
kono
parents:
diff changeset
432 Form : String := "")
kono
parents:
diff changeset
433 is
kono
parents:
diff changeset
434 New_Dir : String (1 .. New_Directory'Length + 1);
kono
parents:
diff changeset
435 Last : Positive := 1;
kono
parents:
diff changeset
436 Start : Positive := 1;
kono
parents:
diff changeset
437
kono
parents:
diff changeset
438 begin
kono
parents:
diff changeset
439 -- First, the invalid case
kono
parents:
diff changeset
440
kono
parents:
diff changeset
441 if not Is_Valid_Path_Name (New_Directory) then
kono
parents:
diff changeset
442 raise Name_Error with
kono
parents:
diff changeset
443 "invalid new directory path name """ & New_Directory & '"';
kono
parents:
diff changeset
444
kono
parents:
diff changeset
445 else
kono
parents:
diff changeset
446 -- Build New_Dir with a directory separator at the end, so that the
kono
parents:
diff changeset
447 -- complete path will be found in the loop below.
kono
parents:
diff changeset
448
kono
parents:
diff changeset
449 New_Dir (1 .. New_Directory'Length) := New_Directory;
kono
parents:
diff changeset
450 New_Dir (New_Dir'Last) := Directory_Separator;
kono
parents:
diff changeset
451
kono
parents:
diff changeset
452 -- If host is windows, and the first two characters are directory
kono
parents:
diff changeset
453 -- separators, we have an UNC path. Skip it.
kono
parents:
diff changeset
454
kono
parents:
diff changeset
455 if Directory_Separator = '\'
kono
parents:
diff changeset
456 and then New_Dir'Length > 2
kono
parents:
diff changeset
457 and then Is_In (New_Dir (1), Dir_Seps)
kono
parents:
diff changeset
458 and then Is_In (New_Dir (2), Dir_Seps)
kono
parents:
diff changeset
459 then
kono
parents:
diff changeset
460 Start := 2;
kono
parents:
diff changeset
461 loop
kono
parents:
diff changeset
462 Start := Start + 1;
kono
parents:
diff changeset
463 exit when Start = New_Dir'Last
kono
parents:
diff changeset
464 or else Is_In (New_Dir (Start), Dir_Seps);
kono
parents:
diff changeset
465 end loop;
kono
parents:
diff changeset
466 end if;
kono
parents:
diff changeset
467
kono
parents:
diff changeset
468 -- Create, if necessary, each directory in the path
kono
parents:
diff changeset
469
kono
parents:
diff changeset
470 for J in Start + 1 .. New_Dir'Last loop
kono
parents:
diff changeset
471
kono
parents:
diff changeset
472 -- Look for the end of an intermediate directory
kono
parents:
diff changeset
473
kono
parents:
diff changeset
474 if not Is_In (New_Dir (J), Dir_Seps) then
kono
parents:
diff changeset
475 Last := J;
kono
parents:
diff changeset
476
kono
parents:
diff changeset
477 -- We have found a new intermediate directory each time we find
kono
parents:
diff changeset
478 -- a first directory separator.
kono
parents:
diff changeset
479
kono
parents:
diff changeset
480 elsif not Is_In (New_Dir (J - 1), Dir_Seps) then
kono
parents:
diff changeset
481
kono
parents:
diff changeset
482 -- No need to create the directory if it already exists
kono
parents:
diff changeset
483
kono
parents:
diff changeset
484 if not Is_Directory (New_Dir (1 .. Last)) then
kono
parents:
diff changeset
485 begin
kono
parents:
diff changeset
486 Create_Directory
kono
parents:
diff changeset
487 (New_Directory => New_Dir (1 .. Last), Form => Form);
kono
parents:
diff changeset
488
kono
parents:
diff changeset
489 exception
kono
parents:
diff changeset
490 when Use_Error =>
kono
parents:
diff changeset
491 if File_Exists (New_Dir (1 .. Last)) then
kono
parents:
diff changeset
492
kono
parents:
diff changeset
493 -- A file with such a name already exists. If it is
kono
parents:
diff changeset
494 -- a directory, then it was apparently just created
kono
parents:
diff changeset
495 -- by another process or thread, and all is well.
kono
parents:
diff changeset
496 -- If it is of some other kind, report an error.
kono
parents:
diff changeset
497
kono
parents:
diff changeset
498 if not Is_Directory (New_Dir (1 .. Last)) then
kono
parents:
diff changeset
499 raise Use_Error with
kono
parents:
diff changeset
500 "file """ & New_Dir (1 .. Last) &
kono
parents:
diff changeset
501 """ already exists and is not a directory";
kono
parents:
diff changeset
502 end if;
kono
parents:
diff changeset
503
kono
parents:
diff changeset
504 else
kono
parents:
diff changeset
505 -- Create_Directory failed for some other reason:
kono
parents:
diff changeset
506 -- propagate the exception.
kono
parents:
diff changeset
507
kono
parents:
diff changeset
508 raise;
kono
parents:
diff changeset
509 end if;
kono
parents:
diff changeset
510 end;
kono
parents:
diff changeset
511 end if;
kono
parents:
diff changeset
512 end if;
kono
parents:
diff changeset
513 end loop;
kono
parents:
diff changeset
514 end if;
kono
parents:
diff changeset
515 end Create_Path;
kono
parents:
diff changeset
516
kono
parents:
diff changeset
517 -----------------------
kono
parents:
diff changeset
518 -- Current_Directory --
kono
parents:
diff changeset
519 -----------------------
kono
parents:
diff changeset
520
kono
parents:
diff changeset
521 function Current_Directory return String is
kono
parents:
diff changeset
522 Path_Len : Natural := Max_Path;
kono
parents:
diff changeset
523 Buffer : String (1 .. 1 + Max_Path + 1);
kono
parents:
diff changeset
524
kono
parents:
diff changeset
525 procedure Local_Get_Current_Dir (Dir : Address; Length : Address);
kono
parents:
diff changeset
526 pragma Import (C, Local_Get_Current_Dir, "__gnat_get_current_dir");
kono
parents:
diff changeset
527
kono
parents:
diff changeset
528 begin
kono
parents:
diff changeset
529 Local_Get_Current_Dir (Buffer'Address, Path_Len'Address);
kono
parents:
diff changeset
530
kono
parents:
diff changeset
531 if Path_Len = 0 then
kono
parents:
diff changeset
532 raise Use_Error with "current directory does not exist";
kono
parents:
diff changeset
533 end if;
kono
parents:
diff changeset
534
kono
parents:
diff changeset
535 -- We need to resolve links because of RM A.16(47), which requires
kono
parents:
diff changeset
536 -- that we not return alternative names for files.
kono
parents:
diff changeset
537
kono
parents:
diff changeset
538 return Normalize_Pathname (Buffer (1 .. Path_Len));
kono
parents:
diff changeset
539 end Current_Directory;
kono
parents:
diff changeset
540
kono
parents:
diff changeset
541 ----------------------
kono
parents:
diff changeset
542 -- Delete_Directory --
kono
parents:
diff changeset
543 ----------------------
kono
parents:
diff changeset
544
kono
parents:
diff changeset
545 procedure Delete_Directory (Directory : String) is
kono
parents:
diff changeset
546 begin
kono
parents:
diff changeset
547 -- First, the invalid cases
kono
parents:
diff changeset
548
kono
parents:
diff changeset
549 if not Is_Valid_Path_Name (Directory) then
kono
parents:
diff changeset
550 raise Name_Error with
kono
parents:
diff changeset
551 "invalid directory path name """ & Directory & '"';
kono
parents:
diff changeset
552
kono
parents:
diff changeset
553 elsif not Is_Directory (Directory) then
kono
parents:
diff changeset
554 raise Name_Error with '"' & Directory & """ not a directory";
kono
parents:
diff changeset
555
kono
parents:
diff changeset
556 -- Do the deletion, checking for error
kono
parents:
diff changeset
557
kono
parents:
diff changeset
558 else
kono
parents:
diff changeset
559 declare
kono
parents:
diff changeset
560 C_Dir_Name : constant String := Directory & ASCII.NUL;
kono
parents:
diff changeset
561 begin
kono
parents:
diff changeset
562 if rmdir (C_Dir_Name) /= 0 then
kono
parents:
diff changeset
563 raise Use_Error with
kono
parents:
diff changeset
564 "deletion of directory """ & Directory & """ failed";
kono
parents:
diff changeset
565 end if;
kono
parents:
diff changeset
566 end;
kono
parents:
diff changeset
567 end if;
kono
parents:
diff changeset
568 end Delete_Directory;
kono
parents:
diff changeset
569
kono
parents:
diff changeset
570 -----------------
kono
parents:
diff changeset
571 -- Delete_File --
kono
parents:
diff changeset
572 -----------------
kono
parents:
diff changeset
573
kono
parents:
diff changeset
574 procedure Delete_File (Name : String) is
kono
parents:
diff changeset
575 Success : Boolean;
kono
parents:
diff changeset
576
kono
parents:
diff changeset
577 begin
kono
parents:
diff changeset
578 -- First, the invalid cases
kono
parents:
diff changeset
579
kono
parents:
diff changeset
580 if not Is_Valid_Path_Name (Name) then
kono
parents:
diff changeset
581 raise Name_Error with "invalid path name """ & Name & '"';
kono
parents:
diff changeset
582
kono
parents:
diff changeset
583 elsif not Is_Regular_File (Name)
kono
parents:
diff changeset
584 and then not Is_Symbolic_Link (Name)
kono
parents:
diff changeset
585 then
kono
parents:
diff changeset
586 raise Name_Error with "file """ & Name & """ does not exist";
kono
parents:
diff changeset
587
kono
parents:
diff changeset
588 else
kono
parents:
diff changeset
589 -- Do actual deletion using System.OS_Lib.Delete_File
kono
parents:
diff changeset
590
kono
parents:
diff changeset
591 Delete_File (Name, Success);
kono
parents:
diff changeset
592
kono
parents:
diff changeset
593 if not Success then
kono
parents:
diff changeset
594 raise Use_Error with "file """ & Name & """ could not be deleted";
kono
parents:
diff changeset
595 end if;
kono
parents:
diff changeset
596 end if;
kono
parents:
diff changeset
597 end Delete_File;
kono
parents:
diff changeset
598
kono
parents:
diff changeset
599 -----------------
kono
parents:
diff changeset
600 -- Delete_Tree --
kono
parents:
diff changeset
601 -----------------
kono
parents:
diff changeset
602
kono
parents:
diff changeset
603 procedure Delete_Tree (Directory : String) is
kono
parents:
diff changeset
604 Search : Search_Type;
kono
parents:
diff changeset
605 Dir_Ent : Directory_Entry_Type;
kono
parents:
diff changeset
606 begin
kono
parents:
diff changeset
607 -- First, the invalid cases
kono
parents:
diff changeset
608
kono
parents:
diff changeset
609 if not Is_Valid_Path_Name (Directory) then
kono
parents:
diff changeset
610 raise Name_Error with
kono
parents:
diff changeset
611 "invalid directory path name """ & Directory & '"';
kono
parents:
diff changeset
612
kono
parents:
diff changeset
613 elsif not Is_Directory (Directory) then
kono
parents:
diff changeset
614 raise Name_Error with '"' & Directory & """ not a directory";
kono
parents:
diff changeset
615
kono
parents:
diff changeset
616 else
kono
parents:
diff changeset
617
kono
parents:
diff changeset
618 -- We used to change the current directory to Directory here,
kono
parents:
diff changeset
619 -- allowing the use of a local Simple_Name for all references. This
kono
parents:
diff changeset
620 -- turned out unfriendly to multitasking programs, where tasks
kono
parents:
diff changeset
621 -- running in parallel of this Delete_Tree could see their current
kono
parents:
diff changeset
622 -- directory change unpredictably. We now resort to Full_Name
kono
parents:
diff changeset
623 -- computations to reach files and subdirs instead.
kono
parents:
diff changeset
624
kono
parents:
diff changeset
625 Start_Search (Search, Directory => Directory, Pattern => "");
kono
parents:
diff changeset
626 while More_Entries (Search) loop
kono
parents:
diff changeset
627 Get_Next_Entry (Search, Dir_Ent);
kono
parents:
diff changeset
628
kono
parents:
diff changeset
629 declare
kono
parents:
diff changeset
630 Fname : constant String := Full_Name (Dir_Ent);
kono
parents:
diff changeset
631 Sname : constant String := Simple_Name (Dir_Ent);
kono
parents:
diff changeset
632
kono
parents:
diff changeset
633 begin
kono
parents:
diff changeset
634 if OS_Lib.Is_Directory (Fname) then
kono
parents:
diff changeset
635 if Sname /= "." and then Sname /= ".." then
kono
parents:
diff changeset
636 Delete_Tree (Fname);
kono
parents:
diff changeset
637 end if;
kono
parents:
diff changeset
638 else
kono
parents:
diff changeset
639 Delete_File (Fname);
kono
parents:
diff changeset
640 end if;
kono
parents:
diff changeset
641 end;
kono
parents:
diff changeset
642 end loop;
kono
parents:
diff changeset
643
kono
parents:
diff changeset
644 End_Search (Search);
kono
parents:
diff changeset
645
kono
parents:
diff changeset
646 declare
kono
parents:
diff changeset
647 C_Dir_Name : constant String := Directory & ASCII.NUL;
kono
parents:
diff changeset
648
kono
parents:
diff changeset
649 begin
kono
parents:
diff changeset
650 if rmdir (C_Dir_Name) /= 0 then
kono
parents:
diff changeset
651 raise Use_Error with
kono
parents:
diff changeset
652 "directory tree rooted at """ &
kono
parents:
diff changeset
653 Directory & """ could not be deleted";
kono
parents:
diff changeset
654 end if;
kono
parents:
diff changeset
655 end;
kono
parents:
diff changeset
656 end if;
kono
parents:
diff changeset
657 end Delete_Tree;
kono
parents:
diff changeset
658
kono
parents:
diff changeset
659 ------------
kono
parents:
diff changeset
660 -- Exists --
kono
parents:
diff changeset
661 ------------
kono
parents:
diff changeset
662
kono
parents:
diff changeset
663 function Exists (Name : String) return Boolean is
kono
parents:
diff changeset
664 begin
kono
parents:
diff changeset
665 -- First, the invalid case
kono
parents:
diff changeset
666
kono
parents:
diff changeset
667 if not Is_Valid_Path_Name (Name) then
kono
parents:
diff changeset
668 raise Name_Error with "invalid path name """ & Name & '"';
kono
parents:
diff changeset
669
kono
parents:
diff changeset
670 else
kono
parents:
diff changeset
671 -- The implementation is in File_Exists
kono
parents:
diff changeset
672
kono
parents:
diff changeset
673 return File_Exists (Name);
kono
parents:
diff changeset
674 end if;
kono
parents:
diff changeset
675 end Exists;
kono
parents:
diff changeset
676
kono
parents:
diff changeset
677 ---------------
kono
parents:
diff changeset
678 -- Extension --
kono
parents:
diff changeset
679 ---------------
kono
parents:
diff changeset
680
kono
parents:
diff changeset
681 function Extension (Name : String) return String is
kono
parents:
diff changeset
682 begin
kono
parents:
diff changeset
683 -- First, the invalid case
kono
parents:
diff changeset
684
kono
parents:
diff changeset
685 if not Is_Valid_Path_Name (Name) then
kono
parents:
diff changeset
686 raise Name_Error with "invalid path name """ & Name & '"';
kono
parents:
diff changeset
687
kono
parents:
diff changeset
688 else
kono
parents:
diff changeset
689 -- Look for first dot that is not followed by a directory separator
kono
parents:
diff changeset
690
kono
parents:
diff changeset
691 for Pos in reverse Name'Range loop
kono
parents:
diff changeset
692
kono
parents:
diff changeset
693 -- If a directory separator is found before a dot, there is no
kono
parents:
diff changeset
694 -- extension.
kono
parents:
diff changeset
695
kono
parents:
diff changeset
696 if Is_In (Name (Pos), Dir_Seps) then
kono
parents:
diff changeset
697 return Empty_String;
kono
parents:
diff changeset
698
kono
parents:
diff changeset
699 elsif Name (Pos) = '.' then
kono
parents:
diff changeset
700
kono
parents:
diff changeset
701 -- We found a dot, build the return value with lower bound 1
kono
parents:
diff changeset
702
kono
parents:
diff changeset
703 declare
kono
parents:
diff changeset
704 subtype Result_Type is String (1 .. Name'Last - Pos);
kono
parents:
diff changeset
705 begin
kono
parents:
diff changeset
706 return Result_Type (Name (Pos + 1 .. Name'Last));
kono
parents:
diff changeset
707 end;
kono
parents:
diff changeset
708 end if;
kono
parents:
diff changeset
709 end loop;
kono
parents:
diff changeset
710
kono
parents:
diff changeset
711 -- No dot were found, there is no extension
kono
parents:
diff changeset
712
kono
parents:
diff changeset
713 return Empty_String;
kono
parents:
diff changeset
714 end if;
kono
parents:
diff changeset
715 end Extension;
kono
parents:
diff changeset
716
kono
parents:
diff changeset
717 ----------------------
kono
parents:
diff changeset
718 -- Fetch_Next_Entry --
kono
parents:
diff changeset
719 ----------------------
kono
parents:
diff changeset
720
kono
parents:
diff changeset
721 procedure Fetch_Next_Entry (Search : Search_Type) is
kono
parents:
diff changeset
722 Name : String (1 .. NAME_MAX);
kono
parents:
diff changeset
723 Last : Natural;
kono
parents:
diff changeset
724
kono
parents:
diff changeset
725 Kind : File_Kind := Ordinary_File;
kono
parents:
diff changeset
726 -- Initialized to avoid a compilation warning
kono
parents:
diff changeset
727
kono
parents:
diff changeset
728 Filename_Addr : Address;
kono
parents:
diff changeset
729 Filename_Len : aliased Integer;
kono
parents:
diff changeset
730
kono
parents:
diff changeset
731 Buffer : array (1 .. SIZEOF_struct_dirent_alloc) of Character;
kono
parents:
diff changeset
732
kono
parents:
diff changeset
733 function readdir_gnat
kono
parents:
diff changeset
734 (Directory : Address;
kono
parents:
diff changeset
735 Buffer : Address;
kono
parents:
diff changeset
736 Last : not null access Integer) return Address;
kono
parents:
diff changeset
737 pragma Import (C, readdir_gnat, "__gnat_readdir");
kono
parents:
diff changeset
738
kono
parents:
diff changeset
739 begin
kono
parents:
diff changeset
740 -- Search.Value.Is_Valid is always True when Fetch_Next_Entry is called
kono
parents:
diff changeset
741
kono
parents:
diff changeset
742 loop
kono
parents:
diff changeset
743 Filename_Addr :=
kono
parents:
diff changeset
744 readdir_gnat
kono
parents:
diff changeset
745 (Address (Search.Value.Dir),
kono
parents:
diff changeset
746 Buffer'Address,
kono
parents:
diff changeset
747 Filename_Len'Access);
kono
parents:
diff changeset
748
kono
parents:
diff changeset
749 -- If no matching entry is found, set Is_Valid to False
kono
parents:
diff changeset
750
kono
parents:
diff changeset
751 if Filename_Addr = Null_Address then
kono
parents:
diff changeset
752 Search.Value.Is_Valid := False;
kono
parents:
diff changeset
753 exit;
kono
parents:
diff changeset
754 end if;
kono
parents:
diff changeset
755
kono
parents:
diff changeset
756 if Filename_Len > Name'Length then
kono
parents:
diff changeset
757 raise Use_Error with "file name too long";
kono
parents:
diff changeset
758 end if;
kono
parents:
diff changeset
759
kono
parents:
diff changeset
760 declare
kono
parents:
diff changeset
761 subtype Name_String is String (1 .. Filename_Len);
kono
parents:
diff changeset
762 Dent_Name : Name_String;
kono
parents:
diff changeset
763 for Dent_Name'Address use Filename_Addr;
kono
parents:
diff changeset
764 pragma Import (Ada, Dent_Name);
kono
parents:
diff changeset
765
kono
parents:
diff changeset
766 begin
kono
parents:
diff changeset
767 Last := Filename_Len;
kono
parents:
diff changeset
768 Name (1 .. Last) := Dent_Name;
kono
parents:
diff changeset
769 end;
kono
parents:
diff changeset
770
kono
parents:
diff changeset
771 -- Check if the entry matches the pattern
kono
parents:
diff changeset
772
kono
parents:
diff changeset
773 if Match (Name (1 .. Last), Search.Value.Pattern) then
kono
parents:
diff changeset
774 declare
kono
parents:
diff changeset
775 C_Full_Name : constant String :=
kono
parents:
diff changeset
776 Compose (To_String (Search.Value.Name),
kono
parents:
diff changeset
777 Name (1 .. Last)) & ASCII.NUL;
kono
parents:
diff changeset
778 Full_Name : String renames
kono
parents:
diff changeset
779 C_Full_Name
kono
parents:
diff changeset
780 (C_Full_Name'First .. C_Full_Name'Last - 1);
kono
parents:
diff changeset
781 Found : Boolean := False;
kono
parents:
diff changeset
782 Attr : aliased File_Attributes;
kono
parents:
diff changeset
783 Exists : Integer;
kono
parents:
diff changeset
784 Error : Integer;
kono
parents:
diff changeset
785
kono
parents:
diff changeset
786 begin
kono
parents:
diff changeset
787 Reset_Attributes (Attr'Access);
kono
parents:
diff changeset
788 Exists := File_Exists_Attr (C_Full_Name'Address, Attr'Access);
kono
parents:
diff changeset
789 Error := Error_Attributes (Attr'Access);
kono
parents:
diff changeset
790
kono
parents:
diff changeset
791 if Error /= 0 then
kono
parents:
diff changeset
792 raise Use_Error
kono
parents:
diff changeset
793 with Full_Name & ": " & Errno_Message (Err => Error);
kono
parents:
diff changeset
794 end if;
kono
parents:
diff changeset
795
kono
parents:
diff changeset
796 if Exists = 1 then
kono
parents:
diff changeset
797
kono
parents:
diff changeset
798 -- Now check if the file kind matches the filter
kono
parents:
diff changeset
799
kono
parents:
diff changeset
800 if Is_Regular_File_Attr
kono
parents:
diff changeset
801 (C_Full_Name'Address, Attr'Access) = 1
kono
parents:
diff changeset
802 then
kono
parents:
diff changeset
803 if Search.Value.Filter (Ordinary_File) then
kono
parents:
diff changeset
804 Kind := Ordinary_File;
kono
parents:
diff changeset
805 Found := True;
kono
parents:
diff changeset
806 end if;
kono
parents:
diff changeset
807
kono
parents:
diff changeset
808 elsif Is_Directory_Attr
kono
parents:
diff changeset
809 (C_Full_Name'Address, Attr'Access) = 1
kono
parents:
diff changeset
810 then
kono
parents:
diff changeset
811 if Search.Value.Filter (Directory) then
kono
parents:
diff changeset
812 Kind := Directory;
kono
parents:
diff changeset
813 Found := True;
kono
parents:
diff changeset
814 end if;
kono
parents:
diff changeset
815
kono
parents:
diff changeset
816 elsif Search.Value.Filter (Special_File) then
kono
parents:
diff changeset
817 Kind := Special_File;
kono
parents:
diff changeset
818 Found := True;
kono
parents:
diff changeset
819 end if;
kono
parents:
diff changeset
820
kono
parents:
diff changeset
821 -- If it does, update Search and return
kono
parents:
diff changeset
822
kono
parents:
diff changeset
823 if Found then
kono
parents:
diff changeset
824 Search.Value.Entry_Fetched := True;
kono
parents:
diff changeset
825 Search.Value.Dir_Entry :=
kono
parents:
diff changeset
826 (Is_Valid => True,
kono
parents:
diff changeset
827 Simple => To_Unbounded_String (Name (1 .. Last)),
kono
parents:
diff changeset
828 Full => To_Unbounded_String (Full_Name),
kono
parents:
diff changeset
829 Kind => Kind);
kono
parents:
diff changeset
830 exit;
kono
parents:
diff changeset
831 end if;
kono
parents:
diff changeset
832 end if;
kono
parents:
diff changeset
833 end;
kono
parents:
diff changeset
834 end if;
kono
parents:
diff changeset
835 end loop;
kono
parents:
diff changeset
836 end Fetch_Next_Entry;
kono
parents:
diff changeset
837
kono
parents:
diff changeset
838 -----------------
kono
parents:
diff changeset
839 -- File_Exists --
kono
parents:
diff changeset
840 -----------------
kono
parents:
diff changeset
841
kono
parents:
diff changeset
842 function File_Exists (Name : String) return Boolean is
kono
parents:
diff changeset
843 function C_File_Exists (A : Address) return Integer;
kono
parents:
diff changeset
844 pragma Import (C, C_File_Exists, "__gnat_file_exists");
kono
parents:
diff changeset
845
kono
parents:
diff changeset
846 C_Name : String (1 .. Name'Length + 1);
kono
parents:
diff changeset
847
kono
parents:
diff changeset
848 begin
kono
parents:
diff changeset
849 C_Name (1 .. Name'Length) := Name;
kono
parents:
diff changeset
850 C_Name (C_Name'Last) := ASCII.NUL;
kono
parents:
diff changeset
851 return C_File_Exists (C_Name'Address) = 1;
kono
parents:
diff changeset
852 end File_Exists;
kono
parents:
diff changeset
853
kono
parents:
diff changeset
854 --------------
kono
parents:
diff changeset
855 -- Finalize --
kono
parents:
diff changeset
856 --------------
kono
parents:
diff changeset
857
kono
parents:
diff changeset
858 procedure Finalize (Search : in out Search_Type) is
kono
parents:
diff changeset
859 begin
kono
parents:
diff changeset
860 if Search.Value /= null then
kono
parents:
diff changeset
861
kono
parents:
diff changeset
862 -- Close the directory, if one is open
kono
parents:
diff changeset
863
kono
parents:
diff changeset
864 if Search.Value.Dir /= No_Dir then
kono
parents:
diff changeset
865 Close (Search.Value.Dir);
kono
parents:
diff changeset
866 end if;
kono
parents:
diff changeset
867
kono
parents:
diff changeset
868 Free (Search.Value);
kono
parents:
diff changeset
869 end if;
kono
parents:
diff changeset
870 end Finalize;
kono
parents:
diff changeset
871
kono
parents:
diff changeset
872 ---------------
kono
parents:
diff changeset
873 -- Full_Name --
kono
parents:
diff changeset
874 ---------------
kono
parents:
diff changeset
875
kono
parents:
diff changeset
876 function Full_Name (Name : String) return String is
kono
parents:
diff changeset
877 begin
kono
parents:
diff changeset
878 -- First, the invalid case
kono
parents:
diff changeset
879
kono
parents:
diff changeset
880 if not Is_Valid_Path_Name (Name) then
kono
parents:
diff changeset
881 raise Name_Error with "invalid path name """ & Name & '"';
kono
parents:
diff changeset
882
kono
parents:
diff changeset
883 else
kono
parents:
diff changeset
884 -- Build the return value with lower bound 1
kono
parents:
diff changeset
885
kono
parents:
diff changeset
886 -- Use System.OS_Lib.Normalize_Pathname
kono
parents:
diff changeset
887
kono
parents:
diff changeset
888 declare
kono
parents:
diff changeset
889 -- We need to resolve links because of (RM A.16(47)), which says
kono
parents:
diff changeset
890 -- we must not return alternative names for files.
kono
parents:
diff changeset
891
kono
parents:
diff changeset
892 Value : constant String := Normalize_Pathname (Name);
kono
parents:
diff changeset
893 subtype Result is String (1 .. Value'Length);
kono
parents:
diff changeset
894
kono
parents:
diff changeset
895 begin
kono
parents:
diff changeset
896 return Result (Value);
kono
parents:
diff changeset
897 end;
kono
parents:
diff changeset
898 end if;
kono
parents:
diff changeset
899 end Full_Name;
kono
parents:
diff changeset
900
kono
parents:
diff changeset
901 function Full_Name (Directory_Entry : Directory_Entry_Type) return String is
kono
parents:
diff changeset
902 begin
kono
parents:
diff changeset
903 -- First, the invalid case
kono
parents:
diff changeset
904
kono
parents:
diff changeset
905 if not Directory_Entry.Is_Valid then
kono
parents:
diff changeset
906 raise Status_Error with "invalid directory entry";
kono
parents:
diff changeset
907
kono
parents:
diff changeset
908 else
kono
parents:
diff changeset
909 -- The value to return has already been computed
kono
parents:
diff changeset
910
kono
parents:
diff changeset
911 return To_String (Directory_Entry.Full);
kono
parents:
diff changeset
912 end if;
kono
parents:
diff changeset
913 end Full_Name;
kono
parents:
diff changeset
914
kono
parents:
diff changeset
915 --------------------
kono
parents:
diff changeset
916 -- Get_Next_Entry --
kono
parents:
diff changeset
917 --------------------
kono
parents:
diff changeset
918
kono
parents:
diff changeset
919 procedure Get_Next_Entry
kono
parents:
diff changeset
920 (Search : in out Search_Type;
kono
parents:
diff changeset
921 Directory_Entry : out Directory_Entry_Type)
kono
parents:
diff changeset
922 is
kono
parents:
diff changeset
923 begin
kono
parents:
diff changeset
924 -- First, the invalid case
kono
parents:
diff changeset
925
kono
parents:
diff changeset
926 if Search.Value = null or else not Search.Value.Is_Valid then
kono
parents:
diff changeset
927 raise Status_Error with "invalid search";
kono
parents:
diff changeset
928 end if;
kono
parents:
diff changeset
929
kono
parents:
diff changeset
930 -- Fetch the next entry, if needed
kono
parents:
diff changeset
931
kono
parents:
diff changeset
932 if not Search.Value.Entry_Fetched then
kono
parents:
diff changeset
933 Fetch_Next_Entry (Search);
kono
parents:
diff changeset
934 end if;
kono
parents:
diff changeset
935
kono
parents:
diff changeset
936 -- It is an error if no valid entry is found
kono
parents:
diff changeset
937
kono
parents:
diff changeset
938 if not Search.Value.Is_Valid then
kono
parents:
diff changeset
939 raise Status_Error with "no next entry";
kono
parents:
diff changeset
940
kono
parents:
diff changeset
941 else
kono
parents:
diff changeset
942 -- Reset Entry_Fetched and return the entry
kono
parents:
diff changeset
943
kono
parents:
diff changeset
944 Search.Value.Entry_Fetched := False;
kono
parents:
diff changeset
945 Directory_Entry := Search.Value.Dir_Entry;
kono
parents:
diff changeset
946 end if;
kono
parents:
diff changeset
947 end Get_Next_Entry;
kono
parents:
diff changeset
948
kono
parents:
diff changeset
949 ----------
kono
parents:
diff changeset
950 -- Kind --
kono
parents:
diff changeset
951 ----------
kono
parents:
diff changeset
952
kono
parents:
diff changeset
953 function Kind (Name : String) return File_Kind is
kono
parents:
diff changeset
954 begin
kono
parents:
diff changeset
955 -- First, the invalid case
kono
parents:
diff changeset
956
kono
parents:
diff changeset
957 if not File_Exists (Name) then
kono
parents:
diff changeset
958 raise Name_Error with "file """ & Name & """ does not exist";
kono
parents:
diff changeset
959
kono
parents:
diff changeset
960 -- If OK, return appropriate kind
kono
parents:
diff changeset
961
kono
parents:
diff changeset
962 elsif Is_Regular_File (Name) then
kono
parents:
diff changeset
963 return Ordinary_File;
kono
parents:
diff changeset
964
kono
parents:
diff changeset
965 elsif Is_Directory (Name) then
kono
parents:
diff changeset
966 return Directory;
kono
parents:
diff changeset
967
kono
parents:
diff changeset
968 else
kono
parents:
diff changeset
969 return Special_File;
kono
parents:
diff changeset
970 end if;
kono
parents:
diff changeset
971 end Kind;
kono
parents:
diff changeset
972
kono
parents:
diff changeset
973 function Kind (Directory_Entry : Directory_Entry_Type) return File_Kind is
kono
parents:
diff changeset
974 begin
kono
parents:
diff changeset
975 -- First, the invalid case
kono
parents:
diff changeset
976
kono
parents:
diff changeset
977 if not Directory_Entry.Is_Valid then
kono
parents:
diff changeset
978 raise Status_Error with "invalid directory entry";
kono
parents:
diff changeset
979
kono
parents:
diff changeset
980 else
kono
parents:
diff changeset
981 -- The value to return has already be computed
kono
parents:
diff changeset
982
kono
parents:
diff changeset
983 return Directory_Entry.Kind;
kono
parents:
diff changeset
984 end if;
kono
parents:
diff changeset
985 end Kind;
kono
parents:
diff changeset
986
kono
parents:
diff changeset
987 -----------------------
kono
parents:
diff changeset
988 -- Modification_Time --
kono
parents:
diff changeset
989 -----------------------
kono
parents:
diff changeset
990
kono
parents:
diff changeset
991 function Modification_Time (Name : String) return Time is
kono
parents:
diff changeset
992 Date : OS_Time;
kono
parents:
diff changeset
993 Year : Year_Type;
kono
parents:
diff changeset
994 Month : Month_Type;
kono
parents:
diff changeset
995 Day : Day_Type;
kono
parents:
diff changeset
996 Hour : Hour_Type;
kono
parents:
diff changeset
997 Minute : Minute_Type;
kono
parents:
diff changeset
998 Second : Second_Type;
kono
parents:
diff changeset
999
kono
parents:
diff changeset
1000 begin
kono
parents:
diff changeset
1001 -- First, the invalid cases
kono
parents:
diff changeset
1002
kono
parents:
diff changeset
1003 if not (Is_Regular_File (Name) or else Is_Directory (Name)) then
kono
parents:
diff changeset
1004 raise Name_Error with '"' & Name & """ not a file or directory";
kono
parents:
diff changeset
1005
kono
parents:
diff changeset
1006 else
kono
parents:
diff changeset
1007 Date := File_Time_Stamp (Name);
kono
parents:
diff changeset
1008
kono
parents:
diff changeset
1009 -- Break down the time stamp into its constituents relative to GMT.
kono
parents:
diff changeset
1010 -- This version of Split does not recognize leap seconds or buffer
kono
parents:
diff changeset
1011 -- space for time zone processing.
kono
parents:
diff changeset
1012
kono
parents:
diff changeset
1013 GM_Split (Date, Year, Month, Day, Hour, Minute, Second);
kono
parents:
diff changeset
1014
kono
parents:
diff changeset
1015 -- The result must be in GMT. Ada.Calendar.
kono
parents:
diff changeset
1016 -- Formatting.Time_Of with default time zone of zero (0) is the
kono
parents:
diff changeset
1017 -- routine of choice.
kono
parents:
diff changeset
1018
kono
parents:
diff changeset
1019 return Time_Of (Year, Month, Day, Hour, Minute, Second, 0.0);
kono
parents:
diff changeset
1020 end if;
kono
parents:
diff changeset
1021 end Modification_Time;
kono
parents:
diff changeset
1022
kono
parents:
diff changeset
1023 function Modification_Time
kono
parents:
diff changeset
1024 (Directory_Entry : Directory_Entry_Type) return Ada.Calendar.Time
kono
parents:
diff changeset
1025 is
kono
parents:
diff changeset
1026 begin
kono
parents:
diff changeset
1027 -- First, the invalid case
kono
parents:
diff changeset
1028
kono
parents:
diff changeset
1029 if not Directory_Entry.Is_Valid then
kono
parents:
diff changeset
1030 raise Status_Error with "invalid directory entry";
kono
parents:
diff changeset
1031
kono
parents:
diff changeset
1032 else
kono
parents:
diff changeset
1033 -- The value to return has already be computed
kono
parents:
diff changeset
1034
kono
parents:
diff changeset
1035 return Modification_Time (To_String (Directory_Entry.Full));
kono
parents:
diff changeset
1036 end if;
kono
parents:
diff changeset
1037 end Modification_Time;
kono
parents:
diff changeset
1038
kono
parents:
diff changeset
1039 ------------------
kono
parents:
diff changeset
1040 -- More_Entries --
kono
parents:
diff changeset
1041 ------------------
kono
parents:
diff changeset
1042
kono
parents:
diff changeset
1043 function More_Entries (Search : Search_Type) return Boolean is
kono
parents:
diff changeset
1044 begin
kono
parents:
diff changeset
1045 if Search.Value = null then
kono
parents:
diff changeset
1046 return False;
kono
parents:
diff changeset
1047
kono
parents:
diff changeset
1048 elsif Search.Value.Is_Valid then
kono
parents:
diff changeset
1049
kono
parents:
diff changeset
1050 -- Fetch the next entry, if needed
kono
parents:
diff changeset
1051
kono
parents:
diff changeset
1052 if not Search.Value.Entry_Fetched then
kono
parents:
diff changeset
1053 Fetch_Next_Entry (Search);
kono
parents:
diff changeset
1054 end if;
kono
parents:
diff changeset
1055 end if;
kono
parents:
diff changeset
1056
kono
parents:
diff changeset
1057 return Search.Value.Is_Valid;
kono
parents:
diff changeset
1058 end More_Entries;
kono
parents:
diff changeset
1059
kono
parents:
diff changeset
1060 ------------
kono
parents:
diff changeset
1061 -- Rename --
kono
parents:
diff changeset
1062 ------------
kono
parents:
diff changeset
1063
kono
parents:
diff changeset
1064 procedure Rename (Old_Name, New_Name : String) is
kono
parents:
diff changeset
1065 Success : Boolean;
kono
parents:
diff changeset
1066
kono
parents:
diff changeset
1067 begin
kono
parents:
diff changeset
1068 -- First, the invalid cases
kono
parents:
diff changeset
1069
kono
parents:
diff changeset
1070 if not Is_Valid_Path_Name (Old_Name) then
kono
parents:
diff changeset
1071 raise Name_Error with "invalid old path name """ & Old_Name & '"';
kono
parents:
diff changeset
1072
kono
parents:
diff changeset
1073 elsif not Is_Valid_Path_Name (New_Name) then
kono
parents:
diff changeset
1074 raise Name_Error with "invalid new path name """ & New_Name & '"';
kono
parents:
diff changeset
1075
kono
parents:
diff changeset
1076 elsif not Is_Regular_File (Old_Name)
kono
parents:
diff changeset
1077 and then not Is_Directory (Old_Name)
kono
parents:
diff changeset
1078 then
kono
parents:
diff changeset
1079 raise Name_Error with "old file """ & Old_Name & """ does not exist";
kono
parents:
diff changeset
1080
kono
parents:
diff changeset
1081 elsif Is_Regular_File (New_Name) or else Is_Directory (New_Name) then
kono
parents:
diff changeset
1082 raise Use_Error with
kono
parents:
diff changeset
1083 "new name """ & New_Name
kono
parents:
diff changeset
1084 & """ designates a file that already exists";
kono
parents:
diff changeset
1085
kono
parents:
diff changeset
1086 -- Do actual rename using System.OS_Lib.Rename_File
kono
parents:
diff changeset
1087
kono
parents:
diff changeset
1088 else
kono
parents:
diff changeset
1089 Rename_File (Old_Name, New_Name, Success);
kono
parents:
diff changeset
1090
kono
parents:
diff changeset
1091 if not Success then
kono
parents:
diff changeset
1092
kono
parents:
diff changeset
1093 -- AI05-0231-1: Name_Error should be raised in case a directory
kono
parents:
diff changeset
1094 -- component of New_Name does not exist (as in New_Name =>
kono
parents:
diff changeset
1095 -- "/no-such-dir/new-filename"). ENOENT indicates that. ENOENT
kono
parents:
diff changeset
1096 -- also indicate that the Old_Name does not exist, but we already
kono
parents:
diff changeset
1097 -- checked for that above. All other errors are Use_Error.
kono
parents:
diff changeset
1098
kono
parents:
diff changeset
1099 if Errno = ENOENT then
kono
parents:
diff changeset
1100 raise Name_Error with
kono
parents:
diff changeset
1101 "file """ & Containing_Directory (New_Name) & """ not found";
kono
parents:
diff changeset
1102
kono
parents:
diff changeset
1103 else
kono
parents:
diff changeset
1104 raise Use_Error with
kono
parents:
diff changeset
1105 "file """ & Old_Name & """ could not be renamed";
kono
parents:
diff changeset
1106 end if;
kono
parents:
diff changeset
1107 end if;
kono
parents:
diff changeset
1108 end if;
kono
parents:
diff changeset
1109 end Rename;
kono
parents:
diff changeset
1110
kono
parents:
diff changeset
1111 ------------
kono
parents:
diff changeset
1112 -- Search --
kono
parents:
diff changeset
1113 ------------
kono
parents:
diff changeset
1114
kono
parents:
diff changeset
1115 procedure Search
kono
parents:
diff changeset
1116 (Directory : String;
kono
parents:
diff changeset
1117 Pattern : String;
kono
parents:
diff changeset
1118 Filter : Filter_Type := (others => True);
kono
parents:
diff changeset
1119 Process : not null access procedure
kono
parents:
diff changeset
1120 (Directory_Entry : Directory_Entry_Type))
kono
parents:
diff changeset
1121 is
kono
parents:
diff changeset
1122 Srch : Search_Type;
kono
parents:
diff changeset
1123 Directory_Entry : Directory_Entry_Type;
kono
parents:
diff changeset
1124
kono
parents:
diff changeset
1125 begin
kono
parents:
diff changeset
1126 Start_Search (Srch, Directory, Pattern, Filter);
kono
parents:
diff changeset
1127 while More_Entries (Srch) loop
kono
parents:
diff changeset
1128 Get_Next_Entry (Srch, Directory_Entry);
kono
parents:
diff changeset
1129 Process (Directory_Entry);
kono
parents:
diff changeset
1130 end loop;
kono
parents:
diff changeset
1131
kono
parents:
diff changeset
1132 End_Search (Srch);
kono
parents:
diff changeset
1133 end Search;
kono
parents:
diff changeset
1134
kono
parents:
diff changeset
1135 -------------------
kono
parents:
diff changeset
1136 -- Set_Directory --
kono
parents:
diff changeset
1137 -------------------
kono
parents:
diff changeset
1138
kono
parents:
diff changeset
1139 procedure Set_Directory (Directory : String) is
kono
parents:
diff changeset
1140 C_Dir_Name : constant String := Directory & ASCII.NUL;
kono
parents:
diff changeset
1141 begin
kono
parents:
diff changeset
1142 if not Is_Valid_Path_Name (Directory) then
kono
parents:
diff changeset
1143 raise Name_Error with
kono
parents:
diff changeset
1144 "invalid directory path name & """ & Directory & '"';
kono
parents:
diff changeset
1145
kono
parents:
diff changeset
1146 elsif not Is_Directory (Directory) then
kono
parents:
diff changeset
1147 raise Name_Error with
kono
parents:
diff changeset
1148 "directory """ & Directory & """ does not exist";
kono
parents:
diff changeset
1149
kono
parents:
diff changeset
1150 elsif chdir (C_Dir_Name) /= 0 then
kono
parents:
diff changeset
1151 raise Name_Error with
kono
parents:
diff changeset
1152 "could not set to designated directory """ & Directory & '"';
kono
parents:
diff changeset
1153 end if;
kono
parents:
diff changeset
1154 end Set_Directory;
kono
parents:
diff changeset
1155
kono
parents:
diff changeset
1156 -----------------
kono
parents:
diff changeset
1157 -- Simple_Name --
kono
parents:
diff changeset
1158 -----------------
kono
parents:
diff changeset
1159
kono
parents:
diff changeset
1160 function Simple_Name (Name : String) return String is
kono
parents:
diff changeset
1161
kono
parents:
diff changeset
1162 function Simple_Name_Internal (Path : String) return String;
kono
parents:
diff changeset
1163 -- This function does the job
kono
parents:
diff changeset
1164
kono
parents:
diff changeset
1165 --------------------------
kono
parents:
diff changeset
1166 -- Simple_Name_Internal --
kono
parents:
diff changeset
1167 --------------------------
kono
parents:
diff changeset
1168
kono
parents:
diff changeset
1169 function Simple_Name_Internal (Path : String) return String is
kono
parents:
diff changeset
1170 Cut_Start : Natural :=
kono
parents:
diff changeset
1171 Strings.Fixed.Index (Path, Dir_Seps, Going => Strings.Backward);
kono
parents:
diff changeset
1172 Cut_End : Natural;
kono
parents:
diff changeset
1173
kono
parents:
diff changeset
1174 begin
kono
parents:
diff changeset
1175 -- Cut_Start pointS to the first simple name character
kono
parents:
diff changeset
1176
kono
parents:
diff changeset
1177 Cut_Start := (if Cut_Start = 0 then Path'First else Cut_Start + 1);
kono
parents:
diff changeset
1178
kono
parents:
diff changeset
1179 -- Cut_End point to the last simple name character
kono
parents:
diff changeset
1180
kono
parents:
diff changeset
1181 Cut_End := Path'Last;
kono
parents:
diff changeset
1182
kono
parents:
diff changeset
1183 Check_For_Standard_Dirs : declare
kono
parents:
diff changeset
1184 BN : constant String := Path (Cut_Start .. Cut_End);
kono
parents:
diff changeset
1185
kono
parents:
diff changeset
1186 Has_Drive_Letter : constant Boolean :=
kono
parents:
diff changeset
1187 OS_Lib.Path_Separator /= ':';
kono
parents:
diff changeset
1188 -- If Path separator is not ':' then we are on a DOS based OS
kono
parents:
diff changeset
1189 -- where this character is used as a drive letter separator.
kono
parents:
diff changeset
1190
kono
parents:
diff changeset
1191 begin
kono
parents:
diff changeset
1192 if BN = "." or else BN = ".." then
kono
parents:
diff changeset
1193 return "";
kono
parents:
diff changeset
1194
kono
parents:
diff changeset
1195 elsif Has_Drive_Letter
kono
parents:
diff changeset
1196 and then BN'Length > 2
kono
parents:
diff changeset
1197 and then Characters.Handling.Is_Letter (BN (BN'First))
kono
parents:
diff changeset
1198 and then BN (BN'First + 1) = ':'
kono
parents:
diff changeset
1199 then
kono
parents:
diff changeset
1200 -- We have a DOS drive letter prefix, remove it
kono
parents:
diff changeset
1201
kono
parents:
diff changeset
1202 return BN (BN'First + 2 .. BN'Last);
kono
parents:
diff changeset
1203
kono
parents:
diff changeset
1204 else
kono
parents:
diff changeset
1205 return BN;
kono
parents:
diff changeset
1206 end if;
kono
parents:
diff changeset
1207 end Check_For_Standard_Dirs;
kono
parents:
diff changeset
1208 end Simple_Name_Internal;
kono
parents:
diff changeset
1209
kono
parents:
diff changeset
1210 -- Start of processing for Simple_Name
kono
parents:
diff changeset
1211
kono
parents:
diff changeset
1212 begin
kono
parents:
diff changeset
1213 -- First, the invalid case
kono
parents:
diff changeset
1214
kono
parents:
diff changeset
1215 if not Is_Valid_Path_Name (Name) then
kono
parents:
diff changeset
1216 raise Name_Error with "invalid path name """ & Name & '"';
kono
parents:
diff changeset
1217
kono
parents:
diff changeset
1218 else
kono
parents:
diff changeset
1219 -- Build the value to return with lower bound 1
kono
parents:
diff changeset
1220
kono
parents:
diff changeset
1221 declare
kono
parents:
diff changeset
1222 Value : constant String := Simple_Name_Internal (Name);
kono
parents:
diff changeset
1223 subtype Result is String (1 .. Value'Length);
kono
parents:
diff changeset
1224 begin
kono
parents:
diff changeset
1225 return Result (Value);
kono
parents:
diff changeset
1226 end;
kono
parents:
diff changeset
1227 end if;
kono
parents:
diff changeset
1228 end Simple_Name;
kono
parents:
diff changeset
1229
kono
parents:
diff changeset
1230 function Simple_Name
kono
parents:
diff changeset
1231 (Directory_Entry : Directory_Entry_Type) return String is
kono
parents:
diff changeset
1232 begin
kono
parents:
diff changeset
1233 -- First, the invalid case
kono
parents:
diff changeset
1234
kono
parents:
diff changeset
1235 if not Directory_Entry.Is_Valid then
kono
parents:
diff changeset
1236 raise Status_Error with "invalid directory entry";
kono
parents:
diff changeset
1237
kono
parents:
diff changeset
1238 else
kono
parents:
diff changeset
1239 -- The value to return has already be computed
kono
parents:
diff changeset
1240
kono
parents:
diff changeset
1241 return To_String (Directory_Entry.Simple);
kono
parents:
diff changeset
1242 end if;
kono
parents:
diff changeset
1243 end Simple_Name;
kono
parents:
diff changeset
1244
kono
parents:
diff changeset
1245 ----------
kono
parents:
diff changeset
1246 -- Size --
kono
parents:
diff changeset
1247 ----------
kono
parents:
diff changeset
1248
kono
parents:
diff changeset
1249 function Size (Name : String) return File_Size is
kono
parents:
diff changeset
1250 C_Name : String (1 .. Name'Length + 1);
kono
parents:
diff changeset
1251
kono
parents:
diff changeset
1252 function C_Size (Name : Address) return int64;
kono
parents:
diff changeset
1253 pragma Import (C, C_Size, "__gnat_named_file_length");
kono
parents:
diff changeset
1254
kono
parents:
diff changeset
1255 begin
kono
parents:
diff changeset
1256 -- First, the invalid case
kono
parents:
diff changeset
1257
kono
parents:
diff changeset
1258 if not Is_Regular_File (Name) then
kono
parents:
diff changeset
1259 raise Name_Error with "file """ & Name & """ does not exist";
kono
parents:
diff changeset
1260
kono
parents:
diff changeset
1261 else
kono
parents:
diff changeset
1262 C_Name (1 .. Name'Length) := Name;
kono
parents:
diff changeset
1263 C_Name (C_Name'Last) := ASCII.NUL;
kono
parents:
diff changeset
1264 return File_Size (C_Size (C_Name'Address));
kono
parents:
diff changeset
1265 end if;
kono
parents:
diff changeset
1266 end Size;
kono
parents:
diff changeset
1267
kono
parents:
diff changeset
1268 function Size (Directory_Entry : Directory_Entry_Type) return File_Size is
kono
parents:
diff changeset
1269 begin
kono
parents:
diff changeset
1270 -- First, the invalid case
kono
parents:
diff changeset
1271
kono
parents:
diff changeset
1272 if not Directory_Entry.Is_Valid then
kono
parents:
diff changeset
1273 raise Status_Error with "invalid directory entry";
kono
parents:
diff changeset
1274
kono
parents:
diff changeset
1275 else
kono
parents:
diff changeset
1276 -- The value to return has already be computed
kono
parents:
diff changeset
1277
kono
parents:
diff changeset
1278 return Size (To_String (Directory_Entry.Full));
kono
parents:
diff changeset
1279 end if;
kono
parents:
diff changeset
1280 end Size;
kono
parents:
diff changeset
1281
kono
parents:
diff changeset
1282 ------------------
kono
parents:
diff changeset
1283 -- Start_Search --
kono
parents:
diff changeset
1284 ------------------
kono
parents:
diff changeset
1285
kono
parents:
diff changeset
1286 procedure Start_Search
kono
parents:
diff changeset
1287 (Search : in out Search_Type;
kono
parents:
diff changeset
1288 Directory : String;
kono
parents:
diff changeset
1289 Pattern : String;
kono
parents:
diff changeset
1290 Filter : Filter_Type := (others => True))
kono
parents:
diff changeset
1291 is
kono
parents:
diff changeset
1292 function opendir (file_name : String) return DIRs;
kono
parents:
diff changeset
1293 pragma Import (C, opendir, "__gnat_opendir");
kono
parents:
diff changeset
1294
kono
parents:
diff changeset
1295 C_File_Name : constant String := Directory & ASCII.NUL;
kono
parents:
diff changeset
1296 Pat : Regexp;
kono
parents:
diff changeset
1297 Dir : Dir_Type_Value;
kono
parents:
diff changeset
1298
kono
parents:
diff changeset
1299 begin
kono
parents:
diff changeset
1300 -- First, the invalid case Name_Error
kono
parents:
diff changeset
1301
kono
parents:
diff changeset
1302 if not Is_Directory (Directory) then
kono
parents:
diff changeset
1303 raise Name_Error with
kono
parents:
diff changeset
1304 "unknown directory """ & Simple_Name (Directory) & '"';
kono
parents:
diff changeset
1305 end if;
kono
parents:
diff changeset
1306
kono
parents:
diff changeset
1307 -- Check the pattern
kono
parents:
diff changeset
1308
kono
parents:
diff changeset
1309 begin
kono
parents:
diff changeset
1310 Pat := Compile
kono
parents:
diff changeset
1311 (Pattern,
kono
parents:
diff changeset
1312 Glob => True,
kono
parents:
diff changeset
1313 Case_Sensitive => Is_Path_Name_Case_Sensitive);
kono
parents:
diff changeset
1314 exception
kono
parents:
diff changeset
1315 when Error_In_Regexp =>
kono
parents:
diff changeset
1316 Free (Search.Value);
kono
parents:
diff changeset
1317 raise Name_Error with "invalid pattern """ & Pattern & '"';
kono
parents:
diff changeset
1318 end;
kono
parents:
diff changeset
1319
kono
parents:
diff changeset
1320 Dir := Dir_Type_Value (opendir (C_File_Name));
kono
parents:
diff changeset
1321
kono
parents:
diff changeset
1322 if Dir = No_Dir then
kono
parents:
diff changeset
1323 raise Use_Error with
kono
parents:
diff changeset
1324 "unreadable directory """ & Simple_Name (Directory) & '"';
kono
parents:
diff changeset
1325 end if;
kono
parents:
diff changeset
1326
kono
parents:
diff changeset
1327 -- If needed, finalize Search
kono
parents:
diff changeset
1328
kono
parents:
diff changeset
1329 Finalize (Search);
kono
parents:
diff changeset
1330
kono
parents:
diff changeset
1331 -- Allocate the default data
kono
parents:
diff changeset
1332
kono
parents:
diff changeset
1333 Search.Value := new Search_Data;
kono
parents:
diff changeset
1334
kono
parents:
diff changeset
1335 -- Initialize some Search components
kono
parents:
diff changeset
1336
kono
parents:
diff changeset
1337 Search.Value.Filter := Filter;
kono
parents:
diff changeset
1338 Search.Value.Name := To_Unbounded_String (Full_Name (Directory));
kono
parents:
diff changeset
1339 Search.Value.Pattern := Pat;
kono
parents:
diff changeset
1340 Search.Value.Dir := Dir;
kono
parents:
diff changeset
1341 Search.Value.Is_Valid := True;
kono
parents:
diff changeset
1342 end Start_Search;
kono
parents:
diff changeset
1343
kono
parents:
diff changeset
1344 end Ada.Directories;