diff --git a/glibc-RHEL-46729.patch b/glibc-RHEL-46729.patch new file mode 100644 index 0000000..f835f99 --- /dev/null +++ b/glibc-RHEL-46729.patch @@ -0,0 +1,578 @@ +commit 45c42b65c29422b773ac94771aa71165e245f8f8 +Author: Martin Coufal +Date: Thu Jan 23 13:04:06 2025 +0100 + + Add new tests for fopen + + Adding some basic tests for fopen, testing different modes, stream + positioning and concurrent read/write operation on files. + Reviewed-by: DJ Delorie + +# Conflicts: +# sysdeps/pthread/Makefile (new test added) + +diff --git a/stdio-common/Makefile b/stdio-common/Makefile +index 74e0edff73a9e468..fe69e48849cb9819 100644 +--- a/stdio-common/Makefile ++++ b/stdio-common/Makefile +@@ -201,6 +201,7 @@ tests := \ + tst-fmemopen2 \ + tst-fmemopen3 \ + tst-fmemopen4 \ ++ tst-fopen \ + tst-fphex \ + tst-fphex-wide \ + tst-fread \ +diff --git a/stdio-common/tst-fopen.c b/stdio-common/tst-fopen.c +new file mode 100644 +index 0000000000000000..8c1fefd116f9f581 +--- /dev/null ++++ b/stdio-common/tst-fopen.c +@@ -0,0 +1,279 @@ ++/* Basic test for fopen. ++ 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 ++ . */ ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#define APPENDED_TEXT "This is appended text. " ++#define DEFAULT_TEXT "Lorem ipsum dolor sit amet, consectetur " \ ++ "adipiscing elit, sed do eiusmod tempor incididunt ut labore et " \ ++ "dolore magna aliqua." ++#define MAX_BUFFER_SIZE 300 ++ ++ ++static int ++do_test (void) ++{ ++ char *temp_file; ++ FILE *fd_file = NULL; ++ char read_buffer[MAX_BUFFER_SIZE] = ""; ++ size_t ret; ++ ++ /* Prepare files. */ ++ int fd = create_temp_file ("tst-fopen.", &temp_file); ++ TEST_VERIFY_EXIT (fd != -1); ++ fd_file = fdopen (fd, "w"); ++ ret = fwrite (DEFAULT_TEXT, sizeof (char), strlen (DEFAULT_TEXT), fd_file); ++ TEST_COMPARE (ret, strlen (DEFAULT_TEXT)); ++ xfclose (fd_file); ++ ++ /* Test 1: This checks for fopen with mode "r". Open text file for ++ reading. The stream is positioned at the beginning of the file. */ ++ printf ("Test 1: This checks for fopen with mode \"r\".\n"); ++ fd_file = fopen (temp_file, "r"); ++ TEST_COMPARE (ferror (fd_file), 0); ++ TEST_VERIFY (fd_file != NULL); ++ TEST_COMPARE (ftell (fd_file), 0); ++ /* Read should succeed. */ ++ ret = fread (read_buffer, sizeof (char), MAX_BUFFER_SIZE, fd_file); ++ TEST_COMPARE (ferror (fd_file), 0); ++ TEST_COMPARE (ret, strlen (DEFAULT_TEXT)); ++ TEST_VERIFY (strcmp (read_buffer, DEFAULT_TEXT) == 0); ++ /* Write should fail. */ ++ errno = 0; ++ ret = fwrite (DEFAULT_TEXT, sizeof (char), strlen (DEFAULT_TEXT), fd_file); ++ TEST_VERIFY (ferror (fd_file) != 0); ++ TEST_COMPARE (errno, EBADF); ++ TEST_COMPARE (ret, 0); ++ clearerr (fd_file); ++ /* Opening non-existent file should fail. */ ++ xfclose (fd_file); ++ errno = 0; ++ fd_file = fopen ("file-that-does-not-exist", "r"); ++ TEST_VERIFY (fd_file == NULL); ++ TEST_COMPARE (errno, ENOENT); ++ TEST_VERIFY (fd_file == NULL); ++ ++ memset (read_buffer, 0, MAX_BUFFER_SIZE); ++ ++ /* Test 2: This checks for fopen with mode "r+". Open for reading and ++ writing. The stream is positioned at the beginning of the file. */ ++ printf ("Test 2: This checks for fopen with mode \"r+\".\n"); ++ fd_file = fopen (temp_file, "r+"); ++ TEST_COMPARE (ferror (fd_file), 0); ++ TEST_VERIFY (fd_file != NULL); ++ TEST_COMPARE (ftell (fd_file), 0); ++ /* Read should succeed. */ ++ ret = fread (read_buffer, sizeof (char), MAX_BUFFER_SIZE, fd_file); ++ TEST_COMPARE (ferror (fd_file), 0); ++ TEST_COMPARE (ret, strlen (DEFAULT_TEXT)); ++ TEST_VERIFY (strcmp (read_buffer, DEFAULT_TEXT) == 0); ++ fflush (fd_file); ++ /* File position indicator expected at 0 + read bytes. */ ++ TEST_COMPARE (ftell (fd_file), ret); ++ /* Write should succeed. */ ++ ret = fwrite (DEFAULT_TEXT, sizeof (char), strlen (DEFAULT_TEXT), fd_file); ++ TEST_COMPARE (ferror (fd_file), 0); ++ TEST_COMPARE (ret, strlen (DEFAULT_TEXT)); ++ /* Opening non-existent file should fail. */ ++ xfclose (fd_file); ++ errno = 0; ++ fd_file = fopen ("file-that-does-not-exist", "r+"); ++ TEST_VERIFY (fd_file == NULL); ++ TEST_COMPARE (errno, ENOENT); ++ TEST_VERIFY (fd_file == NULL); ++ ++ memset (read_buffer, 0, MAX_BUFFER_SIZE); ++ ++ /* Test 3: This checks for fopen with mode "w". Truncate file to zero ++ length or create text file for writing. The stream is positioned ++ at the beginning of the file. */ ++ printf ("Test 3: This checks for fopen with mode \"w\".\n"); ++ fd_file = fopen (temp_file, "w"); ++ TEST_COMPARE (ferror (fd_file), 0); ++ TEST_VERIFY (fd_file != NULL); ++ TEST_COMPARE (ftell (fd_file), 0); ++ /* Read should fail. */ ++ errno = 0; ++ ret = fread (read_buffer, sizeof (char), MAX_BUFFER_SIZE, fd_file); ++ TEST_VERIFY (ferror (fd_file) != 0); ++ TEST_COMPARE (errno, EBADF); ++ TEST_COMPARE (ret, 0); ++ clearerr (fd_file); ++ /* Write should succeed. */ ++ ret = fwrite (DEFAULT_TEXT, sizeof (char), strlen (DEFAULT_TEXT), fd_file); ++ TEST_COMPARE (ferror (fd_file), 0); ++ TEST_COMPARE (ret, strlen (DEFAULT_TEXT)); ++ /* Opening non-existent file should succeed. */ ++ xfclose (fd_file); ++ fd_file = fopen ("/tmp/file-that-does-not-exist", "w"); ++ TEST_COMPARE (ferror (fd_file), 0); ++ TEST_VERIFY (fd_file != NULL); ++ TEST_COMPARE (ftell (fd_file), 0); ++ ++ xfclose (fd_file); ++ remove ("/tmp/file-that-does-not-exist"); ++ memset (read_buffer, 0, MAX_BUFFER_SIZE); ++ ++ /* Test 4: This checks for fopen with mode "w+". Open for reading and ++ writing. The file is created if it does not exist, otherwise it is ++ truncated. The stream is positioned at the beginning of the file. ++ */ ++ printf ("Test 4: This checks for fopen with mode \"w+\".\n"); ++ fd_file = fopen (temp_file, "w+"); ++ TEST_COMPARE (ferror (fd_file), 0); ++ TEST_VERIFY (fd_file != NULL); ++ TEST_COMPARE (ftell (fd_file), 0); ++ /* Read should succeed. */ ++ ret = fread (read_buffer, sizeof (char), MAX_BUFFER_SIZE, fd_file); ++ TEST_COMPARE (ferror (fd_file), 0); ++ TEST_COMPARE (ret, 0); ++ TEST_VERIFY (read_buffer[0] == '\0'); ++ /* Write should succeed. */ ++ ret = fwrite (DEFAULT_TEXT, sizeof (char), strlen (DEFAULT_TEXT), fd_file); ++ TEST_COMPARE (ferror (fd_file), 0); ++ TEST_COMPARE (ret, strlen (DEFAULT_TEXT)); ++ /* Opening non-existent file should succeed. */ ++ xfclose (fd_file); ++ fd_file = fopen ("/tmp/file-that-does-not-exist", "w+"); ++ TEST_COMPARE (ferror (fd_file), 0); ++ TEST_VERIFY (fd_file != NULL); ++ TEST_COMPARE (ftell (fd_file), 0); ++ ++ xfclose (fd_file); ++ remove ("/tmp/file-that-does-not-exist"); ++ memset (read_buffer, 0, MAX_BUFFER_SIZE); ++ ++ /* Test 5: This checks for fopen with mode "a". Open for appending ++ (writing at end of file). The file is created if it does not ++ exist. The stream is positioned at the end of the file. */ ++ printf ("Test 5: This checks for fopen with mode \"a\".\n"); ++ fd_file = fopen (temp_file, "a"); ++ TEST_COMPARE (ferror (fd_file), 0); ++ TEST_VERIFY (fd_file != NULL); ++ TEST_COMPARE (ftell (fd_file), strlen (DEFAULT_TEXT)); ++ /* Read should fail. */ ++ errno = 0; ++ ret = fread (read_buffer, sizeof (char), MAX_BUFFER_SIZE, fd_file); ++ TEST_VERIFY (ferror (fd_file) != 0); ++ TEST_COMPARE (errno, EBADF); ++ TEST_COMPARE (ret, 0); ++ clearerr (fd_file); ++ /* Write should succeed. */ ++ ret = fwrite (APPENDED_TEXT, sizeof (char), strlen (APPENDED_TEXT), fd_file); ++ TEST_COMPARE (ferror (fd_file), 0); ++ TEST_COMPARE (ret, strlen (APPENDED_TEXT)); ++ /* The file position indicator for the stream is advanced by the ++ * number of bytes successfully read or written. */ ++ TEST_COMPARE (ftell (fd_file), strlen (DEFAULT_TEXT) + ret); ++ /* Opening non-existent file should succeed. */ ++ xfclose (fd_file); ++ fd_file = fopen ("/tmp/file-that-does-not-exist", "a"); ++ TEST_COMPARE (ferror (fd_file), 0); ++ TEST_VERIFY (fd_file != NULL); ++ TEST_COMPARE (ftell (fd_file), 0); ++ ++ xfclose (fd_file); ++ remove ("/tmp/file-that-does-not-exist"); ++ memset (read_buffer, 0, MAX_BUFFER_SIZE); ++ ++ /* Test 6: This checks for fopen with mode "a+". Open for reading and ++ appending (writing at end of file). The file is created if it does ++ not exist. Output is always appended to the end of the file. The ++ initial file position for reading is at the beginning of the file, ++ but it is advanced to the end prior to each write. */ ++ printf ("Test 6: This checks for fopen with mode \"a+\".\n"); ++ errno = 0; ++ fd_file = fopen (temp_file, "a+"); ++ TEST_COMPARE (errno, 0); ++ TEST_VERIFY (fd_file != NULL); ++ TEST_COMPARE (ftell (fd_file), 0); ++ /* Read should succeed. */ ++ ret = fread (read_buffer, sizeof (char), MAX_BUFFER_SIZE, fd_file); ++ TEST_COMPARE (ferror (fd_file), 0); ++ TEST_COMPARE (ret, strlen (DEFAULT_TEXT) + strlen (APPENDED_TEXT)); ++ TEST_VERIFY (strcmp (read_buffer, DEFAULT_TEXT APPENDED_TEXT) == 0); ++ /* Write should succeed. */ ++ const char* SECOND_APPEND = "This is second append."; ++ ret = fwrite (SECOND_APPEND, sizeof (char), strlen (SECOND_APPEND), fd_file); ++ TEST_COMPARE (ferror (fd_file), 0); ++ TEST_COMPARE (ret, strlen (SECOND_APPEND)); ++ /* The file position indicator for the stream is advanced by the ++ number of bytes successfully read or written. */ ++ TEST_COMPARE (ftell (fd_file), ++ strlen (DEFAULT_TEXT) + strlen (APPENDED_TEXT) + ret); ++ /* Opening non-existent file should succeed. */ ++ xfclose (fd_file); ++ fd_file = fopen ("/tmp/file-that-does-not-exist", "a+"); ++ TEST_COMPARE (ferror (fd_file), 0); ++ TEST_VERIFY (fd_file != NULL); ++ TEST_COMPARE (ftell (fd_file), 0); ++ ++ xfclose (fd_file); ++ remove ("/tmp/file-that-does-not-exist"); ++ memset (read_buffer, 0, MAX_BUFFER_SIZE); ++ ++ /* Test 7: This checks for fopen with other valid modes set, such as ++ "rc", "we" or "am". The test calls fopen with these modes and ++ checks that no errors appear. */ ++ printf ("Test 7: This checks for fopen with other valid modes set, " ++ "such as \"rc\", \"we\" or \"am\".\n"); ++ /* These modes all operate correctly with the file already present. */ ++ static const char *valid_modes[] = ++ { "rc", "we", "am", "r+x", "wb+", "ab", 0 }; ++ const char **p = valid_modes; ++ while (*p != 0) ++ { ++ fd_file = fopen (temp_file, *p); ++ TEST_COMPARE (ferror (fd_file), 0); ++ TEST_VERIFY (fd_file != NULL); ++ xfclose (fd_file); ++ ++p; ++ } ++ ++ /* Test 8: This checks for fopen with invalid modes. The test calls ++ fopen with these modes and checks that opening existing files with ++ invalid mode fails and that opening non-existing files with invalid ++ mode doesn't create a new file. */ ++ printf ("Test 8: This checks for fopen with invalid modes.\n"); ++ static const char *invalid_modes[] = { "0", "tr", "z", "x", " ", 0 }; ++ p = invalid_modes; ++ while (*p != 0) ++ { ++ errno = 0; ++ fd_file = fopen (temp_file, *p); ++ TEST_VERIFY (fd_file == NULL); ++ TEST_COMPARE (errno, EINVAL); ++ errno = 0; ++ fd_file = fopen ("/tmp/file-that-does-not-exist", *p); ++ TEST_VERIFY (fd_file == NULL); ++ TEST_COMPARE (errno, EINVAL); ++ ++p; ++ TEST_VERIFY (access ("/tmp/file-that-does-not-exist", F_OK) == -1); ++ } ++ ++ return 0; ++} ++ ++#include +diff --git a/sysdeps/pthread/Makefile b/sysdeps/pthread/Makefile +index 43fcdf1182e735e1..58c33a8e49d517ad 100644 +--- a/sysdeps/pthread/Makefile ++++ b/sysdeps/pthread/Makefile +@@ -131,6 +131,7 @@ tests += tst-cnd-basic tst-mtx-trylock tst-cnd-broadcast \ + tst-sem18 \ + tst-sem19 \ + tst-join16 \ ++ tst-fopen-threaded \ + # tests + + tests-time64 := \ +diff --git a/sysdeps/pthread/tst-fopen-threaded.c b/sysdeps/pthread/tst-fopen-threaded.c +new file mode 100644 +index 0000000000000000..5c792c93e3711621 +--- /dev/null ++++ b/sysdeps/pthread/tst-fopen-threaded.c +@@ -0,0 +1,250 @@ ++/* Test for fread and fwrite with multiple threads. ++ 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 ++ . */ ++ ++/* Description of test intent. ++ The test creates NUM_THREADS threads for reading and writing to the ++ prepared file. The prepared file contains 'NUM_THREADS - 1' bytes ++ where each byte is unique number from 0 to 'NUM_THREADS - 2'. If all ++ operations are correctly multi-threaded safe then all concurent read ++ operations should succeed and read a unique 1 byte value. The last ++ thread to read should get an EOF. In concurrent write, all write ++ operations should succeed and the file should contain all unique 1 ++ byte values from 0 to 'NUM_THREADS - 1'. Both concurrent read and ++ concurrent write tests are repeated ITERS times to increase ++ the probability of detecting concurrency issues. */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#define NUM_THREADS 100 ++#define ITERS 10 ++ ++char *temp_file; ++pthread_barrier_t barrier; ++ ++struct thread_data ++{ ++ FILE *fd; ++ /* Read value or value to be written. */ ++ unsigned char value; ++ bool eof; ++}; ++ ++static void * ++threadReadRoutine (void *argv) ++{ ++ struct thread_data *my_data; ++ unsigned char read_buffer; ++ int ret = 0; ++ my_data = (struct thread_data *) argv; ++ /* Wait for all threads to be ready to read. */ ++ xpthread_barrier_wait (&barrier); ++ ++ ret = ++ fread (&read_buffer, sizeof (char), sizeof (read_buffer), my_data->fd); ++ if (feof (my_data->fd) != 0) ++ { ++ clearerr (my_data->fd); ++ my_data->eof = true; ++ } ++ else ++ { ++ TEST_COMPARE (ret, 1); ++ /* Save the read value. */ ++ my_data->value = read_buffer; ++ } ++ TEST_COMPARE (ferror (my_data->fd), 0); ++ return NULL; ++} ++ ++void * ++threadWriteRoutine (void *argv) ++{ ++ struct thread_data *my_data; ++ int ret = 0; ++ my_data = (struct thread_data *) argv; ++ /* Wait for all threads to be ready to write. */ ++ xpthread_barrier_wait (&barrier); ++ ++ ret = fwrite (&my_data->value, sizeof (unsigned char), 1, my_data->fd); ++ TEST_COMPARE (ferror (my_data->fd), 0); ++ TEST_COMPARE (feof (my_data->fd), 0); ++ TEST_COMPARE (ret, 1); ++ return NULL; ++} ++ ++void * ++threadOpenCloseRoutine (void *argv) ++{ ++ /* Wait for all threads to be ready to call fopen and fclose. */ ++ xpthread_barrier_wait (&barrier); ++ ++ FILE *fd = xfopen ("/tmp/openclosetest", "w+"); ++ xfclose (fd); ++ return NULL; ++} ++ ++static int ++do_test (void) ++{ ++ FILE *fd_file = NULL; ++ unsigned char buffer[NUM_THREADS] = "0"; ++ size_t ret = 0; ++ pthread_t threads[NUM_THREADS]; ++ struct thread_data thread_data_array[NUM_THREADS]; ++ bool present_values[NUM_THREADS] = { false }; ++ ++ /* Prepare files. */ ++ for (int i = 0; i < NUM_THREADS; i++) ++ buffer[i] = i; ++ int fd = create_temp_file ("tst-fopen.", &temp_file); ++ TEST_VERIFY_EXIT (fd != -1); ++ fd_file = fdopen (fd, "w"); ++ /* NUM_THREADS - 1: last thread will read EOF */ ++ ret = fwrite (buffer, sizeof (unsigned char), NUM_THREADS - 1, fd_file); ++ TEST_COMPARE (ret, NUM_THREADS - 1); ++ xfclose (fd_file); ++ ++ /* Test 1: Concurrent read. */ ++ for (int reps = 1; reps <= ITERS; reps++) ++ { ++ fd_file = xfopen (temp_file, "r"); ++ xpthread_barrier_init (&barrier, NULL, NUM_THREADS); ++ for (int i = 0; i < NUM_THREADS; i++) ++ { ++ thread_data_array[i].fd = fd_file; ++ /* Initialize with highest possible value so it's easier to debug if ++ anything goes wrong. */ ++ thread_data_array[i].value = 255; ++ thread_data_array[i].eof = false; ++ ++ threads[i] = ++ xpthread_create (support_small_stack_thread_attribute (), ++ threadReadRoutine, ++ (void *) &thread_data_array[i]); ++ } ++ ++ for (int i = 0; i < NUM_THREADS; i++) ++ { ++ xpthread_join (threads[i]); ++ } ++ xpthread_barrier_destroy (&barrier); ++ xfclose (fd_file); ++ ++ /* Verify read values. */ ++ int eof_cnt = 0; ++ for (int i = 0; i < NUM_THREADS; i++) ++ present_values[i] = false; ++ for (int i = 0; i < NUM_THREADS; i++) ++ { ++ if (thread_data_array[i].eof) ++ { ++ /* EOF was read. */ ++ present_values[NUM_THREADS - 1] = true; ++ eof_cnt++; ++ } ++ else ++ { ++ /* The same value shouldn't be read twice. */ ++ TEST_VERIFY (!present_values[thread_data_array[i].value]); ++ present_values[thread_data_array[i].value] = true; ++ } ++ } ++ /* EOF is read exactly once. */ ++ TEST_COMPARE (eof_cnt, 1); ++ for (int i = 0; i < NUM_THREADS; i++) ++ { ++ /* All values should be read. */ ++ TEST_VERIFY (present_values[i]); ++ } ++ } ++ ++ /* Test 2: Concurrent write. */ ++ for (int reps = 1; reps <= ITERS; reps++) ++ { ++ fd_file = xfopen (temp_file, "w"); ++ xpthread_barrier_init (&barrier, NULL, NUM_THREADS); ++ for (int i = 0; i < NUM_THREADS; i++) ++ { ++ thread_data_array[i].fd = fd_file; ++ thread_data_array[i].value = i; ++ ++ threads[i] = ++ xpthread_create (support_small_stack_thread_attribute (), ++ threadWriteRoutine, ++ (void *) &thread_data_array[i]); ++ } ++ ++ for (int i = 0; i < NUM_THREADS; i++) ++ { ++ xpthread_join (threads[i]); ++ } ++ xpthread_barrier_destroy (&barrier); ++ xfclose (fd_file); ++ ++ /* Verify written values. */ ++ for (int i = 0; i < NUM_THREADS; i++) ++ present_values[i] = false; ++ memset (buffer, 0, NUM_THREADS); ++ fd_file = xfopen (temp_file, "r"); ++ ret = fread (buffer, sizeof (unsigned char), NUM_THREADS, fd_file); ++ TEST_COMPARE (ret, NUM_THREADS); ++ for (int i = 0; i < NUM_THREADS; i++) ++ { ++ /* The same value shouldn't be written twice. */ ++ TEST_VERIFY (!present_values[buffer[i]]); ++ present_values[buffer[i]] = true; ++ } ++ for (int i = 0; i < NUM_THREADS; i++) ++ { ++ /* All values should be written. */ ++ TEST_VERIFY (present_values[i]); ++ } ++ xfclose (fd_file); ++ } ++ ++ /* Test 3: Concurrent open/close. */ ++ for (int reps = 1; reps <= ITERS; reps++) ++ { ++ xpthread_barrier_init (&barrier, NULL, NUM_THREADS); ++ for (int i = 0; i < NUM_THREADS; i++) ++ { ++ threads[i] = ++ xpthread_create (support_small_stack_thread_attribute (), ++ threadOpenCloseRoutine, NULL); ++ } ++ for (int i = 0; i < NUM_THREADS; i++) ++ { ++ xpthread_join (threads[i]); ++ } ++ xpthread_barrier_destroy (&barrier); ++ } ++ ++ return 0; ++} ++ ++#include diff --git a/glibc.spec b/glibc.spec index 407af2e..60080c8 100644 --- a/glibc.spec +++ b/glibc.spec @@ -157,7 +157,7 @@ end \ Summary: The GNU libc libraries Name: glibc Version: %{glibcversion} -Release: 170%{?dist} +Release: 171%{?dist} # In general, GPLv2+ is used by programs, LGPLv2+ is used for # libraries. @@ -1120,6 +1120,7 @@ Patch812: glibc-RHEL-57585-3.patch Patch813: glibc-RHEL-57585-4.patch Patch814: glibc-RHEL-57585-5.patch Patch815: glibc-RHEL-67593.patch +Patch816: glibc-RHEL-46729.patch ############################################################################## # Continued list of core "glibc" package information: @@ -3113,6 +3114,9 @@ update_gconv_modules_cache () %endif %changelog +* Mon Mar 03 2025 Frederic Berat - 2.34-171 +- Backport: Add new tests for fopen (RHEL-46729) + * Fri Feb 28 2025 DJ Delorie - 2.34-170 - manual: Update signal descriptions (RHEL-67593)