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 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
;
477 extern char *sys_errlist
[];
486 init_error_tables -- initialize the name and message tables
490 static void init_error_tables ();
494 Using the error_table, which is initialized at compile time, generate
495 the error_names and the sys_errlist (if needed) tables, which are
496 indexed at runtime by a specific errno value.
500 The initialization of the tables may fail under low memory conditions,
501 in which case we don't do anything particularly useful, but we don't
502 bomb either. Who knows, it might succeed at a later point if we free
503 some memory in the meantime. In any case, the other routines know
504 how to deal with lack of a table after trying to initialize it. This
505 may or may not be considered to be a bug, that we don't specifically
506 warn about this particular failure mode.
511 init_error_tables (void)
513 const struct error_info
*eip
;
516 /* If we haven't already scanned the error_table once to find the maximum
517 errno value, then go find it now. */
519 if (num_error_names
== 0)
521 for (eip
= error_table
; eip
-> name
!= NULL
; eip
++)
523 if (eip
-> value
>= num_error_names
)
525 num_error_names
= eip
-> value
+ 1;
530 /* Now attempt to allocate the error_names table, zero it out, and then
531 initialize it from the statically initialized error_table. */
533 if (error_names
== NULL
)
535 nbytes
= num_error_names
* sizeof (char *);
536 if ((error_names
= (const char **) malloc (nbytes
)) != NULL
)
538 memset (error_names
, 0, nbytes
);
539 for (eip
= error_table
; eip
-> name
!= NULL
; eip
++)
541 error_names
[eip
-> value
] = eip
-> name
;
546 #ifndef HAVE_SYS_ERRLIST
548 /* Now attempt to allocate the sys_errlist table, zero it out, and then
549 initialize it from the statically initialized error_table. */
551 if (sys_errlist
== NULL
)
553 nbytes
= num_error_names
* sizeof (char *);
554 if ((sys_errlist
= (const char **) malloc (nbytes
)) != NULL
)
556 memset (sys_errlist
, 0, nbytes
);
557 sys_nerr
= num_error_names
;
558 for (eip
= error_table
; eip
-> name
!= NULL
; eip
++)
560 sys_errlist
[eip
-> value
] = eip
-> msg
;
572 @deftypefn Extension int errno_max (void)
574 Returns the maximum @code{errno} value for which a corresponding
575 symbolic name or message is available. Note that in the case where we
576 use the @code{sys_errlist} supplied by the system, it is possible for
577 there to be more symbolic names than messages, or vice versa. In
578 fact, the manual page for @code{perror(3C)} explicitly warns that one
579 should check the size of the table (@code{sys_nerr}) before indexing
580 it, since new error codes may be added to the system before they are
581 added to the table. Thus @code{sys_nerr} might be smaller than value
582 implied by the largest @code{errno} value defined in @code{<errno.h>}.
584 We return the maximum value that can be used to obtain a meaningful
585 symbolic name or message.
596 if (error_names
== NULL
)
598 init_error_tables ();
600 maxsize
= MAX (sys_nerr
, num_error_names
);
601 return (maxsize
- 1);
604 #ifndef HAVE_STRERROR
608 @deftypefn Supplemental char* strerror (int @var{errnoval})
610 Maps an @code{errno} number to an error message string, the contents
611 of which are implementation defined. On systems which have the
612 external variables @code{sys_nerr} and @code{sys_errlist}, these
613 strings will be the same as the ones used by @code{perror}.
615 If the supplied error number is within the valid range of indices for
616 the @code{sys_errlist}, but no message is available for the particular
617 error number, then returns the string @samp{Error @var{num}}, where
618 @var{num} is the error number.
620 If the supplied error number is not a valid index into
621 @code{sys_errlist}, returns @code{NULL}.
623 The returned string is only guaranteed to be valid only until the
624 next call to @code{strerror}.
631 strerror (int errnoval
)
636 #ifndef HAVE_SYS_ERRLIST
638 if (error_names
== NULL
)
640 init_error_tables ();
645 if ((errnoval
< 0) || (errnoval
>= sys_nerr
))
648 if (errnoval
== evmserr
.value
)
652 /* Out of range, just return NULL */
655 else if ((sys_errlist
== NULL
) || (sys_errlist
[errnoval
] == NULL
))
657 /* In range, but no sys_errlist or no entry at this index. */
658 sprintf (buf
, "Error %d", errnoval
);
663 /* In range, and a valid message. Just return the message. */
664 msg
= (char *) sys_errlist
[errnoval
];
670 #endif /* ! HAVE_STRERROR */
675 @deftypefn Replacement {const char*} strerrno (int @var{errnum})
677 Given an error number returned from a system call (typically returned
678 in @code{errno}), returns a pointer to a string containing the
679 symbolic name of that error number, as found in @code{<errno.h>}.
681 If the supplied error number is within the valid range of indices for
682 symbolic names, but no name is available for the particular error
683 number, then returns the string @samp{Error @var{num}}, where @var{num}
686 If the supplied error number is not within the range of valid
687 indices, then returns @code{NULL}.
689 The contents of the location pointed to are only guaranteed to be
690 valid until the next call to @code{strerrno}.
697 strerrno (int errnoval
)
702 if (error_names
== NULL
)
704 init_error_tables ();
707 if ((errnoval
< 0) || (errnoval
>= num_error_names
))
710 if (errnoval
== evmserr
.value
)
714 /* Out of range, just return NULL */
717 else if ((error_names
== NULL
) || (error_names
[errnoval
] == NULL
))
719 /* In range, but no error_names or no entry at this index. */
720 sprintf (buf
, "Error %d", errnoval
);
721 name
= (const char *) buf
;
725 /* In range, and a valid name. Just return the name. */
726 name
= error_names
[errnoval
];
734 @deftypefn Extension int strtoerrno (const char *@var{name})
736 Given the symbolic name of a error number (e.g., @code{EACCES}), map it
737 to an errno value. If no translation is found, returns 0.
744 strtoerrno (const char *name
)
750 if (error_names
== NULL
)
752 init_error_tables ();
754 for (errnoval
= 0; errnoval
< num_error_names
; errnoval
++)
756 if ((error_names
[errnoval
] != NULL
) &&
757 (strcmp (name
, error_names
[errnoval
]) == 0))
762 if (errnoval
== num_error_names
)
765 if (strcmp (name
, evmserr
.name
) == 0)
766 errnoval
= evmserr
.value
;
776 /* A simple little main that does nothing but print all the errno translations
777 if MAIN is defined and this file is compiled and linked. */
792 errnmax
= errno_max ();
793 printf ("%d entries in names table.\n", num_error_names
);
794 printf ("%d entries in messages table.\n", sys_nerr
);
795 printf ("%d is max useful index.\n", errnmax
);
797 /* Keep printing values until we get to the end of *both* tables, not
798 *either* table. Note that knowing the maximum useful index does *not*
799 relieve us of the responsibility of testing the return pointer for
802 for (errn
= 0; errn
<= errnmax
; errn
++)
804 name
= strerrno (errn
);
805 name
= (name
== NULL
) ? "<NULL>" : name
;
806 msg
= strerror (errn
);
807 msg
= (msg
== NULL
) ? "<NULL>" : msg
;
808 printf ("%-4d%-18s%s\n", errn
, name
, msg
);