mirror of
https://github.com/GerbilSoft/rvthtool.git
synced 2025-06-18 11:35:33 -04:00
Use reentrant time functions if available.
Copied the following from rom-properties: - time_r.h - config.libc.h.in - CheckSymbolExistsOrInline.cmake
This commit is contained in:
parent
2a52eb5e2a
commit
4e5d89ed35
41
cmake/macros/CheckSymbolExistsOrInline.cmake
Normal file
41
cmake/macros/CheckSymbolExistsOrInline.cmake
Normal file
@ -0,0 +1,41 @@
|
||||
# Check if a symbol is available either as a regular function or an inline function.
|
||||
# CHECK_SYMBOL_EXISTS_OR_INLINE(_function _header _sample_code _variable)
|
||||
#
|
||||
# _function - function name to check
|
||||
# _header - header file
|
||||
# _sample_code - sample code to compile
|
||||
# _variable - variable to store the result
|
||||
|
||||
# Based on CHECK_SYMBOL_EXISTS(). (CheckSymbolExists.cmake)
|
||||
|
||||
INCLUDE(CheckSymbolExists)
|
||||
INCLUDE(CheckCSourceCompiles)
|
||||
MACRO(CHECK_SYMBOL_EXISTS_OR_INLINE _function _header _sample_code _variable)
|
||||
# MinGW defines some reentrant functions as inline functions
|
||||
# that are actually wrappers around MSVC "secure" functions.
|
||||
# Check for the function as a regular function first, then check
|
||||
# if it's available in the specified header.
|
||||
IF(NOT DEFINED ${_variable})
|
||||
|
||||
CHECK_SYMBOL_EXISTS(${_function} ${_header} ${_variable})
|
||||
IF(NOT ${_variable})
|
||||
# Function does not exist normally.
|
||||
# Check if it's an inline function in the specified header.
|
||||
MESSAGE(STATUS "Looking for ${_function} as an inline function")
|
||||
CHECK_C_SOURCE_COMPILES(
|
||||
"#define _POSIX_SOURCE
|
||||
#define _POSIX_C_SOURCE 1
|
||||
#include <${_header}>
|
||||
int main(void) { ${_sample_code} }"
|
||||
${_variable}_INLINE)
|
||||
IF(${_variable}_INLINE)
|
||||
MESSAGE(STATUS "Looking for ${_variable} as an inline function - found")
|
||||
SET(${_variable} 1 CACHE INTERNAL "Have function ${_variable} (inline)")
|
||||
ELSE(${_variable}_INLINE)
|
||||
MESSAGE(STATUS "Looking for ${_variable} as an inline function - not found")
|
||||
# ${_variable} is already cached by CHECK_SYMBOL_EXISTS().
|
||||
ENDIF(${_variable}_INLINE)
|
||||
ENDIF(NOT ${_variable})
|
||||
|
||||
ENDIF(NOT DEFINED ${_variable})
|
||||
ENDMACRO(CHECK_SYMBOL_EXISTS_OR_INLINE _function _header _sample_code _variable)
|
@ -1,6 +1,35 @@
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 3.1)
|
||||
PROJECT(src)
|
||||
|
||||
# Check for reentrant time functions.
|
||||
# NOTE: May be _gmtime32_s() or _gmtime64_s() on MSVC 2005+.
|
||||
# The "inline" part will detect that.
|
||||
INCLUDE(CheckSymbolExistsOrInline)
|
||||
CHECK_SYMBOL_EXISTS_OR_INLINE(gmtime_r "time.h" "time_t tm; gmtime_r(&tm, NULL);" HAVE_GMTIME_R)
|
||||
IF(NOT HAVE_GMTIME_R)
|
||||
CHECK_SYMBOL_EXISTS_OR_INLINE(gmtime_s "time.h" "time_t tm; gmtime_s(NULL, &tm);" HAVE_GMTIME_S)
|
||||
ENDIF(NOT HAVE_GMTIME_R)
|
||||
CHECK_SYMBOL_EXISTS_OR_INLINE(localtime_r "time.h" "time_t tm; localtime_r(&tm, NULL);" HAVE_LOCALTIME_R)
|
||||
IF(NOT HAVE_LOCALTIME_R)
|
||||
CHECK_SYMBOL_EXISTS_OR_INLINE(localtime_s "time.h" "time_t tm; localtime_s(NULL, &tm);" HAVE_LOCALTIME_S)
|
||||
ENDIF(NOT HAVE_LOCALTIME_R)
|
||||
|
||||
# Other time functions.
|
||||
CHECK_SYMBOL_EXISTS_OR_INLINE(timegm "time.h" "struct tm tm; time_t x = timegm(&tm);" HAVE_TIMEGM)
|
||||
IF(NOT HAVE_TIMEGM)
|
||||
# NOTE: MSVCRT's _mkgmtime64() has a range of [1970/01/01, 3000/12/31].
|
||||
# glibc and boost both support arbitrary ranges.
|
||||
CHECK_SYMBOL_EXISTS_OR_INLINE(_mkgmtime "time.h" "struct tm tm; time_t x = _mkgmtime(&tm);" HAVE__MKGMTIME)
|
||||
CHECK_SYMBOL_EXISTS_OR_INLINE(_mkgmtime32 "time.h" "struct tm tm; time_t x = _mkgmtime(&tm);" HAVE__MKGMTIME32)
|
||||
CHECK_SYMBOL_EXISTS_OR_INLINE(_mkgmtime64 "time.h" "struct tm tm; time_t x = _mkgmtime64(&tm);" HAVE__MKGMTIME64)
|
||||
ENDIF(NOT HAVE_TIMEGM)
|
||||
IF(NOT HAVE_TIMEGM AND NOT HAVE__MKGMTIME AND NOT HAVE__MKGMTIME32 AND NOT HAVE__MKGMTIME64)
|
||||
MESSAGE(FATAL_ERROR "timegm() or equivalent function not found.")
|
||||
ENDIF(NOT HAVE_TIMEGM AND NOT HAVE__MKGMTIME AND NOT HAVE__MKGMTIME32 AND NOT HAVE__MKGMTIME64)
|
||||
|
||||
# Write the libc configuration file.
|
||||
CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/config.libc.h.in" "${CMAKE_CURRENT_BINARY_DIR}/config.libc.h")
|
||||
|
||||
# C++11 compatibility header.
|
||||
# NOTE: This must be included regardless of C++11 support in the compiler.
|
||||
# gcc-4.6 supports some C++11, but is missing explicit virtual overrides.
|
||||
|
@ -1,20 +1,8 @@
|
||||
/***************************************************************************
|
||||
* c99-compat.msvcrt.h: C99 compatibility header. (MSVC) *
|
||||
* *
|
||||
* Copyright (c) 2011-2018 by David Korth. *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify it *
|
||||
* under the terms of the GNU General Public License as published by the *
|
||||
* Free Software Foundation; either version 2 of the License, or (at your *
|
||||
* option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* Copyright (c) 2011-2022 by David Korth. *
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef __C99_COMPAT_MSVCRT_H__
|
||||
@ -116,20 +104,6 @@
|
||||
# define wcsncasecmp(s1, s2, n) _wcsnicmp(s1, s2, n)
|
||||
#endif
|
||||
|
||||
/** timegm() **/
|
||||
|
||||
/**
|
||||
* Linux, Mac OS X, and other Unix-like operating systems have a
|
||||
* function timegm() that converts `struct tm` to `time_t`.
|
||||
*
|
||||
* MSVCRT's equivalent function is _mkgmtime().
|
||||
*
|
||||
* NOTE: timegm() is NOT part of *any* standard!
|
||||
*/
|
||||
#ifndef timegm
|
||||
# define timegm(tm) _mkgmtime(tm)
|
||||
#endif
|
||||
|
||||
/** strtok_r() **/
|
||||
|
||||
// MSVC has strtok_s(), which is basically the same as strtok_r().
|
||||
|
38
src/config.libc.h.in
Normal file
38
src/config.libc.h.in
Normal file
@ -0,0 +1,38 @@
|
||||
/***************************************************************************
|
||||
* RVT-H Tool *
|
||||
* config.libc.h.in: Common libc function detection. (source file) *
|
||||
* *
|
||||
* Copyright (c) 2016-2022 by David Korth. *
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef __RVTHTOOL_CONFIG_LIBC_H__
|
||||
#define __RVTHTOOL_CONFIG_LIBC_H__
|
||||
|
||||
/** Time functions **/
|
||||
|
||||
/* Define to 1 if you have the `gmtime_r` function. */
|
||||
#cmakedefine HAVE_GMTIME_R 1
|
||||
|
||||
/* Define to 1 if you have the `gmtime_s` function. */
|
||||
#cmakedefine HAVE_GMTIME_S 1
|
||||
|
||||
/* Define to 1 if you have the `localtime_r' function. */
|
||||
#cmakedefine HAVE_LOCALTIME_R 1
|
||||
|
||||
/* Define to 1 if you have the `localtime_s' function. */
|
||||
#cmakedefine HAVE_LOCALTIME_S 1
|
||||
|
||||
/* Define to 1 if you have the `timegm' function. */
|
||||
#cmakedefine HAVE_TIMEGM 1
|
||||
|
||||
/* Define to 1 if you have the `_mkgmtime' function. */
|
||||
#cmakedefine HAVE__MKGMTIME 1
|
||||
|
||||
/* Define to 1 if you have the `_mkgmtime32' function. */
|
||||
#cmakedefine HAVE__MKGMTIME32 1
|
||||
|
||||
/* Define to 1 if you have the `_mkgmtime64' function. */
|
||||
#cmakedefine HAVE__MKGMTIME64 1
|
||||
|
||||
#endif /* __RVTHTOOL_CONFIG_LIBC_H__ */
|
@ -2,20 +2,8 @@
|
||||
* RVT-H Tool (librvth) *
|
||||
* recrypt.cpp: RVT-H "recryption" functions. *
|
||||
* *
|
||||
* Copyright (c) 2018-2019 by David Korth. *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify it *
|
||||
* under the terms of the GNU General Public License as published by the *
|
||||
* Free Software Foundation; either version 2 of the License, or (at your *
|
||||
* option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* Copyright (c) 2018-2022 by David Korth. *
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later *
|
||||
***************************************************************************/
|
||||
|
||||
#include "rvth.hpp"
|
||||
@ -119,9 +107,8 @@ static int rvth_create_id(uint8_t *id, size_t size,
|
||||
// Clear the buffer.
|
||||
memset(buf, 0xFF, sizeof(buf));
|
||||
|
||||
// TODO: gmtime_r(), localtime_r()
|
||||
tmbuf_utc = *gmtime(&now);
|
||||
tmbuf_local = *localtime(&now);
|
||||
gmtime_r(&now, &tmbuf_utc);
|
||||
localtime_r(&now, &tmbuf_local);
|
||||
|
||||
// Timezone offset.
|
||||
tzoffset = ((tmbuf_local.tm_hour * 60) + (tmbuf_local.tm_min)) -
|
||||
|
@ -19,6 +19,8 @@
|
||||
#include "libwiicrypto/cert.h"
|
||||
#include "libwiicrypto/cert_store.h"
|
||||
|
||||
#include "time_r.h"
|
||||
|
||||
// C includes.
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
@ -134,7 +136,8 @@ int RvtH::openGcm(RefFile *f_img)
|
||||
{
|
||||
time_t mtime = f_img->mtime();
|
||||
if (mtime != -1) {
|
||||
mtime = timegm(localtime(&mtime));
|
||||
struct tm tmbuf_local;
|
||||
mtime = timegm(localtime_r(&mtime, &tmbuf_local));
|
||||
}
|
||||
entry->timestamp = mtime;
|
||||
}
|
||||
|
@ -2,25 +2,16 @@
|
||||
* RVT-H Tool (librvth) *
|
||||
* rvth_time.c: RVT-H timestamp functions. *
|
||||
* *
|
||||
* Copyright (c) 2018 by David Korth. *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify it *
|
||||
* under the terms of the GNU General Public License as published by the *
|
||||
* Free Software Foundation; either version 2 of the License, or (at your *
|
||||
* option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* Copyright (c) 2018-2022 by David Korth. *
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later *
|
||||
***************************************************************************/
|
||||
|
||||
#include "rvth_time.h"
|
||||
#include "libwiicrypto/common.h"
|
||||
|
||||
#include "time_r.h"
|
||||
|
||||
// C includes
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
@ -120,8 +111,7 @@ int rvth_timestamp_create(char *buf, size_t size, time_t now)
|
||||
size = 14;
|
||||
}
|
||||
|
||||
// TODO: Use localtime_r().
|
||||
tm_now = *localtime(&now);
|
||||
localtime_r(&now, &tm_now);
|
||||
snprintf(tsbuf, sizeof(tsbuf), "%04d%02d%02d%02d%02d%02d",
|
||||
tm_now.tm_year+1900, tm_now.tm_mon+1, tm_now.tm_mday,
|
||||
tm_now.tm_hour, tm_now.tm_min, tm_now.tm_sec);
|
||||
|
@ -2,7 +2,7 @@
|
||||
* RVT-H Tool *
|
||||
* list-banks.cpp: List banks in an RVT-H disk image. *
|
||||
* *
|
||||
* Copyright (c) 2018-2020 by David Korth. *
|
||||
* Copyright (c) 2018-2022 by David Korth. *
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later *
|
||||
***************************************************************************/
|
||||
|
||||
@ -16,6 +16,8 @@
|
||||
#include "libwiicrypto/gcn_structs.h"
|
||||
#include "libwiicrypto/sig_tools.h"
|
||||
|
||||
#include "time_r.h"
|
||||
|
||||
// C includes. (C++ namespace)
|
||||
#include <cassert>
|
||||
#include <cerrno>
|
||||
@ -131,9 +133,9 @@ int print_bank(const RvtH *rvth, unsigned int bank)
|
||||
}
|
||||
|
||||
// Print the timestamp.
|
||||
// TODO: Reentrant gmtime() if available.
|
||||
if (entry->timestamp != -1) {
|
||||
struct tm timestamp = *gmtime(&entry->timestamp);
|
||||
struct tm timestamp;
|
||||
gmtime_r(&entry->timestamp, ×tamp);
|
||||
printf("- Timestamp: %04d/%02d/%02d %02d:%02d:%02d\n",
|
||||
timestamp.tm_year + 1900, timestamp.tm_mon + 1, timestamp.tm_mday,
|
||||
timestamp.tm_hour, timestamp.tm_min, timestamp.tm_sec);
|
||||
|
90
src/time_r.h
Normal file
90
src/time_r.h
Normal file
@ -0,0 +1,90 @@
|
||||
/***************************************************************************
|
||||
* RVT-H Tool *
|
||||
* time_r.h: Workaround for missing time functions. *
|
||||
* *
|
||||
* Copyright (c) 2017-2022 by David Korth. *
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef __RVTHTOOL_TIME_R_H__
|
||||
#define __RVTHTOOL_TIME_R_H__
|
||||
|
||||
#include "config.libc.h"
|
||||
|
||||
// _POSIX_C_SOURCE is required for *_r() on MinGW-w64.
|
||||
// However, this breaks snprintf() on FreeBSD when using clang/libc++,
|
||||
// so only define it on Windows.
|
||||
// Reference: https://github.com/pocoproject/poco/issues/1045#issuecomment-245987081
|
||||
#ifdef _WIN32
|
||||
# ifndef _POSIX_C_SOURCE
|
||||
# define _POSIX_C_SOURCE 1
|
||||
# endif
|
||||
#endif /* _WIN32 */
|
||||
#include <time.h>
|
||||
|
||||
#ifndef HAVE_GMTIME_R
|
||||
static inline struct tm *gmtime_r(const time_t *timep, struct tm *result)
|
||||
{
|
||||
#ifdef HAVE_GMTIME_S
|
||||
return (gmtime_s(result, timep) == 0 ? result : NULL);
|
||||
#else /* !HAVE_GMTIME_S */
|
||||
// cppcheck-suppress gmtimeCalled
|
||||
struct tm *tm = gmtime(timep);
|
||||
if (tm && result) {
|
||||
*result = *tm;
|
||||
return result;
|
||||
}
|
||||
return NULL;
|
||||
#endif /* GMTIME_S */
|
||||
}
|
||||
#endif /* HAVE_GMTIME_R */
|
||||
|
||||
#ifndef HAVE_LOCALTIME_R
|
||||
static inline struct tm *localtime_r(const time_t *timep, struct tm *result)
|
||||
{
|
||||
#ifdef HAVE_LOCALTIME_S
|
||||
return (localtime_s(result, timep) == 0 ? result : NULL);
|
||||
#else /* !HAVE_LOCALTIME_S */
|
||||
// cppcheck-suppress localtimeCalled
|
||||
struct tm *tm = localtime(timep);
|
||||
if (tm && result) {
|
||||
*result = *tm;
|
||||
return result;
|
||||
}
|
||||
return NULL;
|
||||
#endif /* HAVE_LOCALTIME_S */
|
||||
}
|
||||
#endif /* HAVE_LOCALTIME_R */
|
||||
|
||||
/** timegm() **/
|
||||
|
||||
/**
|
||||
* Linux, Mac OS X, and other Unix-like operating systems have a
|
||||
* function timegm() that converts `struct tm` to `time_t`.
|
||||
*
|
||||
* MSVCRT's equivalent function is _mkgmtime(). Note that it might
|
||||
* write to the original `struct tm`, so we'll need to make a copy.
|
||||
*
|
||||
* NOTE: timegm() is NOT part of *any* standard!
|
||||
*/
|
||||
#if !defined(HAVE_TIMEGM)
|
||||
static inline time_t timegm(struct tm *tm)
|
||||
{
|
||||
struct tm my_tm;
|
||||
my_tm = *tm;
|
||||
#if defined(HAVE__MKGMTIME64)
|
||||
# define USING_MSVCRT_MKGMTIME 1
|
||||
return _mkgmtime64(&my_tm);
|
||||
#elif defined(HAVE__MKGMTIME32)
|
||||
# define USING_MSVCRT_MKGMTIME 1
|
||||
return _mkgmtime32(&my_tm);
|
||||
#elif defined(HAVE__MKGMTIME)
|
||||
# define USING_MSVCRT_MKGMTIME 1
|
||||
return _mkgmtime(&my_tm);
|
||||
#else
|
||||
# error timegm() or equivalent function not found.
|
||||
#endif
|
||||
}
|
||||
#endif /* !HAVE_TIMEGM */
|
||||
|
||||
#endif /* __ROMPROPERTIES_TIME_R_H__ */
|
Loading…
Reference in New Issue
Block a user