A.16.1 The Package Directories.Hierarchical_File_Names
{
AI05-0049-1}
The library package Directories.Hierarchical_File_Names is an optional
package providing operations for file name construction and decomposition
for targets with hierarchical file naming.
Static Semantics
{
AI05-0049-1}
If provided, the library package Directories.Hierarchical_File_Names
has the following declaration:
package Ada.Directories.Hierarchical_File_Names
is
function Is_Simple_Name (Name :
in String)
return Boolean;
function Is_Root_Directory_Name (Name :
in String)
return Boolean;
function Is_Parent_Directory_Name (Name :
in String)
return Boolean;
function Is_Current_Directory_Name (Name :
in String)
return Boolean;
function Is_Full_Name (Name :
in String)
return Boolean;
function Is_Relative_Name (Name :
in String)
return Boolean;
function Simple_Name (Name :
in String)
return String
renames Ada.Directories.Simple_Name;
function Containing_Directory (Name :
in String)
return String
renames Ada.Directories.Containing_Directory;
function Initial_Directory (Name :
in String)
return String;
function Relative_Name (Name :
in String)
return String;
function Compose (Directory :
in String := "";
Relative_Name :
in String;
Extension :
in String := "")
return String;
end Ada.Directories.Hierarchical_File_Names;
{
AI05-0049-1}
{
AI05-0269-1}
In addition to the operations provided in package Directories.Hierarchical_File_Names,
the operations in package Directories can be used with hierarchical file
names. In particular, functions Full_Name, Base_Name, and Extension provide
additional capabilities for hierarchical file names.
function Is_Simple_Name (Name : in String) return Boolean;
Returns True if Name is a simple name, and returns
False otherwise.
function Is_Root_Directory_Name (Name : in String) return Boolean;
Returns True if Name is syntactically a root (a
directory that cannot be decomposed further), and returns False otherwise.
Implementation Note: For Unix and Unix-like
systems, "/" is the root. For Windows, "C:\" and
"\\Computer\Share" are roots.
function Is_Parent_Directory_Name (Name : in String) return Boolean;
Returns True if Name can be used to indicate symbolically
the parent directory of any directory, and returns False otherwise.
Implementation Note: Is_Parent_Directory_Name
returns True if and only if Name is ".." for both Unix and
Windows.
function Is_Current_Directory_Name (Name : in String) return Boolean;
Returns True if Name can be used to indicate symbolically
the directory itself for any directory, and returns False otherwise.
Implementation Note: Is_Current_Directory_Name
returns True if and only if Name is "." for both Unix and Windows.
function Is_Full_Name (Name : in String) return Boolean;
Returns True if the leftmost directory part of
Name is a root, and returns False otherwise.
function Is_Relative_Name (Name : in String) return Boolean;
{
AI05-0049-1}
{
AI05-0269-1}
Returns True if Name allows the identification of an external file (including
directories and special files) but is not a full name, and returns False
otherwise.
Ramification: Relative names include
simple names as a special case. This function returns False if the syntax
of the name is incorrect.
function Initial_Directory (Name : in String) return String;
{
AI05-0049-1}
{
AI05-0248-1}
Returns the leftmost directory part in Name. [That is, it returns a root
directory name (for a full name), or one of a parent directory name,
a current directory name, or a simple name (for a relative name).] The
exception Name_Error is propagated if the string given as Name does not
allow the identification of an external file (including directories and
special files).
function Relative_Name (Name : in String) return String;
Returns the entire file name except the Initial_Directory
portion. The exception Name_Error is propagated if the string given as
Name does not allow the identification of an external file (including
directories and special files), or if Name has a single part (this includes
if any of Is_Simple_Name, Is_Root_Directory_Name, Is_Parent_Directory_Name,
or Is_Current_Directory_Name are True).
Ramification: The result might be a simple
name.
function Compose (Directory : in String := "";
Relative_Name : in String;
Extension : in String := "") return String;
Returns the name of the external file with the
specified Directory, Relative_Name, and Extension. The exception Name_Error
is propagated if the string given as Directory is not the null string
and does not allow the identification of a directory, or if Is_Relative_Name
(Relative_Name) is False, or if the string given as Extension is not
the null string and is not a possible extension, or if Extension is not
the null string and Simple_Name (Relative_Name) is not a base name.
The result of Compose is a full name if Is_Full_Name
(Directory) is True; result is a relative name otherwise.
Ramification: Name_Error is raised by
Compose if Directory is not the null string, and both Is_Full_Name and
Is_Relative_Name return False.
Discussion: A common security problem
is to include a parent directory name in the middle of a file name; this
is often used to navigate outside of an intended root directory. We considered
attempting to prevent that case by having Compose detect it and raise
an exception. But the extra rules necessary were more confusing than
helpful.
We can say more about the details of these operations
by adopting the notation of a subscript to specify how many path fragments
a particular result has. Then, we can abbreviate "Full Name"
as "Full" and "Relative Name" as "Rel".
In this notation, Unix file name "a/b" is a Rel(2), "../c/d"
is a Rel(3), and "/a/b" is a Full(2). Rel(1) is equivalent
to a simple name; thus we don't have to describe that separately.
In this notation,
For N>1,
Containing_Directory(Rel(N)) = Leftmost Rel(N-1),
Containing_Directory(Full(N)) = Leftmost Full(N-1),
Else if N = 1, raise Name_Error.
Similarly,
For N>1,
Relative_Name(Rel(N)) = Rightmost Rel(N-1),
Relative_Name(Full(N)) = Rightmost Full(N-1),
Else if N = 1, raise Name_Error.
Finally, for Compose
(ignoring the extension here):
Compose (Directory => Full(N), Relative_Name => Rel(M)) => Full(N+M)
Compose (Directory => Rel(N), Relative_Name => Rel(M)) => Rel(N+M)
Name_Error if Relative_Name is a Full(M).
We didn't try to write wording to reflect these
details of these functions.
Implementation Advice
{
AI05-0049-1}
Directories.Hierarchical_File_Names should be provided for systems with
hierarchical file naming, and should not be provided on other systems.
Implementation Advice: Directories.Hierarchical_File_Names
should be provided for systems with hierarchical file naming, and should
not be provided on other systems.
Implementation Note: This package should
be provided when targeting Microsoft® Windows®, Unix, Linux,
and most Unix-like systems.
46 {
AI05-0049-1}
These operations operate on file names, not external files. The files
identified by these operations do not need to exist. Name_Error is raised
only as specified or if the file name is malformed and cannot possibly
identify a file. The result of these operations depends only on their
parameters.
47 {
AI05-0049-1}
Containing_Directory raises Use_Error if Name does not have a containing
directory, including when any of Is_Simple_Name, Is_Root_Directory_Name,
Is_Parent_Directory_Name, or Is_Current_Directory_Name are True.
Ramification: In particular, the default
directory is not used to find the containing directory either when Is_Parent_Directory_Name
or Is_Current_Directory_Name is True. As noted above, these functions
operate purely on the syntax of the file names and do not attempt to
interpret them. If interpretation is needed, Directories.Full_Name can
be to expand any shorthands used before calling Containing_Directory.
Extensions to Ada 2005
{
AI05-0049-1}
Package Ada.Directories.Hierarchical_File_Names is
new.
Ada 2005 and 2012 Editions sponsored in part by Ada-Europe