with System.Soft_Links;
with Unchecked_Conversion;
with System; use System;
package body GNAT.OS_Lib is
package SSL renames System.Soft_Links;
function Args_Length (Args : Argument_List) return Natural;
function C_String_Length (S : Address) return Integer;
procedure Spawn_Internal
(Program_Name : String;
Args : Argument_List;
Result : out Integer;
Pid : out Process_Id;
Blocking : Boolean);
function To_Path_String_Access
(Path_Addr : Address;
Path_Len : Integer)
return String_Access;
function Args_Length (Args : Argument_List) return Natural is
Len : Natural := 0;
begin
for J in Args'Range loop
Len := Len + Args (J)'Length + 1; end loop;
return Len;
end Args_Length;
function Argument_String_To_List
(Arg_String : String)
return Argument_List_Access
is
Max_Args : Integer := Arg_String'Length;
New_Argv : Argument_List (1 .. Max_Args);
New_Argc : Natural := 0;
Idx : Integer;
begin
Idx := Arg_String'First;
loop
declare
Quoted : Boolean := False;
Backqd : Boolean := False;
Old_Idx : Integer;
begin
Old_Idx := Idx;
loop
if not (Backqd or Quoted)
and then Arg_String (Idx) = ' '
then
exit;
elsif not (Backqd or Quoted)
and then Arg_String (Idx) = '"'
then
Quoted := True;
elsif (Quoted and not Backqd)
and then Arg_String (Idx) = '"'
then
Idx := Idx + 1;
exit;
elsif Arg_String (Idx) = '\' then
Backqd := True;
elsif Backqd then
Backqd := False;
end if;
Idx := Idx + 1;
exit when Idx > Arg_String'Last;
end loop;
New_Argc := New_Argc + 1;
New_Argv (New_Argc) :=
new String'(Arg_String (Old_Idx .. Idx - 1));
while Idx <= Arg_String'Last and then Arg_String (Idx) = ' ' loop
Idx := Idx + 1;
end loop;
end;
exit when Idx > Arg_String'Last;
end loop;
return new Argument_List'(New_Argv (1 .. New_Argc));
end Argument_String_To_List;
function C_String_Length (S : Address) return Integer is
function Strlen (S : Address) return Integer;
pragma Import (C, Strlen, "strlen");
begin
if S = Null_Address then
return 0;
else
return Strlen (S);
end if;
end C_String_Length;
function Create_File
(Name : C_File_Name;
Fmode : Mode)
return File_Descriptor
is
function C_Create_File
(Name : C_File_Name;
Fmode : Mode)
return File_Descriptor;
pragma Import (C, C_Create_File, "__gnat_open_create");
begin
return C_Create_File (Name, Fmode);
end Create_File;
function Create_File
(Name : String;
Fmode : Mode)
return File_Descriptor
is
C_Name : String (1 .. Name'Length + 1);
begin
C_Name (1 .. Name'Length) := Name;
C_Name (C_Name'Last) := ASCII.NUL;
return Create_File (C_Name (C_Name'First)'Address, Fmode);
end Create_File;
function Create_New_File
(Name : C_File_Name;
Fmode : Mode)
return File_Descriptor
is
function C_Create_New_File
(Name : C_File_Name;
Fmode : Mode)
return File_Descriptor;
pragma Import (C, C_Create_New_File, "__gnat_open_new");
begin
return C_Create_New_File (Name, Fmode);
end Create_New_File;
function Create_New_File
(Name : String;
Fmode : Mode)
return File_Descriptor
is
C_Name : String (1 .. Name'Length + 1);
begin
C_Name (1 .. Name'Length) := Name;
C_Name (C_Name'Last) := ASCII.NUL;
return Create_New_File (C_Name (C_Name'First)'Address, Fmode);
end Create_New_File;
procedure Create_Temp_File
(FD : out File_Descriptor;
Name : out Temp_File_Name)
is
function Open_New_Temp
(Name : System.Address;
Fmode : Mode)
return File_Descriptor;
pragma Import (C, Open_New_Temp, "__gnat_open_new_temp");
begin
FD := Open_New_Temp (Name'Address, Binary);
end Create_Temp_File;
procedure Delete_File (Name : Address; Success : out Boolean) is
R : Integer;
function unlink (A : Address) return Integer;
pragma Import (C, unlink, "unlink");
begin
R := unlink (Name);
Success := (R = 0);
end Delete_File;
procedure Delete_File (Name : String; Success : out Boolean) is
C_Name : String (1 .. Name'Length + 1);
begin
C_Name (1 .. Name'Length) := Name;
C_Name (C_Name'Last) := ASCII.NUL;
Delete_File (C_Name'Address, Success);
end Delete_File;
function File_Time_Stamp (FD : File_Descriptor) return OS_Time is
function File_Time (FD : File_Descriptor) return OS_Time;
pragma Import (C, File_Time, "__gnat_file_time_fd");
begin
return File_Time (FD);
end File_Time_Stamp;
function File_Time_Stamp (Name : C_File_Name) return OS_Time is
function File_Time (Name : Address) return OS_Time;
pragma Import (C, File_Time, "__gnat_file_time_name");
begin
return File_Time (Name);
end File_Time_Stamp;
function File_Time_Stamp (Name : String) return OS_Time is
F_Name : String (1 .. Name'Length + 1);
begin
F_Name (1 .. Name'Length) := Name;
F_Name (F_Name'Last) := ASCII.NUL;
return File_Time_Stamp (F_Name'Address);
end File_Time_Stamp;
procedure Free (Arg : in out String_List_Access) is
X : String_Access;
procedure Free_Array is new Unchecked_Deallocation
(Object => String_List, Name => String_List_Access);
begin
for J in Arg'Range loop
X := Arg (J);
Free (X);
end loop;
Free_Array (Arg);
end Free;
function Get_Debuggable_Suffix return String_Access is
procedure Get_Suffix_Ptr (Length, Ptr : Address);
pragma Import (C, Get_Suffix_Ptr, "__gnat_get_debuggable_suffix_ptr");
procedure Strncpy (Astring_Addr, Cstring : Address; N : Integer);
pragma Import (C, Strncpy, "strncpy");
Suffix_Ptr : Address;
Suffix_Length : Integer;
Result : String_Access;
begin
Get_Suffix_Ptr (Suffix_Length'Address, Suffix_Ptr'Address);
Result := new String (1 .. Suffix_Length);
if Suffix_Length > 0 then
Strncpy (Result.all'Address, Suffix_Ptr, Suffix_Length);
end if;
return Result;
end Get_Debuggable_Suffix;
function Get_Executable_Suffix return String_Access is
procedure Get_Suffix_Ptr (Length, Ptr : Address);
pragma Import (C, Get_Suffix_Ptr, "__gnat_get_executable_suffix_ptr");
procedure Strncpy (Astring_Addr, Cstring : Address; N : Integer);
pragma Import (C, Strncpy, "strncpy");
Suffix_Ptr : Address;
Suffix_Length : Integer;
Result : String_Access;
begin
Get_Suffix_Ptr (Suffix_Length'Address, Suffix_Ptr'Address);
Result := new String (1 .. Suffix_Length);
if Suffix_Length > 0 then
Strncpy (Result.all'Address, Suffix_Ptr, Suffix_Length);
end if;
return Result;
end Get_Executable_Suffix;
function Get_Object_Suffix return String_Access is
procedure Get_Suffix_Ptr (Length, Ptr : Address);
pragma Import (C, Get_Suffix_Ptr, "__gnat_get_object_suffix_ptr");
procedure Strncpy (Astring_Addr, Cstring : Address; N : Integer);
pragma Import (C, Strncpy, "strncpy");
Suffix_Ptr : Address;
Suffix_Length : Integer;
Result : String_Access;
begin
Get_Suffix_Ptr (Suffix_Length'Address, Suffix_Ptr'Address);
Result := new String (1 .. Suffix_Length);
if Suffix_Length > 0 then
Strncpy (Result.all'Address, Suffix_Ptr, Suffix_Length);
end if;
return Result;
end Get_Object_Suffix;
function Getenv (Name : String) return String_Access is
procedure Get_Env_Value_Ptr (Name, Length, Ptr : Address);
pragma Import (C, Get_Env_Value_Ptr, "__gnat_get_env_value_ptr");
procedure Strncpy (Astring_Addr, Cstring : Address; N : Integer);
pragma Import (C, Strncpy, "strncpy");
Env_Value_Ptr : Address;
Env_Value_Length : Integer;
F_Name : String (1 .. Name'Length + 1);
Result : String_Access;
begin
F_Name (1 .. Name'Length) := Name;
F_Name (F_Name'Last) := ASCII.NUL;
Get_Env_Value_Ptr
(F_Name'Address, Env_Value_Length'Address, Env_Value_Ptr'Address);
Result := new String (1 .. Env_Value_Length);
if Env_Value_Length > 0 then
Strncpy (Result.all'Address, Env_Value_Ptr, Env_Value_Length);
end if;
return Result;
end Getenv;
function GM_Day (Date : OS_Time) return Day_Type is
Y : Year_Type;
Mo : Month_Type;
D : Day_Type;
H : Hour_Type;
Mn : Minute_Type;
S : Second_Type;
begin
GM_Split (Date, Y, Mo, D, H, Mn, S);
return D;
end GM_Day;
function GM_Hour (Date : OS_Time) return Hour_Type is
Y : Year_Type;
Mo : Month_Type;
D : Day_Type;
H : Hour_Type;
Mn : Minute_Type;
S : Second_Type;
begin
GM_Split (Date, Y, Mo, D, H, Mn, S);
return H;
end GM_Hour;
function GM_Minute (Date : OS_Time) return Minute_Type is
Y : Year_Type;
Mo : Month_Type;
D : Day_Type;
H : Hour_Type;
Mn : Minute_Type;
S : Second_Type;
begin
GM_Split (Date, Y, Mo, D, H, Mn, S);
return Mn;
end GM_Minute;
function GM_Month (Date : OS_Time) return Month_Type is
Y : Year_Type;
Mo : Month_Type;
D : Day_Type;
H : Hour_Type;
Mn : Minute_Type;
S : Second_Type;
begin
GM_Split (Date, Y, Mo, D, H, Mn, S);
return Mo;
end GM_Month;
function GM_Second (Date : OS_Time) return Second_Type is
Y : Year_Type;
Mo : Month_Type;
D : Day_Type;
H : Hour_Type;
Mn : Minute_Type;
S : Second_Type;
begin
GM_Split (Date, Y, Mo, D, H, Mn, S);
return S;
end GM_Second;
procedure GM_Split
(Date : OS_Time;
Year : out Year_Type;
Month : out Month_Type;
Day : out Day_Type;
Hour : out Hour_Type;
Minute : out Minute_Type;
Second : out Second_Type)
is
procedure To_GM_Time
(P_Time_T, P_Year, P_Month, P_Day, P_Hours, P_Mins, P_Secs : Address);
pragma Import (C, To_GM_Time, "__gnat_to_gm_time");
T : OS_Time := Date;
Y : Integer;
Mo : Integer;
D : Integer;
H : Integer;
Mn : Integer;
S : Integer;
begin
Locked_Processing : begin
SSL.Lock_Task.all;
To_GM_Time
(T'Address, Y'Address, Mo'Address, D'Address,
H'Address, Mn'Address, S'Address);
SSL.Unlock_Task.all;
exception
when others =>
SSL.Unlock_Task.all;
raise;
end Locked_Processing;
Year := Y + 1900;
Month := Mo + 1;
Day := D;
Hour := H;
Minute := Mn;
Second := S;
end GM_Split;
function GM_Year (Date : OS_Time) return Year_Type is
Y : Year_Type;
Mo : Month_Type;
D : Day_Type;
H : Hour_Type;
Mn : Minute_Type;
S : Second_Type;
begin
GM_Split (Date, Y, Mo, D, H, Mn, S);
return Y;
end GM_Year;
function Is_Absolute_Path (Name : String) return Boolean is
function Is_Absolute_Path (Name : Address) return Integer;
pragma Import (C, Is_Absolute_Path, "__gnat_is_absolute_path");
F_Name : String (1 .. Name'Length + 1);
begin
F_Name (1 .. Name'Length) := Name;
F_Name (F_Name'Last) := ASCII.NUL;
return Is_Absolute_Path (F_Name'Address) /= 0;
end Is_Absolute_Path;
function Is_Directory (Name : C_File_Name) return Boolean is
function Is_Directory (Name : Address) return Integer;
pragma Import (C, Is_Directory, "__gnat_is_directory");
begin
return Is_Directory (Name) /= 0;
end Is_Directory;
function Is_Directory (Name : String) return Boolean is
F_Name : String (1 .. Name'Length + 1);
begin
F_Name (1 .. Name'Length) := Name;
F_Name (F_Name'Last) := ASCII.NUL;
return Is_Directory (F_Name'Address);
end Is_Directory;
function Is_Regular_File (Name : C_File_Name) return Boolean is
function Is_Regular_File (Name : Address) return Integer;
pragma Import (C, Is_Regular_File, "__gnat_is_regular_file");
begin
return Is_Regular_File (Name) /= 0;
end Is_Regular_File;
function Is_Regular_File (Name : String) return Boolean is
F_Name : String (1 .. Name'Length + 1);
begin
F_Name (1 .. Name'Length) := Name;
F_Name (F_Name'Last) := ASCII.NUL;
return Is_Regular_File (F_Name'Address);
end Is_Regular_File;
function Is_Writable_File (Name : C_File_Name) return Boolean is
function Is_Writable_File (Name : Address) return Integer;
pragma Import (C, Is_Writable_File, "__gnat_is_writable_file");
begin
return Is_Writable_File (Name) /= 0;
end Is_Writable_File;
function Is_Writable_File (Name : String) return Boolean is
F_Name : String (1 .. Name'Length + 1);
begin
F_Name (1 .. Name'Length) := Name;
F_Name (F_Name'Last) := ASCII.NUL;
return Is_Writable_File (F_Name'Address);
end Is_Writable_File;
function Locate_Exec_On_Path
(Exec_Name : String)
return String_Access
is
function Locate_Exec_On_Path (C_Exec_Name : Address) return Address;
pragma Import (C, Locate_Exec_On_Path, "__gnat_locate_exec_on_path");
procedure Free (Ptr : System.Address);
pragma Import (C, Free, "free");
C_Exec_Name : String (1 .. Exec_Name'Length + 1);
Path_Addr : Address;
Path_Len : Integer;
Result : String_Access;
begin
C_Exec_Name (1 .. Exec_Name'Length) := Exec_Name;
C_Exec_Name (C_Exec_Name'Last) := ASCII.NUL;
Path_Addr := Locate_Exec_On_Path (C_Exec_Name'Address);
Path_Len := C_String_Length (Path_Addr);
if Path_Len = 0 then
return null;
else
Result := To_Path_String_Access (Path_Addr, Path_Len);
Free (Path_Addr);
return Result;
end if;
end Locate_Exec_On_Path;
function Locate_Regular_File
(File_Name : C_File_Name;
Path : C_File_Name)
return String_Access
is
function Locate_Regular_File
(C_File_Name, Path_Val : Address) return Address;
pragma Import (C, Locate_Regular_File, "__gnat_locate_regular_file");
procedure Free (Ptr : System.Address);
pragma Import (C, Free, "free");
Path_Addr : Address;
Path_Len : Integer;
Result : String_Access;
begin
Path_Addr := Locate_Regular_File (File_Name, Path);
Path_Len := C_String_Length (Path_Addr);
if Path_Len = 0 then
return null;
else
Result := To_Path_String_Access (Path_Addr, Path_Len);
Free (Path_Addr);
return Result;
end if;
end Locate_Regular_File;
function Locate_Regular_File
(File_Name : String;
Path : String)
return String_Access
is
C_File_Name : String (1 .. File_Name'Length + 1);
C_Path : String (1 .. Path'Length + 1);
begin
C_File_Name (1 .. File_Name'Length) := File_Name;
C_File_Name (C_File_Name'Last) := ASCII.NUL;
C_Path (1 .. Path'Length) := Path;
C_Path (C_Path'Last) := ASCII.NUL;
return Locate_Regular_File (C_File_Name'Address, C_Path'Address);
end Locate_Regular_File;
function Non_Blocking_Spawn
(Program_Name : String;
Args : Argument_List)
return Process_Id
is
Junk : Integer;
Pid : Process_Id;
begin
Spawn_Internal (Program_Name, Args, Junk, Pid, Blocking => False);
return Pid;
end Non_Blocking_Spawn;
procedure Normalize_Arguments (Args : in out Argument_List) is
procedure Quote_Argument (Arg : in out String_Access);
Argument_Needs_Quote : Boolean;
pragma Import (C, Argument_Needs_Quote, "__gnat_argument_needs_quote");
procedure Quote_Argument (Arg : in out String_Access) is
Res : String (1 .. Arg'Length * 2);
J : Positive := 1;
Quote_Needed : Boolean := False;
begin
if Arg (Arg'First) /= '"' or else Arg (Arg'Last) /= '"' then
Res (J) := '"';
for K in Arg'Range loop
J := J + 1;
if Arg (K) = '"' then
Res (J) := '\';
J := J + 1;
Res (J) := '"';
elsif Arg (K) = ' ' then
Res (J) := Arg (K);
Quote_Needed := True;
else
Res (J) := Arg (K);
end if;
end loop;
if Quote_Needed then
J := J + 1;
Res (J) := '"';
declare
Old : String_Access := Arg;
begin
Arg := new String'(Res (1 .. J));
Free (Old);
end;
end if;
end if;
end Quote_Argument;
begin
if Argument_Needs_Quote then
for K in Args'Range loop
if Args (K) /= null then
Quote_Argument (Args (K));
end if;
end loop;
end if;
end Normalize_Arguments;
function Normalize_Pathname
(Name : String;
Directory : String := "")
return String
is
Max_Path : Integer;
pragma Import (C, Max_Path, "__gnat_max_path_len");
procedure Get_Current_Dir
(Dir : System.Address;
Length : System.Address);
pragma Import (C, Get_Current_Dir, "__gnat_get_current_dir");
Path_Buffer : String (1 .. Max_Path + Max_Path + 2);
End_Path : Natural := 0;
Link_Buffer : String (1 .. Max_Path + 2);
Status : Integer;
Last : Positive;
Start : Natural;
Finish : Positive;
Max_Iterations : constant := 500;
function Readlink
(Path : System.Address;
Buf : System.Address;
Bufsiz : Integer)
return Integer;
pragma Import (C, Readlink, "__gnat_readlink");
function To_Canonical_File_Spec
(Host_File : System.Address)
return System.Address;
pragma Import
(C, To_Canonical_File_Spec, "__gnat_to_canonical_file_spec");
The_Name : String (1 .. Name'Length + 1);
Canonical_File_Addr : System.Address;
Canonical_File_Len : Integer;
Need_To_Check_Drive_Letter : Boolean := False;
function Strlen (S : System.Address) return Integer;
pragma Import (C, Strlen, "strlen");
function Get_Directory return String;
function Final_Value (S : String) return String;
function Get_Directory return String is
begin
if Directory'Length > 0 then
if Directory (Directory'Length) = Directory_Separator then
return Directory;
else
declare
Result : String (1 .. Directory'Length + 1);
begin
Result (1 .. Directory'Length) := Directory;
Result (Result'Length) := Directory_Separator;
return Result;
end;
end if;
else
declare
Buffer : String (1 .. Max_Path + 2);
Path_Len : Natural := Max_Path;
begin
Get_Current_Dir (Buffer'Address, Path_Len'Address);
if Buffer (Path_Len) /= Directory_Separator then
Path_Len := Path_Len + 1;
Buffer (Path_Len) := Directory_Separator;
end if;
return Buffer (1 .. Path_Len);
end;
end if;
end Get_Directory;
Reference_Dir : constant String := Get_Directory;
function Final_Value (S : String) return String is
begin
if Need_To_Check_Drive_Letter
and then S'Length >= 2
and then S (S'First) = '/'
and then S (S'First + 1) in 'A' .. 'Z'
and then (S'Length = 2 or else S (S'First + 2) = '/')
then
declare
Result : String (1 .. S'Length + 1);
begin
Result (1) := '/';
Result (2 .. Result'Last) := S;
return Result;
end;
else
return S;
end if;
end Final_Value;
begin
if Name'Length = 0 then
return "";
end if;
VMS_Conversion : begin
The_Name (1 .. Name'Length) := Name;
The_Name (The_Name'Last) := ASCII.NUL;
Canonical_File_Addr := To_Canonical_File_Spec (The_Name'Address);
Canonical_File_Len := Strlen (Canonical_File_Addr);
if Canonical_File_Len = 0 then
return "";
end if;
declare
subtype Path_String is String (1 .. Canonical_File_Len);
type Path_String_Access is access Path_String;
function Address_To_Access is new
Unchecked_Conversion (Source => Address,
Target => Path_String_Access);
Path_Access : Path_String_Access :=
Address_To_Access (Canonical_File_Addr);
begin
Path_Buffer (1 .. Canonical_File_Len) := Path_Access.all;
End_Path := Canonical_File_Len;
Last := 1;
end;
end VMS_Conversion;
if Directory_Separator /= '/' then
for Index in 1 .. End_Path loop
if Path_Buffer (Index) = '/' then
Path_Buffer (Index) := Directory_Separator;
end if;
end loop;
end if;
for J in 1 .. Max_Iterations loop
if Last = 1
and then not Is_Absolute_Path (Path_Buffer (1 .. End_Path))
then
Path_Buffer
(Reference_Dir'Last + 1 .. Reference_Dir'Length + End_Path) :=
Path_Buffer (1 .. End_Path);
End_Path := Reference_Dir'Length + End_Path;
Path_Buffer (1 .. Reference_Dir'Length) := Reference_Dir;
Last := Reference_Dir'Length;
end if;
if Last = 1 and then End_Path >= 3 then
Need_To_Check_Drive_Letter := (Path_Buffer (1 .. 2)) = "//";
end if;
Start := Last + 1;
Finish := Last;
if Start > End_Path then
return Final_Value (Path_Buffer (1 .. End_Path));
end if;
while Path_Buffer (Start) = Directory_Separator loop
if Start = End_Path then
return Final_Value (Path_Buffer (1 .. End_Path - 1));
else
Path_Buffer (Start .. End_Path - 1) :=
Path_Buffer (Start + 1 .. End_Path);
End_Path := End_Path - 1;
end if;
end loop;
while Finish < End_Path
and then Path_Buffer (Finish + 1) /= Directory_Separator
loop
Finish := Finish + 1;
end loop;
if Start = Finish and then Path_Buffer (Start) = '.' then
if Start = End_Path then
if Last = 1 then
return (1 => Directory_Separator);
else
return Path_Buffer (1 .. Last - 1);
end if;
else
Path_Buffer (Last + 1 .. End_Path - 2) :=
Path_Buffer (Last + 3 .. End_Path);
End_Path := End_Path - 2;
end if;
elsif Finish = Start + 1
and then Path_Buffer (Start .. Finish) = ".."
then
Start := Last;
loop
Start := Start - 1;
exit when Start < 1 or else
Path_Buffer (Start) = Directory_Separator;
end loop;
if Start <= 1 then
if Finish = End_Path then
return (1 => Directory_Separator);
else
Path_Buffer (1 .. End_Path - Finish) :=
Path_Buffer (Finish + 1 .. End_Path);
End_Path := End_Path - Finish;
Last := 1;
end if;
else
if Finish = End_Path then
return Final_Value (Path_Buffer (1 .. Start - 1));
else
Path_Buffer (Start + 1 .. Start + End_Path - Finish - 1) :=
Path_Buffer (Finish + 2 .. End_Path);
End_Path := Start + End_Path - Finish - 1;
Last := Start;
end if;
end if;
else
declare
Saved : Character := Path_Buffer (Finish + 1);
begin
Path_Buffer (Finish + 1) := ASCII.NUL;
Status := Readlink (Path_Buffer'Address,
Link_Buffer'Address,
Link_Buffer'Length);
Path_Buffer (Finish + 1) := Saved;
end;
if Status <= 0 then
Last := Finish + 1;
else
if Is_Absolute_Path (Link_Buffer (1 .. Status)) then
Path_Buffer (Status + 1 .. End_Path - (Finish - Status)) :=
Path_Buffer (Finish + 1 .. End_Path);
End_Path := End_Path - (Finish - Status);
Path_Buffer (1 .. Status) := Link_Buffer (1 .. Status);
Last := 1;
else
Path_Buffer
(Last + Status + 1 .. End_Path - Finish + Last + Status) :=
Path_Buffer (Finish + 1 .. End_Path);
End_Path := End_Path - Finish + Last + Status;
Path_Buffer (Last + 1 .. Last + Status) :=
Link_Buffer (1 .. Status);
end if;
end if;
end if;
end loop;
return "";
end Normalize_Pathname;
function Open_Read
(Name : C_File_Name;
Fmode : Mode)
return File_Descriptor
is
function C_Open_Read
(Name : C_File_Name;
Fmode : Mode)
return File_Descriptor;
pragma Import (C, C_Open_Read, "__gnat_open_read");
begin
return C_Open_Read (Name, Fmode);
end Open_Read;
function Open_Read
(Name : String;
Fmode : Mode)
return File_Descriptor
is
C_Name : String (1 .. Name'Length + 1);
begin
C_Name (1 .. Name'Length) := Name;
C_Name (C_Name'Last) := ASCII.NUL;
return Open_Read (C_Name (C_Name'First)'Address, Fmode);
end Open_Read;
function Open_Read_Write
(Name : C_File_Name;
Fmode : Mode)
return File_Descriptor
is
function C_Open_Read_Write
(Name : C_File_Name;
Fmode : Mode)
return File_Descriptor;
pragma Import (C, C_Open_Read_Write, "__gnat_open_rw");
begin
return C_Open_Read_Write (Name, Fmode);
end Open_Read_Write;
function Open_Read_Write
(Name : String;
Fmode : Mode)
return File_Descriptor
is
C_Name : String (1 .. Name'Length + 1);
begin
C_Name (1 .. Name'Length) := Name;
C_Name (C_Name'Last) := ASCII.NUL;
return Open_Read_Write (C_Name (C_Name'First)'Address, Fmode);
end Open_Read_Write;
procedure Rename_File
(Old_Name : C_File_Name;
New_Name : C_File_Name;
Success : out Boolean)
is
function rename (From, To : Address) return Integer;
pragma Import (C, rename, "rename");
R : Integer;
begin
R := rename (Old_Name, New_Name);
Success := (R = 0);
end Rename_File;
procedure Rename_File
(Old_Name : String;
New_Name : String;
Success : out Boolean)
is
C_Old_Name : String (1 .. Old_Name'Length + 1);
C_New_Name : String (1 .. New_Name'Length + 1);
begin
C_Old_Name (1 .. Old_Name'Length) := Old_Name;
C_Old_Name (C_Old_Name'Last) := ASCII.NUL;
C_New_Name (1 .. New_Name'Length) := New_Name;
C_New_Name (C_New_Name'Last) := ASCII.NUL;
Rename_File (C_Old_Name'Address, C_New_Name'Address, Success);
end Rename_File;
procedure Setenv (Name : String; Value : String) is
F_Name : String (1 .. Name'Length + 1);
F_Value : String (1 .. Value'Length + 1);
procedure Set_Env_Value (Name, Value : System.Address);
pragma Import (C, Set_Env_Value, "__gnat_set_env_value");
begin
F_Name (1 .. Name'Length) := Name;
F_Name (F_Name'Last) := ASCII.NUL;
F_Value (1 .. Value'Length) := Value;
F_Value (F_Value'Last) := ASCII.NUL;
Set_Env_Value (F_Name'Address, F_Value'Address);
end Setenv;
function Spawn
(Program_Name : String;
Args : Argument_List)
return Integer
is
Junk : Process_Id;
Result : Integer;
begin
Spawn_Internal (Program_Name, Args, Result, Junk, Blocking => True);
return Result;
end Spawn;
procedure Spawn
(Program_Name : String;
Args : Argument_List;
Success : out Boolean)
is
begin
Success := (Spawn (Program_Name, Args) = 0);
end Spawn;
procedure Spawn_Internal
(Program_Name : String;
Args : Argument_List;
Result : out Integer;
Pid : out Process_Id;
Blocking : Boolean)
is
procedure Spawn (Args : Argument_List);
N_Args : Argument_List (Args'Range);
procedure Spawn (Args : Argument_List) is
type Chars is array (Positive range <>) of aliased Character;
type Char_Ptr is access constant Character;
Command_Len : constant Positive := Program_Name'Length + 1
+ Args_Length (Args);
Command_Last : Natural := 0;
Command : aliased Chars (1 .. Command_Len);
Arg_List_Len : constant Positive := Args'Length + 2;
Arg_List_Last : Natural := 0;
Arg_List : aliased array (1 .. Arg_List_Len) of Char_Ptr;
procedure Add_To_Command (S : String);
function Portable_Spawn (Args : Address) return Integer;
pragma Import (C, Portable_Spawn, "__gnat_portable_spawn");
function Portable_No_Block_Spawn (Args : Address) return Process_Id;
pragma Import
(C, Portable_No_Block_Spawn, "__gnat_portable_no_block_spawn");
procedure Add_To_Command (S : String) is
First : constant Natural := Command_Last + 1;
begin
Command_Last := Command_Last + S'Length;
for J in S'Range loop
Command (First + J - S'First) := S (J);
end loop;
Command_Last := Command_Last + 1;
Command (Command_Last) := ASCII.NUL;
Arg_List_Last := Arg_List_Last + 1;
Arg_List (Arg_List_Last) := Command (First)'Access;
end Add_To_Command;
begin
Add_To_Command (Program_Name);
for J in Args'Range loop
Add_To_Command (Args (J).all);
end loop;
if Blocking then
Pid := Invalid_Pid;
Result := Portable_Spawn (Arg_List'Address);
else
Pid := Portable_No_Block_Spawn (Arg_List'Address);
Result := Boolean'Pos (Pid /= Invalid_Pid);
end if;
end Spawn;
begin
for K in N_Args'Range loop
N_Args (K) := new String'(Args (K).all);
end loop;
Normalize_Arguments (N_Args);
Spawn (N_Args);
for K in N_Args'Range loop
Free (N_Args (K));
end loop;
end Spawn_Internal;
function To_Path_String_Access
(Path_Addr : Address;
Path_Len : Integer)
return String_Access
is
subtype Path_String is String (1 .. Path_Len);
type Path_String_Access is access Path_String;
function Address_To_Access is new
Unchecked_Conversion (Source => Address,
Target => Path_String_Access);
Path_Access : Path_String_Access := Address_To_Access (Path_Addr);
Return_Val : String_Access;
begin
Return_Val := new String (1 .. Path_Len);
for J in 1 .. Path_Len loop
Return_Val (J) := Path_Access (J);
end loop;
return Return_Val;
end To_Path_String_Access;
procedure Wait_Process (Pid : out Process_Id; Success : out Boolean) is
Status : Integer;
function Portable_Wait (S : Address) return Process_Id;
pragma Import (C, Portable_Wait, "__gnat_portable_wait");
begin
Pid := Portable_Wait (Status'Address);
Success := (Status = 0);
end Wait_Process;
end GNAT.OS_Lib;