/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  | }  |