diff options
| author | Florian Weimer <fweimer@redhat.com> | 2019-06-07 09:27:01 +0200 |
|---|---|---|
| committer | Florian Weimer <fweimer@redhat.com> | 2019-06-07 09:27:01 +0200 |
| commit | 51ea67d54882318c4fa5394c386f4816ddc22408 (patch) | |
| tree | 9b1f881f8d4e8b464a2d3b08b805e97a35457c7d | |
| parent | de751ebc9efa97ce0115e42bd55fa1beeb614380 (diff) | |
| download | 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>
38 files changed, 282 insertions, 9 deletions
@@ -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. @@ -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 400835eefe..3736803bce 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 28480e7608..513319418a 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 d2f0b60ea9..afcdc658b5 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 c7137e2c2c..1ca102a9e2 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 324909d553..a4c31932cb 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 084e475569..fe85a35620 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 f58d16e210..bc3df8dcea 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 0061172f23..6e7b2bb83d 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 38f6abaa30..9b3cee65bb 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 e796d9354b..3eec4c4221 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 0786a15195..a6dd22106d 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 eb628f907b..75edece94a 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 6f240d9a59..edeaf8e722 100644 --- a/sysdeps/unix/sysv/linux/i386/libc.abilist +++ b/sysdeps/unix/sysv/linux/i386/libc.abilist @@ -2203,6 + |
