Line  | Count  | Source (jump to first uncovered line)  | 
1  |  | /* An fseeko() function that, together with fflush(), is POSIX compliant.  | 
2  |  |    Copyright (C) 2007-2025 Free Software Foundation, Inc.  | 
3  |  |  | 
4  |  |    This file is free software: you can redistribute it and/or modify  | 
5  |  |    it under the terms of the GNU Lesser General Public License as  | 
6  |  |    published by the Free Software Foundation; either version 2.1 of the  | 
7  |  |    License, or (at your option) any later version.  | 
8  |  |  | 
9  |  |    This file 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 Lesser General Public License for more details.  | 
13  |  |  | 
14  |  |    You should have received a copy of the GNU Lesser General Public License  | 
15  |  |    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */  | 
16  |  |  | 
17  |  | #include <config.h>  | 
18  |  |  | 
19  |  | /* Specification.  */  | 
20  |  | #include <stdio.h>  | 
21  |  |  | 
22  |  | /* Get off_t, lseek, _POSIX_VERSION.  */  | 
23  |  | #include <unistd.h>  | 
24  |  |  | 
25  |  | #include "stdio-impl.h"  | 
26  |  |  | 
27  |  | int  | 
28  |  | fseeko (FILE *fp, off_t offset, int whence)  | 
29  |  | #undef fseeko  | 
30  |  | #if !HAVE_FSEEKO  | 
31  |  | # undef fseek  | 
32  |  | # define fseeko fseek  | 
33  |  | #endif  | 
34  |  | #if _GL_WINDOWS_64_BIT_OFF_T  | 
35  |  | # undef fseeko  | 
36  |  | # if HAVE__FSEEKI64 && HAVE_DECL__FSEEKI64 /* msvc, mingw since msvcrt8.0, mingw64 */  | 
37  |  | #  define fseeko _fseeki64  | 
38  |  | # else /* mingw before msvcrt8.0 */  | 
39  |  | #  define fseeko fseeko64  | 
40  |  | # endif  | 
41  |  | #endif  | 
42  | 0  | { | 
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 EOF;  | 
47  |  | #endif  | 
48  |  |  | 
49  |  |   /* These tests are based on fpurge.c.  */  | 
50  | 0  | #if defined _IO_EOF_SEEN || defined _IO_ftrylockfile || __GNU_LIBRARY__ == 1  | 
51  |  |   /* GNU libc, BeOS, Haiku, Linux libc5 */  | 
52  | 0  |   if (fp->_IO_read_end == fp->_IO_read_ptr  | 
53  | 0  |       && fp->_IO_write_ptr == fp->_IO_write_base  | 
54  | 0  |       && fp->_IO_save_base == NULL)  | 
55  |  | #elif defined __sferror || defined __DragonFly__ || defined __ANDROID__  | 
56  |  |   /* FreeBSD, NetBSD, OpenBSD, DragonFly, Mac OS X, Cygwin, Minix 3, Android */  | 
57  |  | # if defined __SL64 && defined __SCLE /* Cygwin */  | 
58  |  |   if ((fp->_flags & __SL64) == 0)  | 
59  |  |     { | 
60  |  |       /* Cygwin 1.5.0 through 1.5.24 failed to open stdin in 64-bit  | 
61  |  |          mode; but has an fseeko that requires 64-bit mode.  */  | 
62  |  |       FILE *tmp = fopen ("/dev/null", "r"); | 
63  |  |       if (!tmp)  | 
64  |  |         return -1;  | 
65  |  |       fp->_flags |= __SL64;  | 
66  |  |       fp->_seek64 = tmp->_seek64;  | 
67  |  |       fclose (tmp);  | 
68  |  |     }  | 
69  |  | # endif  | 
70  |  |   if (fp_->_p == fp_->_bf._base  | 
71  |  |       && fp_->_r == 0  | 
72  |  |       && fp_->_w == ((fp_->_flags & (__SLBF | __SNBF | __SRD)) == 0 /* fully buffered and not currently reading? */  | 
73  |  |                      ? fp_->_bf._size  | 
74  |  |                      : 0)  | 
75  |  |       && fp_ub._base == NULL)  | 
76  |  | #elif defined __EMX__               /* emx+gcc */  | 
77  |  |   if (fp->_ptr == fp->_buffer  | 
78  |  |       && fp->_rcount == 0  | 
79  |  |       && fp->_wcount == 0  | 
80  |  |       && fp->_ungetc_count == 0)  | 
81  |  | #elif defined __minix               /* Minix */  | 
82  |  |   if (fp_->_ptr == fp_->_buf  | 
83  |  |       && (fp_->_ptr == NULL || fp_->_count == 0))  | 
84  |  | #elif defined _IOERR                /* AIX, HP-UX, IRIX, OSF/1, Solaris, OpenServer, UnixWare, mingw, MSVC, NonStop Kernel, OpenVMS */  | 
85  |  |   if (fp_->_ptr == fp_->_base  | 
86  |  |       && (fp_->_ptr == NULL || fp_->_cnt == 0))  | 
87  |  | #elif defined __UCLIBC__            /* uClibc */  | 
88  |  |   if (((fp->__modeflags & __FLAG_WRITING) == 0  | 
89  |  |        || fp->__bufpos == fp->__bufstart)  | 
90  |  |       && ((fp->__modeflags & (__FLAG_READONLY | __FLAG_READING)) == 0  | 
91  |  |           || fp->__bufpos == fp->__bufread))  | 
92  |  | #elif defined __QNX__               /* QNX */  | 
93  |  |   if ((fp->_Mode & 0x2000 /* _MWRITE */ ? fp->_Next == fp->_Buf : fp->_Next == fp->_Rend)  | 
94  |  |       && fp->_Rback == fp->_Back + sizeof (fp->_Back)  | 
95  |  |       && fp->_Rsave == NULL)  | 
96  |  | #elif defined __MINT__              /* Atari FreeMiNT */  | 
97  |  |   if (fp->__bufp == fp->__buffer  | 
98  |  |       && fp->__get_limit == fp->__bufp  | 
99  |  |       && fp->__put_limit == fp->__bufp  | 
100  |  |       && !fp->__pushed_back)  | 
101  |  | #elif defined EPLAN9                /* Plan9 */  | 
102  |  |   if (fp->rp == fp->buf  | 
103  |  |       && fp->wp == fp->buf)  | 
104  |  | #elif FUNC_FFLUSH_STDIN < 0 && 200809 <= _POSIX_VERSION  | 
105  |  |   /* Cross-compiling to some other system advertising conformance to  | 
106  |  |      POSIX.1-2008 or later.  Assume fseeko and fflush work as advertised.  | 
107  |  |      If this assumption is incorrect, please report the bug to  | 
108  |  |      bug-gnulib.  */  | 
109  |  |   if (0)  | 
110  |  | #else  | 
111  |  |   #error "Please port gnulib fseeko.c to your platform! Look at the code in fseeko.c, then report this to bug-gnulib."  | 
112  |  | #endif  | 
113  | 0  |     { | 
114  |  |       /* We get here when an fflush() call immediately preceded this one (or  | 
115  |  |          if ftell() has created buffers but no I/O has occurred on a  | 
116  |  |          newly-opened stream).  We know there are no buffers.  */  | 
117  | 0  |       off_t pos = lseek (fileno (fp), offset, whence);  | 
118  | 0  |       if (pos == -1)  | 
119  | 0  |         { | 
120  |  | #if defined __sferror || defined __DragonFly__ || defined __ANDROID__  | 
121  |  |           /* FreeBSD, NetBSD, OpenBSD, DragonFly, Mac OS X, Cygwin, Minix 3, Android */  | 
122  |  |           fp_->_flags &= ~__SOFF;  | 
123  |  | #endif  | 
124  | 0  |           return -1;  | 
125  | 0  |         }  | 
126  |  |  | 
127  | 0  | #if defined _IO_EOF_SEEN || defined _IO_ftrylockfile || __GNU_LIBRARY__ == 1  | 
128  |  |       /* GNU libc, BeOS, Haiku, Linux libc5 */  | 
129  | 0  |       fp->_flags &= ~_IO_EOF_SEEN;  | 
130  | 0  |       fp->_offset = pos;  | 
131  |  | #elif defined __sferror || defined __DragonFly__ || defined __ANDROID__  | 
132  |  |       /* FreeBSD, NetBSD, OpenBSD, DragonFly, Mac OS X, Cygwin, Minix 3, Android */  | 
133  |  | # if defined __CYGWIN__ || (defined __NetBSD__ && __NetBSD_Version__ >= 600000000) || defined __minix  | 
134  |  |       /* fp_->_offset is typed as an integer.  */  | 
135  |  |       fp_->_offset = pos;  | 
136  |  | # else  | 
137  |  |       /* fp_->_offset is an fpos_t.  */  | 
138  |  |       { | 
139  |  |         /* Use a union, since on NetBSD, the compilation flags  | 
140  |  |            determine whether fpos_t is typedef'd to off_t or a struct  | 
141  |  |            containing a single off_t member.  */  | 
142  |  |         union  | 
143  |  |           { | 
144  |  |             fpos_t f;  | 
145  |  |             off_t o;  | 
146  |  |           } u;  | 
147  |  |         u.o = pos;  | 
148  |  |         fp_->_offset = u.f;  | 
149  |  |       }  | 
150  |  | # endif  | 
151  |  |       fp_->_flags |= __SOFF;  | 
152  |  |       fp_->_flags &= ~__SEOF;  | 
153  |  | #elif defined __EMX__               /* emx+gcc */  | 
154  |  |       fp->_flags &= ~_IOEOF;  | 
155  |  | #elif defined _IOERR                /* AIX, HP-UX, IRIX, OSF/1, Solaris, OpenServer, UnixWare, mingw, MSVC, NonStop Kernel, OpenVMS */  | 
156  |  |       fp_->_flag &= ~_IOEOF;  | 
157  |  | #elif defined __MINT__              /* Atari FreeMiNT */  | 
158  |  |       fp->__offset = pos;  | 
159  |  |       fp->__eof = 0;  | 
160  |  | #endif  | 
161  | 0  |       return 0;  | 
162  | 0  |     }  | 
163  | 0  |   return fseeko (fp, offset, whence);  | 
164  | 0  | }  |