Skip to content

N.Err. Linux Errors: Errno

Julio edited this page Jun 2, 2020 · 1 revision

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.

Clone this wiki locally