#include "error.h"
#include <util/generic/strfcpy.h>
#include <cerrno>
#include <cstring>
#if defined(_win_)
#include <util/string/strip.h>
#include <util/network/socket.h>
#include <util/generic/singleton.h>
#include "winint.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
}