Gentoo Archives: gentoo-commits

From: "Andreas K. Hüttel" <dilfridge@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] proj/toolchain/glibc-patches:master commit in: 9999/
Date: Tue, 04 Jan 2022 11:00:50
Message-Id: 1641293919.fb003cf688e133a0fe792bee345b400735b7c333.dilfridge@gentoo
1 commit: fb003cf688e133a0fe792bee345b400735b7c333
2 Author: Andreas K. Hüttel <dilfridge <AT> gentoo <DOT> org>
3 AuthorDate: Tue Jan 4 10:58:39 2022 +0000
4 Commit: Andreas K. Hüttel <dilfridge <AT> gentoo <DOT> org>
5 CommitDate: Tue Jan 4 10:58:39 2022 +0000
6 URL: https://gitweb.gentoo.org/proj/toolchain/glibc-patches.git/commit/?id=fb003cf6
7
8 Add patch series from azanella to fix 32bit qemu on 64bit filesystem regression
9
10 Signed-off-by: Andreas K. Hüttel <dilfridge <AT> gentoo.org>
11
12 ...t-skip-entries-with-zero-d_ino-values-BZ-.patch | 182 ++++++++
13 ...2-linux-Use-getdents64-on-non-LFS-readdir.patch | 204 +++++++++
14 ...nternal-DIR-filepos-as-off64_t-BZ-23960-B.patch | 494 +++++++++++++++++++++
15 9999/0204-linux-Add-__readdir64_unlocked.patch | 181 ++++++++
16 9999/0205-linux-Add-__old_readdir64_unlocked.patch | 184 ++++++++
17 ...etdents64-on-readdir64-compat-implementat.patch | 297 +++++++++++++
18 9999/0207-dirent-Deprecate-getdirentries.patch | 101 +++++
19 7 files changed, 1643 insertions(+)
20
21 diff --git a/9999/0201-linux-Do-not-skip-entries-with-zero-d_ino-values-BZ-.patch b/9999/0201-linux-Do-not-skip-entries-with-zero-d_ino-values-BZ-.patch
22 new file mode 100644
23 index 0000000..5325a91
24 --- /dev/null
25 +++ b/9999/0201-linux-Do-not-skip-entries-with-zero-d_ino-values-BZ-.patch
26 @@ -0,0 +1,182 @@
27 +From 7856a2b7ae88602bc9ee65e08fe652b6a6ad5f7e Mon Sep 17 00:00:00 2001
28 +From: Adhemerval Zanella <adhemerval.zanella@××××××.org>
29 +Date: Tue, 20 Oct 2020 12:18:56 -0300
30 +Subject: [PATCH 1/7] linux: Do not skip entries with zero d_ino values [BZ
31 + #12165]
32 +
33 +According to Linux commit 2adc376c55194 (vfs: avoid creation of inode
34 +number 0 in get_next_ino) Linux did not treat d_ino == 0 as a special
35 +case (it is a valid inode number).
36 +
37 +This patch fixes readdir{64} by not ignoring entried with d_ino being
38 +0.
39 +
40 +Checked on x86_64-linux-gnu and i686-linux-gnu.
41 +---
42 + sysdeps/unix/sysv/linux/readdir.c | 59 +++++++++++------------------
43 + sysdeps/unix/sysv/linux/readdir64.c | 59 +++++++++++------------------
44 + 2 files changed, 44 insertions(+), 74 deletions(-)
45 +
46 +diff --git a/sysdeps/unix/sysv/linux/readdir.c b/sysdeps/unix/sysv/linux/readdir.c
47 +index b480135164..c0619ce06f 100644
48 +--- a/sysdeps/unix/sysv/linux/readdir.c
49 ++++ b/sysdeps/unix/sysv/linux/readdir.c
50 +@@ -25,51 +25,36 @@
51 + struct dirent *
52 + __readdir_unlocked (DIR *dirp)
53 + {
54 +- struct dirent *dp;
55 +- int saved_errno = errno;
56 ++ const int saved_errno = errno;
57 +
58 +- do
59 ++ if (dirp->offset >= dirp->size)
60 + {
61 +- size_t reclen;
62 +-
63 +- if (dirp->offset >= dirp->size)
64 ++ /* We've emptied out our buffer. Refill it. */
65 ++ ssize_t bytes = __getdents (dirp->fd, dirp->data, dirp->allocation);
66 ++ if (bytes <= 0)
67 + {
68 +- /* We've emptied out our buffer. Refill it. */
69 +-
70 +- size_t maxread = dirp->allocation;
71 +- ssize_t bytes;
72 +-
73 +- bytes = __getdents (dirp->fd, dirp->data, maxread);
74 +- if (bytes <= 0)
75 +- {
76 +- /* On some systems getdents fails with ENOENT when the
77 +- open directory has been rmdir'd already. POSIX.1
78 +- requires that we treat this condition like normal EOF. */
79 +- if (bytes < 0 && errno == ENOENT)
80 +- bytes = 0;
81 +-
82 +- /* Don't modifiy errno when reaching EOF. */
83 +- if (bytes == 0)
84 +- __set_errno (saved_errno);
85 +- dp = NULL;
86 +- break;
87 +- }
88 +- dirp->size = (size_t) bytes;
89 +-
90 +- /* Reset the offset into the buffer. */
91 +- dirp->offset = 0;
92 ++ /* On some systems getdents fails with ENOENT when the
93 ++ open directory has been rmdir'd already. POSIX.1
94 ++ requires that we treat this condition like normal EOF. */
95 ++ if (bytes < 0 && errno == ENOENT)
96 ++ bytes = 0;
97 ++
98 ++ /* Don't modifiy errno when reaching EOF. */
99 ++ if (bytes == 0)
100 ++ __set_errno (saved_errno);
101 ++ return NULL;
102 + }
103 ++ dirp->size = bytes;
104 +
105 +- dp = (struct dirent *) &dirp->data[dirp->offset];
106 +-
107 +- reclen = dp->d_reclen;
108 ++ /* Reset the offset into the buffer. */
109 ++ dirp->offset = 0;
110 ++ }
111 +
112 +- dirp->offset += reclen;
113 ++ struct dirent *dp = (struct dirent *) &dirp->data[dirp->offset];
114 +
115 +- dirp->filepos = dp->d_off;
116 ++ dirp->offset += dp->d_reclen;
117 +
118 +- /* Skip deleted files. */
119 +- } while (dp->d_ino == 0);
120 ++ dirp->filepos = dp->d_off;
121 +
122 + return dp;
123 + }
124 +diff --git a/sysdeps/unix/sysv/linux/readdir64.c b/sysdeps/unix/sysv/linux/readdir64.c
125 +index 52b11eb9d9..3aea0b1df1 100644
126 +--- a/sysdeps/unix/sysv/linux/readdir64.c
127 ++++ b/sysdeps/unix/sysv/linux/readdir64.c
128 +@@ -30,55 +30,40 @@
129 + struct dirent64 *
130 + __readdir64 (DIR *dirp)
131 + {
132 +- struct dirent64 *dp;
133 +- int saved_errno = errno;
134 ++ const int saved_errno = errno;
135 +
136 + #if IS_IN (libc)
137 + __libc_lock_lock (dirp->lock);
138 + #endif
139 +
140 +- do
141 ++ if (dirp->offset >= dirp->size)
142 + {
143 +- size_t reclen;
144 +-
145 +- if (dirp->offset >= dirp->size)
146 ++ /* We've emptied out our buffer. Refill it. */
147 ++ ssize_t bytes = __getdents64 (dirp->fd, dirp->data, dirp->allocation);
148 ++ if (bytes <= 0)
149 + {
150 +- /* We've emptied out our buffer. Refill it. */
151 +-
152 +- size_t maxread = dirp->allocation;
153 +- ssize_t bytes;
154 +-
155 +- bytes = __getdents64 (dirp->fd, dirp->data, maxread);
156 +- if (bytes <= 0)
157 +- {
158 +- /* On some systems getdents fails with ENOENT when the
159 +- open directory has been rmdir'd already. POSIX.1
160 +- requires that we treat this condition like normal EOF. */
161 +- if (bytes < 0 && errno == ENOENT)
162 +- bytes = 0;
163 +-
164 +- /* Don't modifiy errno when reaching EOF. */
165 +- if (bytes == 0)
166 +- __set_errno (saved_errno);
167 +- dp = NULL;
168 +- break;
169 +- }
170 +- dirp->size = (size_t) bytes;
171 +-
172 +- /* Reset the offset into the buffer. */
173 +- dirp->offset = 0;
174 ++ /* On some systems getdents fails with ENOENT when the
175 ++ open directory has been rmdir'd already. POSIX.1
176 ++ requires that we treat this condition like normal EOF. */
177 ++ if (bytes < 0 && errno == ENOENT)
178 ++ bytes = 0;
179 ++
180 ++ /* Don't modifiy errno when reaching EOF. */
181 ++ if (bytes == 0)
182 ++ __set_errno (saved_errno);
183 ++ return NULL;
184 + }
185 ++ dirp->size = bytes;
186 +
187 +- dp = (struct dirent64 *) &dirp->data[dirp->offset];
188 +-
189 +- reclen = dp->d_reclen;
190 ++ /* Reset the offset into the buffer. */
191 ++ dirp->offset = 0;
192 ++ }
193 +
194 +- dirp->offset += reclen;
195 ++ struct dirent64 *dp = (struct dirent64 *) &dirp->data[dirp->offset];
196 +
197 +- dirp->filepos = dp->d_off;
198 ++ dirp->offset += dp->d_reclen;
199 +
200 +- /* Skip deleted files. */
201 +- } while (dp->d_ino == 0);
202 ++ dirp->filepos = dp->d_off;
203 +
204 + #if IS_IN (libc)
205 + __libc_lock_unlock (dirp->lock);
206 +--
207 +2.32.0
208 +
209
210 diff --git a/9999/0202-linux-Use-getdents64-on-non-LFS-readdir.patch b/9999/0202-linux-Use-getdents64-on-non-LFS-readdir.patch
211 new file mode 100644
212 index 0000000..90910a6
213 --- /dev/null
214 +++ b/9999/0202-linux-Use-getdents64-on-non-LFS-readdir.patch
215 @@ -0,0 +1,204 @@
216 +From 5180512e6c81b1b0423572594983c74c499b7e1e Mon Sep 17 00:00:00 2001
217 +From: Adhemerval Zanella <adhemerval.zanella@××××××.org>
218 +Date: Tue, 20 Oct 2020 13:37:15 -0300
219 +Subject: [PATCH 2/7] linux: Use getdents64 on non-LFS readdir
220 +
221 +The opendir allocates a translation buffer to be used to return the
222 +non-LFS readdir entry. The obtained dirent64 struct is translated
223 +to the temporary buffer on each readdir call.
224 +
225 +Entries that overflow d_off/d_ino and the buffer reallocation failure
226 +(in case of large d_name) are ignored.
227 +
228 +Checked on x86_64-linux-gnu and i686-linux-gnu.
229 +---
230 + sysdeps/unix/sysv/linux/closedir.c | 4 ++
231 + sysdeps/unix/sysv/linux/dirstream.h | 5 ++
232 + sysdeps/unix/sysv/linux/opendir.c | 21 +++++++
233 + sysdeps/unix/sysv/linux/readdir.c | 97 +++++++++++++++++++++--------
234 + 4 files changed, 101 insertions(+), 26 deletions(-)
235 +
236 +diff --git a/sysdeps/unix/sysv/linux/closedir.c b/sysdeps/unix/sysv/linux/closedir.c
237 +index 4bb5274b00..1f71445ad9 100644
238 +--- a/sysdeps/unix/sysv/linux/closedir.c
239 ++++ b/sysdeps/unix/sysv/linux/closedir.c
240 +@@ -47,6 +47,10 @@ __closedir (DIR *dirp)
241 + __libc_lock_fini (dirp->lock);
242 + #endif
243 +
244 ++#if !_DIRENT_MATCHES_DIRENT64
245 ++ free (dirp->tbuffer);
246 ++#endif
247 ++
248 + free ((void *) dirp);
249 +
250 + return __close_nocancel (fd);
251 +diff --git a/sysdeps/unix/sysv/linux/dirstream.h b/sysdeps/unix/sysv/linux/dirstream.h
252 +index b5e1db8db0..64b1495ba0 100644
253 +--- a/sysdeps/unix/sysv/linux/dirstream.h
254 ++++ b/sysdeps/unix/sysv/linux/dirstream.h
255 +@@ -41,6 +41,11 @@ struct __dirstream
256 +
257 + int errcode; /* Delayed error code. */
258 +
259 ++#if !defined __OFF_T_MATCHES_OFF64_T || !defined __INO_T_MATCHES_INO64_T
260 ++ char *tbuffer; /* Translation buffer for non-LFS calls. */
261 ++ size_t tbuffer_size; /* Size of translation buffer. */
262 ++#endif
263 ++
264 + /* Directory block. We must make sure that this block starts
265 + at an address that is aligned adequately enough to store
266 + dirent entries. Using the alignment of "void *" is not
267 +diff --git a/sysdeps/unix/sysv/linux/opendir.c b/sysdeps/unix/sysv/linux/opendir.c
268 +index 48f254d169..d7df13575e 100644
269 +--- a/sysdeps/unix/sysv/linux/opendir.c
270 ++++ b/sysdeps/unix/sysv/linux/opendir.c
271 +@@ -120,6 +120,27 @@ __alloc_dir (int fd, bool close_fd, int flags,
272 + return NULL;
273 + }
274 +
275 ++#if !_DIRENT_MATCHES_DIRENT64
276 ++ /* Allocates a translation buffer to use as the returned 'struct direct'
277 ++ for non-LFS 'readdir' calls.
278 ++
279 ++ The initial NAME_MAX size should handle most cases, while readdir might
280 ++ expand the buffer if required. */
281 ++ enum
282 ++ {
283 ++ tbuffer_size = sizeof (struct dirent) + NAME_MAX + 1
284 ++ };
285 ++ dirp->tbuffer = malloc (tbuffer_size);
286 ++ if (dirp->tbuffer == NULL)
287 ++ {
288 ++ free (dirp);
289 ++ if (close_fd)
290 ++ __close_nocancel_nostatus (fd);
291 ++ return NULL;
292 ++ }
293 ++ dirp->tbuffer_size = tbuffer_size;
294 ++#endif
295 ++
296 + dirp->fd = fd;
297 + #if IS_IN (libc)
298 + __libc_lock_init (dirp->lock);
299 +diff --git a/sysdeps/unix/sysv/linux/readdir.c b/sysdeps/unix/sysv/linux/readdir.c
300 +index c0619ce06f..8647bb0aef 100644
301 +--- a/sysdeps/unix/sysv/linux/readdir.c
302 ++++ b/sysdeps/unix/sysv/linux/readdir.c
303 +@@ -21,42 +21,87 @@
304 + #if !_DIRENT_MATCHES_DIRENT64
305 + #include <dirstream.h>
306 +
307 ++/* Translate the DP64 entry to the non-LFS one in the translation buffer
308 ++ at dirstream DS. Return true is the translation was possible or
309 ++ false if either an internal fields can be represented in the non-LFS
310 ++ entry or if the translation can not be resized. */
311 ++static bool
312 ++dirstream_entry (struct __dirstream *ds, const struct dirent64 *dp64)
313 ++{
314 ++ off_t d_off = dp64->d_off;
315 ++ if (d_off != dp64->d_off)
316 ++ return false;
317 ++ ino_t d_ino = dp64->d_ino;
318 ++ if (d_ino != dp64->d_ino)
319 ++ return false;
320 ++
321 ++ /* Expand the translation buffer to hold the new name size. */
322 ++ size_t new_reclen = sizeof (struct dirent)
323 ++ + dp64->d_reclen - offsetof (struct dirent64, d_name);
324 ++ if (new_reclen > ds->tbuffer_size)
325 ++ {
326 ++ char *newbuffer = realloc (ds->tbuffer, new_reclen);
327 ++ if (newbuffer == NULL)
328 ++ return false;
329 ++ ds->tbuffer = newbuffer;
330 ++ ds->tbuffer_size = new_reclen;
331 ++ }
332 ++
333 ++ struct dirent *dp = (struct dirent *) ds->tbuffer;
334 ++
335 ++ dp->d_off = d_off;
336 ++ dp->d_ino = d_ino;
337 ++ dp->d_reclen = new_reclen;
338 ++ dp->d_type = dp64->d_type;
339 ++ memcpy (dp->d_name, dp64->d_name,
340 ++ dp64->d_reclen - offsetof (struct dirent64, d_name));
341 ++
342 ++ return true;
343 ++}
344 ++
345 + /* Read a directory entry from DIRP. */
346 + struct dirent *
347 + __readdir_unlocked (DIR *dirp)
348 + {
349 + const int saved_errno = errno;
350 +
351 +- if (dirp->offset >= dirp->size)
352 ++ while (1)
353 + {
354 +- /* We've emptied out our buffer. Refill it. */
355 +- ssize_t bytes = __getdents (dirp->fd, dirp->data, dirp->allocation);
356 +- if (bytes <= 0)
357 ++ if (dirp->offset >= dirp->size)
358 + {
359 +- /* On some systems getdents fails with ENOENT when the
360 +- open directory has been rmdir'd already. POSIX.1
361 +- requires that we treat this condition like normal EOF. */
362 +- if (bytes < 0 && errno == ENOENT)
363 +- bytes = 0;
364 +-
365 +- /* Don't modifiy errno when reaching EOF. */
366 +- if (bytes == 0)
367 +- __set_errno (saved_errno);
368 +- return NULL;
369 ++ /* We've emptied out our buffer. Refill it. */
370 ++ ssize_t bytes = __getdents64 (dirp->fd, dirp->data,
371 ++ dirp->allocation);
372 ++ if (bytes <= 0)
373 ++ {
374 ++ /* On some systems getdents fails with ENOENT when the
375 ++ open directory has been rmdir'd already. POSIX.1
376 ++ requires that we treat this condition like normal EOF. */
377 ++ if (bytes < 0 && errno == ENOENT)
378 ++ bytes = 0;
379 ++
380 ++ /* Don't modifiy errno when reaching EOF. */
381 ++ if (bytes == 0)
382 ++ __set_errno (saved_errno);
383 ++ return NULL;
384 ++ }
385 ++ dirp->size = bytes;
386 ++
387 ++ /* Reset the offset into the buffer. */
388 ++ dirp->offset = 0;
389 ++ }
390 ++
391 ++ struct dirent64 *dp64 = (struct dirent64 *) &dirp->data[dirp->offset];
392 ++ dirp->offset += dp64->d_reclen;
393 ++
394 ++ /* Skip entries which might overflow d_off/d_ino or if the translation
395 ++ buffer can't be resized. */
396 ++ if (dirstream_entry (dirp, dp64))
397 ++ {
398 ++ dirp->filepos = dp64->d_off;
399 ++ return (struct dirent *) dirp->tbuffer;
400 + }
401 +- dirp->size = bytes;
402 +-
403 +- /* Reset the offset into the buffer. */
404 +- dirp->offset = 0;
405 + }
406 +-
407 +- struct dirent *dp = (struct dirent *) &dirp->data[dirp->offset];
408 +-
409 +- dirp->offset += dp->d_reclen;
410 +-
411 +- dirp->filepos = dp->d_off;
412 +-
413 +- return dp;
414 + }
415 +
416 + struct dirent *
417 +--
418 +2.32.0
419 +
420
421 diff --git a/9999/0203-linux-Set-internal-DIR-filepos-as-off64_t-BZ-23960-B.patch b/9999/0203-linux-Set-internal-DIR-filepos-as-off64_t-BZ-23960-B.patch
422 new file mode 100644
423 index 0000000..06e8d14
424 --- /dev/null
425 +++ b/9999/0203-linux-Set-internal-DIR-filepos-as-off64_t-BZ-23960-B.patch
426 @@ -0,0 +1,494 @@
427 +From 7d2845e6ed10f2109d2e0f6432932b6693f0037d Mon Sep 17 00:00:00 2001
428 +From: Adhemerval Zanella <adhemerval.zanella@××××××.org>
429 +Date: Mon, 13 Apr 2020 18:09:20 -0300
430 +Subject: [PATCH 3/7] linux: Set internal DIR filepos as off64_t [BZ #23960, BZ
431 + #24050]
432 +
433 +It allows to obtain the expected entry offset on telldir and set
434 +it correctly on seekdir on platforms where long int is smaller
435 +than off64_t.
436 +
437 +On such cases telldir will mantain an internal list that maps the
438 +DIR object off64_t offsets to the returned long int (the function
439 +return value). The seekdir will then set the correct offset from
440 +the internal list using the telldir as the list key.
441 +
442 +It also removes the overflow check on readdir and the returned value
443 +will be truncated by the non-LFS off_t size. As Joseph has noted
444 +in BZ #23960 comment #22, d_off is an opaque value and since
445 +telldir/seekdir works regardless of the returned dirent d_off value.
446 +
447 +Finally it removed the requirement to check for overflow values on
448 +telldir (BZ #24050).
449 +
450 +Checked on x86_64-linux-gnu, i686-linux-gnu, powerpc-linux-gnu,
451 +and arm-linux-gnueabihf.
452 +---
453 + dirent/Makefile | 2 +-
454 + dirent/tst-seekdir2.c | 158 ++++++++++++++++++++++++++++
455 + sysdeps/unix/sysv/linux/closedir.c | 4 +
456 + sysdeps/unix/sysv/linux/dirstream.h | 6 +-
457 + sysdeps/unix/sysv/linux/opendir.c | 3 +
458 + sysdeps/unix/sysv/linux/readdir.c | 1 +
459 + sysdeps/unix/sysv/linux/rewinddir.c | 5 +
460 + sysdeps/unix/sysv/linux/seekdir.c | 36 ++++++-
461 + sysdeps/unix/sysv/linux/telldir.c | 47 ++++++++-
462 + sysdeps/unix/sysv/linux/telldir.h | 64 +++++++++++
463 + 10 files changed, 317 insertions(+), 9 deletions(-)
464 + create mode 100644 dirent/tst-seekdir2.c
465 + create mode 100644 sysdeps/unix/sysv/linux/telldir.h
466 +
467 +diff --git a/dirent/Makefile b/dirent/Makefile
468 +index afc7226a5b..c7f046b3f7 100644
469 +--- a/dirent/Makefile
470 ++++ b/dirent/Makefile
471 +@@ -31,7 +31,7 @@ routines := opendir closedir readdir readdir_r rewinddir \
472 + scandir-cancel scandir-tail scandir64-tail
473 +
474 + tests := list tst-seekdir opendir-tst1 bug-readdir1 tst-fdopendir \
475 +- tst-fdopendir2 tst-scandir tst-scandir64
476 ++ tst-fdopendir2 tst-scandir tst-scandir64 tst-seekdir2
477 +
478 + CFLAGS-scandir.c += $(uses-callbacks)
479 + CFLAGS-scandir64.c += $(uses-callbacks)
480 +diff --git a/dirent/tst-seekdir2.c b/dirent/tst-seekdir2.c
481 +new file mode 100644
482 +index 0000000000..3e01b361e5
483 +--- /dev/null
484 ++++ b/dirent/tst-seekdir2.c
485 +@@ -0,0 +1,158 @@
486 ++/* Check multiple telldir and seekdir.
487 ++ Copyright (C) 2020 Free Software Foundation, Inc.
488 ++ This file is part of the GNU C Library.
489 ++
490 ++ The GNU C Library is free software; you can redistribute it and/or
491 ++ modify it under the terms of the GNU Lesser General Public
492 ++ License as published by the Free Software Foundation; either
493 ++ version 2.1 of the License, or (at your option) any later version.
494 ++
495 ++ The GNU C Library is distributed in the hope that it will be useful,
496 ++ but WITHOUT ANY WARRANTY; without even the implied warranty of
497 ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
498 ++ Lesser General Public License for more details.
499 ++
500 ++ You should have received a copy of the GNU Lesser General Public
501 ++ License along with the GNU C Library; if not, see
502 ++ <https://www.gnu.org/licenses/>. */
503 ++
504 ++#include <dirent.h>
505 ++#include <stdlib.h>
506 ++#include <unistd.h>
507 ++#include <stdio.h>
508 ++#include <string.h>
509 ++
510 ++#include <support/temp_file.h>
511 ++#include <support/support.h>
512 ++#include <support/check.h>
513 ++
514 ++/* Some filesystems returns a arbitrary value for d_off direnty entry (ext4
515 ++ for instance, where the value is an internal hash key). The idea of
516 ++ create a large number of file is to try trigger a overflow d_off value
517 ++ in a entry to check if telldir/seekdir does work corretly in such
518 ++ case. */
519 ++static const char *dirname;
520 ++static const size_t nfiles = 10240;
521 ++
522 ++static void
523 ++do_prepare (int argc, char *argv[])
524 ++{
525 ++ dirname = support_create_temp_directory ("tst-seekdir2-");
526 ++
527 ++ for (size_t i = 0; i < nfiles; i++)
528 ++ {
529 ++ int fd = create_temp_file_in_dir ("tempfile.", dirname, NULL);
530 ++ TEST_VERIFY_EXIT (fd > 0);
531 ++ close (fd);
532 ++ }
533 ++}
534 ++#define PREPARE do_prepare
535 ++
536 ++/* Check for old non Large File Support (LFS). */
537 ++static int
538 ++do_test_not_lfs (void)
539 ++{
540 ++ DIR *dirp = opendir (dirname);
541 ++ TEST_VERIFY_EXIT (dirp != NULL);
542 ++
543 ++ size_t dirp_count = 0;
544 ++ for (struct dirent *dp = readdir (dirp);
545 ++ dp != NULL;
546 ++ dp = readdir (dirp))
547 ++ dirp_count++;
548 ++
549 ++ /* The 2 extra files are '.' and '..'. */
550 ++ TEST_COMPARE (dirp_count, nfiles + 2);
551 ++
552 ++ rewinddir (dirp);
553 ++
554 ++ long *tdirp = xmalloc (dirp_count * sizeof (long));
555 ++ struct dirent **ddirp = xmalloc (dirp_count * sizeof (struct dirent *));
556 ++
557 ++ size_t i = 0;
558 ++ do
559 ++ {
560 ++ tdirp[i] = telldir (dirp);
561 ++ struct dirent *dp = readdir (dirp);
562 ++ TEST_VERIFY_EXIT (dp != NULL);
563 ++ ddirp[i] = xmalloc (dp->d_reclen);
564 ++ memcpy (ddirp[i], dp, dp->d_reclen);
565 ++ } while (++i < dirp_count);
566 ++
567 ++ for (i = 0; i < dirp_count - 1; i++)
568 ++ {
569 ++ seekdir (dirp, tdirp[i]);
570 ++ struct dirent *dp = readdir (dirp);
571 ++ TEST_COMPARE (strcmp (dp->d_name, ddirp[i]->d_name), 0);
572 ++ TEST_COMPARE (dp->d_ino, ddirp[i]->d_ino);
573 ++ TEST_COMPARE (dp->d_off, ddirp[i]->d_off);
574 ++ }
575 ++
576 ++ closedir (dirp);
577 ++ free (tdirp);
578 ++ for (i = 0; i < dirp_count; i++)
579 ++ free (ddirp[i]);
580 ++ free (ddirp);
581 ++
582 ++ return 0;
583 ++}
584 ++
585 ++/* Same as before but with LFS support. */
586 ++static int
587 ++do_test_lfs (void)
588 ++{
589 ++ DIR *dirp = opendir (dirname);
590 ++ TEST_VERIFY_EXIT (dirp != NULL);
591 ++
592 ++ size_t dirp_count = 0;
593 ++ for (struct dirent64 * dp = readdir64 (dirp);
594 ++ dp != NULL;
595 ++ dp = readdir64 (dirp))
596 ++ dirp_count++;
597 ++
598 ++ /* The 2 extra files are '.' and '..'. */
599 ++ TEST_COMPARE (dirp_count, nfiles + 2);
600 ++
601 ++ rewinddir (dirp);
602 ++
603 ++ long *tdirp = xmalloc (dirp_count * sizeof (long));
604 ++ struct dirent64 **ddirp = xmalloc (dirp_count * sizeof (struct dirent64 *));
605 ++
606 ++ size_t i = 0;
607 ++ do
608 ++ {
609 ++ tdirp[i] = telldir (dirp);
610 ++ struct dirent64 *dp = readdir64 (dirp);
611 ++ TEST_VERIFY_EXIT (dp != NULL);
612 ++ ddirp[i] = xmalloc (dp->d_reclen);
613 ++ memcpy (ddirp[i], dp, dp->d_reclen);
614 ++ } while (++i < dirp_count);
615 ++
616 ++ for (i = 0; i < dirp_count - 1; i++)
617 ++ {
618 ++ seekdir (dirp, tdirp[i]);
619 ++ struct dirent64 *dp = readdir64 (dirp);
620 ++ TEST_COMPARE (strcmp (dp->d_name, ddirp[i]->d_name), 0);
621 ++ TEST_COMPARE (dp->d_ino, ddirp[i]->d_ino);
622 ++ TEST_COMPARE (dp->d_off, ddirp[i]->d_off);
623 ++ }
624 ++
625 ++ closedir (dirp);
626 ++ free (tdirp);
627 ++ for (i = 0; i < dirp_count; i++)
628 ++ free (ddirp[i]);
629 ++ free (ddirp);
630 ++
631 ++ return 0;
632 ++}
633 ++
634 ++static int
635 ++do_test (void)
636 ++{
637 ++ do_test_not_lfs ();
638 ++ do_test_lfs ();
639 ++
640 ++ return 0;
641 ++}
642 ++
643 ++#include <support/test-driver.c>
644 +diff --git a/sysdeps/unix/sysv/linux/closedir.c b/sysdeps/unix/sysv/linux/closedir.c
645 +index 1f71445ad9..1845c48be0 100644
646 +--- a/sysdeps/unix/sysv/linux/closedir.c
647 ++++ b/sysdeps/unix/sysv/linux/closedir.c
648 +@@ -43,6 +43,10 @@ __closedir (DIR *dirp)
649 +
650 + fd = dirp->fd;
651 +
652 ++#ifndef __LP64__
653 ++ dirstream_loc_clear (&dirp->locs);
654 ++#endif
655 ++
656 + #if IS_IN (libc)
657 + __libc_lock_fini (dirp->lock);
658 + #endif
659 +diff --git a/sysdeps/unix/sysv/linux/dirstream.h b/sysdeps/unix/sysv/linux/dirstream.h
660 +index 64b1495ba0..1a3362fda6 100644
661 +--- a/sysdeps/unix/sysv/linux/dirstream.h
662 ++++ b/sysdeps/unix/sysv/linux/dirstream.h
663 +@@ -21,6 +21,7 @@
664 + #include <sys/types.h>
665 +
666 + #include <libc-lock.h>
667 ++#include <telldir.h>
668 +
669 + /* Directory stream type.
670 +
671 +@@ -37,7 +38,7 @@ struct __dirstream
672 + size_t size; /* Total valid data in the block. */
673 + size_t offset; /* Current offset into the block. */
674 +
675 +- off_t filepos; /* Position of next entry to read. */
676 ++ off64_t filepos; /* Position of next entry to read. */
677 +
678 + int errcode; /* Delayed error code. */
679 +
680 +@@ -45,6 +46,9 @@ struct __dirstream
681 + char *tbuffer; /* Translation buffer for non-LFS calls. */
682 + size_t tbuffer_size; /* Size of translation buffer. */
683 + #endif
684 ++#ifndef __LP64__
685 ++ struct dirstream_loc_t locs; /* off64_t to long int map for telldir. */
686 ++#endif
687 +
688 + /* Directory block. We must make sure that this block starts
689 + at an address that is aligned adequately enough to store
690 +diff --git a/sysdeps/unix/sysv/linux/opendir.c b/sysdeps/unix/sysv/linux/opendir.c
691 +index d7df13575e..56365f9da5 100644
692 +--- a/sysdeps/unix/sysv/linux/opendir.c
693 ++++ b/sysdeps/unix/sysv/linux/opendir.c
694 +@@ -150,6 +150,9 @@ __alloc_dir (int fd, bool close_fd, int flags,
695 + dirp->offset = 0;
696 + dirp->filepos = 0;
697 + dirp->errcode = 0;
698 ++#ifndef __LP64__
699 ++ dirstream_loc_init (&dirp->locs);
700 ++#endif
701 +
702 + return dirp;
703 + }
704 +diff --git a/sysdeps/unix/sysv/linux/readdir.c b/sysdeps/unix/sysv/linux/readdir.c
705 +index 8647bb0aef..b26d2756b9 100644
706 +--- a/sysdeps/unix/sysv/linux/readdir.c
707 ++++ b/sysdeps/unix/sysv/linux/readdir.c
708 +@@ -17,6 +17,7 @@
709 + <https://www.gnu.org/licenses/>. */
710 +
711 + #include <dirent.h>
712 ++#include <unistd.h>
713 +
714 + #if !_DIRENT_MATCHES_DIRENT64
715 + #include <dirstream.h>
716 +diff --git a/sysdeps/unix/sysv/linux/rewinddir.c b/sysdeps/unix/sysv/linux/rewinddir.c
717 +index 5b68db7167..74b336bfd8 100644
718 +--- a/sysdeps/unix/sysv/linux/rewinddir.c
719 ++++ b/sysdeps/unix/sysv/linux/rewinddir.c
720 +@@ -33,6 +33,11 @@ __rewinddir (DIR *dirp)
721 + dirp->offset = 0;
722 + dirp->size = 0;
723 + dirp->errcode = 0;
724 ++
725 ++#ifndef __LP64__
726 ++ dirstream_loc_clear (&dirp->locs);
727 ++#endif
728 ++
729 + #if IS_IN (libc)
730 + __libc_lock_unlock (dirp->lock);
731 + #endif
732 +diff --git a/sysdeps/unix/sysv/linux/seekdir.c b/sysdeps/unix/sysv/linux/seekdir.c
733 +index b128ae8e76..2fcf689dc0 100644
734 +--- a/sysdeps/unix/sysv/linux/seekdir.c
735 ++++ b/sysdeps/unix/sysv/linux/seekdir.c
736 +@@ -22,14 +22,40 @@
737 + #include <dirstream.h>
738 +
739 + /* Seek to position POS in DIRP. */
740 +-/* XXX should be __seekdir ? */
741 + void
742 + seekdir (DIR *dirp, long int pos)
743 + {
744 ++ off64_t filepos;
745 ++
746 + __libc_lock_lock (dirp->lock);
747 +- (void) __lseek (dirp->fd, pos, SEEK_SET);
748 +- dirp->size = 0;
749 +- dirp->offset = 0;
750 +- dirp->filepos = pos;
751 ++
752 ++#ifndef __LP64__
753 ++ union dirstream_packed dsp;
754 ++
755 ++ dsp.l = pos;
756 ++
757 ++ if (dsp.p.is_packed == 1)
758 ++ filepos = dsp.p.info;
759 ++ else
760 ++ {
761 ++ size_t index = dsp.p.info;
762 ++
763 ++ if (index >= dirstream_loc_size (&dirp->locs))
764 ++ return;
765 ++ struct dirstream_loc *loc = dirstream_loc_at (&dirp->locs, index);
766 ++ filepos = loc->filepos;
767 ++ }
768 ++#else
769 ++ filepos = pos;
770 ++#endif
771 ++
772 ++ if (dirp->filepos != filepos)
773 ++ {
774 ++ __lseek64 (dirp->fd, filepos, SEEK_SET);
775 ++ dirp->filepos = filepos;
776 ++ dirp->offset = 0;
777 ++ dirp->size = 0;
778 ++ }
779 ++
780 + __libc_lock_unlock (dirp->lock);
781 + }
782 +diff --git a/sysdeps/unix/sysv/linux/telldir.c b/sysdeps/unix/sysv/linux/telldir.c
783 +index b184db8d2c..a0eb1efeff 100644
784 +--- a/sysdeps/unix/sysv/linux/telldir.c
785 ++++ b/sysdeps/unix/sysv/linux/telldir.c
786 +@@ -18,16 +18,59 @@
787 + #include <dirent.h>
788 +
789 + #include <dirstream.h>
790 ++#include <telldir.h>
791 +
792 + /* Return the current position of DIRP. */
793 + long int
794 + telldir (DIR *dirp)
795 + {
796 +- long int ret;
797 ++#ifndef __LP64__
798 ++ /* If the directory position fits in the packet structure returns it.
799 ++ Otherwise, check if the position is already been recorded in the
800 ++ dynamic array. If not, add the new record. */
801 ++
802 ++ union dirstream_packed dsp;
803 ++ size_t i;
804 +
805 + __libc_lock_lock (dirp->lock);
806 +- ret = dirp->filepos;
807 ++
808 ++ if (dirp->filepos < (1U << 31))
809 ++ {
810 ++ dsp.p.is_packed = 1;
811 ++ dsp.p.info = dirp->filepos;
812 ++ goto out;
813 ++ }
814 ++
815 ++ dsp.l = -1;
816 ++
817 ++ for (i = 0; i < dirstream_loc_size (&dirp->locs); i++)
818 ++ {
819 ++ struct dirstream_loc *loc = dirstream_loc_at (&dirp->locs, i);
820 ++ if (loc->filepos == dirp->filepos)
821 ++ break;
822 ++ }
823 ++ if (i == dirstream_loc_size (&dirp->locs))
824 ++ {
825 ++ dirstream_loc_add (&dirp->locs,
826 ++ (struct dirstream_loc) { dirp->filepos });
827 ++ if (dirstream_loc_has_failed (&dirp->locs))
828 ++ goto out;
829 ++ }
830 ++
831 ++ dsp.p.is_packed = 0;
832 ++ /* This assignment might overflow, however most likely ENOMEM would happen
833 ++ long before. */
834 ++ dsp.p.info = i;
835 ++
836 ++out:
837 + __libc_lock_unlock (dirp->lock);
838 +
839 ++ return dsp.l;
840 ++#else
841 ++ long int ret;
842 ++ __libc_lock_lock (dirp->lock);
843 ++ ret = dirp->filepos;
844 ++ __libc_lock_unlock (dirp->lock);
845 + return ret;
846 ++#endif
847 + }
848 +diff --git a/sysdeps/unix/sysv/linux/telldir.h b/sysdeps/unix/sysv/linux/telldir.h
849 +new file mode 100644
850 +index 0000000000..7c45886341
851 +--- /dev/null
852 ++++ b/sysdeps/unix/sysv/linux/telldir.h
853 +@@ -0,0 +1,64 @@
854 ++/* Linux internal telldir definitions.
855 ++ Copyright (C) 2020 Free Software Foundation, Inc.
856 ++ This file is part of the GNU C Library.
857 ++
858 ++ The GNU C Library is free software; you can redistribute it and/or
859 ++ modify it under the terms of the GNU Lesser General Public
860 ++ License as published by the Free Software Foundation; either
861 ++ version 2.1 of the License, or (at your option) any later version.
862 ++
863 ++ The GNU C Library is distributed in the hope that it will be useful,
864 ++ but WITHOUT ANY WARRANTY; without even the implied warranty of
865 ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
866 ++ Lesser General Public License for more details.
867 ++
868 ++ You should have received a copy of the GNU Lesser General Public
869 ++ License along with the GNU C Library; if not, see
870 ++ <https://www.gnu.org/licenses/>. */
871 ++
872 ++#ifndef _TELLDIR_H
873 ++#define _TELLDIR_H 1
874 ++
875 ++#ifndef __LP64__
876 ++
877 ++/* On platforms where long int is smaller than off64_t this is how the
878 ++ returned value is encoded and returned by 'telldir'. If the directory
879 ++ offset can be enconded in 31 bits it is returned in the 'info' member
880 ++ with 'is_packed' set to 1.
881 ++
882 ++ Otherwise, the 'info' member describes an index in a dynamic array at
883 ++ 'DIR' structure. */
884 ++
885 ++union dirstream_packed
886 ++{
887 ++ long int l;
888 ++ struct
889 ++ {
890 ++ unsigned long is_packed:1;
891 ++ unsigned long info:31;
892 ++ } p;
893 ++};
894 ++
895 ++_Static_assert (sizeof (long int) == sizeof (union dirstream_packed),
896 ++ "sizeof (long int) != sizeof (union dirstream_packed)");
897 ++
898 ++/* telldir will mantain a list of offsets that describe the obtained diretory
899 ++ position if it can fit this information in the returned 'dirstream_packed'
900 ++ struct. */
901 ++
902 ++struct dirstream_loc
903 ++{
904 ++ off64_t filepos;
905 ++};
906 ++
907 ++# define DYNARRAY_STRUCT dirstream_loc_t
908 ++# define DYNARRAY_ELEMENT struct dirstream_loc
909 ++# define DYNARRAY_PREFIX dirstream_loc_
910 ++# include <malloc/dynarray-skeleton.c>
911 ++#else
912 ++
913 ++_Static_assert (sizeof (long int) == sizeof (off64_t),
914 ++ "sizeof (long int) != sizeof (off64_t)");
915 ++#endif /* __LP64__ */
916 ++
917 ++#endif /* _TELLDIR_H */
918 +--
919 +2.32.0
920 +
921
922 diff --git a/9999/0204-linux-Add-__readdir64_unlocked.patch b/9999/0204-linux-Add-__readdir64_unlocked.patch
923 new file mode 100644
924 index 0000000..29609dd
925 --- /dev/null
926 +++ b/9999/0204-linux-Add-__readdir64_unlocked.patch
927 @@ -0,0 +1,181 @@
928 +From 1524804c8133564c204340a0d618f04c585d7706 Mon Sep 17 00:00:00 2001
929 +From: Adhemerval Zanella <adhemerval.zanella@××××××.org>
930 +Date: Mon, 13 Apr 2020 08:35:40 -0300
931 +Subject: [PATCH 4/7] linux: Add __readdir64_unlocked
932 +
933 +And use it on readdir_r implementation.
934 +
935 +Checked on i686-linux-gnu.
936 +---
937 + include/dirent.h | 1 +
938 + sysdeps/unix/sysv/linux/readdir64.c | 20 +++++--
939 + sysdeps/unix/sysv/linux/readdir64_r.c | 80 ++++++---------------------
940 + 3 files changed, 33 insertions(+), 68 deletions(-)
941 +
942 +diff --git a/include/dirent.h b/include/dirent.h
943 +index d7567f5e86..0c6715d0e4 100644
944 +--- a/include/dirent.h
945 ++++ b/include/dirent.h
946 +@@ -21,6 +21,7 @@ extern DIR *__fdopendir (int __fd) attribute_hidden;
947 + extern int __closedir (DIR *__dirp) attribute_hidden;
948 + extern struct dirent *__readdir (DIR *__dirp) attribute_hidden;
949 + extern struct dirent *__readdir_unlocked (DIR *__dirp) attribute_hidden;
950 ++extern struct dirent64 *__readdir64_unlocked (DIR *__dirp) attribute_hidden;
951 + extern struct dirent64 *__readdir64 (DIR *__dirp);
952 + libc_hidden_proto (__readdir64)
953 + extern int __readdir_r (DIR *__dirp, struct dirent *__entry,
954 +diff --git a/sysdeps/unix/sysv/linux/readdir64.c b/sysdeps/unix/sysv/linux/readdir64.c
955 +index 3aea0b1df1..5519487ede 100644
956 +--- a/sysdeps/unix/sysv/linux/readdir64.c
957 ++++ b/sysdeps/unix/sysv/linux/readdir64.c
958 +@@ -28,14 +28,10 @@
959 +
960 + /* Read a directory entry from DIRP. */
961 + struct dirent64 *
962 +-__readdir64 (DIR *dirp)
963 ++__readdir64_unlocked (DIR *dirp)
964 + {
965 + const int saved_errno = errno;
966 +
967 +-#if IS_IN (libc)
968 +- __libc_lock_lock (dirp->lock);
969 +-#endif
970 +-
971 + if (dirp->offset >= dirp->size)
972 + {
973 + /* We've emptied out our buffer. Refill it. */
974 +@@ -65,6 +61,20 @@ __readdir64 (DIR *dirp)
975 +
976 + dirp->filepos = dp->d_off;
977 +
978 ++ return dp;
979 ++}
980 ++
981 ++struct dirent64 *
982 ++__readdir64 (DIR *dirp)
983 ++{
984 ++ struct dirent64 *dp;
985 ++
986 ++#if IS_IN (libc)
987 ++ __libc_lock_lock (dirp->lock);
988 ++#endif
989 ++
990 ++ dp = __readdir64_unlocked (dirp);
991 ++
992 + #if IS_IN (libc)
993 + __libc_lock_unlock (dirp->lock);
994 + #endif
995 +diff --git a/sysdeps/unix/sysv/linux/readdir64_r.c b/sysdeps/unix/sysv/linux/readdir64_r.c
996 +index 073a6453d1..058d401279 100644
997 +--- a/sysdeps/unix/sysv/linux/readdir64_r.c
998 ++++ b/sysdeps/unix/sysv/linux/readdir64_r.c
999 +@@ -32,89 +32,43 @@ __readdir64_r (DIR *dirp, struct dirent64 *entry, struct dirent64 **result)
1000 + {
1001 + struct dirent64 *dp;
1002 + size_t reclen;
1003 +- const int saved_errno = errno;
1004 +- int ret;
1005 +
1006 + __libc_lock_lock (dirp->lock);
1007 +-
1008 +- do
1009 ++ while (1)
1010 + {
1011 +- if (dirp->offset >= dirp->size)
1012 +- {
1013 +- /* We've emptied out our buffer. Refill it. */
1014 +-
1015 +- size_t maxread = dirp->allocation;
1016 +- ssize_t bytes;
1017 +-
1018 +- maxread = dirp->allocation;
1019 +-
1020 +- bytes = __getdents64 (dirp->fd, dirp->data, maxread);
1021 +- if (bytes <= 0)
1022 +- {
1023 +- /* On some systems getdents fails with ENOENT when the
1024 +- open directory has been rmdir'd already. POSIX.1
1025 +- requires that we treat this condition like normal EOF. */
1026 +- if (bytes < 0 && errno == ENOENT)
1027 +- {
1028 +- bytes = 0;
1029 +- __set_errno (saved_errno);
1030 +- }
1031 +- if (bytes < 0)
1032 +- dirp->errcode = errno;
1033 +-
1034 +- dp = NULL;
1035 +- break;
1036 +- }
1037 +- dirp->size = (size_t) bytes;
1038 +-
1039 +- /* Reset the offset into the buffer. */
1040 +- dirp->offset = 0;
1041 +- }
1042 +-
1043 +- dp = (struct dirent64 *) &dirp->data[dirp->offset];
1044 ++ dp = __readdir64_unlocked (dirp);
1045 ++ if (dp == NULL)
1046 ++ break;
1047 +
1048 + reclen = dp->d_reclen;
1049 ++ if (reclen <= offsetof (struct dirent64, d_name) + NAME_MAX + 1)
1050 ++ break;
1051 +
1052 +- dirp->offset += reclen;
1053 +-
1054 +- dirp->filepos = dp->d_off;
1055 +-
1056 +- if (reclen > offsetof (struct dirent64, d_name) + NAME_MAX + 1)
1057 ++ /* The record is very long. It could still fit into the caller-supplied
1058 ++ buffer if we can skip padding at the end. */
1059 ++ size_t namelen = _D_EXACT_NAMLEN (dp);
1060 ++ if (namelen <= NAME_MAX)
1061 + {
1062 +- /* The record is very long. It could still fit into the
1063 +- caller-supplied buffer if we can skip padding at the
1064 +- end. */
1065 +- size_t namelen = _D_EXACT_NAMLEN (dp);
1066 +- if (namelen <= NAME_MAX)
1067 +- reclen = offsetof (struct dirent64, d_name) + namelen + 1;
1068 +- else
1069 +- {
1070 +- /* The name is too long. Ignore this file. */
1071 +- dirp->errcode = ENAMETOOLONG;
1072 +- dp->d_ino = 0;
1073 +- continue;
1074 +- }
1075 ++ reclen = offsetof (struct dirent64, d_name) + namelen + 1;
1076 ++ break;
1077 + }
1078 +
1079 +- /* Skip deleted and ignored files. */
1080 ++ /* The name is too long. Ignore this file. */
1081 ++ dirp->errcode = ENAMETOOLONG;
1082 ++ dp->d_ino = 0;
1083 + }
1084 +- while (dp->d_ino == 0);
1085 +
1086 + if (dp != NULL)
1087 + {
1088 + *result = memcpy (entry, dp, reclen);
1089 + entry->d_reclen = reclen;
1090 +- ret = 0;
1091 + }
1092 + else
1093 +- {
1094 +- *result = NULL;
1095 +- ret = dirp->errcode;
1096 +- }
1097 ++ *result = NULL;
1098 +
1099 + __libc_lock_unlock (dirp->lock);
1100 +
1101 +- return ret;
1102 ++ return dp != NULL ? 0 : dirp->errcode;
1103 + }
1104 +
1105 +
1106 +--
1107 +2.32.0
1108 +
1109
1110 diff --git a/9999/0205-linux-Add-__old_readdir64_unlocked.patch b/9999/0205-linux-Add-__old_readdir64_unlocked.patch
1111 new file mode 100644
1112 index 0000000..c1ccb61
1113 --- /dev/null
1114 +++ b/9999/0205-linux-Add-__old_readdir64_unlocked.patch
1115 @@ -0,0 +1,184 @@
1116 +From f16c3815c6ad46450d6e58e179ddf494c52a98a4 Mon Sep 17 00:00:00 2001
1117 +From: Adhemerval Zanella <adhemerval.zanella@××××××.org>
1118 +Date: Tue, 14 Apr 2020 11:14:22 -0300
1119 +Subject: [PATCH 5/7] linux: Add __old_readdir64_unlocked
1120 +
1121 +And use it __old_readdir64_r.
1122 +
1123 +Checked on i686-linux-gnu.
1124 +---
1125 + sysdeps/unix/sysv/linux/olddirent.h | 2 +
1126 + sysdeps/unix/sysv/linux/readdir64.c | 21 +++++--
1127 + sysdeps/unix/sysv/linux/readdir64_r.c | 79 ++++++---------------------
1128 + 3 files changed, 35 insertions(+), 67 deletions(-)
1129 +
1130 +diff --git a/sysdeps/unix/sysv/linux/olddirent.h b/sysdeps/unix/sysv/linux/olddirent.h
1131 +index 3e672d47f5..42ab593c4d 100644
1132 +--- a/sysdeps/unix/sysv/linux/olddirent.h
1133 ++++ b/sysdeps/unix/sysv/linux/olddirent.h
1134 +@@ -32,6 +32,8 @@ struct __old_dirent64
1135 + /* Now define the internal interfaces. */
1136 + extern struct __old_dirent64 *__old_readdir64 (DIR *__dirp);
1137 + libc_hidden_proto (__old_readdir64);
1138 ++extern struct __old_dirent64 *__old_readdir64_unlocked (DIR *__dirp)
1139 ++ attribute_hidden;
1140 + extern int __old_readdir64_r (DIR *__dirp, struct __old_dirent64 *__entry,
1141 + struct __old_dirent64 **__result);
1142 + extern __ssize_t __old_getdents64 (int __fd, char *__buf, size_t __nbytes)
1143 +diff --git a/sysdeps/unix/sysv/linux/readdir64.c b/sysdeps/unix/sysv/linux/readdir64.c
1144 +index 5519487ede..8869e49150 100644
1145 +--- a/sysdeps/unix/sysv/linux/readdir64.c
1146 ++++ b/sysdeps/unix/sysv/linux/readdir64.c
1147 +@@ -101,15 +101,11 @@ versioned_symbol (libc, __readdir64, readdir64, GLIBC_2_2);
1148 +
1149 + attribute_compat_text_section
1150 + struct __old_dirent64 *
1151 +-__old_readdir64 (DIR *dirp)
1152 ++__old_readdir64_unlocked (DIR *dirp)
1153 + {
1154 + struct __old_dirent64 *dp;
1155 + int saved_errno = errno;
1156 +
1157 +-#if IS_IN (libc)
1158 +- __libc_lock_lock (dirp->lock);
1159 +-#endif
1160 +-
1161 + do
1162 + {
1163 + size_t reclen;
1164 +@@ -153,6 +149,21 @@ __old_readdir64 (DIR *dirp)
1165 + /* Skip deleted files. */
1166 + } while (dp->d_ino == 0);
1167 +
1168 ++ return dp;
1169 ++}
1170 ++
1171 ++attribute_compat_text_section
1172 ++struct __old_dirent64 *
1173 ++__old_readdir64 (DIR *dirp)
1174 ++{
1175 ++ struct __old_dirent64 *dp;
1176 ++
1177 ++#if IS_IN (libc)
1178 ++ __libc_lock_lock (dirp->lock);
1179 ++#endif
1180 ++
1181 ++ dp = __old_readdir64_unlocked (dirp);
1182 ++
1183 + #if IS_IN (libc)
1184 + __libc_lock_unlock (dirp->lock);
1185 + #endif
1186 +diff --git a/sysdeps/unix/sysv/linux/readdir64_r.c b/sysdeps/unix/sysv/linux/readdir64_r.c
1187 +index 058d401279..e4a0baeaf7 100644
1188 +--- a/sysdeps/unix/sysv/linux/readdir64_r.c
1189 ++++ b/sysdeps/unix/sysv/linux/readdir64_r.c
1190 +@@ -91,89 +91,44 @@ __old_readdir64_r (DIR *dirp, struct __old_dirent64 *entry,
1191 + {
1192 + struct __old_dirent64 *dp;
1193 + size_t reclen;
1194 +- const int saved_errno = errno;
1195 +- int ret;
1196 +
1197 + __libc_lock_lock (dirp->lock);
1198 +
1199 +- do
1200 ++ while (1)
1201 + {
1202 +- if (dirp->offset >= dirp->size)
1203 +- {
1204 +- /* We've emptied out our buffer. Refill it. */
1205 +-
1206 +- size_t maxread = dirp->allocation;
1207 +- ssize_t bytes;
1208 +-
1209 +- maxread = dirp->allocation;
1210 +-
1211 +- bytes = __old_getdents64 (dirp->fd, dirp->data, maxread);
1212 +- if (bytes <= 0)
1213 +- {
1214 +- /* On some systems getdents fails with ENOENT when the
1215 +- open directory has been rmdir'd already. POSIX.1
1216 +- requires that we treat this condition like normal EOF. */
1217 +- if (bytes < 0 && errno == ENOENT)
1218 +- {
1219 +- bytes = 0;
1220 +- __set_errno (saved_errno);
1221 +- }
1222 +- if (bytes < 0)
1223 +- dirp->errcode = errno;
1224 +-
1225 +- dp = NULL;
1226 +- break;
1227 +- }
1228 +- dirp->size = (size_t) bytes;
1229 +-
1230 +- /* Reset the offset into the buffer. */
1231 +- dirp->offset = 0;
1232 +- }
1233 +-
1234 +- dp = (struct __old_dirent64 *) &dirp->data[dirp->offset];
1235 ++ dp = __old_readdir64_unlocked (dirp);
1236 ++ if (dp == NULL)
1237 ++ break;
1238 +
1239 + reclen = dp->d_reclen;
1240 ++ if (reclen <= offsetof (struct __old_dirent64, d_name) + NAME_MAX + 1)
1241 ++ break;
1242 +
1243 +- dirp->offset += reclen;
1244 +-
1245 +- dirp->filepos = dp->d_off;
1246 +-
1247 +- if (reclen > offsetof (struct __old_dirent64, d_name) + NAME_MAX + 1)
1248 ++ /* The record is very long. It could still fit into the caller-supplied
1249 ++ buffer if we can skip padding at the end. */
1250 ++ size_t namelen = _D_EXACT_NAMLEN (dp);
1251 ++ if (namelen <= NAME_MAX)
1252 + {
1253 +- /* The record is very long. It could still fit into the
1254 +- caller-supplied buffer if we can skip padding at the
1255 +- end. */
1256 +- size_t namelen = _D_EXACT_NAMLEN (dp);
1257 +- if (namelen <= NAME_MAX)
1258 +- reclen = offsetof (struct __old_dirent64, d_name) + namelen + 1;
1259 +- else
1260 +- {
1261 +- /* The name is too long. Ignore this file. */
1262 +- dirp->errcode = ENAMETOOLONG;
1263 +- dp->d_ino = 0;
1264 +- continue;
1265 +- }
1266 ++ reclen = offsetof (struct dirent64, d_name) + namelen + 1;
1267 ++ break;
1268 + }
1269 +
1270 +- /* Skip deleted and ignored files. */
1271 ++ /* The name is too long. Ignore this file. */
1272 ++ dirp->errcode = ENAMETOOLONG;
1273 ++ dp->d_ino = 0;
1274 + }
1275 +- while (dp->d_ino == 0);
1276 +
1277 + if (dp != NULL)
1278 + {
1279 + *result = memcpy (entry, dp, reclen);
1280 + entry->d_reclen = reclen;
1281 +- ret = 0;
1282 + }
1283 + else
1284 +- {
1285 +- *result = NULL;
1286 +- ret = dirp->errcode;
1287 +- }
1288 ++ *result = NULL;
1289 +
1290 + __libc_lock_unlock (dirp->lock);
1291 +
1292 +- return ret;
1293 ++ return dp != NULL ? 0 : dirp->errcode;
1294 + }
1295 +
1296 + compat_symbol (libc, __old_readdir64_r, readdir64_r, GLIBC_2_1);
1297 +--
1298 +2.32.0
1299 +
1300
1301 diff --git a/9999/0206-linux-Use-getdents64-on-readdir64-compat-implementat.patch b/9999/0206-linux-Use-getdents64-on-readdir64-compat-implementat.patch
1302 new file mode 100644
1303 index 0000000..90f5d89
1304 --- /dev/null
1305 +++ b/9999/0206-linux-Use-getdents64-on-readdir64-compat-implementat.patch
1306 @@ -0,0 +1,297 @@
1307 +From 46b9383118182cb2ac2e81637e00fde6c21097bb Mon Sep 17 00:00:00 2001
1308 +From: Adhemerval Zanella <adhemerval.zanella@××××××.org>
1309 +Date: Tue, 20 Oct 2020 16:00:43 -0300
1310 +Subject: [PATCH 6/7] linux: Use getdents64 on readdir64 compat implementation
1311 +
1312 +It uses a similar strategy from the non-LFS readdir that also
1313 +uses getdents64 internally and uses a translation buffer to return
1314 +the compat readdir64 entry.
1315 +
1316 +It allows to remove __old_getdents64.
1317 +
1318 +Checked on i686-linux-gnu.
1319 +---
1320 + sysdeps/unix/sysv/linux/getdents64.c | 93 ------------------------
1321 + sysdeps/unix/sysv/linux/olddirent.h | 2 -
1322 + sysdeps/unix/sysv/linux/opendir.c | 15 +++-
1323 + sysdeps/unix/sysv/linux/readdir64.c | 104 +++++++++++++++++----------
1324 + 4 files changed, 79 insertions(+), 135 deletions(-)
1325 +
1326 +diff --git a/sysdeps/unix/sysv/linux/getdents64.c b/sysdeps/unix/sysv/linux/getdents64.c
1327 +index 6323e003b3..38285e9f4b 100644
1328 +--- a/sysdeps/unix/sysv/linux/getdents64.c
1329 ++++ b/sysdeps/unix/sysv/linux/getdents64.c
1330 +@@ -36,97 +36,4 @@ weak_alias (__getdents64, getdents64)
1331 +
1332 + #if _DIRENT_MATCHES_DIRENT64
1333 + strong_alias (__getdents64, __getdents)
1334 +-#else
1335 +-# include <shlib-compat.h>
1336 +-
1337 +-# if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2)
1338 +-# include <olddirent.h>
1339 +-# include <unistd.h>
1340 +-
1341 +-static ssize_t
1342 +-handle_overflow (int fd, __off64_t offset, ssize_t count)
1343 +-{
1344 +- /* If this is the first entry in the buffer, we can report the
1345 +- error. */
1346 +- if (offset == 0)
1347 +- {
1348 +- __set_errno (EOVERFLOW);
1349 +- return -1;
1350 +- }
1351 +-
1352 +- /* Otherwise, seek to the overflowing entry, so that the next call
1353 +- will report the error, and return the data read so far. */
1354 +- if (__lseek64 (fd, offset, SEEK_SET) != 0)
1355 +- return -1;
1356 +- return count;
1357 +-}
1358 +-
1359 +-ssize_t
1360 +-__old_getdents64 (int fd, char *buf, size_t nbytes)
1361 +-{
1362 +- /* We do not move the individual directory entries. This is only
1363 +- possible if the target type (struct __old_dirent64) is smaller
1364 +- than the source type. */
1365 +- _Static_assert (offsetof (struct __old_dirent64, d_name)
1366 +- <= offsetof (struct dirent64, d_name),
1367 +- "__old_dirent64 is larger than dirent64");
1368 +- _Static_assert (__alignof__ (struct __old_dirent64)
1369 +- <= __alignof__ (struct dirent64),
1370 +- "alignment of __old_dirent64 is larger than dirent64");
1371 +-
1372 +- ssize_t retval = INLINE_SYSCALL_CALL (getdents64, fd, buf, nbytes);
1373 +- if (retval > 0)
1374 +- {
1375 +- /* This is the marker for the first entry. Offset 0 is reserved
1376 +- for the first entry (see rewinddir). Here, we use it as a
1377 +- marker for the first entry in the buffer. We never actually
1378 +- seek to offset 0 because handle_overflow reports the error
1379 +- directly, so it does not matter that the offset is incorrect
1380 +- if entries have been read from the descriptor before (so that
1381 +- the descriptor is not actually at offset 0). */
1382 +- __off64_t previous_offset = 0;
1383 +-
1384 +- char *p = buf;
1385 +- char *end = buf + retval;
1386 +- while (p < end)
1387 +- {
1388 +- struct dirent64 *source = (struct dirent64 *) p;
1389 +-
1390 +- /* Copy out the fixed-size data. */
1391 +- __ino_t ino = source->d_ino;
1392 +- __off64_t offset = source->d_off;
1393 +- unsigned int reclen = source->d_reclen;
1394 +- unsigned char type = source->d_type;
1395 +-
1396 +- /* Check for ino_t overflow. */
1397 +- if (__glibc_unlikely (ino != source->d_ino))
1398 +- return handle_overflow (fd, previous_offset, p - buf);
1399 +-
1400 +- /* Convert to the target layout. Use a separate struct and
1401 +- memcpy to side-step aliasing issues. */
1402 +- struct __old_dirent64 result;
1403 +- result.d_ino = ino;
1404 +- result.d_off = offset;
1405 +- result.d_reclen = reclen;
1406 +- result.d_type = type;
1407 +-
1408 +- /* Write the fixed-sized part of the result to the
1409 +- buffer. */
1410 +- size_t result_name_offset = offsetof (struct __old_dirent64, d_name);
1411 +- memcpy (p, &result, result_name_offset);
1412 +-
1413 +- /* Adjust the position of the name if necessary. Copy
1414 +- everything until the end of the record, including the
1415 +- terminating NUL byte. */
1416 +- if (result_name_offset != offsetof (struct dirent64, d_name))
1417 +- memmove (p + result_name_offset, source->d_name,
1418 +- reclen - offsetof (struct dirent64, d_name));
1419 +-
1420 +- p += reclen;
1421 +- previous_offset = offset;
1422 +- }
1423 +- }
1424 +- return retval;
1425 +-}
1426 +-# endif /* SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2) */
1427 + #endif /* _DIRENT_MATCHES_DIRENT64 */
1428 +diff --git a/sysdeps/unix/sysv/linux/olddirent.h b/sysdeps/unix/sysv/linux/olddirent.h
1429 +index 42ab593c4d..b7c51d5ccc 100644
1430 +--- a/sysdeps/unix/sysv/linux/olddirent.h
1431 ++++ b/sysdeps/unix/sysv/linux/olddirent.h
1432 +@@ -36,8 +36,6 @@ extern struct __old_dirent64 *__old_readdir64_unlocked (DIR *__dirp)
1433 + attribute_hidden;
1434 + extern int __old_readdir64_r (DIR *__dirp, struct __old_dirent64 *__entry,
1435 + struct __old_dirent64 **__result);
1436 +-extern __ssize_t __old_getdents64 (int __fd, char *__buf, size_t __nbytes)
1437 +- attribute_hidden;
1438 + int __old_scandir64 (const char * __dir,
1439 + struct __old_dirent64 *** __namelist,
1440 + int (*__selector) (const struct __old_dirent64 *),
1441 +diff --git a/sysdeps/unix/sysv/linux/opendir.c b/sysdeps/unix/sysv/linux/opendir.c
1442 +index 56365f9da5..de722c98e1 100644
1443 +--- a/sysdeps/unix/sysv/linux/opendir.c
1444 ++++ b/sysdeps/unix/sysv/linux/opendir.c
1445 +@@ -23,6 +23,11 @@
1446 +
1447 + #include <not-cancel.h>
1448 +
1449 ++#include <shlib-compat.h>
1450 ++#if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2)
1451 ++# include <olddirent.h>
1452 ++#endif
1453 ++
1454 + enum {
1455 + opendir_oflags = O_RDONLY|O_NDELAY|O_DIRECTORY|O_LARGEFILE|O_CLOEXEC
1456 + };
1457 +@@ -128,7 +133,15 @@ __alloc_dir (int fd, bool close_fd, int flags,
1458 + expand the buffer if required. */
1459 + enum
1460 + {
1461 +- tbuffer_size = sizeof (struct dirent) + NAME_MAX + 1
1462 ++ tbuffer_size =
1463 ++# if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2)
1464 ++ /* This is used on compat readdir64. */
1465 ++ MAX (sizeof (struct dirent),
1466 ++ sizeof (struct __old_dirent64))
1467 ++# else
1468 ++ sizeof (struct dirent)
1469 ++# endif
1470 ++ + NAME_MAX + 1
1471 + };
1472 + dirp->tbuffer = malloc (tbuffer_size);
1473 + if (dirp->tbuffer == NULL)
1474 +diff --git a/sysdeps/unix/sysv/linux/readdir64.c b/sysdeps/unix/sysv/linux/readdir64.c
1475 +index 8869e49150..7ecc8c1b16 100644
1476 +--- a/sysdeps/unix/sysv/linux/readdir64.c
1477 ++++ b/sysdeps/unix/sysv/linux/readdir64.c
1478 +@@ -99,57 +99,83 @@ versioned_symbol (libc, __readdir64, readdir64, GLIBC_2_2);
1479 + # if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2)
1480 + # include <olddirent.h>
1481 +
1482 ++/* Translate the DP64 entry to the old LFS one in the translation buffer
1483 ++ at dirstream DS. Return true is the translation was possible or
1484 ++ false if either an internal fields can be represented in the non-LFS
1485 ++ entry or if the translation can not be resized. */
1486 ++static bool
1487 ++dirstream_old_entry (struct __dirstream *ds, const struct dirent64 *dp64)
1488 ++{
1489 ++ /* Check for overflow. */
1490 ++ ino_t d_ino = dp64->d_ino;
1491 ++ if (d_ino != dp64->d_ino)
1492 ++ return false;
1493 ++
1494 ++ /* Expand the translation buffer to hold the new namesize. */
1495 ++ size_t d_reclen = sizeof (struct __old_dirent64)
1496 ++ + dp64->d_reclen - offsetof (struct dirent64, d_name);
1497 ++ if (d_reclen > ds->tbuffer_size)
1498 ++ {
1499 ++ char *newbuffer = realloc (ds->tbuffer, d_reclen);
1500 ++ if (newbuffer == NULL)
1501 ++ return false;
1502 ++ ds->tbuffer = newbuffer;
1503 ++ ds->tbuffer_size = d_reclen;
1504 ++ }
1505 ++
1506 ++ struct __old_dirent64 *olddp64 = (struct __old_dirent64 *) ds->tbuffer;
1507 ++
1508 ++ olddp64->d_off = dp64->d_off;
1509 ++ olddp64->d_ino = dp64->d_ino;
1510 ++ olddp64->d_reclen = dp64->d_reclen;
1511 ++ olddp64->d_type = dp64->d_type;
1512 ++ memcpy (olddp64->d_name, dp64->d_name,
1513 ++ dp64->d_reclen - offsetof (struct dirent64, d_name));
1514 ++
1515 ++ return true;
1516 ++}
1517 ++
1518 + attribute_compat_text_section
1519 + struct __old_dirent64 *
1520 + __old_readdir64_unlocked (DIR *dirp)
1521 + {
1522 +- struct __old_dirent64 *dp;
1523 +- int saved_errno = errno;
1524 ++ const int saved_errno = errno;
1525 +
1526 +- do
1527 ++ if (dirp->offset >= dirp->size)
1528 + {
1529 +- size_t reclen;
1530 +-
1531 +- if (dirp->offset >= dirp->size)
1532 ++ /* We've emptied out our buffer. Refill it. */
1533 ++ ssize_t bytes = __getdents64 (dirp->fd, dirp->data, dirp->allocation);
1534 ++ if (bytes <= 0)
1535 + {
1536 +- /* We've emptied out our buffer. Refill it. */
1537 +-
1538 +- size_t maxread = dirp->allocation;
1539 +- ssize_t bytes;
1540 +-
1541 +- bytes = __old_getdents64 (dirp->fd, dirp->data, maxread);
1542 +- if (bytes <= 0)
1543 +- {
1544 +- /* On some systems getdents fails with ENOENT when the
1545 +- open directory has been rmdir'd already. POSIX.1
1546 +- requires that we treat this condition like normal EOF. */
1547 +- if (bytes < 0 && errno == ENOENT)
1548 +- bytes = 0;
1549 +-
1550 +- /* Don't modifiy errno when reaching EOF. */
1551 +- if (bytes == 0)
1552 +- __set_errno (saved_errno);
1553 +- dp = NULL;
1554 +- break;
1555 +- }
1556 +- dirp->size = (size_t) bytes;
1557 +-
1558 +- /* Reset the offset into the buffer. */
1559 +- dirp->offset = 0;
1560 +- }
1561 +-
1562 +- dp = (struct __old_dirent64 *) &dirp->data[dirp->offset];
1563 ++ /* On some systems getdents fails with ENOENT when the
1564 ++ open directory has been rmdir'd already. POSIX.1
1565 ++ requires that we treat this condition like normal EOF. */
1566 ++ if (bytes < 0 && errno == ENOENT)
1567 ++ bytes = 0;
1568 +
1569 +- reclen = dp->d_reclen;
1570 ++ /* Don't modifiy errno when reaching EOF. */
1571 ++ if (bytes == 0)
1572 ++ __set_errno (saved_errno);
1573 ++ return NULL;
1574 ++ }
1575 ++ dirp->size = bytes;
1576 +
1577 +- dirp->offset += reclen;
1578 ++ /* Reset the offset into the buffer. */
1579 ++ dirp->offset = 0;
1580 ++ }
1581 +
1582 +- dirp->filepos = dp->d_off;
1583 ++ struct dirent64 *dp64 = (struct dirent64 *) &dirp->data[dirp->offset];
1584 ++ dirp->offset += dp64->d_reclen;
1585 +
1586 +- /* Skip deleted files. */
1587 +- } while (dp->d_ino == 0);
1588 ++ /* Skip entries which might overflow d_ino or for memory allocation failure
1589 ++ in case of large file names. */
1590 ++ if (dirstream_old_entry (dirp, dp64))
1591 ++ {
1592 ++ dirp->filepos = dp64->d_off;
1593 ++ return (struct __old_dirent64 *) dirp->tbuffer;
1594 ++ }
1595 +
1596 +- return dp;
1597 ++ return NULL;
1598 + }
1599 +
1600 + attribute_compat_text_section
1601 +--
1602 +2.32.0
1603 +
1604
1605 diff --git a/9999/0207-dirent-Deprecate-getdirentries.patch b/9999/0207-dirent-Deprecate-getdirentries.patch
1606 new file mode 100644
1607 index 0000000..7b00018
1608 --- /dev/null
1609 +++ b/9999/0207-dirent-Deprecate-getdirentries.patch
1610 @@ -0,0 +1,101 @@
1611 +From 8180167096d51c9767888a695e60a542b64813f0 Mon Sep 17 00:00:00 2001
1612 +From: Adhemerval Zanella <adhemerval.zanella@××××××.org>
1613 +Date: Fri, 17 Apr 2020 09:59:51 -0300
1614 +Subject: [PATCH 7/7] dirent: Deprecate getdirentries
1615 +
1616 +The interface has some issues:
1617 +
1618 + 1. It is build on top getdents on Linux and requires handling
1619 + non-LFS call using LFS getdents.
1620 +
1621 + 2. It is not wildly used and the non-LFS support is as problematic
1622 + as non-LFS readdir. glibc only exports the LFS getdents.
1623 +
1624 + 3. It is not a direct replacement over BSD since on some plataform
1625 + its signature has changed (FreeBSD 11, for instance, used to
1626 + set the offset as a 'long' and changed to 'off_t' on version 12).
1627 +
1628 +The idea is to eventually move the symbols to compat ones.
1629 +---
1630 + NEWS | 5 +++++
1631 + dirent/dirent.h | 14 ++++++++++----
1632 + sysdeps/unix/sysv/linux/Makefile | 3 +++
1633 + 3 files changed, 18 insertions(+), 4 deletions(-)
1634 +
1635 +diff --git a/NEWS b/NEWS
1636 +index d9b344027b..a18a1d7a8c 100644
1637 +--- a/NEWS
1638 ++++ b/NEWS
1639 +@@ -7,6 +7,11 @@ using `glibc' in the "product" field.
1640 +
1641 + Version 2.34.1
1642 +
1643 ++Deprecated and removed features, and other changes affecting compatibility:
1644 ++
1645 ++* The function getdirentries is now deprecated, applications should use
1646 ++ either getdents64, readdir64 or readdir.
1647 ++
1648 + The following bugs are resolved with this release:
1649 +
1650 + [12889] nptl: Fix race between pthread_kill and thread exit
1651 +diff --git a/dirent/dirent.h b/dirent/dirent.h
1652 +index 1d1fab7e55..8ad5fbf430 100644
1653 +--- a/dirent/dirent.h
1654 ++++ b/dirent/dirent.h
1655 +@@ -348,29 +348,35 @@ extern int alphasort64 (const struct dirent64 **__e1,
1656 + /* Read directory entries from FD into BUF, reading at most NBYTES.
1657 + Reading starts at offset *BASEP, and *BASEP is updated with the new
1658 + position after reading. Returns the number of bytes read; zero when at
1659 +- end of directory; or -1 for errors. */
1660 ++ end of directory; or -1 for errors.
1661 ++ This is deprecated and getdents64 or readdir should be used instead. */
1662 + # ifndef __USE_FILE_OFFSET64
1663 + extern __ssize_t getdirentries (int __fd, char *__restrict __buf,
1664 + size_t __nbytes,
1665 + __off_t *__restrict __basep)
1666 +- __THROW __nonnull ((2, 4));
1667 ++ __THROW __nonnull ((2, 4))
1668 ++ __attribute_deprecated_msg__ ("Use getdents64 instead");
1669 + # else
1670 + # ifdef __REDIRECT
1671 + extern __ssize_t __REDIRECT_NTH (getdirentries,
1672 + (int __fd, char *__restrict __buf,
1673 + size_t __nbytes,
1674 + __off64_t *__restrict __basep),
1675 +- getdirentries64) __nonnull ((2, 4));
1676 ++ getdirentries64)
1677 ++ __THROW __nonnull ((2, 4))
1678 ++ __attribute_deprecated_msg__ ("Use getdents64 instead");
1679 + # else
1680 + # define getdirentries getdirentries64
1681 + # endif
1682 + # endif
1683 +
1684 + # ifdef __USE_LARGEFILE64
1685 ++/* This is deprecated and getdents64 or readdir64 should be used instead. */
1686 + extern __ssize_t getdirentries64 (int __fd, char *__restrict __buf,
1687 + size_t __nbytes,
1688 + __off64_t *__restrict __basep)
1689 +- __THROW __nonnull ((2, 4));
1690 ++ __THROW __nonnull ((2, 4))
1691 ++ __attribute_deprecated_msg__ ("Use getdents64 instead");
1692 + # endif
1693 + #endif /* Use misc. */
1694 +
1695 +diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile
1696 +index 76ad06361c..65ec7529f6 100644
1697 +--- a/sysdeps/unix/sysv/linux/Makefile
1698 ++++ b/sysdeps/unix/sysv/linux/Makefile
1699 +@@ -313,6 +313,9 @@ tests += tst-getdents64
1700 + # The tested readdir64 symbol was replaced in glibc 2.2.
1701 + ifeq ($(have-GLIBC_2.1.3)$(build-shared),yesyes)
1702 + tests += tst-readdir64-compat
1703 ++
1704 ++# Avoid the warning for the weak_alias for _DIRENT_MATCHES_DIRENT64
1705 ++CFLAGS-getdirentries64.c = -Wno-deprecated-declarations
1706 + endif
1707 + endif # $(subdir) == dirent
1708 +
1709 +--
1710 +2.32.0
1711 +