Add more tests for freopen (RHEL-46736)
Resolves: RHEL-46736
This commit is contained in:
parent
a2d1e68858
commit
9c1694b310
67
glibc-RHEL-46736-1.patch
Normal file
67
glibc-RHEL-46736-1.patch
Normal file
@ -0,0 +1,67 @@
|
||||
commit e3fdbe9f39747206b9c3fbb0219f29fd5b35d020
|
||||
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
Date: Thu Apr 8 17:36:07 2021 -0300
|
||||
|
||||
support: Add xmkfifo
|
||||
|
||||
Wrapper support mkfifo.
|
||||
|
||||
diff --git a/support/Makefile b/support/Makefile
|
||||
index 25e8bbefd78c2268..0273c0f6306720c9 100644
|
||||
--- a/support/Makefile
|
||||
+++ b/support/Makefile
|
||||
@@ -137,6 +137,7 @@ libsupport-routines = \
|
||||
xmemstream \
|
||||
xmkdir \
|
||||
xmkdirp \
|
||||
+ xmkfifo \
|
||||
xmmap \
|
||||
xmprotect \
|
||||
xmunmap \
|
||||
diff --git a/support/xmkfifo.c b/support/xmkfifo.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..a8e196dbc209a47d
|
||||
--- /dev/null
|
||||
+++ b/support/xmkfifo.c
|
||||
@@ -0,0 +1,29 @@
|
||||
+/* mkfifo with error checking.
|
||||
+ Copyright (C) 2022 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 <support/check.h>
|
||||
+#include <support/xunistd.h>
|
||||
+#include <sys/stat.h>
|
||||
+
|
||||
+void
|
||||
+xmkfifo (const char *pathname, mode_t mode)
|
||||
+{
|
||||
+ int r = mkfifo (pathname, mode);
|
||||
+ if (r < 0)
|
||||
+ FAIL_EXIT1 ("mkfifo (%s, 0%o): %m", pathname, mode);
|
||||
+}
|
||||
diff --git a/support/xunistd.h b/support/xunistd.h
|
||||
index a25ecf1cf38ef328..94b1e1eb1b1e8253 100644
|
||||
--- a/support/xunistd.h
|
||||
+++ b/support/xunistd.h
|
||||
@@ -61,6 +61,7 @@ void xsymlink (const char *target, const char *linkpath);
|
||||
void xchdir (const char *path);
|
||||
void xfchmod (int fd, mode_t mode);
|
||||
void xchmod (const char *pathname, mode_t mode);
|
||||
+void xmkfifo (const char *pathname, mode_t mode);
|
||||
|
||||
/* Equivalent of "mkdir -p". */
|
||||
void xmkdirp (const char *, mode_t);
|
30
glibc-RHEL-46736-10.patch
Normal file
30
glibc-RHEL-46736-10.patch
Normal file
@ -0,0 +1,30 @@
|
||||
commit 6948ee4edf0c57c556f8d5f394d9191216d05780
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Sat Sep 28 21:06:11 2024 +0200
|
||||
|
||||
stdio-common: Fix memory leak in tst-freopen4* tests on UNSUPPORTED
|
||||
|
||||
The temp_dir allocation leaks if support_can_chroot returns false.
|
||||
|
||||
diff --git a/stdio-common/tst-freopen4-main.c b/stdio-common/tst-freopen4-main.c
|
||||
index e169442cf4df2e9d..7284677a97e10af6 100644
|
||||
--- a/stdio-common/tst-freopen4-main.c
|
||||
+++ b/stdio-common/tst-freopen4-main.c
|
||||
@@ -33,7 +33,7 @@ int
|
||||
do_test (void)
|
||||
{
|
||||
mtrace ();
|
||||
- char *temp_dir = support_create_temp_directory ("tst-freopen4");
|
||||
+ char *temp_dir;
|
||||
FILE *fp;
|
||||
int ret;
|
||||
|
||||
@@ -45,6 +45,8 @@ do_test (void)
|
||||
support_become_root ();
|
||||
if (!support_can_chroot ())
|
||||
return EXIT_UNSUPPORTED;
|
||||
+
|
||||
+ temp_dir = support_create_temp_directory ("tst-freopen4");
|
||||
xchroot (temp_dir);
|
||||
|
||||
/* Test freopen with NULL, renamed file. This verifies that
|
216
glibc-RHEL-46736-11.patch
Normal file
216
glibc-RHEL-46736-11.patch
Normal file
@ -0,0 +1,216 @@
|
||||
commit 42c810c2cf3554afbdd60885b7da6bb4e702466f
|
||||
Author: Joseph Myers <josmyers@redhat.com>
|
||||
Date: Mon Oct 7 19:44:25 2024 +0000
|
||||
|
||||
Add freopen special-case tests: thread cancellation
|
||||
|
||||
Add tests of freopen adding or removing "c" (non-cancelling I/O) from
|
||||
the mode string (so completing my planned tests of freopen with
|
||||
different features used in the mode strings). Note that it's in the
|
||||
nature of the uncertain time at which cancellation might act (possibly
|
||||
during freopen, possibly during subsequent reads) that these can leak
|
||||
memory or file descriptors, so these do not include leak tests.
|
||||
|
||||
Tested for x86_64.
|
||||
|
||||
diff --git a/stdio-common/Makefile b/stdio-common/Makefile
|
||||
index c920f55ed2119900..09d3622823203f74 100644
|
||||
--- a/stdio-common/Makefile
|
||||
+++ b/stdio-common/Makefile
|
||||
@@ -180,10 +180,12 @@ tests := \
|
||||
tst-freopen4 \
|
||||
tst-freopen5 \
|
||||
tst-freopen6 \
|
||||
+ tst-freopen7 \
|
||||
tst-freopen64-2 \
|
||||
tst-freopen64-3 \
|
||||
tst-freopen64-4 \
|
||||
tst-freopen64-6 \
|
||||
+ tst-freopen64-7 \
|
||||
tst-fseek \
|
||||
tst-fwrite \
|
||||
tst-getline \
|
||||
@@ -480,3 +482,6 @@ $(objpfx)tst-setvbuf1-cmp.out: tst-setvbuf1.expect $(objpfx)tst-setvbuf1.out
|
||||
|
||||
$(objpfx)tst-printf-round: $(libm)
|
||||
$(objpfx)tst-scanf-round: $(libm)
|
||||
+
|
||||
+$(objpfx)tst-freopen7: $(shared-thread-library)
|
||||
+$(objpfx)tst-freopen64-7: $(shared-thread-library)
|
||||
diff --git a/stdio-common/tst-freopen64-7.c b/stdio-common/tst-freopen64-7.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..f34c2805210079b9
|
||||
--- /dev/null
|
||||
+++ b/stdio-common/tst-freopen64-7.c
|
||||
@@ -0,0 +1,2 @@
|
||||
+#define FREOPEN freopen64
|
||||
+#include <tst-freopen7-main.c>
|
||||
diff --git a/stdio-common/tst-freopen7-main.c b/stdio-common/tst-freopen7-main.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..965e0b4adce750cc
|
||||
--- /dev/null
|
||||
+++ b/stdio-common/tst-freopen7-main.c
|
||||
@@ -0,0 +1,155 @@
|
||||
+/* Test freopen cancellation handling.
|
||||
+ Copyright (C) 2024 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 <errno.h>
|
||||
+#include <fcntl.h>
|
||||
+#include <mcheck.h>
|
||||
+#include <pthread.h>
|
||||
+#include <semaphore.h>
|
||||
+#include <stdio.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <wchar.h>
|
||||
+
|
||||
+#include <support/check.h>
|
||||
+#include <support/file_contents.h>
|
||||
+#include <support/support.h>
|
||||
+#include <support/temp_file.h>
|
||||
+#include <support/test-driver.h>
|
||||
+#include <support/xstdio.h>
|
||||
+#include <support/xthread.h>
|
||||
+#include <support/xunistd.h>
|
||||
+
|
||||
+char *file1, *file2, *file3, *fifo;
|
||||
+
|
||||
+sem_t sem;
|
||||
+
|
||||
+void *
|
||||
+test_rc_to_r (void *p)
|
||||
+{
|
||||
+ int ret;
|
||||
+ FILE *fp, *fp2;
|
||||
+ ret = sem_post (&sem);
|
||||
+ TEST_VERIFY_EXIT (ret == 0);
|
||||
+ fp = xfopen (file1, "rc");
|
||||
+ for (int i = 0; i < 1000000; i++)
|
||||
+ {
|
||||
+ fgetc (fp);
|
||||
+ fseek (fp, 0, SEEK_SET);
|
||||
+ }
|
||||
+ fp2 = xfopen (file3, "wc");
|
||||
+ fputs ("rc_to_r got to freopen", fp2);
|
||||
+ xfclose (fp2);
|
||||
+ /* Cancellation should occur at some point from here onwards
|
||||
+ (possibly leaking memory and file descriptors associated with the
|
||||
+ FILE). */
|
||||
+ fp = FREOPEN (file2, "r", fp);
|
||||
+ TEST_VERIFY_EXIT (fp != NULL);
|
||||
+ for (;;)
|
||||
+ {
|
||||
+ fgetc (fp);
|
||||
+ fseek (fp, 0, SEEK_SET);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+void *
|
||||
+test_r_to_rc (void *p)
|
||||
+{
|
||||
+ int ret;
|
||||
+ FILE *fp;
|
||||
+ fp = xfopen (file1, "r");
|
||||
+ fp = FREOPEN (fifo, "rc", fp);
|
||||
+ TEST_VERIFY_EXIT (fp != NULL);
|
||||
+ ret = sem_post (&sem);
|
||||
+ TEST_VERIFY_EXIT (ret == 0);
|
||||
+ /* No cancellation should occur for I/O on fifo. */
|
||||
+ ret = fgetc (fp);
|
||||
+ /* At this point, the other thread has called pthread_cancel and
|
||||
+ then written a byte to the fifo, so this thread is cancelled at
|
||||
+ the next cancellation point. */
|
||||
+ TEST_VERIFY (ret == 'x');
|
||||
+ xfclose (fp);
|
||||
+ fp = xfopen (file3, "wc");
|
||||
+ fputs ("r_to_rc got to fclose", fp);
|
||||
+ xfclose (fp);
|
||||
+ pthread_testcancel ();
|
||||
+ FAIL_EXIT1 ("test_r_to_rc not cancelled\n");
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ char *temp_dir = support_create_temp_directory ("tst-freopen-cancel");
|
||||
+ file1 = xasprintf ("%s/file1", temp_dir);
|
||||
+ support_write_file_string (file1, "file1");
|
||||
+ add_temp_file (file1);
|
||||
+ file2 = xasprintf ("%s/file2", temp_dir);
|
||||
+ support_write_file_string (file2, "file2");
|
||||
+ add_temp_file (file2);
|
||||
+ file3 = xasprintf ("%s/file3", temp_dir);
|
||||
+ support_write_file_string (file3, "file3");
|
||||
+ add_temp_file (file3);
|
||||
+ fifo = xasprintf ("%s/fifo", temp_dir);
|
||||
+ xmkfifo (fifo, 0666);
|
||||
+ add_temp_file (fifo);
|
||||
+ int ret;
|
||||
+ pthread_t thr;
|
||||
+ void *retval;
|
||||
+
|
||||
+ /* Test changing to/from c (cancellation disabled). */
|
||||
+
|
||||
+ verbose_printf ("Testing rc -> r\n");
|
||||
+ ret = sem_init (&sem, 0, 0);
|
||||
+ TEST_VERIFY_EXIT (ret == 0);
|
||||
+ thr = xpthread_create (NULL, test_rc_to_r, NULL);
|
||||
+ ret = sem_wait (&sem);
|
||||
+ TEST_VERIFY_EXIT (ret == 0);
|
||||
+ xpthread_cancel (thr);
|
||||
+ ret = pthread_join (thr, &retval);
|
||||
+ TEST_COMPARE (ret, 0);
|
||||
+ TEST_VERIFY (retval == PTHREAD_CANCELED);
|
||||
+ TEST_OPEN_AND_COMPARE_FILE_STRING (file3, "rc_to_r got to freopen");
|
||||
+
|
||||
+ verbose_printf ("Testing r -> rc\n");
|
||||
+ ret = sem_init (&sem, 0, 0);
|
||||
+ TEST_VERIFY_EXIT (ret == 0);
|
||||
+ thr = xpthread_create (NULL, test_r_to_rc, NULL);
|
||||
+ FILE *fp = xfopen (fifo, "w");
|
||||
+ ret = sem_wait (&sem);
|
||||
+ TEST_VERIFY_EXIT (ret == 0);
|
||||
+ /* This call happens while, or before, the other thread is waiting
|
||||
+ to read a character from the fifo. It thus verifies that
|
||||
+ cancellation does not occur from the fgetc call in that thread
|
||||
+ (it should instead occur only in pthread_testcancel call),
|
||||
+ because the expected string is only written to file3 after that
|
||||
+ thread closes the fifo. */
|
||||
+ xpthread_cancel (thr);
|
||||
+ fputc ('x', fp);
|
||||
+ xfclose (fp);
|
||||
+ ret = pthread_join (thr, &retval);
|
||||
+ TEST_COMPARE (ret, 0);
|
||||
+ TEST_VERIFY (retval == PTHREAD_CANCELED);
|
||||
+ TEST_OPEN_AND_COMPARE_FILE_STRING (file3, "r_to_rc got to fclose");
|
||||
+
|
||||
+ free (temp_dir);
|
||||
+ free (file1);
|
||||
+ free (file2);
|
||||
+ free (file3);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
||||
diff --git a/stdio-common/tst-freopen7.c b/stdio-common/tst-freopen7.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..03d0de798e3d2616
|
||||
--- /dev/null
|
||||
+++ b/stdio-common/tst-freopen7.c
|
||||
@@ -0,0 +1,2 @@
|
||||
+#define FREOPEN freopen
|
||||
+#include <tst-freopen7-main.c>
|
168
glibc-RHEL-46736-2.patch
Normal file
168
glibc-RHEL-46736-2.patch
Normal file
@ -0,0 +1,168 @@
|
||||
commit da55fae9e277a0c138d4395fee505e5d2f8b2b84
|
||||
Author: Carlos O'Donell <carlos@redhat.com>
|
||||
Date: Tue May 23 08:34:56 2023 -0400
|
||||
|
||||
support: Reformat Makefile.
|
||||
|
||||
Add list end markers.
|
||||
Sort text using scripts/sort-makefile-lines.py.
|
||||
|
||||
No code generation changes observed in non-test binary artifacts.
|
||||
No regressions on x86_64 and i686.
|
||||
|
||||
Conflicts:
|
||||
support/Makefile
|
||||
(different backport order)
|
||||
|
||||
|
||||
diff --git a/support/Makefile b/support/Makefile
|
||||
index 0273c0f6306720c9..17a4157563f9ecd6 100644
|
||||
--- a/support/Makefile
|
||||
+++ b/support/Makefile
|
||||
@@ -41,7 +41,7 @@ libsupport-routines = \
|
||||
resolv_response_context_free \
|
||||
resolv_test \
|
||||
set_fortify_handler \
|
||||
- support_stack_alloc \
|
||||
+ support-open-dev-null-range \
|
||||
support_become_root \
|
||||
support_can_chroot \
|
||||
support_capture_subprocess \
|
||||
@@ -65,12 +65,11 @@ libsupport-routines = \
|
||||
support_fuse \
|
||||
support_isolate_in_subprocess \
|
||||
support_need_proc \
|
||||
+ support_openpty \
|
||||
support_path_support_time64 \
|
||||
+ support_paths \
|
||||
support_process_state \
|
||||
support_ptrace \
|
||||
- support-open-dev-null-range \
|
||||
- support_openpty \
|
||||
- support_paths \
|
||||
support_quote_blob \
|
||||
support_quote_blob_wide \
|
||||
support_quote_string \
|
||||
@@ -84,6 +83,8 @@ libsupport-routines = \
|
||||
support_shared_allocate \
|
||||
support_small_stack_thread_attribute \
|
||||
support_socket_so_timestamp_time64 \
|
||||
+ support_stack_alloc \
|
||||
+ support_stack_alloc \
|
||||
support_stat_nanoseconds \
|
||||
support_subprocess \
|
||||
support_test_compare_blob \
|
||||
@@ -96,11 +97,11 @@ libsupport-routines = \
|
||||
support_write_file_string \
|
||||
temp_file \
|
||||
timespec \
|
||||
- timespec-time64 \
|
||||
timespec-add \
|
||||
timespec-add-time64 \
|
||||
timespec-sub \
|
||||
timespec-sub-time64 \
|
||||
+ timespec-time64 \
|
||||
write_message \
|
||||
xaccept \
|
||||
xaccept4 \
|
||||
@@ -108,6 +109,8 @@ libsupport-routines = \
|
||||
xbind \
|
||||
xcalloc \
|
||||
xchdir \
|
||||
+ xchmod \
|
||||
+ xchmod \
|
||||
xchroot \
|
||||
xclock_gettime \
|
||||
xclock_gettime_time64 \
|
||||
@@ -116,7 +119,6 @@ libsupport-routines = \
|
||||
xclone \
|
||||
xclose \
|
||||
xclosedir \
|
||||
- xchmod \
|
||||
xconnect \
|
||||
xcopy_file_range \
|
||||
xdlfcn \
|
||||
@@ -147,11 +149,17 @@ libsupport-routines = \
|
||||
xpipe \
|
||||
xpoll \
|
||||
xposix_memalign \
|
||||
+ xposix_spawn \
|
||||
+ xposix_spawn \
|
||||
+ xposix_spawn_file_actions_addclose \
|
||||
+ xposix_spawn_file_actions_addclose \
|
||||
+ xposix_spawn_file_actions_adddup2 \
|
||||
+ xposix_spawn_file_actions_adddup2 \
|
||||
xpthread_attr_destroy \
|
||||
xpthread_attr_init \
|
||||
+ xpthread_attr_setaffinity_np \
|
||||
xpthread_attr_setdetachstate \
|
||||
xpthread_attr_setguardsize \
|
||||
- xpthread_attr_setaffinity_np \
|
||||
xpthread_attr_setstack \
|
||||
xpthread_attr_setstacksize \
|
||||
xpthread_barrier_destroy \
|
||||
@@ -162,8 +170,8 @@ libsupport-routines = \
|
||||
xpthread_barrierattr_setpshared \
|
||||
xpthread_cancel \
|
||||
xpthread_check_return \
|
||||
- xpthread_cond_wait \
|
||||
xpthread_cond_signal \
|
||||
+ xpthread_cond_wait \
|
||||
xpthread_create \
|
||||
xpthread_detach \
|
||||
xpthread_join \
|
||||
@@ -182,8 +190,8 @@ libsupport-routines = \
|
||||
xpthread_mutexattr_setrobust \
|
||||
xpthread_mutexattr_settype \
|
||||
xpthread_once \
|
||||
- xpthread_rwlock_init \
|
||||
xpthread_rwlock_destroy \
|
||||
+ xpthread_rwlock_init \
|
||||
xpthread_rwlock_rdlock \
|
||||
xpthread_rwlock_unlock \
|
||||
xpthread_rwlock_wrlock \
|
||||
@@ -204,9 +212,6 @@ libsupport-routines = \
|
||||
xsigstack \
|
||||
xsocket \
|
||||
xstatx \
|
||||
- xposix_spawn \
|
||||
- xposix_spawn_file_actions_addclose \
|
||||
- xposix_spawn_file_actions_adddup2 \
|
||||
xstrdup \
|
||||
xstrndup \
|
||||
xsymlink \
|
||||
@@ -215,6 +220,7 @@ libsupport-routines = \
|
||||
xuselocale \
|
||||
xwaitpid \
|
||||
xwrite \
|
||||
+ # libsupport-routines
|
||||
|
||||
libsupport-static-only-routines := $(libsupport-routines)
|
||||
# Only build one variant of the library.
|
||||
@@ -278,8 +284,16 @@ LDLIBS-test-container = $(libsupport)
|
||||
others += test-container
|
||||
others-noinstall += test-container
|
||||
|
||||
-others += shell-container echo-container true-container
|
||||
-others-noinstall += shell-container echo-container true-container
|
||||
+others += \
|
||||
+ echo-container \
|
||||
+ shell-container \
|
||||
+ true-container \
|
||||
+ # others
|
||||
+others-noinstall += \
|
||||
+ echo-container \
|
||||
+ shell-container \
|
||||
+ true-container \
|
||||
+ # others-noinstall
|
||||
|
||||
others += $(LINKS_DSO_PROGRAM)
|
||||
others-noinstall += $(LINKS_DSO_PROGRAM)
|
||||
@@ -317,6 +331,7 @@ tests = \
|
||||
tst-xdirent \
|
||||
tst-xreadlink \
|
||||
tst-xsigstack \
|
||||
+ # tests
|
||||
|
||||
ifeq ($(run-built-tests),yes)
|
||||
tests-special = \
|
261
glibc-RHEL-46736-3.patch
Normal file
261
glibc-RHEL-46736-3.patch
Normal file
@ -0,0 +1,261 @@
|
||||
commit 96d0bf98cafd0b63721f369ca21ec64590551d47
|
||||
Author: Joseph Myers <josmyers@redhat.com>
|
||||
Date: Tue Sep 3 13:53:01 2024 +0000
|
||||
|
||||
Add support/ code for checking file contents
|
||||
|
||||
For use in freopen tests, add various support/ helper interfaces for
|
||||
use in checking file contents.
|
||||
|
||||
Tested for x86_64.
|
||||
|
||||
diff --git a/support/Makefile b/support/Makefile
|
||||
index 38ad266a0dec8e36..e70322cea06f137b 100644
|
||||
--- a/support/Makefile
|
||||
+++ b/support/Makefile
|
||||
@@ -48,6 +48,8 @@ libsupport-routines = \
|
||||
support_check_stat_fd \
|
||||
support_check_stat_path \
|
||||
support_chroot \
|
||||
+ support_compare_file_bytes \
|
||||
+ support_compare_file_string \
|
||||
support_copy_file \
|
||||
support_copy_file_range \
|
||||
support_create_timer \
|
||||
@@ -64,6 +66,8 @@ libsupport-routines = \
|
||||
support_fuse \
|
||||
support_isolate_in_subprocess \
|
||||
support_need_proc \
|
||||
+ support_open_and_compare_file_bytes \
|
||||
+ support_open_and_compare_file_string \
|
||||
support_openpty \
|
||||
support_path_support_time64 \
|
||||
support_paths \
|
||||
diff --git a/support/file_contents.h b/support/file_contents.h
|
||||
new file mode 100644
|
||||
index 0000000000000000..9b2d750aae8a885a
|
||||
--- /dev/null
|
||||
+++ b/support/file_contents.h
|
||||
@@ -0,0 +1,63 @@
|
||||
+/* Functionality for checking file contents.
|
||||
+ Copyright (C) 2024 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/>. */
|
||||
+
|
||||
+#ifndef SUPPORT_FILE_CONTENTS_H
|
||||
+#define SUPPORT_FILE_CONTENTS_H
|
||||
+
|
||||
+#include <support/check.h>
|
||||
+#include <stdio.h>
|
||||
+
|
||||
+__BEGIN_DECLS
|
||||
+
|
||||
+/* Check that an already-open file has exactly the given bytes,
|
||||
+ starting at the current location in the file. The file position
|
||||
+ indicator is updated to point after the bytes compared. Return 0
|
||||
+ if equal, 1 otherwise or on read error. */
|
||||
+int support_compare_file_bytes (FILE *fp, const char *contents, size_t length);
|
||||
+
|
||||
+/* Check that an already-open file has exactly the given string as
|
||||
+ contents, starting at the current offset. The file position
|
||||
+ indicator is updated to point after the bytes compared. Return 0
|
||||
+ if equal, 1 otherwise or on read error. */
|
||||
+int support_compare_file_string (FILE *fp, const char *contents);
|
||||
+
|
||||
+/* Check that a not-currently-open file has exactly the given bytes.
|
||||
+ Return 0 if equal, 1 otherwise or on read error. */
|
||||
+int support_open_and_compare_file_bytes (const char *file,
|
||||
+ const char *contents,
|
||||
+ size_t length);
|
||||
+
|
||||
+/* Check that a not-currently-open file has exactly the given string
|
||||
+ as contents, starting at the current offset. Return 0 if equal, 1
|
||||
+ otherwise or on read error. */
|
||||
+int support_open_and_compare_file_string (const char *file,
|
||||
+ const char *contents);
|
||||
+
|
||||
+/* Compare bytes read from an open file with the given string. The
|
||||
+ file position indicator is updated to point after the bytes
|
||||
+ compared. */
|
||||
+#define TEST_COMPARE_FILE_STRING(FP, CONTENTS) \
|
||||
+ TEST_COMPARE (support_compare_file_string (FP, CONTENTS), 0)
|
||||
+
|
||||
+/* Read a file and compare bytes read from it with the given string. */
|
||||
+#define TEST_OPEN_AND_COMPARE_FILE_STRING(FILE, CONTENTS) \
|
||||
+ TEST_COMPARE (support_open_and_compare_file_string (FILE, CONTENTS), 0)
|
||||
+
|
||||
+__END_DECLS
|
||||
+
|
||||
+#endif /* SUPPORT_FILE_CONTENTS_H */
|
||||
diff --git a/support/support_compare_file_bytes.c b/support/support_compare_file_bytes.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..e261e1da8f7b02b2
|
||||
--- /dev/null
|
||||
+++ b/support/support_compare_file_bytes.c
|
||||
@@ -0,0 +1,42 @@
|
||||
+/* Compare bytes from an open file.
|
||||
+ Copyright (C) 2024 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/file_contents.h>
|
||||
+
|
||||
+/* Check that an already-open file has exactly the given bytes,
|
||||
+ starting at the current offset. */
|
||||
+
|
||||
+int
|
||||
+support_compare_file_bytes (FILE *fp, const char *contents, size_t length)
|
||||
+{
|
||||
+ int c;
|
||||
+ while (length > 0)
|
||||
+ {
|
||||
+ c = getc (fp);
|
||||
+ if (c == EOF || (unsigned char) c != (unsigned char) contents[0])
|
||||
+ return 1;
|
||||
+ contents++;
|
||||
+ length--;
|
||||
+ }
|
||||
+ c = getc (fp);
|
||||
+ if (c != EOF || ferror (fp))
|
||||
+ return 1;
|
||||
+ return 0;
|
||||
+}
|
||||
diff --git a/support/support_compare_file_string.c b/support/support_compare_file_string.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..04513c3af197037d
|
||||
--- /dev/null
|
||||
+++ b/support/support_compare_file_string.c
|
||||
@@ -0,0 +1,28 @@
|
||||
+/* Compare string from an open file.
|
||||
+ Copyright (C) 2024 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 <string.h>
|
||||
+
|
||||
+#include <support/file_contents.h>
|
||||
+
|
||||
+int
|
||||
+support_compare_file_string (FILE *fp, const char *contents)
|
||||
+{
|
||||
+ return support_compare_file_bytes (fp, contents, strlen (contents));
|
||||
+}
|
||||
diff --git a/support/support_open_and_compare_file_bytes.c b/support/support_open_and_compare_file_bytes.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..f804ed8e460d82f0
|
||||
--- /dev/null
|
||||
+++ b/support/support_open_and_compare_file_bytes.c
|
||||
@@ -0,0 +1,33 @@
|
||||
+/* Compare bytes from a file.
|
||||
+ Copyright (C) 2024 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 <support/file_contents.h>
|
||||
+#include <support/xstdio.h>
|
||||
+
|
||||
+/* Check that a not-currently-open file has exactly the given
|
||||
+ bytes. */
|
||||
+
|
||||
+int
|
||||
+support_open_and_compare_file_bytes (const char *file, const char *contents,
|
||||
+ size_t length)
|
||||
+{
|
||||
+ FILE *fp = xfopen (file, "r");
|
||||
+ int ret = support_compare_file_bytes (fp, contents, length);
|
||||
+ xfclose (fp);
|
||||
+ return ret;
|
||||
+}
|
||||
diff --git a/support/support_open_and_compare_file_string.c b/support/support_open_and_compare_file_string.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..2b596d4c88b697f2
|
||||
--- /dev/null
|
||||
+++ b/support/support_open_and_compare_file_string.c
|
||||
@@ -0,0 +1,32 @@
|
||||
+/* Compare string from a file.
|
||||
+ Copyright (C) 2024 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 <string.h>
|
||||
+
|
||||
+#include <support/file_contents.h>
|
||||
+#include <support/xstdio.h>
|
||||
+
|
||||
+/* Check that a not-currently-open file has exactly the given string
|
||||
+ as contents, starting at the current offset. */
|
||||
+
|
||||
+int
|
||||
+support_open_and_compare_file_string (const char *file, const char *contents)
|
||||
+{
|
||||
+ return support_open_and_compare_file_bytes (file, contents,
|
||||
+ strlen (contents));
|
||||
+}
|
739
glibc-RHEL-46736-4.patch
Normal file
739
glibc-RHEL-46736-4.patch
Normal file
@ -0,0 +1,739 @@
|
||||
commit ed4bb289cf739f537deb735eaa01be531df084b9
|
||||
Author: Joseph Myers <josmyers@redhat.com>
|
||||
Date: Wed Sep 4 16:32:21 2024 +0000
|
||||
|
||||
Add more thorough tests of freopen
|
||||
|
||||
freopen is rather minimally tested in libio/tst-freopen and
|
||||
libio/test-freopen. Add some more thorough tests, covering different
|
||||
cases for change of mode in particular. The tests are run for both
|
||||
freopen and freopen64 (given that those functions have two separate
|
||||
copies of much of the code, so any bug fix directly in the freopen
|
||||
code would probably need applying in both places).
|
||||
|
||||
Note that there are two parts of the tests disabled because of bugs
|
||||
discovered through running the tests, with bug numbers given in
|
||||
comments. I expect to address those separately. The tests also don't
|
||||
cover changes to cancellation ("c" in mode); I think that will better
|
||||
be handled through a separate test. Also to handle separately:
|
||||
testing on stdin / stdout / stderr; documenting lack of support for
|
||||
streams opened with popen / fmemopen / open_memstream / fopencookie;
|
||||
maybe also a chroot test without /proc; maybe also more thorough tests
|
||||
for large file handling on 32-bit systems (freopen64).
|
||||
|
||||
Tested for x86_64.
|
||||
|
||||
Conflicts:
|
||||
stdio-common/Makefile
|
||||
(tst-fread already backported)
|
||||
|
||||
diff --git a/stdio-common/Makefile b/stdio-common/Makefile
|
||||
index ea8598bbe3a6dfdd..5eddc4bfbf4e7fb9 100644
|
||||
--- a/stdio-common/Makefile
|
||||
+++ b/stdio-common/Makefile
|
||||
@@ -175,6 +175,10 @@ tests := \
|
||||
tst-fphex \
|
||||
tst-fphex-wide \
|
||||
tst-fread \
|
||||
+ tst-freopen2 \
|
||||
+ tst-freopen3 \
|
||||
+ tst-freopen64-2 \
|
||||
+ tst-freopen64-3 \
|
||||
tst-fseek \
|
||||
tst-fwrite \
|
||||
tst-getline \
|
||||
@@ -246,6 +250,8 @@ tests-special += \
|
||||
ifeq (yes,$(build-shared))
|
||||
ifneq ($(PERL),no)
|
||||
tests-special += \
|
||||
+ $(objpfx)tst-freopen2-mem.out \
|
||||
+ $(objpfx)tst-freopen64-2-mem.out \
|
||||
$(objpfx)tst-getline-enomem-mem.out \
|
||||
$(objpfx)tst-getline-mem.out \
|
||||
$(objpfx)tst-printf-bz18872-mem.out \
|
||||
@@ -256,6 +262,10 @@ tests-special += \
|
||||
# tests-special
|
||||
|
||||
generated += \
|
||||
+ tst-freopen2-mem.out \
|
||||
+ tst-freopen2.mtrace \
|
||||
+ tst-freopen64-2-mem.out \
|
||||
+ tst-freopen64-2.mtrace \
|
||||
tst-getline-enomem-mem.out \
|
||||
tst-getline-enomem.mtrace \
|
||||
tst-getline-mem.out \
|
||||
@@ -328,6 +338,12 @@ tst-getline-ENV = \
|
||||
tst-getline-enomem-ENV = \
|
||||
MALLOC_TRACE=$(objpfx)tst-getline-enomem.mtrace \
|
||||
LD_PRELOAD=$(common-objpfx)malloc/libc_malloc_debug.so
|
||||
+tst-freopen2-ENV = \
|
||||
+ MALLOC_TRACE=$(objpfx)tst-freopen2.mtrace \
|
||||
+ LD_PRELOAD=$(common-objpfx)malloc/libc_malloc_debug.so
|
||||
+tst-freopen64-2-ENV = \
|
||||
+ MALLOC_TRACE=$(objpfx)tst-freopen64-2.mtrace \
|
||||
+ LD_PRELOAD=$(common-objpfx)malloc/libc_malloc_debug.so
|
||||
|
||||
$(objpfx)tst-unbputc.out: tst-unbputc.sh $(objpfx)tst-unbputc
|
||||
$(SHELL) $< $(common-objpfx) '$(test-program-prefix)'; \
|
||||
diff --git a/stdio-common/tst-freopen2-main.c b/stdio-common/tst-freopen2-main.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..22b21afebf709563
|
||||
--- /dev/null
|
||||
+++ b/stdio-common/tst-freopen2-main.c
|
||||
@@ -0,0 +1,526 @@
|
||||
+/* Test freopen.
|
||||
+ Copyright (C) 2024 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 <errno.h>
|
||||
+#include <fcntl.h>
|
||||
+#include <mcheck.h>
|
||||
+#include <stdio.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <wchar.h>
|
||||
+
|
||||
+#include <support/check.h>
|
||||
+#include <support/descriptors.h>
|
||||
+#include <support/file_contents.h>
|
||||
+#include <support/support.h>
|
||||
+#include <support/temp_file.h>
|
||||
+#include <support/test-driver.h>
|
||||
+#include <support/xstdio.h>
|
||||
+
|
||||
+#define START_TEST(DESC) \
|
||||
+ do \
|
||||
+ { \
|
||||
+ fds = support_descriptors_list (); \
|
||||
+ verbose_printf (DESC); \
|
||||
+ } \
|
||||
+ while (0)
|
||||
+
|
||||
+#define END_TEST \
|
||||
+ do \
|
||||
+ { \
|
||||
+ support_descriptors_check (fds); \
|
||||
+ support_descriptors_free (fds); \
|
||||
+ } \
|
||||
+ while (0)
|
||||
+
|
||||
+int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ mtrace ();
|
||||
+ struct support_descriptors *fds;
|
||||
+ char *temp_dir = support_create_temp_directory ("tst-freopen2");
|
||||
+ char *file1 = xasprintf ("%s/file1", temp_dir);
|
||||
+ support_write_file_string (file1, "file1");
|
||||
+ add_temp_file (file1);
|
||||
+ char *file2 = xasprintf ("%s/file2", temp_dir);
|
||||
+ support_write_file_string (file2, "file2");
|
||||
+ add_temp_file (file2);
|
||||
+ char *file3 = xasprintf ("%s/file3", temp_dir);
|
||||
+ char *file4 = xasprintf ("%s/file4", temp_dir);
|
||||
+ char *file1a = xasprintf ("%s/file1a", temp_dir);
|
||||
+ FILE *fp;
|
||||
+ int ret;
|
||||
+ wint_t wc;
|
||||
+
|
||||
+ /* Test each pair of old and new modes from r w a. */
|
||||
+
|
||||
+ START_TEST ("Testing r -> r\n");
|
||||
+ fp = xfopen (file1, "r");
|
||||
+ fp = FREOPEN (file2, "r", fp);
|
||||
+ TEST_VERIFY_EXIT (fp != NULL);
|
||||
+ TEST_COMPARE_FILE_STRING (fp, "file2");
|
||||
+ xfclose (fp);
|
||||
+ END_TEST;
|
||||
+
|
||||
+ START_TEST ("Testing r -> w\n");
|
||||
+ fp = xfopen (file1, "r");
|
||||
+ fp = FREOPEN (file2, "w", fp);
|
||||
+ TEST_VERIFY_EXIT (fp != NULL);
|
||||
+ ret = fputs ("File2new", fp);
|
||||
+ TEST_VERIFY (ret >= 0);
|
||||
+ xfclose (fp);
|
||||
+ TEST_OPEN_AND_COMPARE_FILE_STRING (file1, "file1");
|
||||
+ TEST_OPEN_AND_COMPARE_FILE_STRING (file2, "File2new");
|
||||
+ END_TEST;
|
||||
+
|
||||
+ START_TEST ("Testing r -> a\n");
|
||||
+ fp = xfopen (file1, "r");
|
||||
+ fp = FREOPEN (file2, "a", fp);
|
||||
+ TEST_VERIFY_EXIT (fp != NULL);
|
||||
+ ret = fputs ("3", fp);
|
||||
+ TEST_VERIFY (ret >= 0);
|
||||
+ xfclose (fp);
|
||||
+ TEST_OPEN_AND_COMPARE_FILE_STRING (file2, "File2new3");
|
||||
+ END_TEST;
|
||||
+
|
||||
+ START_TEST ("Testing w -> r\n");
|
||||
+ fp = xfopen (file1, "w");
|
||||
+ fp = FREOPEN (file2, "r", fp);
|
||||
+ TEST_VERIFY_EXIT (fp != NULL);
|
||||
+ TEST_COMPARE_FILE_STRING (fp, "File2new3");
|
||||
+ xfclose (fp);
|
||||
+ END_TEST;
|
||||
+
|
||||
+ START_TEST ("Testing w -> w\n");
|
||||
+ fp = xfopen (file1, "w");
|
||||
+ fp = FREOPEN (file2, "w", fp);
|
||||
+ TEST_VERIFY_EXIT (fp != NULL);
|
||||
+ ret = fputs ("next", fp);
|
||||
+ TEST_VERIFY (ret >= 0);
|
||||
+ xfclose (fp);
|
||||
+ TEST_OPEN_AND_COMPARE_FILE_STRING (file1, "");
|
||||
+ TEST_OPEN_AND_COMPARE_FILE_STRING (file2, "next");
|
||||
+ END_TEST;
|
||||
+
|
||||
+ START_TEST ("Testing w -> a\n");
|
||||
+ fp = xfopen (file1, "w");
|
||||
+ fp = FREOPEN (file2, "a", fp);
|
||||
+ TEST_VERIFY_EXIT (fp != NULL);
|
||||
+ ret = fputs ("4", fp);
|
||||
+ TEST_VERIFY (ret >= 0);
|
||||
+ xfclose (fp);
|
||||
+ TEST_OPEN_AND_COMPARE_FILE_STRING (file2, "next4");
|
||||
+ END_TEST;
|
||||
+
|
||||
+ START_TEST ("Testing a -> r\n");
|
||||
+ fp = xfopen (file1, "a");
|
||||
+ fp = FREOPEN (file2, "r", fp);
|
||||
+ TEST_VERIFY_EXIT (fp != NULL);
|
||||
+ TEST_COMPARE_FILE_STRING (fp, "next4");
|
||||
+ xfclose (fp);
|
||||
+ END_TEST;
|
||||
+
|
||||
+ START_TEST ("Testing a -> w\n");
|
||||
+ fp = xfopen (file1, "a");
|
||||
+ fp = FREOPEN (file2, "w", fp);
|
||||
+ TEST_VERIFY_EXIT (fp != NULL);
|
||||
+ ret = fputs ("another", fp);
|
||||
+ TEST_VERIFY (ret >= 0);
|
||||
+ xfclose (fp);
|
||||
+ TEST_OPEN_AND_COMPARE_FILE_STRING (file2, "another");
|
||||
+ END_TEST;
|
||||
+
|
||||
+ START_TEST ("Testing a -> a\n");
|
||||
+ fp = xfopen (file1, "a");
|
||||
+ fp = FREOPEN (file2, "a", fp);
|
||||
+ TEST_VERIFY_EXIT (fp != NULL);
|
||||
+ ret = fputs ("5", fp);
|
||||
+ TEST_VERIFY (ret >= 0);
|
||||
+ xfclose (fp);
|
||||
+ TEST_OPEN_AND_COMPARE_FILE_STRING (file2, "another5");
|
||||
+ END_TEST;
|
||||
+
|
||||
+ /* Test for file originally opened with fopen64. */
|
||||
+ START_TEST ("Testing fopen64 a -> a\n");
|
||||
+ fp = fopen64 (file1, "a");
|
||||
+ TEST_VERIFY_EXIT (fp != NULL);
|
||||
+ fp = FREOPEN (file2, "a", fp);
|
||||
+ TEST_VERIFY_EXIT (fp != NULL);
|
||||
+ ret = fputs ("64", fp);
|
||||
+ TEST_VERIFY (ret >= 0);
|
||||
+ xfclose (fp);
|
||||
+ TEST_OPEN_AND_COMPARE_FILE_STRING (file2, "another564");
|
||||
+ END_TEST;
|
||||
+
|
||||
+ /* Test calling freopen more than once on the same FILE *. */
|
||||
+
|
||||
+ START_TEST ("Testing r -> w -> r\n");
|
||||
+ fp = xfopen (file1, "r");
|
||||
+ fp = FREOPEN (file2, "w", fp);
|
||||
+ TEST_VERIFY_EXIT (fp != NULL);
|
||||
+ ret = fputs ("freopen-twice", fp);
|
||||
+ TEST_VERIFY (ret >= 0);
|
||||
+ fp = FREOPEN (file2, "r", fp);
|
||||
+ TEST_VERIFY_EXIT (fp != NULL);
|
||||
+ TEST_COMPARE_FILE_STRING (fp, "freopen-twice");
|
||||
+ xfclose (fp);
|
||||
+ TEST_OPEN_AND_COMPARE_FILE_STRING (file2, "freopen-twice");
|
||||
+ END_TEST;
|
||||
+
|
||||
+ START_TEST ("Testing r -> w -> r (exactly one freopen64)\n");
|
||||
+ fp = xfopen (file1, "r");
|
||||
+ fp = OTHER_FREOPEN (file2, "w", fp);
|
||||
+ TEST_VERIFY_EXIT (fp != NULL);
|
||||
+ ret = fputs ("freopen-twice64", fp);
|
||||
+ TEST_VERIFY (ret >= 0);
|
||||
+ fp = FREOPEN (file2, "r", fp);
|
||||
+ TEST_VERIFY_EXIT (fp != NULL);
|
||||
+ TEST_COMPARE_FILE_STRING (fp, "freopen-twice64");
|
||||
+ xfclose (fp);
|
||||
+ TEST_OPEN_AND_COMPARE_FILE_STRING (file2, "freopen-twice64");
|
||||
+ END_TEST;
|
||||
+
|
||||
+ /* Test changing to/from b (binary, no-op). */
|
||||
+
|
||||
+ START_TEST ("Testing rb -> r\n");
|
||||
+ fp = xfopen (file1, "rb");
|
||||
+ fp = FREOPEN (file2, "r", fp);
|
||||
+ TEST_VERIFY_EXIT (fp != NULL);
|
||||
+ TEST_COMPARE_FILE_STRING (fp, "freopen-twice64");
|
||||
+ xfclose (fp);
|
||||
+ END_TEST;
|
||||
+
|
||||
+ START_TEST ("Testing r -> rb\n");
|
||||
+ fp = xfopen (file1, "r");
|
||||
+ fp = FREOPEN (file2, "rb", fp);
|
||||
+ TEST_VERIFY_EXIT (fp != NULL);
|
||||
+ TEST_COMPARE_FILE_STRING (fp, "freopen-twice64");
|
||||
+ xfclose (fp);
|
||||
+ END_TEST;
|
||||
+
|
||||
+ /* Test changing to/from + (read-and-write). */
|
||||
+
|
||||
+ START_TEST ("Testing r -> w+\n");
|
||||
+ fp = xfopen (file1, "r");
|
||||
+ fp = FREOPEN (file2, "w+", fp);
|
||||
+ TEST_VERIFY_EXIT (fp != NULL);
|
||||
+ ret = fputs ("latest", fp);
|
||||
+ TEST_VERIFY (ret >= 0);
|
||||
+ ret = fseek (fp, 0, SEEK_SET);
|
||||
+ TEST_COMPARE (ret, 0);
|
||||
+ TEST_COMPARE_FILE_STRING (fp, "latest");
|
||||
+ xfclose (fp);
|
||||
+ TEST_OPEN_AND_COMPARE_FILE_STRING (file2, "latest");
|
||||
+ END_TEST;
|
||||
+
|
||||
+ START_TEST ("Testing w -> a+\n");
|
||||
+ fp = xfopen (file1, "w");
|
||||
+ fp = FREOPEN (file2, "a+", fp);
|
||||
+ TEST_VERIFY_EXIT (fp != NULL);
|
||||
+ ret = fputs ("suffix", fp);
|
||||
+ TEST_VERIFY (ret >= 0);
|
||||
+ ret = fseek (fp, 0, SEEK_SET);
|
||||
+ TEST_COMPARE (ret, 0);
|
||||
+ TEST_COMPARE_FILE_STRING (fp, "latestsuffix");
|
||||
+ xfclose (fp);
|
||||
+ TEST_OPEN_AND_COMPARE_FILE_STRING (file2, "latestsuffix");
|
||||
+ END_TEST;
|
||||
+
|
||||
+ START_TEST ("Testing a -> r+\n");
|
||||
+ fp = xfopen (file1, "a");
|
||||
+ fp = FREOPEN (file2, "r+", fp);
|
||||
+ TEST_VERIFY_EXIT (fp != NULL);
|
||||
+ TEST_COMPARE_FILE_STRING (fp, "latestsuffix");
|
||||
+ ret = fseek (fp, 0, SEEK_SET);
|
||||
+ TEST_COMPARE (ret, 0);
|
||||
+ ret = fputs ("new", fp);
|
||||
+ TEST_VERIFY (ret >= 0);
|
||||
+ xfclose (fp);
|
||||
+ TEST_OPEN_AND_COMPARE_FILE_STRING (file2, "newestsuffix");
|
||||
+ END_TEST;
|
||||
+
|
||||
+ START_TEST ("Testing r+ -> w\n");
|
||||
+ fp = xfopen (file1, "r+");
|
||||
+ fp = FREOPEN (file2, "w", fp);
|
||||
+ TEST_VERIFY_EXIT (fp != NULL);
|
||||
+ ret = fputs ("plusto", fp);
|
||||
+ TEST_VERIFY (ret >= 0);
|
||||
+ ret = fseek (fp, 0, SEEK_SET);
|
||||
+ TEST_COMPARE (ret, 0);
|
||||
+ errno = 0;
|
||||
+ TEST_COMPARE (fgetc (fp), EOF);
|
||||
+ TEST_COMPARE (errno, EBADF);
|
||||
+ clearerr (fp);
|
||||
+ xfclose (fp);
|
||||
+ TEST_OPEN_AND_COMPARE_FILE_STRING (file2, "plusto");
|
||||
+ END_TEST;
|
||||
+
|
||||
+ START_TEST ("Testing w+ -> a\n");
|
||||
+ fp = xfopen (file1, "w+");
|
||||
+ fp = FREOPEN (file2, "a", fp);
|
||||
+ TEST_VERIFY_EXIT (fp != NULL);
|
||||
+ ret = fputs ("more", fp);
|
||||
+ TEST_VERIFY (ret >= 0);
|
||||
+ ret = fseek (fp, 0, SEEK_SET);
|
||||
+ TEST_COMPARE (ret, 0);
|
||||
+ errno = 0;
|
||||
+ TEST_COMPARE (fgetc (fp), EOF);
|
||||
+ TEST_COMPARE (errno, EBADF);
|
||||
+ clearerr (fp);
|
||||
+ xfclose (fp);
|
||||
+ TEST_OPEN_AND_COMPARE_FILE_STRING (file2, "plustomore");
|
||||
+ END_TEST;
|
||||
+
|
||||
+ START_TEST ("Testing a+ -> r\n");
|
||||
+ fp = xfopen (file1, "a+");
|
||||
+ fp = FREOPEN (file2, "rr", fp);
|
||||
+ TEST_VERIFY_EXIT (fp != NULL);
|
||||
+ TEST_COMPARE_FILE_STRING (fp, "plustomore");
|
||||
+ ret = fputs ("2", fp);
|
||||
+ TEST_COMPARE (ret, EOF);
|
||||
+ clearerr (fp);
|
||||
+ xfclose (fp);
|
||||
+ TEST_OPEN_AND_COMPARE_FILE_STRING (file2, "plustomore");
|
||||
+ END_TEST;
|
||||
+
|
||||
+ /* Test changing to/from e (FD_CLOEXEC). */
|
||||
+
|
||||
+ START_TEST ("Testing re -> r\n");
|
||||
+ fp = xfopen (file1, "re");
|
||||
+ ret = fcntl (fileno (fp), F_GETFD);
|
||||
+ TEST_VERIFY (ret != -1);
|
||||
+ TEST_COMPARE (ret & FD_CLOEXEC, FD_CLOEXEC);
|
||||
+ fp = FREOPEN (file2, "r", fp);
|
||||
+ TEST_VERIFY_EXIT (fp != NULL);
|
||||
+ ret = fcntl (fileno (fp), F_GETFD);
|
||||
+ TEST_VERIFY (ret != -1);
|
||||
+#if 0 /* Fails to clear FD_CLOEXEC (bug 32134). */
|
||||
+ TEST_COMPARE (ret & FD_CLOEXEC, 0);
|
||||
+#endif
|
||||
+ TEST_COMPARE_FILE_STRING (fp, "plustomore");
|
||||
+ xfclose (fp);
|
||||
+ END_TEST;
|
||||
+
|
||||
+ START_TEST ("Testing r -> re\n");
|
||||
+ fp = xfopen (file1, "r");
|
||||
+ ret = fcntl (fileno (fp), F_GETFD);
|
||||
+ TEST_VERIFY (ret != -1);
|
||||
+ TEST_COMPARE (ret & FD_CLOEXEC, 0);
|
||||
+ fp = FREOPEN (file2, "re", fp);
|
||||
+ TEST_VERIFY_EXIT (fp != NULL);
|
||||
+ ret = fcntl (fileno (fp), F_GETFD);
|
||||
+ TEST_VERIFY (ret != -1);
|
||||
+ TEST_COMPARE (ret & FD_CLOEXEC, FD_CLOEXEC);
|
||||
+ TEST_COMPARE_FILE_STRING (fp, "plustomore");
|
||||
+ xfclose (fp);
|
||||
+ END_TEST;
|
||||
+
|
||||
+ /* Test changing to/from m (mmap) (a no-op as far as testing
|
||||
+ semantics is concerned). */
|
||||
+
|
||||
+ START_TEST ("Testing rm -> r\n");
|
||||
+ fp = xfopen (file1, "rm");
|
||||
+ fp = FREOPEN (file2, "r", fp);
|
||||
+ TEST_VERIFY_EXIT (fp != NULL);
|
||||
+ TEST_COMPARE_FILE_STRING (fp, "plustomore");
|
||||
+ xfclose (fp);
|
||||
+ END_TEST;
|
||||
+
|
||||
+ START_TEST ("Testing r -> rm\n");
|
||||
+ fp = xfopen (file1, "r");
|
||||
+ fp = FREOPEN (file2, "rm", fp);
|
||||
+ TEST_VERIFY_EXIT (fp != NULL);
|
||||
+ TEST_COMPARE_FILE_STRING (fp, "plustomore");
|
||||
+ xfclose (fp);
|
||||
+ END_TEST;
|
||||
+
|
||||
+ /* Test changing to/from x (O_EXCL). */
|
||||
+
|
||||
+ START_TEST ("Testing wx -> w\n");
|
||||
+ fp = xfopen (file3, "wx");
|
||||
+ add_temp_file (file3);
|
||||
+ fp = FREOPEN (file2, "w", fp);
|
||||
+ TEST_VERIFY_EXIT (fp != NULL);
|
||||
+ ret = fputs ("wxtow", fp);
|
||||
+ TEST_VERIFY (ret >= 0);
|
||||
+ xfclose (fp);
|
||||
+ TEST_OPEN_AND_COMPARE_FILE_STRING (file2, "wxtow");
|
||||
+ END_TEST;
|
||||
+
|
||||
+ START_TEST ("Testing w -> wx (file does not exist)\n");
|
||||
+ fp = xfopen (file1, "w");
|
||||
+ fp = FREOPEN (file4, "wx", fp);
|
||||
+ TEST_VERIFY_EXIT (fp != NULL);
|
||||
+ add_temp_file (file4);
|
||||
+ ret = fputs ("wtowx", fp);
|
||||
+ TEST_VERIFY (ret >= 0);
|
||||
+ xfclose (fp);
|
||||
+ TEST_OPEN_AND_COMPARE_FILE_STRING (file4, "wtowx");
|
||||
+ END_TEST;
|
||||
+
|
||||
+ /* Test with ,ccs=CHARSET. */
|
||||
+
|
||||
+ START_TEST ("testing w,ccs=utf-8 -> r\n");
|
||||
+ fp = xfopen (file1, "w,ccs=utf-8");
|
||||
+ ret = fputws (L"\xc0\xc1", fp);
|
||||
+ TEST_VERIFY (ret >= 0);
|
||||
+ fp = FREOPEN (file2, "r", fp);
|
||||
+ TEST_VERIFY_EXIT (fp != NULL);
|
||||
+ TEST_COMPARE_FILE_STRING (fp, "wxtow");
|
||||
+ xfclose (fp);
|
||||
+ END_TEST;
|
||||
+
|
||||
+ START_TEST ("testing w,ccs=iso-8859-1 -> r,ccs=utf-8\n");
|
||||
+ fp = xfopen (file2, "w,ccs=iso-8859-1");
|
||||
+ ret = fputws (L"\xc0\xc1", fp);
|
||||
+ TEST_VERIFY (ret >= 0);
|
||||
+#if 0 /* Doesn't work (bug 23675). */
|
||||
+ fp = FREOPEN (file1, "r,ccs=utf-8", fp);
|
||||
+ TEST_VERIFY_EXIT (fp != NULL);
|
||||
+#else /* Works instead. */
|
||||
+ xfclose (fp);
|
||||
+ fp = xfopen (file1, "r,ccs=utf-8");
|
||||
+#endif
|
||||
+ wc = fgetwc (fp);
|
||||
+ TEST_COMPARE (wc, (wint_t) 0xc0);
|
||||
+ wc = fgetwc (fp);
|
||||
+ TEST_COMPARE (wc, (wint_t) 0xc1);
|
||||
+ wc = fgetwc (fp);
|
||||
+ TEST_COMPARE (wc, WEOF);
|
||||
+ xfclose (fp);
|
||||
+ END_TEST;
|
||||
+
|
||||
+ START_TEST ("testing r,ccs=utf-8 -> r\n");
|
||||
+ fp = xfopen (file1, "r,ccs=utf-8");
|
||||
+ fp = FREOPEN (file1, "r", fp);
|
||||
+ TEST_VERIFY_EXIT (fp != NULL);
|
||||
+ TEST_COMPARE_FILE_STRING (fp, "\u00c0\u00c1");
|
||||
+ xfclose (fp);
|
||||
+ END_TEST;
|
||||
+
|
||||
+ /* Test that errors closing the old file are ignored. */
|
||||
+
|
||||
+ START_TEST ("testing errors closing old file ignored\n");
|
||||
+ fp = xfopen ("/dev/full", "w");
|
||||
+ fputc ('x', fp);
|
||||
+ fp = FREOPEN (file1, "r", fp);
|
||||
+ TEST_VERIFY_EXIT (fp != NULL);
|
||||
+ TEST_COMPARE_FILE_STRING (fp, "\u00c0\u00c1");
|
||||
+ xfclose (fp);
|
||||
+ END_TEST;
|
||||
+
|
||||
+ /* Test that error / EOF state from the old file are cleared. */
|
||||
+
|
||||
+ START_TEST ("testing error state from old file cleared\n");
|
||||
+ fp = xfopen ("/dev/full", "w");
|
||||
+ fputc ('x', fp);
|
||||
+ fflush (fp);
|
||||
+ TEST_VERIFY (ferror (fp));
|
||||
+ TEST_VERIFY (!feof (fp));
|
||||
+ fp = FREOPEN (file2, "w", fp);
|
||||
+ TEST_VERIFY_EXIT (fp != NULL);
|
||||
+ TEST_VERIFY (!ferror (fp));
|
||||
+ TEST_VERIFY (!feof (fp));
|
||||
+ xfclose (fp);
|
||||
+ END_TEST;
|
||||
+
|
||||
+ START_TEST ("testing EOF state from old file cleared\n");
|
||||
+ fp = xfopen ("/dev/null", "r");
|
||||
+ fgetc (fp);
|
||||
+ TEST_VERIFY (!ferror (fp));
|
||||
+ TEST_VERIFY (feof (fp));
|
||||
+ fp = FREOPEN (file2, "r", fp);
|
||||
+ TEST_VERIFY_EXIT (fp != NULL);
|
||||
+ TEST_VERIFY (!ferror (fp));
|
||||
+ TEST_VERIFY (!feof (fp));
|
||||
+ xfclose (fp);
|
||||
+ END_TEST;
|
||||
+
|
||||
+ /* Test freopen with NULL, same mode (should flush content and reset
|
||||
+ file offset). */
|
||||
+
|
||||
+ START_TEST ("testing freopen with NULL, same mode\n");
|
||||
+ fp = xfopen (file1, "r+");
|
||||
+ ret = fputs ("same mode", fp);
|
||||
+ TEST_VERIFY (ret >= 0);
|
||||
+ fp = FREOPEN (NULL, "r+", fp);
|
||||
+ TEST_VERIFY_EXIT (fp != NULL);
|
||||
+ TEST_COMPARE_FILE_STRING (fp, "same mode");
|
||||
+ xfclose (fp);
|
||||
+ END_TEST;
|
||||
+
|
||||
+ /* Test freopen with NULL, different mode. */
|
||||
+
|
||||
+ START_TEST ("testing freopen with NULL, different mode\n");
|
||||
+ fp = xfopen (file1, "w");
|
||||
+ ret = fputs ("different mode", fp);
|
||||
+ TEST_VERIFY (ret >= 0);
|
||||
+ fp = FREOPEN (NULL, "r", fp);
|
||||
+ TEST_VERIFY_EXIT (fp != NULL);
|
||||
+ TEST_COMPARE_FILE_STRING (fp, "different mode");
|
||||
+ xfclose (fp);
|
||||
+ END_TEST;
|
||||
+
|
||||
+ /* Test freopen with NULL, renamed file. This verifies that
|
||||
+ reopening succeeds (and resets the file position indicator to
|
||||
+ start of file) even when the original path could no longer be
|
||||
+ opened. */
|
||||
+
|
||||
+ START_TEST ("testing freopen with NULL, renamed file\n");
|
||||
+ fp = xfopen (file1, "r+");
|
||||
+ ret = fputs ("file has been renamed", fp);
|
||||
+ TEST_VERIFY (ret >= 0);
|
||||
+ ret = rename (file1, file1a);
|
||||
+ TEST_COMPARE (ret, 0);
|
||||
+ fp = FREOPEN (NULL, "r+", fp);
|
||||
+ TEST_VERIFY_EXIT (fp != NULL);
|
||||
+ TEST_COMPARE_FILE_STRING (fp, "file has been renamed");
|
||||
+ xfclose (fp);
|
||||
+ ret = rename (file1a, file1);
|
||||
+ TEST_COMPARE (ret, 0);
|
||||
+ END_TEST;
|
||||
+
|
||||
+ /* Test freopen with NULL, deleted file. This verifies that
|
||||
+ reopening succeeds (and resets the file position indicator to
|
||||
+ start of file) even when the original path could no longer be
|
||||
+ opened. */
|
||||
+
|
||||
+ START_TEST ("testing freopen with NULL, deleted file\n");
|
||||
+ fp = xfopen (file1, "r+");
|
||||
+ ret = fputs ("file has now been deleted", fp);
|
||||
+ TEST_VERIFY (ret >= 0);
|
||||
+ ret = remove (file1);
|
||||
+ TEST_COMPARE (ret, 0);
|
||||
+ fp = FREOPEN (NULL, "r+", fp);
|
||||
+ TEST_VERIFY_EXIT (fp != NULL);
|
||||
+ TEST_COMPARE_FILE_STRING (fp, "file has now been deleted");
|
||||
+ xfclose (fp);
|
||||
+ /* Recreate the file so it is present when expected for temporary
|
||||
+ file deletion. */
|
||||
+ support_write_file_string (file1, "file1");
|
||||
+ END_TEST;
|
||||
+
|
||||
+ free (temp_dir);
|
||||
+ free (file1);
|
||||
+ free (file2);
|
||||
+ free (file3);
|
||||
+ free (file4);
|
||||
+ free (file1a);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
||||
diff --git a/stdio-common/tst-freopen2.c b/stdio-common/tst-freopen2.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..11ec7a9783b7caa3
|
||||
--- /dev/null
|
||||
+++ b/stdio-common/tst-freopen2.c
|
||||
@@ -0,0 +1,3 @@
|
||||
+#define FREOPEN freopen
|
||||
+#define OTHER_FREOPEN freopen64
|
||||
+#include <tst-freopen2-main.c>
|
||||
diff --git a/stdio-common/tst-freopen3-main.c b/stdio-common/tst-freopen3-main.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..5107e1f98e189e4b
|
||||
--- /dev/null
|
||||
+++ b/stdio-common/tst-freopen3-main.c
|
||||
@@ -0,0 +1,90 @@
|
||||
+/* Test freopen failure.
|
||||
+ Copyright (C) 2024 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 <errno.h>
|
||||
+#include <fcntl.h>
|
||||
+#include <stdio.h>
|
||||
+#include <stdlib.h>
|
||||
+
|
||||
+#include <support/check.h>
|
||||
+#include <support/descriptors.h>
|
||||
+#include <support/file_contents.h>
|
||||
+#include <support/support.h>
|
||||
+#include <support/temp_file.h>
|
||||
+#include <support/test-driver.h>
|
||||
+#include <support/xstdio.h>
|
||||
+
|
||||
+#define START_TEST(DESC) \
|
||||
+ do \
|
||||
+ { \
|
||||
+ fds = support_descriptors_list (); \
|
||||
+ verbose_printf (DESC); \
|
||||
+ } \
|
||||
+ while (0)
|
||||
+
|
||||
+#define END_TEST \
|
||||
+ do \
|
||||
+ { \
|
||||
+ support_descriptors_check (fds); \
|
||||
+ support_descriptors_free (fds); \
|
||||
+ } \
|
||||
+ while (0)
|
||||
+
|
||||
+int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ struct support_descriptors *fds;
|
||||
+ char *temp_dir = support_create_temp_directory ("tst-freopen3");
|
||||
+ char *file1 = xasprintf ("%s/file1", temp_dir);
|
||||
+ support_write_file_string (file1, "file1");
|
||||
+ add_temp_file (file1);
|
||||
+ char *file2 = xasprintf ("%s/file2", temp_dir);
|
||||
+ support_write_file_string (file2, "file2");
|
||||
+ add_temp_file (file2);
|
||||
+ char *file_nodir = xasprintf ("%s/nodir/file", temp_dir);
|
||||
+ FILE *fp;
|
||||
+ int ret;
|
||||
+ int fd;
|
||||
+
|
||||
+ START_TEST ("Testing w -> wx (file exists)\n");
|
||||
+ fp = xfopen (file1, "w");
|
||||
+ fp = FREOPEN (file2, "wx", fp);
|
||||
+ TEST_VERIFY (fp == NULL);
|
||||
+ END_TEST;
|
||||
+
|
||||
+ /* Test old file is closed even when opening the new file fails. */
|
||||
+
|
||||
+ START_TEST ("testing r -> r (opening new file fails)\n");
|
||||
+ fp = xfopen (file1, "r");
|
||||
+ fd = fileno (fp);
|
||||
+ fp = FREOPEN (file_nodir, "r", fp);
|
||||
+ TEST_VERIFY (fp == NULL);
|
||||
+ errno = 0;
|
||||
+ ret = fcntl (fd, F_GETFL);
|
||||
+ TEST_COMPARE (ret, -1);
|
||||
+ TEST_COMPARE (errno, EBADF);
|
||||
+ END_TEST;
|
||||
+
|
||||
+ free (temp_dir);
|
||||
+ free (file1);
|
||||
+ free (file2);
|
||||
+ free (file_nodir);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
||||
diff --git a/stdio-common/tst-freopen3.c b/stdio-common/tst-freopen3.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..5041b6b2332c8af1
|
||||
--- /dev/null
|
||||
+++ b/stdio-common/tst-freopen3.c
|
||||
@@ -0,0 +1,2 @@
|
||||
+#define FREOPEN freopen
|
||||
+#include <tst-freopen3-main.c>
|
||||
diff --git a/stdio-common/tst-freopen64-2.c b/stdio-common/tst-freopen64-2.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..88fdc64d8c6548f5
|
||||
--- /dev/null
|
||||
+++ b/stdio-common/tst-freopen64-2.c
|
||||
@@ -0,0 +1,3 @@
|
||||
+#define FREOPEN freopen64
|
||||
+#define OTHER_FREOPEN freopen
|
||||
+#include <tst-freopen2-main.c>
|
||||
diff --git a/stdio-common/tst-freopen64-3.c b/stdio-common/tst-freopen64-3.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..b91b6d2c033a1a79
|
||||
--- /dev/null
|
||||
+++ b/stdio-common/tst-freopen64-3.c
|
||||
@@ -0,0 +1,2 @@
|
||||
+#define FREOPEN freopen64
|
||||
+#include <tst-freopen3-main.c>
|
69
glibc-RHEL-46736-5.patch
Normal file
69
glibc-RHEL-46736-5.patch
Normal file
@ -0,0 +1,69 @@
|
||||
commit f512634ddef242ef0ff025ddeba64ce51035040f
|
||||
Author: Joseph Myers <josmyers@redhat.com>
|
||||
Date: Thu Sep 5 11:15:29 2024 +0000
|
||||
|
||||
Clear flags2 flags set from mode in freopen (bug 32134)
|
||||
|
||||
As reported in bug 32134, freopen does not clear the flags set in
|
||||
fp->_flags2 by the "e", "m" or "c" mode characters. Clear these so
|
||||
that they can be set or not as appropriate from the mode string passed
|
||||
to freopen. The relevant test for "e" in tst-freopen2-main.c is
|
||||
enabled accordingly; "c" is expected to be covered in a separately
|
||||
written test (and while tst-freopen2-main.c does include transitions
|
||||
to and from "m", that's not really a semantic flag intended to result
|
||||
in behaving in an observably different way).
|
||||
|
||||
Tested for x86_64.
|
||||
|
||||
diff --git a/libio/freopen.c b/libio/freopen.c
|
||||
index c947a5aecfde3c80..bed034d89441f200 100644
|
||||
--- a/libio/freopen.c
|
||||
+++ b/libio/freopen.c
|
||||
@@ -63,6 +63,9 @@ freopen (const char *filename, const char *mode, FILE *fp)
|
||||
up here. */
|
||||
_IO_old_file_close_it (fp);
|
||||
_IO_JUMPS_FUNC_UPDATE (fp, &_IO_old_file_jumps);
|
||||
+ fp->_flags2 &= ~(_IO_FLAGS2_MMAP
|
||||
+ | _IO_FLAGS2_NOTCANCEL
|
||||
+ | _IO_FLAGS2_CLOEXEC);
|
||||
result = _IO_old_file_fopen (fp, gfilename, mode);
|
||||
}
|
||||
else
|
||||
@@ -72,6 +75,9 @@ freopen (const char *filename, const char *mode, FILE *fp)
|
||||
_IO_JUMPS_FILE_plus (fp) = &_IO_file_jumps;
|
||||
if (_IO_vtable_offset (fp) == 0 && fp->_wide_data != NULL)
|
||||
fp->_wide_data->_wide_vtable = &_IO_wfile_jumps;
|
||||
+ fp->_flags2 &= ~(_IO_FLAGS2_MMAP
|
||||
+ | _IO_FLAGS2_NOTCANCEL
|
||||
+ | _IO_FLAGS2_CLOEXEC);
|
||||
result = _IO_file_fopen (fp, gfilename, mode, 1);
|
||||
if (result != NULL)
|
||||
result = __fopen_maybe_mmap (result);
|
||||
diff --git a/libio/freopen64.c b/libio/freopen64.c
|
||||
index fb02c201bd83c401..9a314c65c1d8a5a4 100644
|
||||
--- a/libio/freopen64.c
|
||||
+++ b/libio/freopen64.c
|
||||
@@ -56,6 +56,9 @@ freopen64 (const char *filename, const char *mode, FILE *fp)
|
||||
_IO_JUMPS_FILE_plus (fp) = &_IO_file_jumps;
|
||||
if (_IO_vtable_offset (fp) == 0 && fp->_wide_data != NULL)
|
||||
fp->_wide_data->_wide_vtable = &_IO_wfile_jumps;
|
||||
+ fp->_flags2 &= ~(_IO_FLAGS2_MMAP
|
||||
+ | _IO_FLAGS2_NOTCANCEL
|
||||
+ | _IO_FLAGS2_CLOEXEC);
|
||||
result = _IO_file_fopen (fp, gfilename, mode, 0);
|
||||
fp->_flags2 &= ~_IO_FLAGS2_NOCLOSE;
|
||||
if (result != NULL)
|
||||
diff --git a/stdio-common/tst-freopen2-main.c b/stdio-common/tst-freopen2-main.c
|
||||
index 22b21afebf709563..5dad41c76b02e6de 100644
|
||||
--- a/stdio-common/tst-freopen2-main.c
|
||||
+++ b/stdio-common/tst-freopen2-main.c
|
||||
@@ -308,9 +308,7 @@ do_test (void)
|
||||
TEST_VERIFY_EXIT (fp != NULL);
|
||||
ret = fcntl (fileno (fp), F_GETFD);
|
||||
TEST_VERIFY (ret != -1);
|
||||
-#if 0 /* Fails to clear FD_CLOEXEC (bug 32134). */
|
||||
TEST_COMPARE (ret & FD_CLOEXEC, 0);
|
||||
-#endif
|
||||
TEST_COMPARE_FILE_STRING (fp, "plustomore");
|
||||
xfclose (fp);
|
||||
END_TEST;
|
119
glibc-RHEL-46736-6.patch
Normal file
119
glibc-RHEL-46736-6.patch
Normal file
@ -0,0 +1,119 @@
|
||||
commit 9c0d6f7a1046aba111e25e34ec07242853e859dc
|
||||
Author: Joseph Myers <josmyers@redhat.com>
|
||||
Date: Thu Sep 5 11:16:59 2024 +0000
|
||||
|
||||
Fix memory leak on freopen error return (bug 32140)
|
||||
|
||||
As reported in bug 32140, freopen leaks the FILE object when it
|
||||
returns NULL: there is no valid use of the FILE * pointer (including
|
||||
passing to freopen again or to fclose) after such an error return, so
|
||||
the underlying object should be freed. Add code to free it.
|
||||
|
||||
Note 1: while I think it's clear from the relevant standards that the
|
||||
object should be freed and the FILE * can't be used after the call in
|
||||
this case (the stream is closed, which ends the lifetime of the FILE),
|
||||
it's entirely possible that some existing code does in fact try to use
|
||||
the existing FILE * in some way and could be broken by this change.
|
||||
(Though the most common case for freopen may be stdin / stdout /
|
||||
stderr, which _IO_deallocate_file explicitly checks for and does not
|
||||
deallocate.)
|
||||
|
||||
Note 2: the deallocation is only done in the _IO_IS_FILEBUF case.
|
||||
Other kinds of streams bypass all the freopen logic handling closing
|
||||
the file, meaning a call to _IO_deallocate_file would neither be safe
|
||||
(the FILE might still be linked into the list of all open FILEs) nor
|
||||
sufficient (other internal memory allocations associated with the file
|
||||
would not have been freed). I think the validity of freopen for any
|
||||
other kind of stream will need clarifying with the Austin Group, but
|
||||
if it is valid in any such case (where "valid" means "not undefined
|
||||
behavior so required to close the stream" rather than "required to
|
||||
successfully associate the stream with the new file in cases where
|
||||
fopen would work"), more significant changes would be needed to ensure
|
||||
the stream gets fully closed.
|
||||
|
||||
Tested for x86_64.
|
||||
|
||||
diff --git a/libio/freopen.c b/libio/freopen.c
|
||||
index bed034d89441f200..03f8961a61b12e80 100644
|
||||
--- a/libio/freopen.c
|
||||
+++ b/libio/freopen.c
|
||||
@@ -114,5 +114,7 @@ freopen (const char *filename, const char *mode, FILE *fp)
|
||||
|
||||
end:
|
||||
_IO_release_lock (fp);
|
||||
+ if (result == NULL && (fp->_flags & _IO_IS_FILEBUF) != 0)
|
||||
+ _IO_deallocate_file (fp);
|
||||
return result;
|
||||
}
|
||||
diff --git a/libio/freopen64.c b/libio/freopen64.c
|
||||
index 9a314c65c1d8a5a4..abcbd80a5bd92e69 100644
|
||||
--- a/libio/freopen64.c
|
||||
+++ b/libio/freopen64.c
|
||||
@@ -94,5 +94,7 @@ freopen64 (const char *filename, const char *mode, FILE *fp)
|
||||
|
||||
end:
|
||||
_IO_release_lock (fp);
|
||||
+ if (result == NULL && (fp->_flags & _IO_IS_FILEBUF) != 0)
|
||||
+ _IO_deallocate_file (fp);
|
||||
return result;
|
||||
}
|
||||
diff --git a/stdio-common/Makefile b/stdio-common/Makefile
|
||||
index 5eddc4bfbf4e7fb9..bd3c785537ba0330 100644
|
||||
--- a/stdio-common/Makefile
|
||||
+++ b/stdio-common/Makefile
|
||||
@@ -251,7 +251,9 @@ ifeq (yes,$(build-shared))
|
||||
ifneq ($(PERL),no)
|
||||
tests-special += \
|
||||
$(objpfx)tst-freopen2-mem.out \
|
||||
+ $(objpfx)tst-freopen3-mem.out \
|
||||
$(objpfx)tst-freopen64-2-mem.out \
|
||||
+ $(objpfx)tst-freopen64-3-mem.out \
|
||||
$(objpfx)tst-getline-enomem-mem.out \
|
||||
$(objpfx)tst-getline-mem.out \
|
||||
$(objpfx)tst-printf-bz18872-mem.out \
|
||||
@@ -264,8 +266,12 @@ tests-special += \
|
||||
generated += \
|
||||
tst-freopen2-mem.out \
|
||||
tst-freopen2.mtrace \
|
||||
+ tst-freopen3-mem.out \
|
||||
+ tst-freopen3.mtrace \
|
||||
tst-freopen64-2-mem.out \
|
||||
tst-freopen64-2.mtrace \
|
||||
+ tst-freopen64-3-mem.out \
|
||||
+ tst-freopen64-3.mtrace \
|
||||
tst-getline-enomem-mem.out \
|
||||
tst-getline-enomem.mtrace \
|
||||
tst-getline-mem.out \
|
||||
@@ -344,6 +350,12 @@ tst-freopen2-ENV = \
|
||||
tst-freopen64-2-ENV = \
|
||||
MALLOC_TRACE=$(objpfx)tst-freopen64-2.mtrace \
|
||||
LD_PRELOAD=$(common-objpfx)malloc/libc_malloc_debug.so
|
||||
+tst-freopen3-ENV = \
|
||||
+ MALLOC_TRACE=$(objpfx)tst-freopen3.mtrace \
|
||||
+ LD_PRELOAD=$(common-objpfx)malloc/libc_malloc_debug.so
|
||||
+tst-freopen64-3-ENV = \
|
||||
+ MALLOC_TRACE=$(objpfx)tst-freopen64-3.mtrace \
|
||||
+ LD_PRELOAD=$(common-objpfx)malloc/libc_malloc_debug.so
|
||||
|
||||
$(objpfx)tst-unbputc.out: tst-unbputc.sh $(objpfx)tst-unbputc
|
||||
$(SHELL) $< $(common-objpfx) '$(test-program-prefix)'; \
|
||||
diff --git a/stdio-common/tst-freopen3-main.c b/stdio-common/tst-freopen3-main.c
|
||||
index 5107e1f98e189e4b..990a6e5921843793 100644
|
||||
--- a/stdio-common/tst-freopen3-main.c
|
||||
+++ b/stdio-common/tst-freopen3-main.c
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
+#include <mcheck.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
@@ -48,6 +49,7 @@
|
||||
int
|
||||
do_test (void)
|
||||
{
|
||||
+ mtrace ();
|
||||
struct support_descriptors *fds;
|
||||
char *temp_dir = support_create_temp_directory ("tst-freopen3");
|
||||
char *file1 = xasprintf ("%s/file1", temp_dir);
|
86
glibc-RHEL-46736-7.patch
Normal file
86
glibc-RHEL-46736-7.patch
Normal file
@ -0,0 +1,86 @@
|
||||
commit e44ca1c085b3bd41266c882ea1cb0fd436231635
|
||||
Author: Joseph Myers <josmyers@redhat.com>
|
||||
Date: Thu Sep 5 20:08:10 2024 +0000
|
||||
|
||||
Fix freopen handling of ,ccs= (bug 23675)
|
||||
|
||||
As reported in bug 23675 and shown up in the recently added tests of
|
||||
different cases of freopen (relevant part of the test currently
|
||||
conditioned under #if 0 to avoid a failure resulting from this bug),
|
||||
freopen wrongly forces the stream to unoriented even when a mode with
|
||||
,ccs= is specified, though such a mode is supposed to result in a
|
||||
wide-oriented stream. Move the clearing of _mode to before the actual
|
||||
reopening occurs, so that the main fopen implementation can leave a
|
||||
wide-oriented stream in the ,ccs= case.
|
||||
|
||||
Tested for x86_64.
|
||||
|
||||
diff --git a/libio/freopen.c b/libio/freopen.c
|
||||
index 03f8961a61b12e80..d71a4cfffdc35280 100644
|
||||
--- a/libio/freopen.c
|
||||
+++ b/libio/freopen.c
|
||||
@@ -66,6 +66,7 @@ freopen (const char *filename, const char *mode, FILE *fp)
|
||||
fp->_flags2 &= ~(_IO_FLAGS2_MMAP
|
||||
| _IO_FLAGS2_NOTCANCEL
|
||||
| _IO_FLAGS2_CLOEXEC);
|
||||
+ fp->_mode = 0;
|
||||
result = _IO_old_file_fopen (fp, gfilename, mode);
|
||||
}
|
||||
else
|
||||
@@ -78,6 +79,7 @@ freopen (const char *filename, const char *mode, FILE *fp)
|
||||
fp->_flags2 &= ~(_IO_FLAGS2_MMAP
|
||||
| _IO_FLAGS2_NOTCANCEL
|
||||
| _IO_FLAGS2_CLOEXEC);
|
||||
+ fp->_mode = 0;
|
||||
result = _IO_file_fopen (fp, gfilename, mode, 1);
|
||||
if (result != NULL)
|
||||
result = __fopen_maybe_mmap (result);
|
||||
@@ -85,9 +87,6 @@ freopen (const char *filename, const char *mode, FILE *fp)
|
||||
fp->_flags2 &= ~_IO_FLAGS2_NOCLOSE;
|
||||
if (result != NULL)
|
||||
{
|
||||
- /* unbound stream orientation */
|
||||
- result->_mode = 0;
|
||||
-
|
||||
if (fd != -1 && _IO_fileno (result) != fd)
|
||||
{
|
||||
/* At this point we have both file descriptors already allocated,
|
||||
diff --git a/libio/freopen64.c b/libio/freopen64.c
|
||||
index abcbd80a5bd92e69..64af2c5f7c80a3e9 100644
|
||||
--- a/libio/freopen64.c
|
||||
+++ b/libio/freopen64.c
|
||||
@@ -59,15 +59,13 @@ freopen64 (const char *filename, const char *mode, FILE *fp)
|
||||
fp->_flags2 &= ~(_IO_FLAGS2_MMAP
|
||||
| _IO_FLAGS2_NOTCANCEL
|
||||
| _IO_FLAGS2_CLOEXEC);
|
||||
+ fp->_mode = 0;
|
||||
result = _IO_file_fopen (fp, gfilename, mode, 0);
|
||||
fp->_flags2 &= ~_IO_FLAGS2_NOCLOSE;
|
||||
if (result != NULL)
|
||||
result = __fopen_maybe_mmap (result);
|
||||
if (result != NULL)
|
||||
{
|
||||
- /* unbound stream orientation */
|
||||
- result->_mode = 0;
|
||||
-
|
||||
if (fd != -1 && _IO_fileno (result) != fd)
|
||||
{
|
||||
/* At this point we have both file descriptors already allocated,
|
||||
diff --git a/stdio-common/tst-freopen2-main.c b/stdio-common/tst-freopen2-main.c
|
||||
index 5dad41c76b02e6de..74c3125fca697fe3 100644
|
||||
--- a/stdio-common/tst-freopen2-main.c
|
||||
+++ b/stdio-common/tst-freopen2-main.c
|
||||
@@ -386,13 +386,8 @@ do_test (void)
|
||||
fp = xfopen (file2, "w,ccs=iso-8859-1");
|
||||
ret = fputws (L"\xc0\xc1", fp);
|
||||
TEST_VERIFY (ret >= 0);
|
||||
-#if 0 /* Doesn't work (bug 23675). */
|
||||
fp = FREOPEN (file1, "r,ccs=utf-8", fp);
|
||||
TEST_VERIFY_EXIT (fp != NULL);
|
||||
-#else /* Works instead. */
|
||||
- xfclose (fp);
|
||||
- fp = xfopen (file1, "r,ccs=utf-8");
|
||||
-#endif
|
||||
wc = fgetwc (fp);
|
||||
TEST_COMPARE (wc, (wint_t) 0xc0);
|
||||
wc = fgetwc (fp);
|
33
glibc-RHEL-46736-8.patch
Normal file
33
glibc-RHEL-46736-8.patch
Normal file
@ -0,0 +1,33 @@
|
||||
commit a2509a8bc955988f01f389a1cf74db3a9da42409
|
||||
Author: Joseph Myers <josmyers@redhat.com>
|
||||
Date: Fri Sep 6 20:38:23 2024 +0000
|
||||
|
||||
Document limitations on streams passed to freopen
|
||||
|
||||
As recently discussed, document that freopen does not work with
|
||||
streams opened with functions such as popen, fmemopen, open_memstream
|
||||
or fopencookie. I've filed
|
||||
<https://austingroupbugs.net/view.php?id=1855> to clarify this issue
|
||||
in POSIX.
|
||||
|
||||
Tested with "make info" and "make html".
|
||||
|
||||
diff --git a/manual/stdio.texi b/manual/stdio.texi
|
||||
index 60ab7e7a5d505bb6..a2d9292a787b9fa3 100644
|
||||
--- a/manual/stdio.texi
|
||||
+++ b/manual/stdio.texi
|
||||
@@ -330,6 +330,14 @@ this ability, so using @code{freopen} is more portable.
|
||||
When the sources are compiled with @code{_FILE_OFFSET_BITS == 64} on a
|
||||
32 bit machine this function is in fact @code{freopen64} since the LFS
|
||||
interface replaces transparently the old interface.
|
||||
+
|
||||
+@Theglibc{} only supports use of @code{freopen} on streams opened with
|
||||
+@code{fopen} or @code{fopen64} and on the original values of the
|
||||
+standard streams @code{stdin}, @code{stdout}, and @code{stderr}; such
|
||||
+a stream may be reopened multiple times with @code{freopen}. If it is
|
||||
+called on another kind of stream (opened with functions such as
|
||||
+@code{popen}, @code{fmemopen}, @code{open_memstream}, and
|
||||
+@code{fopencookie}), @code{freopen} fails and returns a null pointer.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun {FILE *} freopen64 (const char *@var{filename}, const char *@var{opentype}, FILE *@var{stream})
|
495
glibc-RHEL-46736-9.patch
Normal file
495
glibc-RHEL-46736-9.patch
Normal file
@ -0,0 +1,495 @@
|
||||
commit e0f3bf10acf4aab27752847828bfecd3fce41190
|
||||
Author: Joseph Myers <josmyers@redhat.com>
|
||||
Date: Fri Sep 20 23:26:31 2024 +0000
|
||||
|
||||
Add freopen special-case tests: chroot, EFBIG, stdin/stdout/stderr
|
||||
|
||||
Add tests of special cases for freopen that were omitted from the more
|
||||
general tests of different modes and similar issues. The special
|
||||
cases in the three tests here are logically unconnected, it was simply
|
||||
convenient to put these tests in one patch.
|
||||
|
||||
* Test freopen with a NULL path to the new file, in a chroot. Rather
|
||||
than asserting that this fails (logically, failure in this case is
|
||||
an implementation detail; it's not required for freopen to rely on
|
||||
/proc), verify that either it fails (without memory leaks) or that
|
||||
it succeeds and behaves as expected on success. There is no check
|
||||
for file descriptor leaks because the machinery for that also
|
||||
depends on /proc, so can't be used in a chroot.
|
||||
|
||||
* Test that freopen and freopen64 are genuinely different in
|
||||
configurations with 32-bit off_t by checking for an EFBIG trying to
|
||||
write past 2GB in a file opened with freopen in such a configuration
|
||||
but no error with 64-bit off_t or when opening with freopen64.
|
||||
|
||||
* Test freopen of stdin, stdout and stderr.
|
||||
|
||||
Tested for x86_64 and x86.
|
||||
|
||||
diff --git a/stdio-common/Makefile b/stdio-common/Makefile
|
||||
index bd3c785537ba0330..c920f55ed2119900 100644
|
||||
--- a/stdio-common/Makefile
|
||||
+++ b/stdio-common/Makefile
|
||||
@@ -177,8 +177,13 @@ tests := \
|
||||
tst-fread \
|
||||
tst-freopen2 \
|
||||
tst-freopen3 \
|
||||
+ tst-freopen4 \
|
||||
+ tst-freopen5 \
|
||||
+ tst-freopen6 \
|
||||
tst-freopen64-2 \
|
||||
tst-freopen64-3 \
|
||||
+ tst-freopen64-4 \
|
||||
+ tst-freopen64-6 \
|
||||
tst-fseek \
|
||||
tst-fwrite \
|
||||
tst-getline \
|
||||
@@ -252,8 +257,13 @@ ifneq ($(PERL),no)
|
||||
tests-special += \
|
||||
$(objpfx)tst-freopen2-mem.out \
|
||||
$(objpfx)tst-freopen3-mem.out \
|
||||
+ $(objpfx)tst-freopen4-mem.out \
|
||||
+ $(objpfx)tst-freopen5-mem.out \
|
||||
+ $(objpfx)tst-freopen6-mem.out \
|
||||
$(objpfx)tst-freopen64-2-mem.out \
|
||||
$(objpfx)tst-freopen64-3-mem.out \
|
||||
+ $(objpfx)tst-freopen64-4-mem.out \
|
||||
+ $(objpfx)tst-freopen64-6-mem.out \
|
||||
$(objpfx)tst-getline-enomem-mem.out \
|
||||
$(objpfx)tst-getline-mem.out \
|
||||
$(objpfx)tst-printf-bz18872-mem.out \
|
||||
@@ -268,10 +278,20 @@ generated += \
|
||||
tst-freopen2.mtrace \
|
||||
tst-freopen3-mem.out \
|
||||
tst-freopen3.mtrace \
|
||||
+ tst-freopen4-mem.out \
|
||||
+ tst-freopen4.mtrace \
|
||||
+ tst-freopen5-mem.out \
|
||||
+ tst-freopen5.mtrace \
|
||||
+ tst-freopen6-mem.out \
|
||||
+ tst-freopen6.mtrace \
|
||||
tst-freopen64-2-mem.out \
|
||||
tst-freopen64-2.mtrace \
|
||||
tst-freopen64-3-mem.out \
|
||||
tst-freopen64-3.mtrace \
|
||||
+ tst-freopen64-4-mem.out \
|
||||
+ tst-freopen64-4.mtrace \
|
||||
+ tst-freopen64-6-mem.out \
|
||||
+ tst-freopen64-6.mtrace \
|
||||
tst-getline-enomem-mem.out \
|
||||
tst-getline-enomem.mtrace \
|
||||
tst-getline-mem.out \
|
||||
@@ -356,6 +376,21 @@ tst-freopen3-ENV = \
|
||||
tst-freopen64-3-ENV = \
|
||||
MALLOC_TRACE=$(objpfx)tst-freopen64-3.mtrace \
|
||||
LD_PRELOAD=$(common-objpfx)malloc/libc_malloc_debug.so
|
||||
+tst-freopen4-ENV = \
|
||||
+ MALLOC_TRACE=$(objpfx)tst-freopen4.mtrace \
|
||||
+ LD_PRELOAD=$(common-objpfx)malloc/libc_malloc_debug.so
|
||||
+tst-freopen64-4-ENV = \
|
||||
+ MALLOC_TRACE=$(objpfx)tst-freopen64-4.mtrace \
|
||||
+ LD_PRELOAD=$(common-objpfx)malloc/libc_malloc_debug.so
|
||||
+tst-freopen5-ENV = \
|
||||
+ MALLOC_TRACE=$(objpfx)tst-freopen5.mtrace \
|
||||
+ LD_PRELOAD=$(common-objpfx)malloc/libc_malloc_debug.so
|
||||
+tst-freopen6-ENV = \
|
||||
+ MALLOC_TRACE=$(objpfx)tst-freopen6.mtrace \
|
||||
+ LD_PRELOAD=$(common-objpfx)malloc/libc_malloc_debug.so
|
||||
+tst-freopen64-6-ENV = \
|
||||
+ MALLOC_TRACE=$(objpfx)tst-freopen64-6.mtrace \
|
||||
+ LD_PRELOAD=$(common-objpfx)malloc/libc_malloc_debug.so
|
||||
|
||||
$(objpfx)tst-unbputc.out: tst-unbputc.sh $(objpfx)tst-unbputc
|
||||
$(SHELL) $< $(common-objpfx) '$(test-program-prefix)'; \
|
||||
diff --git a/stdio-common/tst-freopen4-main.c b/stdio-common/tst-freopen4-main.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..e169442cf4df2e9d
|
||||
--- /dev/null
|
||||
+++ b/stdio-common/tst-freopen4-main.c
|
||||
@@ -0,0 +1,100 @@
|
||||
+/* Test freopen in chroot.
|
||||
+ Copyright (C) 2024 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 <mcheck.h>
|
||||
+#include <stdio.h>
|
||||
+#include <stdlib.h>
|
||||
+
|
||||
+#include <support/check.h>
|
||||
+#include <support/file_contents.h>
|
||||
+#include <support/namespace.h>
|
||||
+#include <support/support.h>
|
||||
+#include <support/temp_file.h>
|
||||
+#include <support/test-driver.h>
|
||||
+#include <support/xstdio.h>
|
||||
+#include <support/xunistd.h>
|
||||
+
|
||||
+int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ mtrace ();
|
||||
+ char *temp_dir = support_create_temp_directory ("tst-freopen4");
|
||||
+ FILE *fp;
|
||||
+ int ret;
|
||||
+
|
||||
+ /* These chroot tests verify that either reopening a renamed or
|
||||
+ deleted file works even in the absence of /proc, or that it fails
|
||||
+ (without memory leaks); thus, for example, such reopening does
|
||||
+ not crash in the absence of /proc. */
|
||||
+
|
||||
+ support_become_root ();
|
||||
+ if (!support_can_chroot ())
|
||||
+ return EXIT_UNSUPPORTED;
|
||||
+ xchroot (temp_dir);
|
||||
+
|
||||
+ /* Test freopen with NULL, renamed file. This verifies that
|
||||
+ reopening succeeds (and resets the file position indicator to
|
||||
+ start of file) even when the original path could no longer be
|
||||
+ opened, or fails without a memory leak. (It is not possible to
|
||||
+ use <support/descriptors.h> to test for file descriptor leaks
|
||||
+ here, because that also depends on /proc.) */
|
||||
+
|
||||
+ verbose_printf ("testing freopen with NULL, renamed file\n");
|
||||
+ fp = xfopen ("/file1", "w+");
|
||||
+ ret = fputs ("file has been renamed", fp);
|
||||
+ TEST_VERIFY (ret >= 0);
|
||||
+ ret = rename ("/file1", "/file1a");
|
||||
+ TEST_COMPARE (ret, 0);
|
||||
+ fp = FREOPEN (NULL, "r+", fp);
|
||||
+ if (fp != NULL)
|
||||
+ {
|
||||
+ puts ("freopen of renamed file succeeded");
|
||||
+ TEST_COMPARE_FILE_STRING (fp, "file has been renamed");
|
||||
+ xfclose (fp);
|
||||
+ }
|
||||
+ else
|
||||
+ puts ("freopen of renamed file failed (OK)");
|
||||
+ ret = rename ("/file1a", "/file1");
|
||||
+ TEST_COMPARE (ret, 0);
|
||||
+
|
||||
+ /* Test freopen with NULL, deleted file. This verifies that
|
||||
+ reopening succeeds (and resets the file position indicator to
|
||||
+ start of file) even when the original path could no longer be
|
||||
+ opened, or fails without a memory leak. */
|
||||
+
|
||||
+ verbose_printf ("testing freopen with NULL, deleted file\n");
|
||||
+ fp = xfopen ("/file1", "r+");
|
||||
+ ret = fputs ("file has now been deleted", fp);
|
||||
+ TEST_VERIFY (ret >= 0);
|
||||
+ ret = remove ("/file1");
|
||||
+ TEST_COMPARE (ret, 0);
|
||||
+ fp = FREOPEN (NULL, "r+", fp);
|
||||
+ if (fp != NULL)
|
||||
+ {
|
||||
+ puts ("freopen of deleted file succeeded");
|
||||
+ TEST_COMPARE_FILE_STRING (fp, "file has now been deleted");
|
||||
+ xfclose (fp);
|
||||
+ }
|
||||
+ else
|
||||
+ puts ("freopen of deleted file failed (OK)");
|
||||
+
|
||||
+ free (temp_dir);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
||||
diff --git a/stdio-common/tst-freopen4.c b/stdio-common/tst-freopen4.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..f39ec0d21730879f
|
||||
--- /dev/null
|
||||
+++ b/stdio-common/tst-freopen4.c
|
||||
@@ -0,0 +1,2 @@
|
||||
+#define FREOPEN freopen
|
||||
+#include <tst-freopen4-main.c>
|
||||
diff --git a/stdio-common/tst-freopen5.c b/stdio-common/tst-freopen5.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..f32626bccfe5c10a
|
||||
--- /dev/null
|
||||
+++ b/stdio-common/tst-freopen5.c
|
||||
@@ -0,0 +1,144 @@
|
||||
+/* Test freopen and freopen64 with large offsets.
|
||||
+ Copyright (C) 2024 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 <errno.h>
|
||||
+#include <mcheck.h>
|
||||
+#include <stdio.h>
|
||||
+#include <stdlib.h>
|
||||
+
|
||||
+#include <support/check.h>
|
||||
+#include <support/descriptors.h>
|
||||
+#include <support/support.h>
|
||||
+#include <support/temp_file.h>
|
||||
+#include <support/test-driver.h>
|
||||
+#include <support/xstdio.h>
|
||||
+
|
||||
+#define START_TEST(DESC) \
|
||||
+ do \
|
||||
+ { \
|
||||
+ fds = support_descriptors_list (); \
|
||||
+ verbose_printf (DESC); \
|
||||
+ } \
|
||||
+ while (0)
|
||||
+
|
||||
+#define END_TEST \
|
||||
+ do \
|
||||
+ { \
|
||||
+ support_descriptors_check (fds); \
|
||||
+ support_descriptors_free (fds); \
|
||||
+ } \
|
||||
+ while (0)
|
||||
+
|
||||
+int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ mtrace ();
|
||||
+ struct support_descriptors *fds;
|
||||
+ FILE *fp;
|
||||
+ int ret;
|
||||
+
|
||||
+ char *temp_dir = support_create_temp_directory ("tst-freopen5");
|
||||
+ /* This file is removed at the end of each test rather than left
|
||||
+ around between tests to avoid problems with subsequent tests
|
||||
+ reopening it as a large (2GB + 1 byte) file. */
|
||||
+ char *file1 = xasprintf ("%s/file1", temp_dir);
|
||||
+
|
||||
+ /* fopen with freopen64: large offsets OK. */
|
||||
+ START_TEST ("testing fopen with freopen64\n");
|
||||
+ fp = fopen ("/dev/null", "r");
|
||||
+ TEST_VERIFY_EXIT (fp != NULL);
|
||||
+ fp = freopen64 (file1, "w", fp);
|
||||
+ TEST_VERIFY_EXIT (fp != NULL);
|
||||
+ setbuf (fp, NULL);
|
||||
+ ret = fseeko64 (fp, 1LL << 32, SEEK_SET);
|
||||
+ TEST_COMPARE (ret, 0);
|
||||
+ ret = fputc ('x', fp);
|
||||
+ TEST_COMPARE (ret, 'x');
|
||||
+ xfclose (fp);
|
||||
+ ret = remove (file1);
|
||||
+ TEST_COMPARE (ret, 0);
|
||||
+ END_TEST;
|
||||
+
|
||||
+ /* fopen64 with freopen64: large offsets OK. */
|
||||
+ START_TEST ("testing fopen64 with freopen64\n");
|
||||
+ fp = fopen64 ("/dev/null", "r");
|
||||
+ TEST_VERIFY_EXIT (fp != NULL);
|
||||
+ fp = freopen64 (file1, "w", fp);
|
||||
+ TEST_VERIFY_EXIT (fp != NULL);
|
||||
+ setbuf (fp, NULL);
|
||||
+ ret = fseeko64 (fp, 1LL << 32, SEEK_SET);
|
||||
+ TEST_COMPARE (ret, 0);
|
||||
+ ret = fputc ('x', fp);
|
||||
+ TEST_COMPARE (ret, 'x');
|
||||
+ xfclose (fp);
|
||||
+ ret = remove (file1);
|
||||
+ TEST_COMPARE (ret, 0);
|
||||
+ END_TEST;
|
||||
+
|
||||
+ /* fopen with freopen: large offsets not OK on 32-bit systems. */
|
||||
+ START_TEST ("testing fopen with freopen\n");
|
||||
+ fp = fopen ("/dev/null", "r");
|
||||
+ TEST_VERIFY_EXIT (fp != NULL);
|
||||
+ fp = freopen (file1, "w", fp);
|
||||
+ TEST_VERIFY_EXIT (fp != NULL);
|
||||
+ setbuf (fp, NULL);
|
||||
+ ret = fseeko64 (fp, 1LL << 32, SEEK_SET);
|
||||
+ TEST_COMPARE (ret, 0);
|
||||
+ errno = 0;
|
||||
+ ret = fputc ('x', fp);
|
||||
+ if (sizeof (off_t) == 4)
|
||||
+ {
|
||||
+ TEST_COMPARE (ret, EOF);
|
||||
+ TEST_COMPARE (errno, EFBIG);
|
||||
+ }
|
||||
+ else
|
||||
+ TEST_COMPARE (ret, 'x');
|
||||
+ fclose (fp);
|
||||
+ ret = remove (file1);
|
||||
+ TEST_COMPARE (ret, 0);
|
||||
+ END_TEST;
|
||||
+
|
||||
+ /* fopen64 with freopen: large offsets not OK on 32-bit systems. */
|
||||
+ START_TEST ("testing fopen64 with freopen\n");
|
||||
+ fp = fopen64 ("/dev/null", "r");
|
||||
+ TEST_VERIFY_EXIT (fp != NULL);
|
||||
+ fp = freopen (file1, "w", fp);
|
||||
+ TEST_VERIFY_EXIT (fp != NULL);
|
||||
+ setbuf (fp, NULL);
|
||||
+ ret = fseeko64 (fp, 1LL << 32, SEEK_SET);
|
||||
+ TEST_COMPARE (ret, 0);
|
||||
+ errno = 0;
|
||||
+ ret = fputc ('x', fp);
|
||||
+ if (sizeof (off_t) == 4)
|
||||
+ {
|
||||
+ TEST_COMPARE (ret, EOF);
|
||||
+ TEST_COMPARE (errno, EFBIG);
|
||||
+ }
|
||||
+ else
|
||||
+ TEST_COMPARE (ret, 'x');
|
||||
+ fclose (fp);
|
||||
+ ret = remove (file1);
|
||||
+ TEST_COMPARE (ret, 0);
|
||||
+ END_TEST;
|
||||
+
|
||||
+ free (temp_dir);
|
||||
+ free (file1);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
||||
diff --git a/stdio-common/tst-freopen6-main.c b/stdio-common/tst-freopen6-main.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..f493f42fd7486b72
|
||||
--- /dev/null
|
||||
+++ b/stdio-common/tst-freopen6-main.c
|
||||
@@ -0,0 +1,98 @@
|
||||
+/* Test freopen of stdin / stdout / stderr.
|
||||
+ Copyright (C) 2024 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 <errno.h>
|
||||
+#include <mcheck.h>
|
||||
+#include <stdio.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <unistd.h>
|
||||
+
|
||||
+#include <support/check.h>
|
||||
+#include <support/file_contents.h>
|
||||
+#include <support/support.h>
|
||||
+#include <support/temp_file.h>
|
||||
+#include <support/test-driver.h>
|
||||
+#include <support/xstdio.h>
|
||||
+
|
||||
+int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ mtrace ();
|
||||
+ char *temp_dir = support_create_temp_directory ("tst-freopen6");
|
||||
+ char *file1 = xasprintf ("%s/file1", temp_dir);
|
||||
+ support_write_file_string (file1, "file1");
|
||||
+ add_temp_file (file1);
|
||||
+ FILE *fp;
|
||||
+ int ret;
|
||||
+
|
||||
+ verbose_printf ("Testing reopening stdin\n");
|
||||
+ fp = FREOPEN (file1, "r", stdin);
|
||||
+ TEST_VERIFY_EXIT (fp == stdin);
|
||||
+ ret = getchar ();
|
||||
+ TEST_COMPARE (ret, 'f');
|
||||
+ ret = getchar ();
|
||||
+ TEST_COMPARE (ret, 'i');
|
||||
+ ret = getchar ();
|
||||
+ TEST_COMPARE (ret, 'l');
|
||||
+ ret = getchar ();
|
||||
+ TEST_COMPARE (ret, 'e');
|
||||
+ ret = getchar ();
|
||||
+ TEST_COMPARE (ret, '1');
|
||||
+ ret = getchar ();
|
||||
+ TEST_COMPARE (ret, EOF);
|
||||
+ xfclose (fp);
|
||||
+
|
||||
+ verbose_printf ("Testing reopening stderr\n");
|
||||
+ fp = FREOPEN (file1, "w+", stderr);
|
||||
+ TEST_VERIFY_EXIT (fp == stderr);
|
||||
+ errno = EINVAL;
|
||||
+ perror ("test");
|
||||
+ ret = fseek (fp, 0, SEEK_SET);
|
||||
+ TEST_COMPARE (ret, 0);
|
||||
+ TEST_COMPARE_FILE_STRING (fp, "test: Invalid argument\n");
|
||||
+ xfclose (fp);
|
||||
+
|
||||
+ verbose_printf ("Testing reopening stdout\n");
|
||||
+ /* Defer checks until the old stdout has been restored to make it
|
||||
+ more likely any errors are written to the old stdout (rather than
|
||||
+ the temporary file used for the redirected stdout). */
|
||||
+ int old_stdout = dup (STDOUT_FILENO);
|
||||
+ TEST_VERIFY_EXIT (old_stdout != -1);
|
||||
+ int ret_fseek = 0;
|
||||
+ int ret_compare = 0;
|
||||
+ fp = FREOPEN (file1, "w+", stdout);
|
||||
+ int fp_eq_stdout = fp == stdout;
|
||||
+ if (fp != NULL)
|
||||
+ {
|
||||
+ printf ("reopened\n");
|
||||
+ ret_fseek = fseek (fp, 0, SEEK_SET);
|
||||
+ ret_compare = support_compare_file_string (fp, "reopened\n");
|
||||
+ }
|
||||
+ xfclose (fp);
|
||||
+ stdout = fdopen (old_stdout, "w");
|
||||
+ TEST_VERIFY (fp_eq_stdout);
|
||||
+ TEST_COMPARE (ret_fseek, 0);
|
||||
+ TEST_COMPARE (ret_compare, 0);
|
||||
+ xfclose (stdout);
|
||||
+
|
||||
+ free (temp_dir);
|
||||
+ free (file1);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
||||
diff --git a/stdio-common/tst-freopen6.c b/stdio-common/tst-freopen6.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..8fd6957b54fa9bc2
|
||||
--- /dev/null
|
||||
+++ b/stdio-common/tst-freopen6.c
|
||||
@@ -0,0 +1,2 @@
|
||||
+#define FREOPEN freopen
|
||||
+#include <tst-freopen6-main.c>
|
||||
diff --git a/stdio-common/tst-freopen64-4.c b/stdio-common/tst-freopen64-4.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..1411be2bfa0105c1
|
||||
--- /dev/null
|
||||
+++ b/stdio-common/tst-freopen64-4.c
|
||||
@@ -0,0 +1,2 @@
|
||||
+#define FREOPEN freopen64
|
||||
+#include <tst-freopen4-main.c>
|
||||
diff --git a/stdio-common/tst-freopen64-6.c b/stdio-common/tst-freopen64-6.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..3ec509a36c2471f6
|
||||
--- /dev/null
|
||||
+++ b/stdio-common/tst-freopen64-6.c
|
||||
@@ -0,0 +1,2 @@
|
||||
+#define FREOPEN freopen64
|
||||
+#include <tst-freopen6-main.c>
|
16
glibc.spec
16
glibc.spec
@ -157,7 +157,7 @@ end \
|
||||
Summary: The GNU libc libraries
|
||||
Name: glibc
|
||||
Version: %{glibcversion}
|
||||
Release: 139%{?dist}
|
||||
Release: 140%{?dist}
|
||||
|
||||
# In general, GPLv2+ is used by programs, LGPLv2+ is used for
|
||||
# libraries.
|
||||
@ -917,6 +917,17 @@ Patch678: glibc-RHEL-46733-1.patch
|
||||
Patch679: glibc-RHEL-46733-2.patch
|
||||
Patch680: glibc-RHEL-46733-3.patch
|
||||
Patch681: glibc-RHEL-54413.patch
|
||||
Patch682: glibc-RHEL-46736-1.patch
|
||||
Patch683: glibc-RHEL-46736-2.patch
|
||||
Patch684: glibc-RHEL-46736-3.patch
|
||||
Patch685: glibc-RHEL-46736-4.patch
|
||||
Patch686: glibc-RHEL-46736-5.patch
|
||||
Patch687: glibc-RHEL-46736-6.patch
|
||||
Patch688: glibc-RHEL-46736-7.patch
|
||||
Patch689: glibc-RHEL-46736-8.patch
|
||||
Patch690: glibc-RHEL-46736-9.patch
|
||||
Patch691: glibc-RHEL-46736-10.patch
|
||||
Patch692: glibc-RHEL-46736-11.patch
|
||||
|
||||
##############################################################################
|
||||
# Continued list of core "glibc" package information:
|
||||
@ -3076,6 +3087,9 @@ update_gconv_modules_cache ()
|
||||
%endif
|
||||
|
||||
%changelog
|
||||
* Thu Nov 7 2024 Florian Weimer <fweimer@redhat.com> - 2.34-140
|
||||
- Add more tests for freopen (RHEL-46736)
|
||||
|
||||
* Thu Nov 7 2024 Florian Weimer <fweimer@redhat.com> - 2.34-139
|
||||
- Add more tests of getline (RHEL-54413)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user