1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-02-13 20:01:56 +00:00
srs/trunk/3rdparty/srt-1-fit/srtcore/srt_compat.c

141 lines
4.8 KiB
C
Raw Normal View History

/*
* SRT - Secure, Reliable, Transport
* Copyright (c) 2018 Haivision Systems Inc.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
*/
// Implementation file for srt_compat.h
/*****************************************************************************
written by
Haivision Systems Inc.
*****************************************************************************/
// Prevents from misconfiguration through preprocessor.
#include <srt_compat.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#if defined(__unix__) && !defined(BSD)
#include <features.h>
#endif
#if defined(_WIN32)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif
static const char* SysStrError_Fallback(int errnum, char* buf, size_t buflen)
{
#if defined(_MSC_VER) && _MSC_VER < 1900
_snprintf(buf, buflen - 1, "ERROR CODE %d", errnum);
buf[buflen - 1] = '\0';
#else
snprintf(buf, buflen, "ERROR CODE %d", errnum);
#endif
return buf;
}
// This function is a portable and thread-safe version of `strerror`.
// It requires a user-supplied buffer to store the message. The returned
// value is always equal to the given buffer pointer. If the system
// error message is longer than the given buflen, it will be trimmed.
// When the error code is incorrect for the given error message function,
// a fallback message will be returned, either as returned by the underlying
// function, or crafted by this function as a response to error in an
// underlying function.
extern const char * SysStrError(int errnum, char * buf, size_t buflen)
{
if (buf == NULL || buflen < 4) // Required to put ??? into it as a fallback
{
errno = EFAULT;
return buf;
}
buf[0] = '\0';
#if defined(_WIN32)
const char* lpMsgBuf;
// Note: Intentionally the "fixed char size" types are used despite using
// character size dependent FormatMessage (instead of FormatMessageA) so that
// your compilation fails when you use wide characters.
// The problem is that when TCHAR != char, then the buffer written this way
// would have to be converted to ASCII, not just copied by strncpy.
FormatMessage(0
| FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_SYSTEM
| FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, // no lpSource
errnum, // dwMessageId (as controlled by FORMAT_MESSAGE_FROM_SYSTEM)
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
// This below parameter normally should contain a pointer to an allocated buffer,
// and this way it's LPTSTR. But when FORMAT_MESSAGE_ALLOCATE_BUFFER, then it is
// expected to be a the value of LPTSTR* type, converted to LPTSTR, that designates
// a pointer to a variable of type LPTSTR, to which the newly allocated buffer is
// assigned. This buffer should be freed afterwards using LocalFree().
(LPSTR)&lpMsgBuf,
0, NULL);
if (lpMsgBuf)
{
strncpy(buf, lpMsgBuf, buflen-1);
buf[buflen-1] = 0;
LocalFree((HLOCAL)lpMsgBuf);
}
else
{
SysStrError_Fallback(errnum, buf, buflen);
}
return buf;
#elif (!defined(__GNU_LIBRARY__) && !defined(__GLIBC__) ) \
|| (( (_POSIX_C_SOURCE >= 200112L) || (_XOPEN_SOURCE >= 600)) && ! _GNU_SOURCE )
// POSIX/XSI-compliant version.
// Overall general POSIX version: returns status.
// 0 for success, otherwise it's:
// - possibly -1 and the error code is in ::errno
// - possibly the error code itself
// The details of the errror are not interesting; simply
// craft a fallback message in this case.
if (strerror_r(errnum, buf, buflen) != 0)
{
return SysStrError_Fallback(errnum, buf, buflen);
}
return buf;
#else
// GLIBC is non-standard under these conditions.
// GNU version: returns the pointer to the message.
// This is either equal to the local buffer (buf)
// or some system-wide (constant) storage. To maintain
// stability of the API, this overall function shall
// always return the local buffer and the message in
// this buffer - so these cases should be distinguished
// and the internal storage copied to the buffer.
char * gnu_buffer = strerror_r(errnum, buf, buflen);
if (!gnu_buffer)
{
// This should never happen, so just a paranoid check
return SysStrError_Fallback(errnum, buf, buflen);
}
// If they are the same, the message is already copied
// (and it's usually a "fallback message" for an error case).
if (gnu_buffer != buf)
{
strncpy(buf, gnu_buffer, buflen-1);
buf[buflen-1] = 0; // guarantee what strncpy doesn't
}
return buf;
#endif
}