1 /* Extended support for using errno values.
2 Written by Fred Fish. fnf@cygnus.com
3 This file is in the public domain. --Per Bothner. */
7 #ifdef HAVE_SYS_ERRLIST
8 /* Note that errno.h (not sure what OS) or stdio.h (BSD 4.4, at least)
9 might declare sys_errlist in a way that the compiler might consider
10 incompatible with our later declaration, perhaps by using const
11 attributes. So we hide the declaration in errno.h (if any) using a
13 #define sys_nerr sys_nerr__
14 #define sys_errlist sys_errlist__
18 #include "libiberty.h"
23 #ifdef HAVE_SYS_ERRLIST
28 /* Routines imported from standard C runtime libraries. */
43 # define MAX(a,b) ((a) > (b) ? (a) : (b))
46 static void init_error_tables (void);
48 /* Translation table for errno values. See intro(2) in most UNIX systems
49 Programmers Reference Manuals.
51 Note that this table is generally only accessed when it is used at runtime
52 to initialize errno name and message tables that are indexed by errno
55 Not all of these errnos will exist on all systems. This table is the only
56 thing that should have to be updated as new error numbers are introduced.
57 It's sort of ugly, but at least its portable. */
61 const int value
; /* The numeric value from <errno.h> */
62 const char *const name
; /* The equivalent symbolic value */
63 #ifndef HAVE_SYS_ERRLIST
64 const char *const msg
; /* Short message about this value */
68 #ifndef HAVE_SYS_ERRLIST
69 # define ENTRY(value, name, msg) {value, name, msg}
71 # define ENTRY(value, name, msg) {value, name}
74 static const struct error_info error_table
[] =
77 ENTRY(EPERM
, "EPERM", "Not owner"),
80 ENTRY(ENOENT
, "ENOENT", "No such file or directory"),
83 ENTRY(ESRCH
, "ESRCH", "No such process"),
86 ENTRY(EINTR
, "EINTR", "Interrupted system call"),
89 ENTRY(EIO
, "EIO", "I/O error"),
92 ENTRY(ENXIO
, "ENXIO", "No such device or address"),
95 ENTRY(E2BIG
, "E2BIG", "Arg list too long"),
98 ENTRY(ENOEXEC
, "ENOEXEC", "Exec format error"),
101 ENTRY(EBADF
, "EBADF", "Bad file number"),
104 ENTRY(ECHILD
, "ECHILD", "No child processes"),
106 #if defined (EWOULDBLOCK) /* Put before EAGAIN, sometimes aliased */
107 ENTRY(EWOULDBLOCK
, "EWOULDBLOCK", "Operation would block"),
110 ENTRY(EAGAIN
, "EAGAIN", "No more processes"),
113 ENTRY(ENOMEM
, "ENOMEM", "Not enough space"),
116 ENTRY(EACCES
, "EACCES", "Permission denied"),
119 ENTRY(EFAULT
, "EFAULT", "Bad address"),
121 #if defined (ENOTBLK)
122 ENTRY(ENOTBLK
, "ENOTBLK", "Block device required"),
125 ENTRY(EBUSY
, "EBUSY", "Device busy"),
128 ENTRY(EEXIST
, "EEXIST", "File exists"),
131 ENTRY(EXDEV
, "EXDEV", "Cross-device link"),
134 ENTRY(ENODEV
, "ENODEV", "No such device"),
136 #if defined (ENOTDIR)
137 ENTRY(ENOTDIR
, "ENOTDIR", "Not a directory"),
140 ENTRY(EISDIR
, "EISDIR", "Is a directory"),
143 ENTRY(EINVAL
, "EINVAL", "Invalid argument"),
146 ENTRY(ENFILE
, "ENFILE", "File table overflow"),
149 ENTRY(EMFILE
, "EMFILE", "Too many open files"),
152 ENTRY(ENOTTY
, "ENOTTY", "Not a typewriter"),
154 #if defined (ETXTBSY)
155 ENTRY(ETXTBSY
, "ETXTBSY", "Text file busy"),
158 ENTRY(EFBIG
, "EFBIG", "File too large"),
161 ENTRY(ENOSPC
, "ENOSPC", "No space left on device"),
164 ENTRY(ESPIPE
, "ESPIPE", "Illegal seek"),
167 ENTRY(EROFS
, "EROFS", "Read-only file system"),
170 ENTRY(EMLINK
, "EMLINK", "Too many links"),
173 ENTRY(EPIPE
, "EPIPE", "Broken pipe"),
176 ENTRY(EDOM
, "EDOM", "Math argument out of domain of func"),
179 ENTRY(ERANGE
, "ERANGE", "Math result not representable"),
182 ENTRY(ENOMSG
, "ENOMSG", "No message of desired type"),
185 ENTRY(EIDRM
, "EIDRM", "Identifier removed"),
188 ENTRY(ECHRNG
, "ECHRNG", "Channel number out of range"),
190 #if defined (EL2NSYNC)
191 ENTRY(EL2NSYNC
, "EL2NSYNC", "Level 2 not synchronized"),
194 ENTRY(EL3HLT
, "EL3HLT", "Level 3 halted"),
197 ENTRY(EL3RST
, "EL3RST", "Level 3 reset"),
200 ENTRY(ELNRNG
, "ELNRNG", "Link number out of range"),
202 #if defined (EUNATCH)
203 ENTRY(EUNATCH
, "EUNATCH", "Protocol driver not attached"),
206 ENTRY(ENOCSI
, "ENOCSI", "No CSI structure available"),
209 ENTRY(EL2HLT
, "EL2HLT", "Level 2 halted"),
211 #if defined (EDEADLK)
212 ENTRY(EDEADLK
, "EDEADLK", "Deadlock condition"),
215 ENTRY(ENOLCK
, "ENOLCK", "No record locks available"),
218 ENTRY(EBADE
, "EBADE", "Invalid exchange"),
221 ENTRY(EBADR
, "EBADR", "Invalid request descriptor"),
224 ENTRY(EXFULL
, "EXFULL", "Exchange full"),
227 ENTRY(ENOANO
, "ENOANO", "No anode"),
229 #if defined (EBADRQC)
230 ENTRY(EBADRQC
, "EBADRQC", "Invalid request code"),
232 #if defined (EBADSLT)
233 ENTRY(EBADSLT
, "EBADSLT", "Invalid slot"),
235 #if defined (EDEADLOCK)
236 ENTRY(EDEADLOCK
, "EDEADLOCK", "File locking deadlock error"),
239 ENTRY(EBFONT
, "EBFONT", "Bad font file format"),
242 ENTRY(ENOSTR
, "ENOSTR", "Device not a stream"),
244 #if defined (ENODATA)
245 ENTRY(ENODATA
, "ENODATA", "No data available"),
248 ENTRY(ETIME
, "ETIME", "Timer expired"),
251 ENTRY(ENOSR
, "ENOSR", "Out of streams resources"),
254 ENTRY(ENONET
, "ENONET", "Machine is not on the network"),
257 ENTRY(ENOPKG
, "ENOPKG", "Package not installed"),
259 #if defined (EREMOTE)
260 ENTRY(EREMOTE
, "EREMOTE", "Object is remote"),
262 #if defined (ENOLINK)
263 ENTRY(ENOLINK
, "ENOLINK", "Link has been severed"),
266 ENTRY(EADV
, "EADV", "Advertise error"),
269 ENTRY(ESRMNT
, "ESRMNT", "Srmount error"),
272 ENTRY(ECOMM
, "ECOMM", "Communication error on send"),
275 ENTRY(EPROTO
, "EPROTO", "Protocol error"),
277 #if defined (EMULTIHOP)
278 ENTRY(EMULTIHOP
, "EMULTIHOP", "Multihop attempted"),
280 #if defined (EDOTDOT)
281 ENTRY(EDOTDOT
, "EDOTDOT", "RFS specific error"),
283 #if defined (EBADMSG)
284 ENTRY(EBADMSG
, "EBADMSG", "Not a data message"),
286 #if defined (ENAMETOOLONG)
287 ENTRY(ENAMETOOLONG
, "ENAMETOOLONG", "File name too long"),
289 #if defined (EOVERFLOW)
290 ENTRY(EOVERFLOW
, "EOVERFLOW", "Value too large for defined data type"),
292 #if defined (ENOTUNIQ)
293 ENTRY(ENOTUNIQ
, "ENOTUNIQ", "Name not unique on network"),
296 ENTRY(EBADFD
, "EBADFD", "File descriptor in bad state"),
298 #if defined (EREMCHG)
299 ENTRY(EREMCHG
, "EREMCHG", "Remote address changed"),
301 #if defined (ELIBACC)
302 ENTRY(ELIBACC
, "ELIBACC", "Can not access a needed shared library"),
304 #if defined (ELIBBAD)
305 ENTRY(ELIBBAD
, "ELIBBAD", "Accessing a corrupted shared library"),
307 #if defined (ELIBSCN)
308 ENTRY(ELIBSCN
, "ELIBSCN", ".lib section in a.out corrupted"),
310 #if defined (ELIBMAX)
311 ENTRY(ELIBMAX
, "ELIBMAX", "Attempting to link in too many shared libraries"),
313 #if defined (ELIBEXEC)
314 ENTRY(ELIBEXEC
, "ELIBEXEC", "Cannot exec a shared library directly"),
317 ENTRY(EILSEQ
, "EILSEQ", "Illegal byte sequence"),
320 ENTRY(ENOSYS
, "ENOSYS", "Operation not applicable"),
323 ENTRY(ELOOP
, "ELOOP", "Too many symbolic links encountered"),
325 #if defined (ERESTART)
326 ENTRY(ERESTART
, "ERESTART", "Interrupted system call should be restarted"),
328 #if defined (ESTRPIPE)
329 ENTRY(ESTRPIPE
, "ESTRPIPE", "Streams pipe error"),
331 #if defined (ENOTEMPTY)
332 ENTRY(ENOTEMPTY
, "ENOTEMPTY", "Directory not empty"),
335 ENTRY(EUSERS
, "EUSERS", "Too many users"),
337 #if defined (ENOTSOCK)
338 ENTRY(ENOTSOCK
, "ENOTSOCK", "Socket operation on non-socket"),
340 #if defined (EDESTADDRREQ)
341 ENTRY(EDESTADDRREQ
, "EDESTADDRREQ", "Destination address required"),
343 #if defined (EMSGSIZE)
344 ENTRY(EMSGSIZE
, "EMSGSIZE", "Message too long"),
346 #if defined (EPROTOTYPE)
347 ENTRY(EPROTOTYPE
, "EPROTOTYPE", "Protocol wrong type for socket"),
349 #if defined (ENOPROTOOPT)
350 ENTRY(ENOPROTOOPT
, "ENOPROTOOPT", "Protocol option not available"),
352 #if defined (EPROTONOSUPPORT)
353 ENTRY(EPROTONOSUPPORT
, "EPROTONOSUPPORT", "Protocol not supported"),
355 #if defined (ESOCKTNOSUPPORT)
356 ENTRY(ESOCKTNOSUPPORT
, "ESOCKTNOSUPPORT", "Socket type not supported"),
358 #if defined (EOPNOTSUPP)
359 ENTRY(EOPNOTSUPP
, "EOPNOTSUPP", "Operation not supported on transport endpoint"),
361 #if defined (EPFNOSUPPORT)
362 ENTRY(EPFNOSUPPORT
, "EPFNOSUPPORT", "Protocol family not supported"),
364 #if defined (EAFNOSUPPORT)
365 ENTRY(EAFNOSUPPORT
, "EAFNOSUPPORT", "Address family not supported by protocol"),
367 #if defined (EADDRINUSE)
368 ENTRY(EADDRINUSE
, "EADDRINUSE", "Address already in use"),
370 #if defined (EADDRNOTAVAIL)
371 ENTRY(EADDRNOTAVAIL
, "EADDRNOTAVAIL","Cannot assign requested address"),
373 #if defined (ENETDOWN)
374 ENTRY(ENETDOWN
, "ENETDOWN", "Network is down"),
376 #if defined (ENETUNREACH)
377 ENTRY(ENETUNREACH
, "ENETUNREACH", "Network is unreachable"),
379 #if defined (ENETRESET)
380 ENTRY(ENETRESET
, "ENETRESET", "Network dropped connection because of reset"),
382 #if defined (ECONNABORTED)
383 ENTRY(ECONNABORTED
, "ECONNABORTED", "Software caused connection abort"),
385 #if defined (ECONNRESET)
386 ENTRY(ECONNRESET
, "ECONNRESET", "Connection reset by peer"),
388 #if defined (ENOBUFS)
389 ENTRY(ENOBUFS
, "ENOBUFS", "No buffer space available"),
391 #if defined (EISCONN)
392 ENTRY(EISCONN
, "EISCONN", "Transport endpoint is already connected"),
394 #if defined (ENOTCONN)
395 ENTRY(ENOTCONN
, "ENOTCONN", "Transport endpoint is not connected"),
397 #if defined (ESHUTDOWN)
398 ENTRY(ESHUTDOWN
, "ESHUTDOWN", "Cannot send after transport endpoint shutdown"),
400 #if defined (ETOOMANYREFS)
401 ENTRY(ETOOMANYREFS
, "ETOOMANYREFS", "Too many references: cannot splice"),
403 #if defined (ETIMEDOUT)
404 ENTRY(ETIMEDOUT
, "ETIMEDOUT", "Connection timed out"),
406 #if defined (ECONNREFUSED)
407 ENTRY(ECONNREFUSED
, "ECONNREFUSED", "Connection refused"),
409 #if defined (EHOSTDOWN)
410 ENTRY(EHOSTDOWN
, "EHOSTDOWN", "Host is down"),
412 #if defined (EHOSTUNREACH)
413 ENTRY(EHOSTUNREACH
, "EHOSTUNREACH", "No route to host"),
415 #if defined (EALREADY)
416 ENTRY(EALREADY
, "EALREADY", "Operation already in progress"),
418 #if defined (EINPROGRESS)
419 ENTRY(EINPROGRESS
, "EINPROGRESS", "Operation now in progress"),
422 ENTRY(ESTALE
, "ESTALE", "Stale NFS file handle"),
424 #if defined (EUCLEAN)
425 ENTRY(EUCLEAN
, "EUCLEAN", "Structure needs cleaning"),
427 #if defined (ENOTNAM)
428 ENTRY(ENOTNAM
, "ENOTNAM", "Not a XENIX named type file"),
430 #if defined (ENAVAIL)
431 ENTRY(ENAVAIL
, "ENAVAIL", "No XENIX semaphores available"),
434 ENTRY(EISNAM
, "EISNAM", "Is a named type file"),
436 #if defined (EREMOTEIO)
437 ENTRY(EREMOTEIO
, "EREMOTEIO", "Remote I/O error"),
443 /* This is not in the table, because the numeric value of EVMSERR (32767)
444 lies outside the range of sys_errlist[]. */
445 static struct { int value
; const char *name
, *msg
; }
446 evmserr
= { EVMSERR
, "EVMSERR", "VMS-specific error" };
449 /* Translation table allocated and initialized at runtime. Indexed by the
450 errno value to find the equivalent symbolic value. */
452 static const char **error_names
;
453 static int num_error_names
= 0;
455 /* Translation table allocated and initialized at runtime, if it does not
456 already exist in the host environment. Indexed by the errno value to find
457 the descriptive string.
459 We don't export it for use in other modules because even though it has the
460 same name, it differs from other implementations in that it is dynamically
461 initialized rather than statically initialized. */
463 #ifndef HAVE_SYS_ERRLIST
465 #define sys_nerr sys_nerr__
466 #define sys_errlist sys_errlist__
468 static const char **sys_errlist
;
473 extern char *sys_errlist
[];
481 init_error_tables -- initialize the name and message tables
485 static void init_error_tables ();
489 Using the error_table, which is initialized at compile time, generate
490 the error_names and the sys_errlist (if needed) tables, which are
491 indexed at runtime by a specific errno value.
495 The initialization of the tables may fail under low memory conditions,
496 in which case we don't do anything particularly useful, but we don't
497 bomb either. Who knows, it might succeed at a later point if we free
498 some memory in the meantime. In any case, the other routines know
499 how to deal with lack of a table after trying to initialize it. This
500 may or may not be considered to be a bug, that we don't specifically
501 warn about this particular failure mode.
506 init_error_tables (void)
508 const struct error_info
*eip
;
511 /* If we haven't already scanned the error_table once to find the maximum
512 errno value, then go find it now. */
514 if (num_error_names
== 0)
516 for (eip
= error_table
; eip
-> name
!= NULL
; eip
++)
518 if (eip
-> value
>= num_error_names
)
520 num_error_names
= eip
-> value
+ 1;
525 /* Now attempt to allocate the error_names table, zero it out, and then
526 initialize it from the statically initialized error_table. */
528 if (error_names
== NULL
)
530 nbytes
= num_error_names
* sizeof (char *);
531 if ((error_names
= (const char **) malloc (nbytes
)) != NULL
)
533 memset (error_names
, 0, nbytes
);
534 for (eip
= error_table
; eip
-> name
!= NULL
; eip
++)
536 error_names
[eip
-> value
] = eip
-> name
;
541 #ifndef HAVE_SYS_ERRLIST
543 /* Now attempt to allocate the sys_errlist table, zero it out, and then
544 initialize it from the statically initialized error_table. */
546 if (sys_errlist
== NULL
)
548 nbytes
= num_error_names
* sizeof (char *);
549 if ((sys_errlist
= (const char **) malloc (nbytes
)) != NULL
)
551 memset (sys_errlist
, 0, nbytes
);
552 sys_nerr
= num_error_names
;
553 for (eip
= error_table
; eip
-> name
!= NULL
; eip
++)
555 sys_errlist
[eip
-> value
] = eip
-> msg
;
567 @deftypefn Extension int errno_max (void)
569 Returns the maximum @code{errno} value for which a corresponding
570 symbolic name or message is available. Note that in the case where we
571 use the @code{sys_errlist} supplied by the system, it is possible for
572 there to be more symbolic names than messages, or vice versa. In
573 fact, the manual page for @code{perror(3C)} explicitly warns that one
574 should check the size of the table (@code{sys_nerr}) before indexing
575 it, since new error codes may be added to the system before they are
576 added to the table. Thus @code{sys_nerr} might be smaller than value
577 implied by the largest @code{errno} value defined in @code{<errno.h>}.
579 We return the maximum value that can be used to obtain a meaningful
580 symbolic name or message.
591 if (error_names
== NULL
)
593 init_error_tables ();
595 maxsize
= MAX (sys_nerr
, num_error_names
);
596 return (maxsize
- 1);
599 #ifndef HAVE_STRERROR
603 @deftypefn Supplemental char* strerror (int @var{errnoval})
605 Maps an @code{errno} number to an error message string, the contents
606 of which are implementation defined. On systems which have the
607 external variables @code{sys_nerr} and @code{sys_errlist}, these
608 strings will be the same as the ones used by @code{perror}.
610 If the supplied error number is within the valid range of indices for
611 the @code{sys_errlist}, but no message is available for the particular
612 error number, then returns the string @samp{Error @var{num}}, where
613 @var{num} is the error number.
615 If the supplied error number is not a valid index into
616 @code{sys_errlist}, returns @code{NULL}.
618 The returned string is only guaranteed to be valid only until the
619 next call to @code{strerror}.
626 strerror (int errnoval
)
631 #ifndef HAVE_SYS_ERRLIST
633 if (error_names
== NULL
)
635 init_error_tables ();
640 if ((errnoval
< 0) || (errnoval
>= sys_nerr
))
643 if (errnoval
== evmserr
.value
)
647 /* Out of range, just return NULL */
650 else if ((sys_errlist
== NULL
) || (sys_errlist
[errnoval
] == NULL
))
652 /* In range, but no sys_errlist or no entry at this index. */
653 sprintf (buf
, "Error %d", errnoval
);
658 /* In range, and a valid message. Just return the message. */
659 msg
= (char *) sys_errlist
[errnoval
];
665 #endif /* ! HAVE_STRERROR */
670 @deftypefn Replacement {const char*} strerrno (int @var{errnum})
672 Given an error number returned from a system call (typically returned
673 in @code{errno}), returns a pointer to a string containing the
674 symbolic name of that error number, as found in @code{<errno.h>}.
676 If the supplied error number is within the valid range of indices for
677 symbolic names, but no name is available for the particular error
678 number, then returns the string @samp{Error @var{num}}, where @var{num}
681 If the supplied error number is not within the range of valid
682 indices, then returns @code{NULL}.
684 The contents of the location pointed to are only guaranteed to be
685 valid until the next call to @code{strerrno}.
692 strerrno (int errnoval
)
697 if (error_names
== NULL
)
699 init_error_tables ();
702 if ((errnoval
< 0) || (errnoval
>= num_error_names
))
705 if (errnoval
== evmserr
.value
)
709 /* Out of range, just return NULL */
712 else if ((error_names
== NULL
) || (error_names
[errnoval
] == NULL
))
714 /* In range, but no error_names or no entry at this index. */
715 sprintf (buf
, "Error %d", errnoval
);
716 name
= (const char *) buf
;
720 /* In range, and a valid name. Just return the name. */
721 name
= error_names
[errnoval
];
729 @deftypefn Extension int strtoerrno (const char *@var{name})
731 Given the symbolic name of a error number (e.g., @code{EACCES}), map it
732 to an errno value. If no translation is found, returns 0.
739 strtoerrno (const char *name
)
745 if (error_names
== NULL
)
747 init_error_tables ();
749 for (errnoval
= 0; errnoval
< num_error_names
; errnoval
++)
751 if ((error_names
[errnoval
] != NULL
) &&
752 (strcmp (name
, error_names
[errnoval
]) == 0))
757 if (errnoval
== num_error_names
)
760 if (strcmp (name
, evmserr
.name
) == 0)
761 errnoval
= evmserr
.value
;
771 /* A simple little main that does nothing but print all the errno translations
772 if MAIN is defined and this file is compiled and linked. */
787 errnmax
= errno_max ();
788 printf ("%d entries in names table.\n", num_error_names
);
789 printf ("%d entries in messages table.\n", sys_nerr
);
790 printf ("%d is max useful index.\n", errnmax
);
792 /* Keep printing values until we get to the end of *both* tables, not
793 *either* table. Note that knowing the maximum useful index does *not*
794 relieve us of the responsibility of testing the return pointer for
797 for (errn
= 0; errn
<= errnmax
; errn
++)
799 name
= strerrno (errn
);
800 name
= (name
== NULL
) ? "<NULL>" : name
;
801 msg
= strerror (errn
);
802 msg
= (msg
== NULL
) ? "<NULL>" : msg
;
803 printf ("%-4d%-18s%s\n", errn
, name
, msg
);