Line data Source code
1 : #define STRERROR_OVERRIDE_IMPL 1
2 : #include "strerror_override.h"
3 :
4 : /*
5 : * Override strerror() to get consistent output across platforms.
6 : */
7 :
8 : static struct
9 : {
10 : int errno_value;
11 : const char *errno_str;
12 : } errno_list[] = {
13 : /* clang-format off */
14 : #define STRINGIFY(x) #x
15 : #define ENTRY(x) {x, &STRINGIFY(undef_ ## x)[6]}
16 : ENTRY(EPERM),
17 : ENTRY(ENOENT),
18 : ENTRY(ESRCH),
19 : ENTRY(EINTR),
20 : ENTRY(EIO),
21 : ENTRY(ENXIO),
22 : ENTRY(E2BIG),
23 : #ifdef ENOEXEC
24 : ENTRY(ENOEXEC),
25 : #endif
26 : ENTRY(EBADF),
27 : ENTRY(ECHILD),
28 : ENTRY(EDEADLK),
29 : ENTRY(ENOMEM),
30 : ENTRY(EACCES),
31 : ENTRY(EFAULT),
32 : #ifdef ENOTBLK
33 : ENTRY(ENOTBLK),
34 : #endif
35 : ENTRY(EBUSY),
36 : ENTRY(EEXIST),
37 : ENTRY(EXDEV),
38 : ENTRY(ENODEV),
39 : ENTRY(ENOTDIR),
40 : ENTRY(EISDIR),
41 : ENTRY(EINVAL),
42 : ENTRY(ENFILE),
43 : ENTRY(EMFILE),
44 : ENTRY(ENOTTY),
45 : #ifdef ETXTBSY
46 : ENTRY(ETXTBSY),
47 : #endif
48 : ENTRY(EFBIG),
49 : ENTRY(ENOSPC),
50 : ENTRY(ESPIPE),
51 : ENTRY(EROFS),
52 : ENTRY(EMLINK),
53 : ENTRY(EPIPE),
54 : ENTRY(EDOM),
55 : ENTRY(ERANGE),
56 : ENTRY(EAGAIN),
57 : { 0, (char *)0 }
58 : };
59 : /* clang-format on */
60 :
61 : // Enabled during tests
62 : static int _json_c_strerror_enable = 0;
63 : extern char *getenv(const char *name); // Avoid including stdlib.h
64 :
65 : #define PREFIX "ERRNO="
66 : static char errno_buf[128] = PREFIX;
67 0 : char *_json_c_strerror(int errno_in)
68 : {
69 : int start_idx;
70 : char digbuf[20];
71 : int ii, jj;
72 :
73 0 : if (!_json_c_strerror_enable)
74 0 : _json_c_strerror_enable = (getenv("_JSON_C_STRERROR_ENABLE") == NULL) ? -1 : 1;
75 0 : if (_json_c_strerror_enable == -1)
76 0 : return strerror(errno_in);
77 :
78 : // Avoid standard functions, so we don't need to include any
79 : // headers, or guess at signatures.
80 :
81 0 : for (ii = 0; errno_list[ii].errno_str != (char *)0; ii++)
82 : {
83 0 : const char *errno_str = errno_list[ii].errno_str;
84 0 : if (errno_list[ii].errno_value != errno_in)
85 0 : continue;
86 :
87 0 : for (start_idx = sizeof(PREFIX) - 1, jj = 0; errno_str[jj] != '\0';
88 0 : jj++, start_idx++)
89 : {
90 0 : errno_buf[start_idx] = errno_str[jj];
91 : }
92 0 : errno_buf[start_idx] = '\0';
93 0 : return errno_buf;
94 : }
95 :
96 : // It's not one of the known errno values, return the numeric value.
97 0 : for (ii = 0; errno_in > 10; errno_in /= 10, ii++)
98 : {
99 0 : digbuf[ii] = "0123456789"[(errno_in % 10)];
100 : }
101 0 : digbuf[ii] = "0123456789"[(errno_in % 10)];
102 :
103 : // Reverse the digits
104 0 : for (start_idx = sizeof(PREFIX) - 1; ii >= 0; ii--, start_idx++)
105 : {
106 0 : errno_buf[start_idx] = digbuf[ii];
107 : }
108 0 : return errno_buf;
109 : }
|