aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFlorian Weimer <fweimer@redhat.com>2019-06-07 09:27:01 +0200
committerFlorian Weimer <fweimer@redhat.com>2019-06-07 09:27:01 +0200
commit51ea67d54882318c4fa5394c386f4816ddc22408 (patch)
tree9b1f881f8d4e8b464a2d3b08b805e97a35457c7d
parentde751ebc9efa97ce0115e42bd55fa1beeb614380 (diff)
downloadglibc-51ea67d54882318c4fa5394c386f4816ddc22408.tar.gz
glibc-51ea67d54882318c4fa5394c386f4816ddc22408.tar.xz
glibc-51ea67d54882318c4fa5394c386f4816ddc22408.zip
Linux: Add getdents64 system call
No 32-bit system call wrapper is added because the interface is problematic because it cannot deal with 64-bit inode numbers and 64-bit directory hashes. A future commit will deprecate the undocumented getdirentries and getdirentries64 functions. Reviewed-by: Carlos O'Donell <carlos@redhat.com>
-rw-r--r--ChangeLog75
-rw-r--r--NEWS2
-rw-r--r--include/dirent.h10
-rw-r--r--manual/filesys.texi38
-rw-r--r--sysdeps/unix/sysv/linux/Makefile1
-rw-r--r--sysdeps/unix/sysv/linux/Versions2
-rw-r--r--sysdeps/unix/sysv/linux/aarch64/libc.abilist1
-rw-r--r--sysdeps/unix/sysv/linux/alpha/libc.abilist1
-rw-r--r--sysdeps/unix/sysv/linux/arm/libc.abilist1
-rw-r--r--sysdeps/unix/sysv/linux/bits/unistd_ext.h6
-rw-r--r--sysdeps/unix/sysv/linux/csky/libc.abilist1
-rw-r--r--sysdeps/unix/sysv/linux/getdents.c4
-rw-r--r--sysdeps/unix/sysv/linux/getdents64.c6
-rw-r--r--sysdeps/unix/sysv/linux/hppa/libc.abilist1
-rw-r--r--sysdeps/unix/sysv/linux/i386/libc.abilist1
-rw-r--r--sysdeps/unix/sysv/linux/ia64/libc.abilist1
-rw-r--r--sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist1
-rw-r--r--sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist1
-rw-r--r--sysdeps/unix/sysv/linux/microblaze/libc.abilist1
-rw-r--r--sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist1
-rw-r--r--sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist1
-rw-r--r--sysdeps/unix/sysv/linux/mips/mips64/getdents64.c7
-rw-r--r--sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist1
-rw-r--r--sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist1
-rw-r--r--sysdeps/unix/sysv/linux/nios2/libc.abilist1
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist1
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist1
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist1
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist1
-rw-r--r--sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist1
-rw-r--r--sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist1
-rw-r--r--sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist1
-rw-r--r--sysdeps/unix/sysv/linux/sh/libc.abilist1
-rw-r--r--sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist1
-rw-r--r--sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist1
-rw-r--r--sysdeps/unix/sysv/linux/tst-getdents64.c113
-rw-r--r--sysdeps/unix/sysv/linux/x86_64/64/libc.abilist1
-rw-r--r--sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist1
38 files changed, 282 insertions, 9 deletions
diff --git a/ChangeLog b/ChangeLog
index d988bc53095..55afdcbfbda 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,78 @@
+2019-06-07 Florian Weimer <fweimer@redhat.com>
+
+ Linux: Add getdents64 system call.
+ * include/dirnent.h (getdents): Add comment and change buffer
+ argument type to void *.
+ (getdents64): Likewise. Add hidden prototype.
+ * sysdeps/unix/sysv/linux/bits/Versions (GLIBC_2.30): Export
+ getdents64.
+ * sysdeps/unix/sysv/linux/Makefile [$(subdir) == dirent] (tests):
+ Add tst-getdents64.
+ * sysdeps/unix/sysv/linux/bits/unistd_ext.h (getdents64): Declare.
+ * sysdeps/unix/sysv/linux/getdents.c (__getdents): Change buffer
+ argument type to void *.
+ * sysdeps/unix/sysv/linux/getdents64.c (__getdents64): Likewise.
+ Add hidden definition and getdents64 alias.
+ * sysdeps/unix/sysv/linux/mips/mips64/getdents64.c (__getdents64):
+ Likewise.
+ * sysdeps/unix/sysv/linux/tst-getdents64.c: New file.
+ * manual/filesys.texi (Accessing Directories): Add Low-level
+ Directory Access node reference.
+ (Opening a Directory): Cross-reference it.
+ (Low-level Directory Access): New node.
+ * sysdeps/unix/sysv/linux/aarch64/libc.abilist (GLIBC_2.30): Add
+ getdents64.
+ * sysdeps/unix/sysv/linux/alpha/libc.abilist (GLIBC_2.30):
+ Likewise.
+ * sysdeps/unix/sysv/linux/arm/libc.abilist (GLIBC_2.30): Likewise.
+ * sysdeps/unix/sysv/linux/csky/libc.abilist (GLIBC_2.30):
+ Likewise.
+ * sysdeps/unix/sysv/linux/hppa/libc.abilist (GLIBC_2.30):
+ Likewise.
+ * sysdeps/unix/sysv/linux/i386/libc.abilist (GLIBC_2.30):
+ Likewise.
+ * sysdeps/unix/sysv/linux/ia64/libc.abilist (GLIBC_2.30):
+ Likewise.
+ * sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist (GLIBC_2.30):
+ Likewise.
+ * sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist (GLIBC_2.30):
+ Likewise.
+ * sysdeps/unix/sysv/linux/microblaze/libc.abilist (GLIBC_2.30):
+ Likewise.
+ * sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
+ (GLIBC_2.30): Likewise.
+ * sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
+ (GLIBC_2.30): Likewise.
+ * sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
+ (GLIBC_2.30): Likewise.
+ * sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
+ (GLIBC_2.30): Likewise.
+ * sysdeps/unix/sysv/linux/nios2/libc.abilist (GLIBC_2.30):
+ Likewise.
+ * sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
+ (GLIBC_2.30): Likewise.
+ * sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
+ (GLIBC_2.30): Likewise.
+ * sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
+ (GLIBC_2.30): Likewise.
+ * sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
+ (GLIBC_2.30): Likewise.
+ * sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist (GLIBC_2.30):
+ Likewise.
+ * sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist (GLIBC_2.30):
+ Likewise.
+ * sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist (GLIBC_2.30):
+ Likewise.
+ * sysdeps/unix/sysv/linux/sh/libc.abilist (GLIBC_2.30): Likewise.
+ * sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist (GLIBC_2.30):
+ Likewise.
+ * sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist (GLIBC_2.30):
+ Likewise.
+ * sysdeps/unix/sysv/linux/x86_64/64/libc.abilist (GLIBC_2.30):
+ Likewise.
+ * sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist (GLIBC_2.30):
+ Likewise.
+
2019-06-06 Paul A. Clarke <pc@us.ibm.com>
* sysdeps/powerpc/fpu_control.h (_FPU_MASK_RC): New.
diff --git a/NEWS b/NEWS
index 31ead24851c..00f9e855a29 100644
--- a/NEWS
+++ b/NEWS
@@ -20,7 +20,7 @@ Major new features:
twalk function, but it passes an additional caller-supplied argument
to the callback function.
-* On Linux, the gettid and tgkill functions have been added.
+* On Linux, the getdents64, gettid, and tgkill functions have been added.
* Minguo (Republic of China) calendar support has been added as an
alternative calendar for the following locales: zh_TW, cmn_TW, hak_TW,
diff --git a/include/dirent.h b/include/dirent.h
index 400835eefe2..3736803bcef 100644
--- a/include/dirent.h
+++ b/include/dirent.h
@@ -35,10 +35,14 @@ extern __ssize_t __getdirentries (int __fd, char *__restrict __buf,
size_t __nbytes,
__off_t *__restrict __basep)
__THROW __nonnull ((2, 4));
-extern __ssize_t __getdents (int __fd, char *__buf, size_t __nbytes)
- attribute_hidden;
-extern __ssize_t __getdents64 (int __fd, char *__buf, size_t __nbytes)
+
+/* These functions are only implemented on Linux. The public
+ interface for getdents64 is declared in <unistd.h>. */
+extern __ssize_t __getdents (int __fd, void *__buf, size_t __nbytes)
attribute_hidden;
+extern __ssize_t __getdents64 (int __fd, void *__buf, size_t __nbytes);
+libc_hidden_proto (__getdents64)
+
extern int __alphasort64 (const struct dirent64 **a, const struct dirent64 **b)
__attribute_pure__;
extern int __versionsort64 (const struct dirent64 **a,
diff --git a/manual/filesys.texi b/manual/filesys.texi
index 28480e76084..513319418a8 100644
--- a/manual/filesys.texi
+++ b/manual/filesys.texi
@@ -242,6 +242,7 @@ here to the stream facilities for ordinary files, described in
* Scanning Directory Content:: Get entries for user selected subset of
contents in given directory.
* Simple Directory Lister Mark II:: Revised version of the program.
+* Low-level Directory Access:: AS-Safe functions for directory access.
@end menu
@node Directory Entries
@@ -360,6 +361,10 @@ You shouldn't ever allocate objects of the @code{struct dirent} or
you. Instead, you refer to these objects using the pointers returned by
the following functions.
+Directory streams are a high-level interface. On Linux, alternative
+interfaces for accessing directories using file descriptors are
+available. @xref{Low-level Directory Access}.
+
@deftypefun {DIR *} opendir (const char *@var{dirname})
@standards{POSIX.1, dirent.h}
@safety{@prelim{}@mtsafe{}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{} @acsfd{}}}
@@ -826,6 +831,39 @@ After the call the returned entries are available for direct use.
Note the simple selector function in this example. Since we want to see
all directory entries we always return @code{1}.
+@node Low-level Directory Access
+@subsection Low-level Directory Access
+
+The stream-based directory functions are not AS-Safe and cannot be
+used after @code{vfork}. @xref{POSIX Safety Concepts}. The functions
+below provide an alternative that can be used in these contexts.
+
+Directory data is obtained from a file descriptor, as created by the
+@code{open} function, with or without the @code{O_DIRECTORY} flag.
+@xref{Opening and Closing Files}.
+
+@deftypefun ssize_t getdents64 (int @var{fd}, void *@var{buffer}, size_t @var{length})
+@standards{Linux, unistd.h}
+@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
+The @code{getdents64} function reads at most @var{length} bytes of
+directory entry data from the file descriptor @var{fd} and stores it
+into the byte array starting at @var{buffer}.
+
+On success, the function returns the number of bytes written to the
+buffer. This number is zero if @var{fd} is already at the end of the
+directory stream. On error, the function returns @code{-1} and sets
+@code{errno} to the appropriate error code.
+
+The data is stored as a sequence of @code{struct dirent64} records,
+which can be traversed using the @code{d_reclen} member. The buffer
+should be large enough to hold the largest possible directory entry.
+Note that some file systems support file names longer than
+@code{NAME_MAX} bytes (e.g., because they support up to 255 Unicode
+characters), so a buffer size of at least 1024 is recommended.
+
+This function is specific to Linux.
+@end deftypefun
+
@node Working with Directory Trees
@section Working with Directory Trees
diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile
index d2f0b60ea9b..afcdc658b51 100644
--- a/sysdeps/unix/sysv/linux/Makefile
+++ b/sysdeps/unix/sysv/linux/Makefile
@@ -188,6 +188,7 @@ inhibit-glue = yes
ifeq ($(subdir),dirent)
sysdep_routines += getdirentries getdirentries64
+tests += tst-getdents64
tests-internal += tst-readdir64-compat
endif
diff --git a/sysdeps/unix/sysv/linux/Versions b/sysdeps/unix/sysv/linux/Versions
index c7137e2c2cc..1ca102a9e2e 100644
--- a/sysdeps/unix/sysv/linux/Versions
+++ b/sysdeps/unix/sysv/linux/Versions
@@ -175,7 +175,7 @@ libc {
getcpu;
}
GLIBC_2.30 {
- gettid; tgkill;
+ getdents64; gettid; tgkill;
}
GLIBC_PRIVATE {
# functions used in other libraries
diff --git a/sysdeps/unix/sysv/linux/aarch64/libc.abilist b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
index 324909d5538..a4c31932cb9 100644
--- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
@@ -2141,6 +2141,7 @@ GLIBC_2.28 thrd_yield F
GLIBC_2.29 getcpu F
GLIBC_2.29 posix_spawn_file_actions_addchdir_np F
GLIBC_2.29 posix_spawn_file_actions_addfchdir_np F
+GLIBC_2.30 getdents64 F
GLIBC_2.30 gettid F
GLIBC_2.30 tgkill F
GLIBC_2.30 twalk_r F
diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sysv/linux/alpha/libc.abilist
index 084e4755694..fe85a356200 100644
--- a/sysdeps/unix/sysv/linux/alpha/libc.abilist
+++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist
@@ -2216,6 +2216,7 @@ GLIBC_2.30 __nldbl_vwarn F
GLIBC_2.30 __nldbl_vwarnx F
GLIBC_2.30 __nldbl_warn F
GLIBC_2.30 __nldbl_warnx F
+GLIBC_2.30 getdents64 F
GLIBC_2.30 gettid F
GLIBC_2.30 tgkill F
GLIBC_2.30 twalk_r F
diff --git a/sysdeps/unix/sysv/linux/arm/libc.abilist b/sysdeps/unix/sysv/linux/arm/libc.abilist
index f58d16e2107..bc3df8dcea3 100644
--- a/sysdeps/unix/sysv/linux/arm/libc.abilist
+++ b/sysdeps/unix/sysv/linux/arm/libc.abilist
@@ -126,6 +126,7 @@ GLIBC_2.28 thrd_yield F
GLIBC_2.29 getcpu F
GLIBC_2.29 posix_spawn_file_actions_addchdir_np F
GLIBC_2.29 posix_spawn_file_actions_addfchdir_np F
+GLIBC_2.30 getdents64 F
GLIBC_2.30 gettid F
GLIBC_2.30 tgkill F
GLIBC_2.30 twalk_r F
diff --git a/sysdeps/unix/sysv/linux/bits/unistd_ext.h b/sysdeps/unix/sysv/linux/bits/unistd_ext.h
index 0061172f238..6e7b2bb83d7 100644
--- a/sysdeps/unix/sysv/linux/bits/unistd_ext.h
+++ b/sysdeps/unix/sysv/linux/bits/unistd_ext.h
@@ -22,6 +22,12 @@
#ifdef __USE_GNU
+/* Read from the directory descriptor FD into LENGTH bytes at BUFFER.
+ Return the number of bytes read on success (0 for end of
+ directory), and -1 for failure. */
+extern ssize_t getdents64 (int __fd, void *__buffer, size_t __length)
+ __THROW __nonnull ((2));
+
/* Return the kernel thread ID (TID) of the current thread. The
returned value is not subject to caching. Most Linux system calls
accept a TID in place of a PID. Using the TID to change properties
diff --git a/sysdeps/unix/sysv/linux/csky/libc.abilist b/sysdeps/unix/sysv/linux/csky/libc.abilist
index 38f6abaa305..9b3cee65bb5 100644
--- a/sysdeps/unix/sysv/linux/csky/libc.abilist
+++ b/sysdeps/unix/sysv/linux/csky/libc.abilist
@@ -2085,6 +2085,7 @@ GLIBC_2.29 xdrstdio_create F
GLIBC_2.29 xencrypt F
GLIBC_2.29 xprt_register F
GLIBC_2.29 xprt_unregister F
+GLIBC_2.30 getdents64 F
GLIBC_2.30 gettid F
GLIBC_2.30 tgkill F
GLIBC_2.30 twalk_r F
diff --git a/sysdeps/unix/sysv/linux/getdents.c b/sysdeps/unix/sysv/linux/getdents.c
index e796d9354b5..3eec4c42212 100644
--- a/sysdeps/unix/sysv/linux/getdents.c
+++ b/sysdeps/unix/sysv/linux/getdents.c
@@ -31,8 +31,10 @@
/* Pack the dirent64 struct down into 32-bit offset/inode fields, and
ensure that no overflow occurs. */
ssize_t
-__getdents (int fd, char *buf, size_t nbytes)
+__getdents (int fd, void *buf0, size_t nbytes)
{
+ char *buf = buf0;
+
union
{
/* For !_DIRENT_MATCHES_DIRENT64 kernel 'linux_dirent64' has the same
diff --git a/sysdeps/unix/sysv/linux/getdents64.c b/sysdeps/unix/sysv/linux/getdents64.c
index 0786a151952..a6dd22106db 100644
--- a/sysdeps/unix/sysv/linux/getdents64.c
+++ b/sysdeps/unix/sysv/linux/getdents64.c
@@ -20,12 +20,14 @@
#include <dirent.h>
#include <errno.h>
-/* The kernel struct linux_dirent64 matches the 'struct getdents64' type. */
+/* The kernel struct linux_dirent64 matches the 'struct dirent64' type. */
ssize_t
-__getdents64 (int fd, char *buf, size_t nbytes)
+__getdents64 (int fd, void *buf, size_t nbytes)
{
return INLINE_SYSCALL_CALL (getdents64, fd, buf, nbytes);
}
+libc_hidden_def (__getdents64)
+weak_alias (__getdents64, getdents64)
#if _DIRENT_MATCHES_DIRENT64
strong_alias (__getdents64, __getdents)
diff --git a/sysdeps/unix/sysv/linux/hppa/libc.abilist b/sysdeps/unix/sysv/linux/hppa/libc.abilist
index eb628f907bc..75edece94a1 100644
--- a/sysdeps/unix/sysv/linux/hppa/libc.abilist
+++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist
@@ -2037,6 +2037,7 @@ GLIBC_2.3.4 setipv4sourcefilter F
GLIBC_2.3.4 setsourcefilter F
GLIBC_2.3.4 xdr_quad_t F
GLIBC_2.3.4 xdr_u_quad_t F
+GLIBC_2.30 getdents64 F
GLIBC_2.30 gettid F
GLIBC_2.30 tgkill F
GLIBC_2.30 twalk_r F
diff --git a/sysdeps/unix/sysv/linux/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist
index 6f240d9a591..edeaf8e7220 100644
--- a/sysdeps/unix/sysv/linux/i386/libc.abilist
+++ b/sysdeps/unix/sysv/linux/i386/libc.abilist
@@ -2203,6 +2203,7 @@ GLIBC_2.3.4 setsourcefilter F
GLIBC_2.3.4 vm86 F
GLIBC_2.3.4 xdr_quad_t F
GLIBC_2.3.4 xdr_u_quad_t F
+GLIBC_2.30 getdents64 F
GLIBC_2.30 gettid F
GLIBC_2.30 tgkill F
GLIBC_2.30 twalk_r F
diff --git a/sysdeps/unix/sysv/linux/ia64/libc.abilist b/sysdeps/unix/sysv/linux/ia64/libc.abilist
index e589e3d7e2d..b5d460eeb21 100644
--- a/sysdeps/unix/sysv/linux/ia64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/ia64/libc.abilist
@@ -2069,6 +2069,7 @@ GLIBC_2.3.4 setipv4sourcefilter F
GLIBC_2.3.4 setsourcefilter F
GLIBC_2.3.4 xdr_quad_t F
GLIBC_2.3.4 xdr_u_quad_t F
+GLIBC_2.30 getdents64 F
GLIBC_2.30 gettid F
GLIBC_2.30 tgkill F
GLIBC_2.30 twalk_r F
diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
index 02c3ceee8d7..05633b3cb82 100644
--- a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
@@ -127,6 +127,7 @@ GLIBC_2.28 thrd_yield F
GLIBC_2.29 getcpu F
GLIBC_2.29 posix_spawn_file_actions_addchdir_np F
GLIBC_2.29 posix_spawn_file_actions_addfchdir_np F
+GLIBC_2.30 getdents64 F
GLIBC_2.30 gettid F
GLIBC_2.30 tgkill F
GLIBC_2.30 twalk_r F
diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
index f9a86bd9516..47eb7b46082 100644
--- a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
@@ -2146,6 +2146,7 @@ GLIBC_2.3.4 setipv4sourcefilter F
GLIBC_2.3.4 setsourcefilter F
GLIBC_2.3.4 xdr_quad_t F
GLIBC_2.3.4 xdr_u_quad_t F
+GLIBC_2.30 getdents64 F
GLIBC_2.30 gettid F
GLIBC_2.30 tgkill F
GLIBC_2.30 twalk_r F
diff --git a/sysdeps/unix/sysv/linux/microblaze/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
index d153fe0df53..f7ced487f78 100644
--- a/sysdeps/unix/sysv/linux/microblaze/libc.abilist
+++ b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
@@ -2133,6 +2133,7 @@ GLIBC_2.28 thrd_yield F
GLIBC_2.29 getcpu F
GLIBC_2.29 posix_spawn_file_actions_addchdir_np F
GLIBC_2.29 posix_spawn_file_actions_addfchdir_np F
+GLIBC_2.30 getdents64 F
GLIBC_2.30 gettid F
GLIBC_2.30 tgkill F
GLIBC_2.30 twalk_r F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
index fb3a9b18fcf..e49dc4272eb 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
@@ -2120,6 +2120,7 @@ GLIBC_2.3.4 setipv4sourcefilter F
GLIBC_2.3.4 setsourcefilter F
GLIBC_2.3.4 xdr_quad_t F
GLIBC_2.3.4 xdr_u_quad_t F
+GLIBC_2.30 getdents64 F
GLIBC_2.30 gettid F
GLIBC_2.30 tgkill F
GLIBC_2.30 twalk_r F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
index 22c80418f6f..daa3b60c5b0 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
@@ -2118,6 +2118,7 @@ GLIBC_2.3.4 setipv4sourcefilter F
GLIBC_2.3.4 setsourcefilter F
GLIBC_2.3.4 xdr_quad_t F
GLIBC_2.3.4 xdr_u_quad_t F
+GLIBC_2.30 getdents64 F
GLIBC_2.30 gettid F
GLIBC_2.30 tgkill F
GLIBC_2.30 twalk_r F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/getdents64.c b/sysdeps/unix/sysv/linux/mips/mips64/getdents64.c
index 8771c3c9043..1e22fa4325b 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/getdents64.c
+++ b/sysdeps/unix/sysv/linux/mips/mips64/getdents64.c
@@ -25,8 +25,10 @@
#include <scratch_buffer.h>
ssize_t
-__getdents64 (int fd, char *buf, size_t nbytes)
+__getdents64 (int fd, void *buf0, size_t nbytes)
{
+ char *buf = buf0;
+
#ifdef __NR_getdents64
ssize_t ret = INLINE_SYSCALL_CALL (getdents64, fd, buf, nbytes);
if (ret != -1)
@@ -107,6 +109,9 @@ __getdents64 (int fd, char *buf, size_t nbytes)
scratch_buffer_free (&tmpbuf);
return (char *) dp - buf;
}
+libc_hidden_def (__getdents64)
+weak_alias (__getdents64, getdents64)
+
#if _DIRENT_MATCHES_DIRENT64
strong_alias (__getdents64, __getdents)
#endif
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
index a32aafb5527..457ce0b6f2a 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
@@ -2126,6 +2126,7 @@ GLIBC_2.3.4 setipv4sourcefilter F
GLIBC_2.3.4 setsourcefilter F
GLIBC_2.3.4 xdr_quad_t F
GLIBC_2.3.4 xdr_u_quad_t F
+GLIBC_2.30 getdents64 F
GLIBC_2.30 gettid F
GLIBC_2.30 tgkill F
GLIBC_2.30 twalk_r F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
index 45342a587e0..63d5c03bfb1 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
@@ -2120,6 +2120,7 @@ GLIBC_2.3.4 setipv4sourcefilter F
GLIBC_2.3.4 setsourcefilter F
GLIBC_2.3.4 xdr_quad_t F
GLIBC_2.3.4 xdr_u_quad_t F
+GLIBC_2.30 getdents64 F
GLIBC_2.30 gettid F
GLIBC_2.30 tgkill F
GLIBC_2.30 twalk_r F
diff --git a/sysdeps/unix/sysv/linux/nios2/libc.abilist b/sysdeps/unix/sysv/linux/nios2/libc.abilist
index fe1e96c170d..7fec0c96705 100644
--- a/sysdeps/unix/sysv/linux/nios2/libc.abilist
+++ b/sysdeps/unix/sysv/linux/nios2/libc.abilist
@@ -2174,6 +2174,7 @@ GLIBC_2.28 thrd_yield F
GLIBC_2.29 getcpu F
GLIBC_2.29 posix_spawn_file_actions_addchdir_np F
GLIBC_2.29 posix_spawn_file_actions_addfchdir_np F
+GLIBC_2.30 getdents64 F
GLIBC_2.30 gettid F
GLIBC_2.30 tgkill F
GLIBC_2.30 twalk_r F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
index cbcad5db989..9200a543098 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
@@ -2176,6 +2176,7 @@ GLIBC_2.30 __nldbl_vwarn F
GLIBC_2.30 __nldbl_vwarnx F
GLIBC_2.30 __nldbl_warn F
GLIBC_2.30 __nldbl_warnx F
+GLIBC_2.30 getdents64 F
GLIBC_2.30 gettid F
GLIBC_2.30 tgkill F
GLIBC_2.30 twalk_r F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
index 060994eccf3..ef7779905f6 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
@@ -2209,6 +2209,7 @@ GLIBC_2.30 __nldbl_vwarn F
GLIBC_2.30 __nldbl_vwarnx F
GLIBC_2.30 __nldbl_warn F
GLIBC_2.30 __nldbl_warnx F
+GLIBC_2.30 getdents64 F
GLIBC_2.30 gettid F
GLIBC_2.30 tgkill F
GLIBC_2.30 twalk_r F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
index af68ed8d013..2860df8ebca 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
@@ -2039,6 +2039,7 @@ GLIBC_2.30 __nldbl_vwarn F
GLIBC_2.30 __nldbl_vwarnx F
GLIBC_2.30 __nldbl_warn F
GLIBC_2.30 __nldbl_warnx F
+GLIBC_2.30 getdents64 F
GLIBC_2.30 gettid F
GLIBC_2.30 tgkill F
GLIBC_2.30 twalk_r F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
index d317dc0586f..2229a1dcc04 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
@@ -2243,6 +2243,7 @@ GLIBC_2.30 __nldbl_vwarn F
GLIBC_2.30 __nldbl_vwarnx F
GLIBC_2.30 __nldbl_warn F
GLIBC_2.30 __nldbl_warnx F
+GLIBC_2.30 getdents64 F
GLIBC_2.30 gettid F
GLIBC_2.30 tgkill F
GLIBC_2.30 twalk_r F
diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
index 07d75c04815..31010e6cf7b 100644
--- a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
@@ -2103,6 +2103,7 @@ GLIBC_2.28 thrd_yield F
GLIBC_2.29 getcpu F
GLIBC_2.29 posix_spawn_file_actions_addchdir_np F
GLIBC_2.29 posix_spawn_file_actions_addfchdir_np F
+GLIBC_2.30 getdents64 F
GLIBC_2.30 gettid F
GLIBC_2.30 tgkill F
GLIBC_2.30 twalk_r F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
index 0fdcd6109c0..576295deff3 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
@@ -2171,6 +2171,7 @@ GLIBC_2.30 __nldbl_vwarn F
GLIBC_2.30 __nldbl_vwarnx F
GLIBC_2.30 __nldbl_warn F
GLIBC_2.30 __nldbl_warnx F
+GLIBC_2.30 getdents64 F
GLIBC_2.30 gettid F
GLIBC_2.30 tgkill F
GLIBC_2.30 twalk_r F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
index ca871ad4bea..abf04736831 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
@@ -2075,6 +2075,7 @@ GLIBC_2.30 __nldbl_vwarn F
GLIBC_2.30 __nldbl_vwarnx F
GLIBC_2.30 __nldbl_warn F
GLIBC_2.30 __nldbl_warnx F
+GLIBC_2.30 getdents64 F
GLIBC_2.30 gettid F
GLIBC_2.30 tgkill F
GLIBC_2.30 twalk_r F
diff --git a/sysdeps/unix/sysv/linux/sh/libc.abilist b/sysdeps/unix/sysv/linux/sh/libc.abilist
index b559e5b3161..41977f6e9c7 100644
--- a/sysdeps/unix/sysv/linux/sh/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sh/libc.abilist
@@ -2041,6 +2041,7 @@ GLIBC_2.3.4 setipv4sourcefilter F
GLIBC_2.3.4 setsourcefilter F
GLIBC_2.3.4 xdr_quad_t F
GLIBC_2.3.4 xdr_u_quad_t F
+GLIBC_2.30 getdents64 F
GLIBC_2.30 gettid F
GLIBC_2.30 tgkill F
GLIBC_2.30 twalk_r F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
index 37daaa28e49..3d2f00ca527 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
@@ -2165,6 +2165,7 @@ GLIBC_2.30 __nldbl_vwarn F
GLIBC_2.30 __nldbl_vwarnx F
GLIBC_2.30 __nldbl_warn F
GLIBC_2.30 __nldbl_warnx F
+GLIBC_2.30 getdents64 F
GLIBC_2.30 gettid F
GLIBC_2.30 tgkill F
GLIBC_2.30 twalk_r F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
index 5f0a3adc3c2..2f20643e8ec 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
@@ -2092,6 +2092,7 @@ GLIBC_2.3.4 setipv4sourcefilter F
GLIBC_2.3.4 setsourcefilter F
GLIBC_2.3.4 xdr_quad_t F
GLIBC_2.3.4 xdr_u_quad_t F
+GLIBC_2.30 getdents64 F
GLIBC_2.30 gettid F
GLIBC_2.30 tgkill F
GLIBC_2.30 twalk_r F
diff --git a/sysdeps/unix/sysv/linux/tst-getdents64.c b/sysdeps/unix/sysv/linux/tst-getdents64.c
new file mode 100644
index 00000000000..c1f7721221e
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/tst-getdents64.c
@@ -0,0 +1,113 @@
+/* Test for reading directories with getdents64.
+ Copyright (C) 2019 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
+ <http://www.gnu.org/licenses/>. */
+
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <support/check.h>
+#include <support/support.h>
+#include <support/xunistd.h>
+#include <unistd.h>
+
+static int
+do_test (void)
+{
+ /* The test compares the iteration order with readdir64. */
+ DIR *reference = opendir (".");
+ TEST_VERIFY_EXIT (reference != NULL);
+
+ int fd = xopen (".", O_RDONLY | O_DIRECTORY, 0);
+ TEST_VERIFY (fd >= 0);
+
+ /* Perform two passes, with a rewind operating between passes. */
+ for (int pass = 0; pass < 2; ++pass)
+ {
+ /* Check that we need to fill the buffer multiple times. */
+ int read_count = 0;
+
+ while (true)
+ {
+ /* Simple way to make sure that the memcpy below does not read
+ non-existing data. */
+ struct
+ {
+ char buffer[1024];
+ struct dirent64 pad;
+ } data;
+
+ ssize_t ret = getdents64 (fd, &data.buffer, sizeof (data.buffer));
+ if (ret < 0)
+ FAIL_EXIT1 ("getdents64: %m");
+ if (ret == 0)
+ break;
+ ++read_count;
+
+ char *current = data.buffer;
+ char *end = data.buffer + ret;
+ while (current != end)
+ {
+ struct dirent64 entry;
+ memcpy (&entry, current, sizeof (entry));
+ /* Truncate overlong strings. */
+ entry.d_name[sizeof (entry.d_name) - 1] = '\0';
+ TEST_VERIFY (strlen (entry.d_name) < sizeof (entry.d_name) - 1);
+
+ errno = 0;
+ struct dirent64 *refentry = readdir64 (reference);
+ if (refentry == NULL && errno == 0)
+ FAIL_EXIT1 ("readdir64 failed too early, at: %s",
+ entry.d_name);
+ else if (refentry == NULL)
+ FAIL_EXIT1 ("readdir64: %m");
+
+ TEST_COMPARE_STRING (entry.d_name, refentry->d_name);
+ TEST_COMPARE (entry.d_ino, refentry->d_ino);
+ TEST_COMPARE (entry.d_off, refentry->d_off);
+ TEST_COMPARE (entry.d_type, refentry->d_type);
+
+ /* Offset zero is reserved for the first entry. */
+ TEST_VERIFY (entry.d_off != 0);
+
+ TEST_VERIFY_EXIT (entry.d_reclen <= end - current);
+ current += entry.d_reclen;
+ }
+ }
+
+ /* We expect to have reached the end of the stream. */
+ errno = 0;
+ TEST_VERIFY (readdir64 (reference) == NULL);
+ TEST_COMPARE (errno, 0);
+
+ /* direntries_read has been called more than once. */
+ TEST_VERIFY (read_count > 0);
+
+ /* Rewind both directory streams. */
+ xlseek (fd, 0, SEEK_SET);
+ rewinddir (reference);
+ }
+
+ xclose (fd);
+ closedir (reference);
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
index c82b3ba7b8c..59f85d93736 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
@@ -2050,6 +2050,7 @@ GLIBC_2.3.4 setipv4sourcefilter F
GLIBC_2.3.4 setsourcefilter F
GLIBC_2.3.4 xdr_quad_t F
GLIBC_2.3.4 xdr_u_quad_t F
+GLIBC_2.30 getdents64 F
GLIBC_2.30 gettid F
GLIBC_2.30 tgkill F
GLIBC_2.30 twalk_r F
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
index ed89c34c553..67a4e238d63 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
@@ -2149,6 +2149,7 @@ GLIBC_2.28 thrd_yield F
GLIBC_2.29 getcpu F
GLIBC_2.29 posix_spawn_file_actions_addchdir_np F
GLIBC_2.29 posix_spawn_file_actions_addfchdir_np F
+GLIBC_2.30 getdents64 F
GLIBC_2.30 gettid F
GLIBC_2.30 tgkill F
GLIBC_2.30 twalk_r F