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