Bump to 0.17
[platform/upstream/json-c.git] / strerror_override.c
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 char *_json_c_strerror(int errno_in)
68 {
69         int start_idx;
70         char digbuf[20];
71         int ii, jj;
72
73         if (!_json_c_strerror_enable)
74                 _json_c_strerror_enable = (getenv("_JSON_C_STRERROR_ENABLE") == NULL) ? -1 : 1;
75         if (_json_c_strerror_enable == -1)
76                 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         for (ii = 0; errno_list[ii].errno_str != (char *)0; ii++)
82         {
83                 const char *errno_str = errno_list[ii].errno_str;
84                 if (errno_list[ii].errno_value != errno_in)
85                         continue;
86
87                 for (start_idx = sizeof(PREFIX) - 1, jj = 0; errno_str[jj] != '\0';
88                      jj++, start_idx++)
89                 {
90                         errno_buf[start_idx] = errno_str[jj];
91                 }
92                 errno_buf[start_idx] = '\0';
93                 return errno_buf;
94         }
95
96         // It's not one of the known errno values, return the numeric value.
97         for (ii = 0; errno_in >= 10; errno_in /= 10, ii++)
98         {
99                 digbuf[ii] = "0123456789"[(errno_in % 10)];
100         }
101         digbuf[ii] = "0123456789"[(errno_in % 10)];
102
103         // Reverse the digits
104         for (start_idx = sizeof(PREFIX) - 1; ii >= 0; ii--, start_idx++)
105         {
106                 errno_buf[start_idx] = digbuf[ii];
107         }
108         errno_buf[start_idx] = '\0';
109         return errno_buf;
110 }