mirror of
				https://github.com/ossrs/srs.git
				synced 2025-03-09 15:49:59 +00:00 
			
		
		
		
	fix https://github.com/ossrs/srs/issues/3155 Build srt-1-fit fails with `standard attributes in middle of decl-specifiers` on GCC 12,Arch Linux. See https://github.com/Haivision/srt/releases/tag/v1.5.3
		
			
				
	
	
		
			146 lines
		
	
	
	
		
			4.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			146 lines
		
	
	
	
		
			4.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * 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 "platform_sys.h"
 | 
						|
 | 
						|
#include <srt_compat.h>
 | 
						|
 | 
						|
#include <string.h>
 | 
						|
#include <stdio.h>
 | 
						|
#include <errno.h>
 | 
						|
#if defined(__unix__) && !defined(BSD) && !defined(SUNOS)
 | 
						|
#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.
 | 
						|
    FormatMessageA(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)
 | 
						|
    {
 | 
						|
#ifdef _MSC_VER
 | 
						|
        strncpy_s(buf, buflen, lpMsgBuf, _TRUNCATE);
 | 
						|
#else
 | 
						|
        strncpy(buf, lpMsgBuf, buflen-1);
 | 
						|
        buf[buflen-1] = 0;
 | 
						|
#endif
 | 
						|
        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
 | 
						|
}
 |