diff mbox

[Ada] Normalize_Pathname with unresolved reference directory

Message ID 20151118101054.GA53690@adacore.com
State New
Headers show

Commit Message

Arnaud Charlet Nov. 18, 2015, 10:10 a.m. UTC
This change removes an unnecessary limitation whereby Normalize_Pathname
would not accept an unresolved path name as the reference directory, and
would furthermore return incorrect results, rather than an error diagnostic,
in the case where input did not comply with this limitation.

The following test case must produce the indicated output:

$ gnatmake -q resolve_against_dotdot
$ ./resolve_against_dotdot
/a/b/dir
/a/b/dir
/tmp/bar/dir

with Ada.Text_IO; use Ada.Text_IO;
with GNAT.OS_Lib; use GNAT.OS_Lib;

procedure Resolve_Against_DotDot is
begin
   Put_Line (Normalize_Pathname ("../dir", "/a/b/c"));
   Put_Line (Normalize_Pathname ("../dir", "/a/b/c/SUB/.."));
   Put_Line (Normalize_Pathname ("/tmp/foo/../bar/dir", "/a/b/c/SUB/.."));
end;

Tested on x86_64-pc-linux-gnu, committed on trunk

2015-11-18  Thomas Quinot  <quinot@adacore.com>

	* s-os_lib.ads, s-os_lib.adb(Normalize_Pathname): Support the case of
	an unresolved Directory argument, by recursively resolving it
	against the current dir.
diff mbox

Patch

Index: s-os_lib.adb
===================================================================
--- s-os_lib.adb	(revision 230522)
+++ s-os_lib.adb	(working copy)
@@ -2081,34 +2081,35 @@ 
       -------------------
 
       function Get_Directory (Dir : String) return String is
-         Result : String (1 .. Dir'Length + 1);
-         Length : constant Natural := Dir'Length;
-
       begin
          --  Directory given, add directory separator if needed
 
-         if Length > 0 then
-            Result (1 .. Length) := Dir;
+         if Dir'Length > 0 then
+            declare
+               Result : String   :=
+                          Normalize_Pathname (Dir, "") & Directory_Separator;
+               Last   : Positive := Result'Last - 1;
 
-            --  On Windows, change all '/' to '\'
+            begin
+               --  On Windows, change all '/' to '\'
 
-            if On_Windows then
-               for J in 1 .. Length loop
-                  if Result (J) = '/' then
-                     Result (J) := Directory_Separator;
-                  end if;
-               end loop;
-            end if;
+               if On_Windows then
+                  for J in Result'First .. Last - 1 loop
+                     if Result (J) = '/' then
+                        Result (J) := Directory_Separator;
+                     end if;
+                  end loop;
+               end if;
 
-            --  Add directory separator, if needed
+               --  Include additional directory separator, if needed
 
-            if Result (Length) = Directory_Separator then
-               return Result (1 .. Length);
-            else
-               Result (Result'Length) := Directory_Separator;
-               return Result;
-            end if;
+               if Result (Last) /= Directory_Separator then
+                  Last := Last + 1;
+               end if;
 
+               return Result (Result'First .. Last);
+            end;
+
          --  Directory name not given, get current directory
 
          else
Index: s-os_lib.ads
===================================================================
--- s-os_lib.ads	(revision 230522)
+++ s-os_lib.ads	(working copy)
@@ -505,19 +505,17 @@ 
       Resolve_Links  : Boolean := True;
       Case_Sensitive : Boolean := True) return String;
    --  Returns a file name as an absolute path name, resolving all relative
-   --  directories, and symbolic links. The parameter Directory is a fully
-   --  resolved path name for a directory, or the empty string (the default).
-   --  Name is the name of a file, which is either relative to the given
-   --  directory name, if Directory is non-null, or to the current working
-   --  directory if Directory is null. The result returned is the normalized
-   --  name of the file. For most cases, if two file names designate the same
-   --  file through different paths, Normalize_Pathname will return the same
-   --  canonical name in both cases. However, there are cases when this is not
-   --  true; for example, this is not true in Unix for two hard links
-   --  designating the same file.
+   --  directories, and symbolic links. If Name is a relative path, it is
+   --  interpreted relative to Directory, or to the current directory if
+   --  Directory is the empty string (the default). The result returned is
+   --  the normalized name of the file, containing no "." or ".." components,
+   --  and no duplicated directory separators. For most cases, if two file
+   --  names designate the same file through different paths,
+   --  Normalize_Pathname will return the same canonical name in both cases.
+   --  However, there are cases when this is not true; for example, this is
+   --  not true in Unix for two hard links designating the same file.
    --
-   --  On Windows, the returned path will start with a drive letter except
-   --  when Directory is not empty and does not include a drive letter. If
+   --  On Windows, the returned path will start with a drive letter. If
    --  Directory is empty (the default) and Name is a relative path or an
    --  absolute path without drive letter, the letter of the current drive
    --  will start the returned path. If Case_Sensitive is True (the default),