Is there any function in UNIX to the convert errno to its corresponding string for e.g. EIDRM to "EIDRM". Its very annoying to debug to check for errors with these integer errnos.
6 Answers
strerror() should do it. http://linux.die.net/man/3/strerror
FYI, so that you can find these things more easily, yourself: If you type man errno (or whatever function you're investigating), and look at the very bottom of the man page, you'll see a list of related functions. If you man each of those (taking a guess about which one(s) to do first based on their names) you'll often find the answer to similar questions.
- 9,064
- 3
- 30
- 32
-
1strerror will actually turn them into much more useful strings than just "EIDRM" as the op asked, but that's the answer I would have given too. – Paul Tomblin Oct 10 '09 at 02:48
-
4those strings are actually not that useful, because the man pages for the system calls often specify error behaviors in terms of the enum code. The string is at best a hint. – orm Jan 06 '16 at 21:05
-
2Danger, Will Robinson! `strerror()`'s strings are _localised_, as I found out when I was checking an error string for "No such file or directory" but my user's platform was returning "Arquivo ou diretório não encontrado" instead. (This was in a language where the errno value itself wasn't exposed.) – David Given Feb 25 '16 at 23:21
-
@orm Yeah, those strings are very useful for beginner users in the common cases, but beyond a certain point those hints can be unhelpful or even misleading. – mtraceur Aug 11 '19 at 07:11
-
@davidgiven It sounds like you ran into exactly the kind of uses that led me to write [the `errnoname` library](https://github.com/mentalisttraceur/errnoname): having to parse error strings programmatically because that was the only form that the error information was being made available in. For me the biggest offenders are tools like `rm`, `mv`, and the iproute2 commands, all of which lack other ways to distinguish for example errors that actually mean idempotent success from other errors. Now we just have to convince everyone to put `errno` names in parsable ways into their error messages. – mtraceur Aug 11 '19 at 07:18
Just another solution that solves exactly the problem you have, but in Python instead of C:
>>> import errno
>>> errno.errorcode[errno.EIDRM]
'EIDRM'
- 16,003
- 7
- 41
- 61
-
1This is a good answer, but worth knowing that Python only includes a subset of all possible `errno` values, so on some systems, it won't have entries for all of them. For typical cases this is a non-issue, but if you are using this as a generic way to look up error codes, you may run into this. – mtraceur Aug 11 '19 at 07:23
There's now an errno utility distributed with the moreutils package.
$ errno -h
Usage: errno [-lsS] [--list] [--search] [--search-all-locales] [keyword]
$ errno -l
EPERM 1 Operation not permitted
ENOENT 2 No such file or directory
ESRCH 3 No such process
EINTR 4 Interrupted system call
EIO 5 Input/output error
ENXIO 6 No such device or address
E2BIG 7 Argument list too long
ENOEXEC 8 Exec format error
...
$ errno 11
EAGAIN 11 Resource temporarily unavailable
$ errno -s Ouput
EIO 5 Input/output error
- 5
- 3
- 2,334
- 1
- 25
- 32
I'm not sure about such enum-style names, but for debugging and error reporting purposes you may use perror(3) or strerror(3) C functions that return a human-readable representation of the error code. Please refer to the man pages for more details.
- 16,003
- 7
- 41
- 61
-
I thought perror() just prints to STDERR rather than converting the number to a value. Do I misremember (and misread the man page)? – atk Oct 10 '09 at 02:53
-
Yes, `perror` is a debugging facility for `errno`-related issues and it writes its messages to `STDERR`. – Andrey Vlasovskikh Oct 10 '09 at 02:55
If you do indeed want EIDRM and not its error string: no. However, on OpenBSD,
man errno|egrep ' [0-9]+ E[A-Z]+'|sed 's/^ *//'|cut -d' ' -f1,2
prints out a nice table of "...\n89 EIDM\n..." that you can convert further into a data structure for the programming language that you'd like to have this function in.
- 1,769
- 13
- 15
There is no standard function to do this in UNIX.
But I recently wrote the errnoname library that has an errnoname function which does exactly this.
strerror (also strerror_r, strerror_l, perror) print a "human friendly" hint about what the error was, but their outputs are
- usually undocumented,
- not standardized,
- not guaranteed to follow any constrains on length or format,
- often different depending on locale settings, and
- do not always make sense in all situations (for example they tend to print
File existsforEEXIST, even though that error is often returned for things that are not files).
Which means that they are superficially user-friendly but
- other code cannot parse them as reliably (worse for automation, monitoring, scripting, wrapper programs, etc),
- can mislead in the edge cases, and
- get in the way of technical experienced users.
Ironically there is nothing preventing those functions from just using the errno symbolic name as their error string in all circumstances - it would be within the letter of the standard, especially if they only did it for a specific locale, like the special C locale. But no libc I know of does this.
Anyway, since my errnoname is released under the "Zero-Clause BSD license" (0BSD), which is a permissive license, or more accurately a public-domain-equivalent license, you can do whatever you want with it.
To make this answer stand alone, while still fitting within the answer character limits, below are two abbreviated variants of the errnoname function.
In errnoname they are both implemented, but here I've separated out the gist of each to make them more readable.
Couple of notes:
This covers all or most of
errnonames for Linux, Darwin (Mac OS X and iOS X), FreeBSD, NetBSD, OpenBSD, DragonflyBSD, and several closed source Unixes, as of start of January 2020.It returns a null pointer if you give it an
errnovalue it does not know the name of.
Variant 1: Simple, Universal
This one is very portable and simple with no edge-cases to worry about. It will compile with just about any C89 or better compiler you can throw at it. (Probably even C++ compilers, which is becoming more rare as the languages diverge.)
This variant can compile to very efficient code (an array lookup instead of a switch statement) on modern compilers when the optimizations are turned up high enough, but might not depending on the exact situation.
#include <errno.h>
char const * errnoname(int errno_)
{
switch(errno_)
{
#ifdef E2BIG
case E2BIG: return "E2BIG";
#endif
#ifdef EACCES
case EACCES: return "EACCES";
#endif
/*
repeat for the other 100+ errno names,
don't forget to handle possible duplicates
like EAGAIN and EWOULDBLOCK
*/
}
return 0;
}
Variant 2: Explicitly Efficient, Good For Most Systems
This one is more obviously efficient, and will compile to efficient code very reliably, because it makes the array lookup explicit and does not depend on the computer optimizations.
It is safe to use so long as the system has positive, relatively small, and reasonably contiguous errno values.
Can only compile on compilers that implement out-of-order designated initializers for arrays (C99 or better, excluding all C++ versions so far.)
#include <errno.h>
char const * errnoname(int errno_)
{
static char const * const names[] =
{
#ifdef E2BIG
[E2BIG] = "E2BIG",
#endif
#ifdef EACCES
[EACCES] = "EACCES",
#endif
/*
repeat for the other 100+ errno names,
don't forget to handle possible duplicates
like EAGAIN and EWOULDBLOCK
*/
};
if(errno_ >= 0 && errno_ < (sizeof(names) / sizeof(*names)))
{
return names[errno_];
}
return 0;
}
- 2,433
- 18
- 28
-
Nice idea to have an errnoname() function but too bad it's using a switch-case. For error-handling it might be good, BUT for other purposes like a tracer it's unnecessarily sub-optimal. You should have created a big array, using errno codes as indexes. I mean, using the syntax { ..., [index] = value, ... }. Of course you can have holes there as well. – vvaltchev Dec 29 '19 at 18:29
-
1@vvaltchev I've now added an array-based implementation as an option (activated by defining `ERRNONAME_SAFE_TO_USE_ARRAY` when compiling) to [errnoname](https://github.com/mentalisttraceur/errnoname). (Documented in the [Optimization](https://github.com/mentalisttraceur/errnoname#optimization) section.) Thank you for bringing it up. I was waiting to hear if there was demand for the array-based approach before revisting how I wanted to tackle it. – mtraceur Dec 30 '19 at 11:35
-
Good job, man! Your project earned its first GitHub star :-) I implemented a custom solution for my case (I needed only Linux errno codes), but it's still is good to know that you added that feature. Anyway, yeah, I understand the concern that *theoretically* there might exist big errno codes on some system, but in practice on all the UNIX systems I've ever seen in my life, they are just almost sequential numbers, typically less than a few hundred in total. @mtraceur – vvaltchev Dec 30 '19 at 17:13
-
@vvaltchev On further testing: I have a gcc 4.8.5 (released five years ago) lying around, and it manages to optimise the switch version into an array lookup automatically with either `-O2`, `-O3`, or `-Os` optimization flags. (This is on an ARMv7 Linux device, where `errno` are strictly contiguous. It hilariously then fails to combine a pair of `sub r0, r0, #1` and `cmp r0, #132` instructions into one `cmp r0, #133` instruction, but other than that the switch-based and array-based C code generate identical machine code.) – mtraceur Jan 19 '20 at 16:11
-
I think that one instruction difference is because it decided to make the array 132 elements, where the 0th index is the 1st errno, instead of the manual array version where the 1st index is the 1st errno. Notably, manually adding a `case 0: return 0` did not change the result - so I guess the optimizer is making its decision on an abstract form of the logic which has already recognized that the zero-case is the same as any other out-of-bounds case, and which precludes it from heuristically noticing that one extra array entry is probably more efficient than one always-executed instruction. – mtraceur Jan 19 '20 at 16:33
-
Modern clang 9.0.1 for aarch64 Linux exhibits the same behavior - identical code, but for the choice of the array starting from the first errno and thus needing `sub` then `cmp` instead of just `cmp`. – mtraceur Jan 19 '20 at 17:08
-
I could have sworn I tested with higher optimizations turned on and didn't see the switch cases get turned into array lookups. But apparently I must have messed up, and only tested with optimizations "turned off" (anything below `-O2` is basically willfully making our code inefficient and is unsuitable for reasoning about how to optimize at the source code level, but apparently I slipped up and did just that). I think I maybe assumed @vvaltchev's criticism came from a place of having already tried `-O2` or better, but in any case it's my fault for missing that earlier. – mtraceur Jan 19 '20 at 17:14
-
I must admit - if I had known for sure that `-O2` or better even five years ago was already turning switch statements like that into array lookups, I maybe would have just left it as just a simple switch statement, and not implemented a second array-based variant. However, the explicit array-based variant is nice to have as an option for edge-cases where such compiler optimizations are not available or do not kick in (such as if there is a gap in `errno` values, or too many gaps, or too large of a gap, but human judgment still shows it being better to do an array lookup.) – mtraceur Jan 19 '20 at 17:22
-
@vvaltchev - oh, in reply to your original reply, thanks! I was glad to see your response. Yeah, implementing your own is probably the better and simpler thing to do when you know you are only supporting a specific well-known fixed set of systems or `errno` names. (And you are right that all `errno` values will be small and contiguous on typical systems for typical uses. Other downsides of the array-based variant include f.e. it being more likely to be subtly wrong due to human error and requiring more careful thought to verify correctly, even though I did it correctly as far as I can tell.) – mtraceur Jan 19 '20 at 18:07