However, I get a cryptic linker error when I try to use it:
x86_64-linux-gnu-gnatlink-12 test_ioctl.ali
/usr/bin/ld: errno: TLS definition in /lib/x86_64-linux-gnu/libc.so.6 section .tbss mismatches non-TLS reference in ./test_ioctl.o
/usr/bin/ld: /lib/x86_64-linux-gnu/libc.so.6: error adding symbols: bad value
collect2: error: ld returned 1 exit status
x86_64-linux-gnu-gnatlink-12: error when calling /usr/bin/x86_64-linux-gnu-gcc-12
gnatmake: *** link failed.
It seems that errno is not a normal symbol and even in C applications the C header needs to be imported so that this issue does not happen, it is not enough to declare it as extern…
so, on a Mac, errno is in fact a function call to whatever __error is pointing to (or maybe, my C isn’t that great, __error() returns a pointer to the appropriate actual errno? otherwise, how could you say e.g. errno = EINVAL; ?).
For portability, you’d have to write a C function to pick up errno and return that, and then import that function.
First of all it is int.
Second, a along story, but its short version is that you cannot link to an object. Linux provides a function that returns the address of errno. Use it:
function errno return int is
function errno_location return access int;
pragma Import (C, errno_location, "__errno_location");
begin
return errno_location.all;
end errno;
Use GNAT.OS_Lib.Errno and GNAT.OSLib.Errno_Message:
function Errno return Integer;
function Errno_Message
(Err : Integer := Errno;
Default : String := "") return String;
-- Return a message describing the given Errno value. If none is provided
-- by the system, return Default if not empty, else return a generic
-- message indicating the numeric errno value.