1------------------------------------------------------------------------------ 2-- -- 3-- GNAT RUN-TIME COMPONENTS -- 4-- -- 5-- A D A . D I R E C T O R I E S -- 6-- -- 7-- S p e c -- 8-- -- 9-- Copyright (C) 2004-2019, Free Software Foundation, Inc. -- 10-- -- 11-- This specification is derived for use with GNAT from AI-00248, which is -- 12-- expected to be a part of a future expected revised Ada Reference Manual. -- 13-- The copyright notice above, and the license provisions that follow apply -- 14-- solely to the contents of the part following the private keyword. -- 15-- -- 16-- GNAT is free software; you can redistribute it and/or modify it under -- 17-- terms of the GNU General Public License as published by the Free Soft- -- 18-- ware Foundation; either version 3, or (at your option) any later ver- -- 19-- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- 20-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -- 21-- or FITNESS FOR A PARTICULAR PURPOSE. -- 22-- -- 23-- As a special exception under Section 7 of GPL version 3, you are granted -- 24-- additional permissions described in the GCC Runtime Library Exception, -- 25-- version 3.1, as published by the Free Software Foundation. -- 26-- -- 27-- You should have received a copy of the GNU General Public License and -- 28-- a copy of the GCC Runtime Library Exception along with this program; -- 29-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- 30-- <http://www.gnu.org/licenses/>. -- 31-- -- 32-- GNAT was originally developed by the GNAT team at New York University. -- 33-- Extensive contributions were provided by Ada Core Technologies Inc. -- 34-- -- 35------------------------------------------------------------------------------ 36 37-- Ada 2005: Implementation of Ada.Directories (AI95-00248). Note that this 38-- unit is available without -gnat05. That seems reasonable, since you only 39-- get it if you explicitly ask for it. 40 41-- External files may be classified as directories, special files, or ordinary 42-- files. A directory is an external file that is a container for files on 43-- the target system. A special file is an external file that cannot be 44-- created or read by a predefined Ada Input-Output package. External files 45-- that are not special files or directories are called ordinary files. 46 47-- A file name is a string identifying an external file. Similarly, a 48-- directory name is a string identifying a directory. The interpretation of 49-- file names and directory names is implementation-defined. 50 51-- The full name of an external file is a full specification of the name of 52-- the file. If the external environment allows alternative specifications of 53-- the name (for example, abbreviations), the full name should not use such 54-- alternatives. A full name typically will include the names of all of 55-- directories that contain the item. The simple name of an external file is 56-- the name of the item, not including any containing directory names. Unless 57-- otherwise specified, a file name or directory name parameter to a 58-- predefined Ada input-output subprogram can be a full name, a simple name, 59-- or any other form of name supported by the implementation. 60 61-- The default directory is the directory that is used if a directory or 62-- file name is not a full name (that is, when the name does not fully 63-- identify all of the containing directories). 64 65-- A directory entry is a single item in a directory, identifying a single 66-- external file (including directories and special files). 67 68-- For each function that returns a string, the lower bound of the returned 69-- value is 1. 70 71with Ada.Calendar; 72with Ada.Finalization; 73with Ada.IO_Exceptions; 74with Ada.Strings.Unbounded; 75 76package Ada.Directories is 77 78 ----------------------------------- 79 -- Directory and File Operations -- 80 ----------------------------------- 81 82 function Current_Directory return String; 83 -- Returns the full directory name for the current default directory. The 84 -- name returned must be suitable for a future call to Set_Directory. 85 -- The exception Use_Error is propagated if a default directory is not 86 -- supported by the external environment. 87 88 procedure Set_Directory (Directory : String); 89 -- Sets the current default directory. The exception Name_Error is 90 -- propagated if the string given as Directory does not identify an 91 -- existing directory. The exception Use_Error is propagated if the 92 -- external environment does not support making Directory (in the absence 93 -- of Name_Error) a default directory. 94 95 procedure Create_Directory 96 (New_Directory : String; 97 Form : String := ""); 98 -- Creates a directory with name New_Directory. The Form parameter can be 99 -- used to give system-dependent characteristics of the directory; the 100 -- interpretation of the Form parameter is implementation-defined. A null 101 -- string for Form specifies the use of the default options of the 102 -- implementation of the new directory. The exception Name_Error is 103 -- propagated if the string given as New_Directory does not allow the 104 -- identification of a directory. The exception Use_Error is propagated if 105 -- the external environment does not support the creation of a directory 106 -- with the given name (in the absence of Name_Error) and form. 107 -- 108 -- The Form parameter is ignored 109 110 procedure Delete_Directory (Directory : String); 111 -- Deletes an existing empty directory with name Directory. The exception 112 -- Name_Error is propagated if the string given as Directory does not 113 -- identify an existing directory. The exception Use_Error is propagated 114 -- if the external environment does not support the deletion of the 115 -- directory (or some portion of its contents) with the given name (in the 116 -- absence of Name_Error). 117 118 procedure Create_Path 119 (New_Directory : String; 120 Form : String := ""); 121 -- Creates zero or more directories with name New_Directory. Each 122 -- non-existent directory named by New_Directory is created. For example, 123 -- on a typical Unix system, Create_Path ("/usr/me/my"); would create 124 -- directory "me" in directory "usr", then create directory "my" 125 -- in directory "me". The Form can be used to give system-dependent 126 -- characteristics of the directory; the interpretation of the Form 127 -- parameter is implementation-defined. A null string for Form specifies 128 -- the use of the default options of the implementation of the new 129 -- directory. The exception Name_Error is propagated if the string given 130 -- as New_Directory does not allow the identification of any directory. The 131 -- exception Use_Error is propagated if the external environment does not 132 -- support the creation of any directories with the given name (in the 133 -- absence of Name_Error) and form. 134 -- 135 -- The Form parameter is ignored 136 137 procedure Delete_Tree (Directory : String); 138 -- Deletes an existing directory with name Directory. The directory and 139 -- all of its contents (possibly including other directories) are deleted. 140 -- The exception Name_Error is propagated if the string given as Directory 141 -- does not identify an existing directory. The exception Use_Error is 142 -- propagated if the external environment does not support the deletion 143 -- of the directory or some portion of its contents with the given name 144 -- (in the absence of Name_Error). If Use_Error is propagated, it is 145 -- unspecified if a portion of the contents of the directory are deleted. 146 147 procedure Delete_File (Name : String); 148 -- Deletes an existing ordinary or special file with Name. The exception 149 -- Name_Error is propagated if the string given as Name does not identify 150 -- an existing ordinary or special external file. The exception Use_Error 151 -- is propagated if the external environment does not support the deletion 152 -- of the file with the given name (in the absence of Name_Error). 153 154 procedure Rename (Old_Name, New_Name : String); 155 -- Renames an existing external file (including directories) with Old_Name 156 -- to New_Name. The exception Name_Error is propagated if the string given 157 -- as Old_Name does not identify an existing external file. The exception 158 -- Use_Error is propagated if the external environment does not support the 159 -- renaming of the file with the given name (in the absence of Name_Error). 160 -- In particular, Use_Error is propagated if a file or directory already 161 -- exists with New_Name. 162 163 procedure Copy_File 164 (Source_Name : String; 165 Target_Name : String; 166 Form : String := ""); 167 -- Copies the contents of the existing external file with Source_Name to 168 -- Target_Name. The resulting external file is a duplicate of the source 169 -- external file. The Form argument can be used to give system-dependent 170 -- characteristics of the resulting external file; the interpretation of 171 -- the Form parameter is implementation-defined. Exception Name_Error is 172 -- propagated if the string given as Source_Name does not identify an 173 -- existing external ordinary or special file or if the string given as 174 -- Target_Name does not allow the identification of an external file. The 175 -- exception Use_Error is propagated if the external environment does not 176 -- support the creating of the file with the name given by Target_Name and 177 -- form given by Form, or copying of the file with the name given by 178 -- Source_Name (in the absence of Name_Error). 179 -- 180 -- Interpretation of the Form parameter: 181 -- 182 -- The Form parameter is case-insensitive 183 -- 184 -- Two fields are recognized in the Form parameter: 185 -- preserve=<value> 186 -- mode=<value> 187 -- 188 -- <value> starts immediately after the character '=' and ends with the 189 -- character immediately preceding the next comma (',') or with the 190 -- last character of the parameter. 191 -- 192 -- The allowed values for preserve= are: 193 -- 194 -- no_attributes: Do not try to preserve any file attributes. This 195 -- is the default if no preserve= is found in Form. 196 -- 197 -- all_attributes: Try to preserve all file attributes (timestamps, 198 -- access rights). 199 -- 200 -- timestamps: Preserve the timestamp of the copied file, but not 201 -- the other file attributes. 202 -- 203 -- The allowed values for mode= are: 204 -- 205 -- copy: Only copy if the destination file does not already 206 -- exist. If it already exists, Copy_File will fail. 207 -- 208 -- overwrite: Copy the file in all cases. Overwrite an already 209 -- existing destination file. This is the default if 210 -- no mode= is found in Form. 211 -- 212 -- append: Append the original file to the destination file. 213 -- If the destination file does not exist, the 214 -- destination file is a copy of the source file. 215 -- When mode=append, the field preserve=, if it 216 -- exists, is not taken into account. 217 -- 218 -- If the Form parameter includes one or both of the fields and the value 219 -- or values are incorrect, Copy_File fails with Use_Error. 220 -- 221 -- Examples of correct Forms: 222 -- Form => "preserve=no_attributes,mode=overwrite" (the default) 223 -- Form => "mode=append" 224 -- Form => "mode=copy,preserve=all_attributes" 225 -- 226 -- Examples of incorrect Forms: 227 -- Form => "preserve=junk" 228 -- Form => "mode=internal,preserve=timestamps" 229 230 ---------------------------------------- 231 -- File and directory name operations -- 232 ---------------------------------------- 233 234 type Name_Case_Kind is 235 (Unknown, Case_Sensitive, Case_Insensitive, Case_Preserving); 236 -- The type Name_Case_Kind represents the kind of file-name equivalence 237 -- rule for directories. 238 239 function Full_Name (Name : String) return String; 240 -- Returns the full name corresponding to the file name specified by Name. 241 -- The exception Name_Error is propagated if the string given as Name does 242 -- not allow the identification of an external file (including directories 243 -- and special files). 244 245 function Simple_Name (Name : String) return String; 246 -- Returns the simple name portion of the file name specified by Name. The 247 -- exception Name_Error is propagated if the string given as Name does not 248 -- allow the identification of an external file (including directories and 249 -- special files). 250 251 function Containing_Directory (Name : String) return String; 252 -- Returns the name of the containing directory of the external file 253 -- (including directories) identified by Name. If more than one directory 254 -- can contain Name, the directory name returned is implementation-defined. 255 -- The exception Name_Error is propagated if the string given as Name does 256 -- not allow the identification of an external file. The exception 257 -- Use_Error is propagated if the external file does not have a containing 258 -- directory. 259 260 function Extension (Name : String) return String; 261 -- Returns the extension name corresponding to Name. The extension name is 262 -- a portion of a simple name (not including any separator characters), 263 -- typically used to identify the file class. If the external environment 264 -- does not have extension names, then the null string is returned. 265 -- The exception Name_Error is propagated if the string given as Name does 266 -- not allow the identification of an external file. 267 268 function Base_Name (Name : String) return String; 269 -- Returns the base name corresponding to Name. The base name is the 270 -- remainder of a simple name after removing any extension and extension 271 -- separators. The exception Name_Error is propagated if the string given 272 -- as Name does not allow the identification of an external file 273 -- (including directories and special files). 274 275 function Compose 276 (Containing_Directory : String := ""; 277 Name : String; 278 Extension : String := "") return String; 279 -- Returns the name of the external file with the specified 280 -- Containing_Directory, Name, and Extension. If Extension is the null 281 -- string, then Name is interpreted as a simple name; otherwise Name is 282 -- interpreted as a base name. The exception Name_Error is propagated if 283 -- the string given as Containing_Directory is not null and does not allow 284 -- the identification of a directory, or if the string given as Extension 285 -- is not null and is not a possible extension, or if the string given as 286 -- Name is not a possible simple name (if Extension is null) or base name 287 -- (if Extension is non-null). 288 289 function Name_Case_Equivalence (Name : String) return Name_Case_Kind; 290 -- Returns the file-name equivalence rule for the directory containing 291 -- Name. Raises Name_Error if Name is not a full name. Returns 292 -- Case_Sensitive if file names that differ only in the case of letters are 293 -- considered different names. If file names that differ only in the case 294 -- of letters are considered the same name, then Case_Preserving is 295 -- returned if names have the case of the file name used when a file is 296 -- created; and Case_Insensitive is returned otherwise. Returns Unknown if 297 -- the file-name equivalence is not known. 298 299 -------------------------------- 300 -- File and directory queries -- 301 -------------------------------- 302 303 type File_Kind is (Directory, Ordinary_File, Special_File); 304 -- The type File_Kind represents the kind of file represented by an 305 -- external file or directory. 306 307 type File_Size is range 0 .. Long_Long_Integer'Last; 308 -- The type File_Size represents the size of an external file 309 310 function Exists (Name : String) return Boolean; 311 -- Returns True if external file represented by Name exists, and False 312 -- otherwise. The exception Name_Error is propagated if the string given as 313 -- Name does not allow the identification of an external file (including 314 -- directories and special files). 315 316 function Kind (Name : String) return File_Kind; 317 -- Returns the kind of external file represented by Name. The exception 318 -- Name_Error is propagated if the string given as Name does not allow the 319 -- identification of an existing external file. 320 321 function Size (Name : String) return File_Size; 322 -- Returns the size of the external file represented by Name. The size of 323 -- an external file is the number of stream elements contained in the file. 324 -- If the external file is discontiguous (not all elements exist), the 325 -- result is implementation-defined. If the external file is not an 326 -- ordinary file, the result is implementation-defined. The exception 327 -- Name_Error is propagated if the string given as Name does not allow the 328 -- identification of an existing external file. The exception 329 -- Constraint_Error is propagated if the file size is not a value of type 330 -- File_Size. 331 332 function Modification_Time (Name : String) return Ada.Calendar.Time; 333 -- Returns the time that the external file represented by Name was most 334 -- recently modified. If the external file is not an ordinary file, the 335 -- result is implementation-defined. The exception Name_Error is propagated 336 -- if the string given as Name does not allow the identification of an 337 -- existing external file. The exception Use_Error is propagated if the 338 -- external environment does not support the reading the modification time 339 -- of the file with the name given by Name (in the absence of Name_Error). 340 341 ------------------------- 342 -- Directory Searching -- 343 ------------------------- 344 345 type Directory_Entry_Type is limited private; 346 -- The type Directory_Entry_Type represents a single item in a directory. 347 -- These items can only be created by the Get_Next_Entry procedure in this 348 -- package. Information about the item can be obtained from the functions 349 -- declared in this package. A default initialized object of this type is 350 -- invalid; objects returned from Get_Next_Entry are valid. 351 352 type Filter_Type is array (File_Kind) of Boolean; 353 -- The type Filter_Type specifies which directory entries are provided from 354 -- a search operation. If the Directory component is True, directory 355 -- entries representing directories are provided. If the Ordinary_File 356 -- component is True, directory entries representing ordinary files are 357 -- provided. If the Special_File component is True, directory entries 358 -- representing special files are provided. 359 360 type Search_Type is limited private; 361 -- The type Search_Type contains the state of a directory search. A 362 -- default-initialized Search_Type object has no entries available 363 -- (More_Entries returns False). 364 365 procedure Start_Search 366 (Search : in out Search_Type; 367 Directory : String; 368 Pattern : String; 369 Filter : Filter_Type := (others => True)); 370 -- Starts a search in the directory entry in the directory named by 371 -- Directory for entries matching Pattern. Pattern represents a file name 372 -- matching pattern. If Pattern is null, all items in the directory are 373 -- matched; otherwise, the interpretation of Pattern is implementation- 374 -- defined. Only items which match Filter will be returned. After a 375 -- successful call on Start_Search, the object Search may have entries 376 -- available, but it may have no entries available if no files or 377 -- directories match Pattern and Filter. The exception Name_Error is 378 -- propagated if the string given by Directory does not identify an 379 -- existing directory, or if Pattern does not allow the identification of 380 -- any possible external file or directory. The exception Use_Error is 381 -- propagated if the external environment does not support the searching 382 -- of the directory with the given name (in the absence of Name_Error). 383 384 procedure End_Search (Search : in out Search_Type); 385 -- Ends the search represented by Search. After a successful call on 386 -- End_Search, the object Search will have no entries available. Note 387 -- that it is not necessary to call End_Search if the call to Start_Search 388 -- was unsuccessful and raised an exception (but it is harmless to make 389 -- the call in this case). 390 391 function More_Entries (Search : Search_Type) return Boolean; 392 -- Returns True if more entries are available to be returned by a call 393 -- to Get_Next_Entry for the specified search object, and False otherwise. 394 395 procedure Get_Next_Entry 396 (Search : in out Search_Type; 397 Directory_Entry : out Directory_Entry_Type); 398 -- Returns the next Directory_Entry for the search described by Search that 399 -- matches the pattern and filter. If no further matches are available, 400 -- Status_Error is raised. It is implementation-defined as to whether the 401 -- results returned by this routine are altered if the contents of the 402 -- directory are altered while the Search object is valid (for example, by 403 -- another program). The exception Use_Error is propagated if the external 404 -- environment does not support continued searching of the directory 405 -- represented by Search. 406 407 procedure Search 408 (Directory : String; 409 Pattern : String; 410 Filter : Filter_Type := (others => True); 411 Process : not null access procedure 412 (Directory_Entry : Directory_Entry_Type)); 413 -- Searches in the directory named by Directory for entries matching 414 -- Pattern. The subprogram designated by Process is called with each 415 -- matching entry in turn. Pattern represents a pattern for matching file 416 -- names. If Pattern is null, all items in the directory are matched; 417 -- otherwise, the interpretation of Pattern is implementation-defined. 418 -- Only items that match Filter will be returned. The exception Name_Error 419 -- is propagated if the string given by Directory does not identify 420 -- an existing directory, or if Pattern does not allow the identification 421 -- of any possible external file or directory. The exception Use_Error is 422 -- propagated if the external environment does not support the searching 423 -- of the directory with the given name (in the absence of Name_Error). 424 425 ------------------------------------- 426 -- Operations on Directory Entries -- 427 ------------------------------------- 428 429 function Simple_Name (Directory_Entry : Directory_Entry_Type) return String; 430 -- Returns the simple external name of the external file (including 431 -- directories) represented by Directory_Entry. The format of the name 432 -- returned is implementation-defined. The exception Status_Error is 433 -- propagated if Directory_Entry is invalid. 434 435 function Full_Name (Directory_Entry : Directory_Entry_Type) return String; 436 -- Returns the full external name of the external file (including 437 -- directories) represented by Directory_Entry. The format of the name 438 -- returned is implementation-defined. The exception Status_Error is 439 -- propagated if Directory_Entry is invalid. 440 441 function Kind (Directory_Entry : Directory_Entry_Type) return File_Kind; 442 -- Returns the kind of external file represented by Directory_Entry. The 443 -- exception Status_Error is propagated if Directory_Entry is invalid. 444 445 function Size (Directory_Entry : Directory_Entry_Type) return File_Size; 446 -- Returns the size of the external file represented by Directory_Entry. 447 -- The size of an external file is the number of stream elements contained 448 -- in the file. If the external file is discontiguous (not all elements 449 -- exist), the result is implementation-defined. If the external file 450 -- represented by Directory_Entry is not an ordinary file, the result is 451 -- implementation-defined. The exception Status_Error is propagated if 452 -- Directory_Entry is invalid. The exception Constraint_Error is propagated 453 -- if the file size is not a value of type File_Size. 454 455 function Modification_Time 456 (Directory_Entry : Directory_Entry_Type) return Ada.Calendar.Time; 457 -- Returns the time that the external file represented by Directory_Entry 458 -- was most recently modified. If the external file represented by 459 -- Directory_Entry is not an ordinary file, the result is 460 -- implementation-defined. The exception Status_Error is propagated if 461 -- Directory_Entry is invalid. The exception Use_Error is propagated if 462 -- the external environment does not support the reading the modification 463 -- time of the file represented by Directory_Entry. 464 465 ---------------- 466 -- Exceptions -- 467 ---------------- 468 469 Status_Error : exception renames Ada.IO_Exceptions.Status_Error; 470 Name_Error : exception renames Ada.IO_Exceptions.Name_Error; 471 Use_Error : exception renames Ada.IO_Exceptions.Use_Error; 472 Device_Error : exception renames Ada.IO_Exceptions.Device_Error; 473 474private 475 type Directory_Entry_Type is record 476 Is_Valid : Boolean := False; 477 Simple : Ada.Strings.Unbounded.Unbounded_String; 478 Full : Ada.Strings.Unbounded.Unbounded_String; 479 Kind : File_Kind := Ordinary_File; 480 end record; 481 482 -- The type Search_Data is defined in the body, so that the spec does not 483 -- depend on packages of the GNAT hierarchy. 484 485 type Search_Data; 486 type Search_Ptr is access Search_Data; 487 488 -- Search_Type need to be a controlled type, because it includes component 489 -- of type Dir_Type (in GNAT.Directory_Operations) that need to be closed 490 -- (if opened) during finalization. The component need to be an access 491 -- value, because Search_Data is not fully defined in the spec. 492 493 type Search_Type is new Ada.Finalization.Controlled with record 494 Value : Search_Ptr; 495 end record; 496 497 procedure Finalize (Search : in out Search_Type); 498 -- Close the directory, if opened, and deallocate Value 499 500 procedure End_Search (Search : in out Search_Type) renames Finalize; 501 502end Ada.Directories; 503