1/* An ftello() function that works around platform bugs. 2 Copyright (C) 2007, 2009-2014 Free Software Foundation, Inc. 3 4 This program is free software: you can redistribute it and/or modify 5 it under the terms of the GNU General Public License as published by 6 the Free Software Foundation; either version 3 of the License, or 7 (at your option) any later version. 8 9 This program is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 GNU General Public License for more details. 13 14 You should have received a copy of the GNU General Public License 15 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 16 17#include <config.h> 18 19/* Specification. */ 20#include <stdio.h> 21 22/* Get lseek. */ 23#include <unistd.h> 24 25#include "stdio-impl.h" 26 27off_t 28ftello (FILE *fp) 29#undef ftello 30#if !HAVE_FTELLO 31# undef ftell 32# define ftello ftell 33#endif 34#if _GL_WINDOWS_64_BIT_OFF_T 35# undef ftello 36# if HAVE__FTELLI64 /* msvc, mingw64 */ 37# define ftello _ftelli64 38# else /* mingw */ 39# define ftello ftello64 40# endif 41#endif 42{ 43#if LSEEK_PIPE_BROKEN 44 /* mingw gives bogus answers rather than failure on non-seekable files. */ 45 if (lseek (fileno (fp), 0, SEEK_CUR) == -1) 46 return -1; 47#endif 48 49#if FTELLO_BROKEN_AFTER_SWITCHING_FROM_READ_TO_WRITE /* Solaris */ 50 /* The Solaris stdio leaves the _IOREAD flag set after reading from a file 51 reaches EOF and the program then starts writing to the file. ftello 52 gets confused by this. */ 53 if (fp_->_flag & _IOWRT) 54 { 55 off_t pos; 56 57 /* Call ftello nevertheless, for the side effects that it does on fp. */ 58 ftello (fp); 59 60 /* Compute the file position ourselves. */ 61 pos = lseek (fileno (fp), (off_t) 0, SEEK_CUR); 62 if (pos >= 0) 63 { 64 if ((fp_->_flag & _IONBF) == 0 && fp_->_base != NULL) 65 pos += fp_->_ptr - fp_->_base; 66 } 67 return pos; 68 } 69#endif 70 71#if defined __SL64 && defined __SCLE /* Cygwin */ 72 if ((fp->_flags & __SL64) == 0) 73 { 74 /* Cygwin 1.5.0 through 1.5.24 failed to open stdin in 64-bit 75 mode; but has an ftello that requires 64-bit mode. */ 76 FILE *tmp = fopen ("/dev/null", "r"); 77 if (!tmp) 78 return -1; 79 fp->_flags |= __SL64; 80 fp->_seek64 = tmp->_seek64; 81 fclose (tmp); 82 } 83#endif 84 return ftello (fp); 85} 86