N.Err. Linux Errors: Errno
Errno contains a number for the error returned by the last library function.
Most standard C library errors are returned in an integer variable called "errno
". You can examine errno
in your Ada programs by importing it.
errno : integer;
pragma import( C, errno);
Note: In Multithreading programs, be aware that an integer errno may not be not "thread safe" because it can be shared between threads.
In some C libraries you cannot import errno directly. For example, in modern versions of the GNU C library on Linux, errno is a C preprocessor macro for a function instead of an integer variable. A marco is used to make errno safe for mulitthreaded applications. However, Ada cannot import a macro because a macro has no storage space. The best solution I've found is to create C wrapper functions to work with errno for you.
#include <errno.h>
/* C_errno -- wrapper functions to errno variable */
int C_errno() {
return errno;
}
void C_reset_errno() {
errno = 0;
}
And then import these C functions into Ada using:
-- C wrapper functions of errno
function C_errno return integer;
pragma import( C, C_errno, "C_errno" );
procedure C_reset_errno;
pragma import( C, C_reset_errno, "C_reset_errno" );
Linux provides two functions for working with errno error numbers.
type string255is new string(1..255);
type strptr is access string255;
-- error messages are no longer than 255 characters
procedure perror( message : string);
pragma import( C, perror );
Perror
prints a standard error description with a leading message to standard error.
function strerror( error_number : integer ) return strptr;
pragma import( C, strerror);
Retuns a C string standard error description.
Thread-safe version of strerror called stderror_r.
The following example program makes a deliberate error with the link function and prints the error message using perror and stderror.
with ada.text_io, ada.strings.fixed;
use ada.text_io, ada.strings.fixed;
procedure perr is
-- an example of perror and strerror error messages
procedure perror( message : string );
pragma import( C, perror );
-- print a standard error description with a leading message
type string255 is new string(1..255);
type strptr is access string255;
-- error messages are no longer than 255 characters
function strerror( error_number : integer ) return strptr;
pragma import( C, strerror);
-- get a standard error description
errno : integer;
pragma import( C, errno );
-- last error number
function link( path1, path2 : string ) return integer;
pragma import( C, link);
-- we'll use the link function to create an error
LinkResult : integer; -- value returned by link
ErrorMessagePtr : strptr; -- pointer to stderror message
NullLocation : integer; -- location of NUL in stderror message
begin
Put_Line( "This is an example of perror and strerror");
New_Line;
-- make a deliberate error and print it with perror
Put_Line( "Trying to link a non-existent file to itself.." );
LinkResult := Link( "blahblah", "blahblah" );
if LinkResult = -1 then
perror( "Link failed" );
end if;
New_Line;
-- Retrieve the last error message with strerror.
-- Because strerror returns a C string, only print the
-- string up to the first NUL character.
ErrorMessagePtr := StrError( Errno );
NullLocation := Index( string( ErrorMessagePtr.all ), "" & ASCII.NUL );
Put( "The last error message was '" );
Put( Head( string( ErrorMessagePtr.all ), NullLocation-1 ) );
Put_Line( "'." );
end perr;
This is an example of perror and strerror Trying to link a non-existent file to itself. Link failed: No such file or directory The last error message was 'No such file or directory'.
A table of error numbers is in the appendix.