/**************************************************************************** ** GeomIO Library ** Copyright FougSys (2 Mar. 2015) ** contact@fougsys.fr ** ** This software is a reusable library whose purpose is to provide complete ** I/O support for various CAD file formats (eg. STL) ** ** This software is governed by the CeCILL-B license under French law and ** abiding by the rules of distribution of free software. You can use, ** modify and/ or redistribute the software under the terms of the CeCILL-B ** license as circulated by CEA, CNRS and INRIA at the following URL ** "http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html". ****************************************************************************/ #include "stream.h" #include #include #include #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 # include /* 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() { gmio_stream_t null_stream = { 0 }; return null_stream; } static gmio_bool_t gmio_stream_stdio_at_end(void* cookie) { return feof((FILE*) cookie); } static int gmio_stream_stdio_error(void* cookie) { return ferror((FILE*) cookie); } static size_t gmio_stream_stdio_read( void* cookie, void* ptr, size_t item_size, size_t item_count) { return fread(ptr, item_size, item_count, (FILE*) cookie); } static size_t gmio_stream_stdio_write( void* cookie, const void* ptr, size_t item_size, size_t item_count) { return fwrite(ptr, item_size, item_count, (FILE*) cookie); } static size_t gmio_stream_stdio_size(void* cookie) { 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) { rewind((FILE*) cookie); } gmio_stream_t gmio_stream_stdio(FILE* file) { gmio_stream_t stream = { 0 }; stream.cookie = file; stream.at_end_func = gmio_stream_stdio_at_end; stream.error_func = gmio_stream_stdio_error; stream.read_func = gmio_stream_stdio_read; stream.write_func = gmio_stream_stdio_write; stream.size_func = gmio_stream_stdio_size; stream.rewind_func = gmio_stream_stdio_rewind; return stream; }