diff options
| -rw-r--r-- | libio/fileops.c | 9 | ||||
| -rw-r--r-- | stdio-common/Makefile | 1 | ||||
| -rw-r--r-- | stdio-common/tst-fseek-mmap.c | 59 |
3 files changed, 68 insertions, 1 deletions
diff --git a/libio/fileops.c b/libio/fileops.c index e868d520b6..b00a5d24ab 100644 --- a/libio/fileops.c +++ b/libio/fileops.c @@ -1107,11 +1107,18 @@ _IO_file_seekoff_mmap (FILE *fp, off64_t offset, int dir, int mode) if (mode == 0) return fp->_offset - (fp->_IO_read_end - fp->_IO_read_ptr); + if (_IO_in_backup (fp)) + { + if (dir == _IO_seek_cur) + offset += fp->_IO_read_ptr - fp->_IO_read_end; + _IO_switch_to_main_get_area (fp); + } + switch (dir) { case _IO_seek_cur: /* Adjust for read-ahead (bytes is buffer). */ - offset += fp->_IO_read_ptr - fp->_IO_read_base; + offset += fp->_offset - (fp->_IO_read_end - fp->_IO_read_ptr); break; case _IO_seek_set: break; diff --git a/stdio-common/Makefile b/stdio-common/Makefile index 26c1b881cc..f80b9ec57b 100644 --- a/stdio-common/Makefile +++ b/stdio-common/Makefile @@ -262,6 +262,7 @@ tests := \ tst-freopen64-7 \ tst-freopen7 \ tst-fseek \ + tst-fseek-mmap \ tst-fwrite \ tst-fwrite-memstrm \ tst-fwrite-overflow \ diff --git a/stdio-common/tst-fseek-mmap.c b/stdio-common/tst-fseek-mmap.c new file mode 100644 index 0000000000..86fa99a1a2 --- /dev/null +++ b/stdio-common/tst-fseek-mmap.c @@ -0,0 +1,59 @@ +/* Test fseek on files using mmap (bug 32529). + Copyright (C) 2025 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <stdio.h> + +#include <support/check.h> +#include <support/temp_file.h> +#include <support/xstdio.h> +#include <support/xunistd.h> + +int +do_test (void) +{ + char *filename = NULL; + int fd = create_temp_file ("tst-fseek-mmap", &filename); + TEST_VERIFY_EXIT (fd != -1); + xclose (fd); + + /* Test fseek after ungetc (bug 32529). */ + FILE *fp = xfopen (filename, "w"); + TEST_VERIFY (0 <= fputs ("test", fp)); + xfclose (fp); + + fp = xfopen (filename, "rm"); + TEST_COMPARE (fgetc (fp), 't'); + TEST_COMPARE (ungetc ('u', fp), 'u'); + TEST_COMPARE (fseek (fp, 0, SEEK_CUR), 0); + xfclose (fp); + + /* Test fseek positioning after fflush (another issue covered by the + same fix). */ + fp = xfopen (filename, "rm"); + TEST_COMPARE (fgetc (fp), 't'); + TEST_COMPARE (fflush (fp), 0); + TEST_COMPARE (ftell (fp), 1); + TEST_COMPARE (fseek (fp, 0, SEEK_CUR), 0); + TEST_COMPARE (ftell (fp), 1); + TEST_COMPARE (fgetc (fp), 'e'); + xfclose (fp); + + return 0; +} + +#include <support/test-driver.c> |
