aboutsummaryrefslogtreecommitdiffstats
path: root/util/system/error.cpp
blob: f778ec42cbe5c32abbe8e12f215afca22e20a810 (plain) (blame)
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
#include "tls.h"
#include "error.h"

#include <util/string/strip.h>
#include <util/generic/strfcpy.h>

#include <cerrno>
#include <cstdio>
#include <cstring>

#if defined(_win_)
    #include <util/network/socket.h>
    #include <util/generic/singleton.h>
    #include "winint.h"
#elif defined(_unix_)
    #include <unistd.h>
#endif

void ClearLastSystemError() {
#if defined(_win_)
    SetLastError(0);
#else
    errno = 0;
#endif
}

int LastSystemError() {
#if defined(_win_)
    int ret = GetLastError();

    if (ret)
        return ret;

    ret = WSAGetLastError();

    if (ret)
        return ret;
    // when descriptors number are over maximum, errno set in this variable
    ret = *(_errno());
    return ret;

#else
    return errno;
#endif
}

#if defined(_win_)
namespace {
    struct TErrString {
        inline TErrString() noexcept {
            data[0] = 0;
        }

        char data[1024];
    };
}
#endif

const char* LastSystemErrorText(int code) {
#if defined(_win_)
    TErrString& text(*Singleton<TErrString>());
    LastSystemErrorText(text.data, sizeof(text.data), code);

    return text.data;
#else
    return strerror(code);
#endif
}

#ifdef _win_
static char* Strip(char* s) {
    size_t len = strlen(s);
    const char* ptr = s;
    Strip(ptr, len);
    if (ptr != s)
        memmove(s, ptr, len);
    s[len] = 0;
    return s;
}
#endif // _win_

void LastSystemErrorText(char* str, size_t size, int code) {
#if defined(_win_)
    FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0, code, 0, str, DWORD(size), 0);
    Strip(str);
#elif defined(_sun_)
    strfcpy(str, strerror(code), size);
#elif defined(_freebsd_) || defined(_darwin_) || defined(_musl_) || defined(_bionic_)
    strerror_r(code, str, size);
#elif defined(_linux_) | defined(_cygwin_)
    char* msg = strerror_r(code, str, size);
    strncpy(str, msg, size);
#else
    #error port me gently!
#endif
}