gmio_core: provide a POSIX implementation for gmio_stream_stdio_size()
This commit is contained in:
parent
a04b9b2cda
commit
76ee571cd5
@ -25,7 +25,7 @@ project(gmio C)
|
||||
|
||||
# Options
|
||||
option(BUILD_SHARED_LIBS "Build shared libraries (DLL)" ON)
|
||||
option(BUILD_STRICT_C90 "Build with strict conformance to C90 standard. If disabled, C99 features can be used (eg. strtof(), <stdint.h>, ...)" ON)
|
||||
option(BUILD_STRICT_C90 "Build with strict conformance to C90 standard" OFF)
|
||||
option(BUILD_WITH_LIBSTL "Build the libSTL module" ON)
|
||||
|
||||
# Add core source files
|
||||
@ -39,31 +39,49 @@ math(EXPR GMIO_TARGET_ARCH_BIT_SIZE "8 * ${CMAKE_SIZEOF_VOID_P}")
|
||||
include(TestBigEndian)
|
||||
test_big_endian(GMIO_HOST_IS_BIG_ENDIAN)
|
||||
|
||||
# Find available C99 features
|
||||
if(NOT BUILD_STRICT_C90)
|
||||
# Have <stdint.h> ?
|
||||
check_include_files(stdint.h GMIO_HAVE_STDINT_H)
|
||||
|
||||
# Have strtof() ?
|
||||
check_function_exists(strtof GMIO_HAVE_STRTOF_FUNC)
|
||||
|
||||
# Have powf() ?
|
||||
check_function_exists(powf GMIO_HAVE_POWF_FUNC)
|
||||
|
||||
# Have <stdbool.h> ?
|
||||
check_include_files(stdbool.h GMIO_HAVE_STDBOOL_H)
|
||||
# Adapt C compiler flags to satisfy the BUILD_STRICT_C90 option
|
||||
# It must be done before checking of C99 and POSIX features
|
||||
if(BUILD_STRICT_C90)
|
||||
if(CMAKE_COMPILER_IS_GNUCC)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ansi")
|
||||
elseif(MSVC)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Za")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Have alloca()-like function ?
|
||||
check_c_source_compiles(
|
||||
set(CMAKE_REQUIRED_FLAGS "${CMAKE_C_FLAGS}")
|
||||
|
||||
# Some compilers (like GCC v4.9) don't disable <stdint.h> in STRICT_ANSI mode
|
||||
check_include_files(stdint.h GMIO_HAVE_STDINT_H)
|
||||
|
||||
check_include_files(sys/types.h GMIO_HAVE_SYS_TYPES_H)
|
||||
check_include_files(sys/stat.h GMIO_HAVE_SYS_STAT_H)
|
||||
check_function_exists(fileno GMIO_HAVE_POSIX_FILENO_FUNC)
|
||||
check_function_exists(fstat64 GMIO_HAVE_POSIX_FSTAT64_FUNC)
|
||||
if(WIN32)
|
||||
check_function_exists(_fstat64 GMIO_HAVE_WIN__FSTAT64_FUNC)
|
||||
endif()
|
||||
|
||||
# Find available C99 and compiler/OS specific features
|
||||
if(NOT BUILD_STRICT_C90)
|
||||
check_function_exists(strtof GMIO_HAVE_STRTOF_FUNC)
|
||||
check_function_exists(powf GMIO_HAVE_POWF_FUNC)
|
||||
check_include_files(stdbool.h GMIO_HAVE_STDBOOL_H)
|
||||
|
||||
# Have BSD-like alloca() function ?
|
||||
check_c_source_compiles(
|
||||
"#include <alloca.h>
|
||||
int main() { void* ptr = alloca(256); return 0; }"
|
||||
GMIO_HAVE_BSD_ALLOCA_FUNC)
|
||||
|
||||
check_c_source_compiles(
|
||||
if(WIN32)
|
||||
# Have Win32 _alloca() function ?
|
||||
check_c_source_compiles(
|
||||
"#include <malloc.h>
|
||||
int main() { void* ptr = _alloca(256); return 0; }"
|
||||
GMIO_HAVE_WIN_ALLOCA_FUNC)
|
||||
GMIO_HAVE_WIN_ALLOCA_FUNC) # TODO: rename to GMIO_HAVE_WIN__ALLOCA_FUNC
|
||||
endif() # WIN32
|
||||
endif()
|
||||
|
||||
# Have builtin byte swap functions ?
|
||||
if(CMAKE_COMPILER_IS_GNUCC)
|
||||
@ -87,9 +105,6 @@ include_directories(${CMAKE_BINARY_DIR}) # For generated "config.h"
|
||||
|
||||
# Specific flags for GCC
|
||||
if(CMAKE_COMPILER_IS_GNUCC)
|
||||
if(BUILD_STRICT_C90)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ansi")
|
||||
endif()
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pedantic-errors -fstrict-aliasing")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Winline -Wextra -Wstrict-aliasing -Wcast-align -Wlogical-op -Wfloat-equal")
|
||||
|
||||
|
@ -23,6 +23,12 @@
|
||||
#cmakedefine GMIO_HAVE_STRTOF_FUNC
|
||||
#cmakedefine GMIO_HAVE_POWF_FUNC
|
||||
|
||||
#cmakedefine GMIO_HAVE_SYS_TYPES_H
|
||||
#cmakedefine GMIO_HAVE_SYS_STAT_H
|
||||
#cmakedefine GMIO_HAVE_POSIX_FILENO_FUNC
|
||||
#cmakedefine GMIO_HAVE_POSIX_FSTAT64_FUNC
|
||||
#cmakedefine GMIO_HAVE_WIN__FSTAT64_FUNC
|
||||
|
||||
#cmakedefine GMIO_HAVE_GCC_BUILTIN_BSWAP16_FUNC
|
||||
#cmakedefine GMIO_HAVE_GCC_BUILTIN_BSWAP32_FUNC
|
||||
|
||||
|
@ -23,6 +23,18 @@
|
||||
#if defined(WIN64) || defined(_WIN64) || defined(__WIN64__) \
|
||||
|| defined(WIN32) || defined(_WIN32) || defined(__WIN32__) \
|
||||
|| defined(__NT__)
|
||||
# define GMIO_OS_WIN
|
||||
#endif /* Windows */
|
||||
|
||||
#if defined(__linux) || defined(__linux__) || defined(linux)
|
||||
# define GMIO_OS_LINUX
|
||||
#endif /* Linux */
|
||||
|
||||
#if defined(__APPLE__)
|
||||
# define GMIO_OS_MAC
|
||||
#endif /* Apple */
|
||||
|
||||
#ifdef GMIO_OS_WIN
|
||||
# define GMIO_DECL_EXPORT __declspec(dllexport)
|
||||
# define GMIO_DECL_IMPORT __declspec(dllimport)
|
||||
#else
|
||||
@ -118,7 +130,7 @@ typedef double gmio_float64_t;
|
||||
# elif defined(_MSC_VER)
|
||||
# define GMIO_INLINE __inline static
|
||||
# elif !defined(DOXYGEN)
|
||||
# define GMIO_INLINE
|
||||
# define GMIO_INLINE static
|
||||
# else
|
||||
/*! Expands to the C compiler specific inline keyword (if any) */
|
||||
# define GMIO_INLINE
|
||||
|
@ -19,9 +19,53 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* TODO: add cmake step to check availability of <sys/xxx.h> header files */
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#if defined(GMIO_HAVE_SYS_TYPES_H) && defined(GMIO_HAVE_SYS_STAT_H)
|
||||
|
||||
/* Activate 64bit variants of stat(), fstat(), ...
|
||||
* See:
|
||||
* http://linux.die.net/man/2/fstat64
|
||||
* https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man2/fstat.2.html
|
||||
*/
|
||||
# ifdef GMIO_OS_LINUX
|
||||
# if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS != 64
|
||||
# undef _FILE_OFFSET_BITS
|
||||
# endif
|
||||
# if !defined(_FILE_OFFSET_BITS)
|
||||
# define _FILE_OFFSET_BITS=64
|
||||
# endif
|
||||
# if !defined(_POSIX_C_SOURCE)
|
||||
/* This enables fileno() */
|
||||
# define _POSIX_C_SOURCE
|
||||
# endif
|
||||
# define GMIO_FSTAT64_OVERRIDE
|
||||
# endif /* Linux */
|
||||
|
||||
# ifdef GMIO_OS_MAC
|
||||
# if !defined(_DARWIN_USE_64_BIT_INODE)
|
||||
# define _DARWIN_USE_64_BIT_INODE
|
||||
# endif
|
||||
# define GMIO_FSTAT64_OVERRIDE
|
||||
# endif /* Apple */
|
||||
|
||||
# include <sys/types.h>
|
||||
# include <sys/stat.h>
|
||||
|
||||
/* Define wrapper around the stat structure and the fstat() function */
|
||||
# ifdef GMIO_HAVE_WIN__FSTAT64_FUNC
|
||||
typedef struct __stat64 gmio_stat_t;
|
||||
GMIO_INLINE int gmio_fstat(int fd, gmio_stat_t* buf)
|
||||
{ return _fstat64(fd, buf); }
|
||||
# elif defined(GMIO_FSTAT64_OVERRIDE) || !defined(GMIO_HAVE_POSIX_FSTAT64_FUNC)
|
||||
typedef struct stat gmio_stat_t;
|
||||
GMIO_INLINE int gmio_fstat(int fd, gmio_stat_t* buf)
|
||||
{ return fstat(fd, buf); }
|
||||
# elif defined(GMIO_HAVE_POSIX_FSTAT64_FUNC)
|
||||
typedef struct stat64 gmio_stat_t;
|
||||
GMIO_INLINE int gmio_fstat(int fd, gmio_stat_t* buf)
|
||||
{ return fstat64(fd, buf); }
|
||||
# endif
|
||||
|
||||
#endif /* GMIO_HAVE_SYS_TYPES_H && GMIO_HAVE_SYS_STAT_H */
|
||||
|
||||
gmio_stream_t gmio_stream_null()
|
||||
{
|
||||
@ -53,9 +97,58 @@ static size_t gmio_stream_stdio_write(
|
||||
|
||||
static size_t gmio_stream_stdio_size(void* cookie)
|
||||
{
|
||||
struct stat stat_buf;
|
||||
fstat(fileno((FILE*) cookie), &stat_buf);
|
||||
return stat_buf.st_size;
|
||||
FILE* file = (FILE*) cookie;
|
||||
|
||||
#if defined(GMIO_HAVE_SYS_TYPES_H) \
|
||||
&& defined(GMIO_HAVE_SYS_STAT_H) \
|
||||
&& defined(GMIO_HAVE_POSIX_FILENO_FUNC)
|
||||
|
||||
const int fd = fileno(file);
|
||||
if (fd != -1) {
|
||||
gmio_stat_t buf;
|
||||
if (gmio_fstat(fd, &buf) == 0)
|
||||
return buf.st_size;
|
||||
}
|
||||
return 0;
|
||||
|
||||
#else
|
||||
|
||||
/* Excerpted from: https://www.securecoding.cert.org
|
||||
* item FIO19-C
|
||||
*
|
||||
* Subclause 7.21.9.2 of the C Standard [ISO/IEC 9899:2011] specifies the
|
||||
* following behavior for fseek() when opening a binary file in binary mode:
|
||||
* A binary stream need not meaningfully support fseek calls with a
|
||||
* whence value of SEEK_END.
|
||||
*
|
||||
* In addition, footnote 268 of subclause 7.21.3 says:
|
||||
* Setting the file position indicator to end-of-file, as with
|
||||
* fseek(file, 0, SEEK_END), has undefined behavior for a binary stream
|
||||
* (because of possible trailing null characters) or for any stream with
|
||||
* state-dependent encoding that does not assuredly end in the initial
|
||||
* shift state.
|
||||
*
|
||||
* Subclause 7.21.9.4 of the C Standard [ISO/IEC 9899:2011] specifies the
|
||||
* following behavior for ftell() when opening a text file in text mode:
|
||||
* For a text stream, its file position indicator contains unspecified
|
||||
* information, usable by the fseek function for returning the file
|
||||
* position indicator for the stream to its position at the time of the
|
||||
* ftell call.
|
||||
* Consequently, the return value of ftell() for streams opened in text mode
|
||||
* should never be used for offset calculations other than in calls to
|
||||
* fseek().
|
||||
*/
|
||||
|
||||
long size = 0L;
|
||||
const long old_pos = ftell(file);
|
||||
|
||||
fseek(file, 0L, SEEK_END);
|
||||
size = ftell(file);
|
||||
fseek(file, old_pos, SEEK_SET);
|
||||
|
||||
return size;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
static void gmio_stream_stdio_rewind(void* cookie)
|
||||
|
Loading…
Reference in New Issue
Block a user