/src/json-c/strerror_override.c
Line | Count | Source (jump to first uncovered line) |
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 | 0 | #define PREFIX "ERRNO=" |
66 | | static char errno_buf[128] = PREFIX; |
67 | | char *_json_c_strerror(int errno_in) |
68 | 0 | { |
69 | 0 | int start_idx; |
70 | 0 | char digbuf[20]; |
71 | 0 | 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 | 0 | { |
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 | 0 | { |
90 | 0 | errno_buf[start_idx] = errno_str[jj]; |
91 | 0 | } |
92 | 0 | errno_buf[start_idx] = '\0'; |
93 | 0 | return errno_buf; |
94 | 0 | } |
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 | 0 | { |
99 | 0 | digbuf[ii] = "0123456789"[(errno_in % 10)]; |
100 | 0 | } |
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 | 0 | { |
106 | 0 | errno_buf[start_idx] = digbuf[ii]; |
107 | 0 | } |
108 | 0 | errno_buf[start_idx] = '\0'; |
109 | 0 | return errno_buf; |
110 | 0 | } |