1/* Get directory entries. Linux LFS version.
2 Copyright (C) 1997-2018 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library. If not, see
17 <http://www.gnu.org/licenses/>. */
18
19#include <string.h>
20#include <dirent.h>
21#include <errno.h>
22
23/* The kernel struct linux_dirent64 matches the 'struct getdents64' type. */
24ssize_t
25__getdents64 (int fd, char *buf, size_t nbytes)
26{
27 return INLINE_SYSCALL_CALL (getdents64, fd, buf, nbytes);
28}
29
30#if _DIRENT_MATCHES_DIRENT64
31strong_alias (__getdents64, __getdents)
32#else
33# include <shlib-compat.h>
34
35# if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2)
36# include <olddirent.h>
37
38/* kernel definition of as of 3.2. */
39struct compat_linux_dirent
40{
41 /* Both d_ino and d_off are compat_ulong_t which are defined in all
42 architectures as 'u32'. */
43 uint32_t d_ino;
44 uint32_t d_off;
45 unsigned short d_reclen;
46 char d_name[1];
47};
48
49ssize_t
50__old_getdents64 (int fd, char *buf, size_t nbytes)
51{
52 ssize_t retval = INLINE_SYSCALL_CALL (getdents, fd, buf, nbytes);
53
54 /* The kernel added the d_type value after the name. Change this now. */
55 if (retval != -1)
56 {
57 union
58 {
59 struct compat_linux_dirent k;
60 struct dirent u;
61 } *kbuf = (void *) buf;
62
63 while ((char *) kbuf < buf + retval)
64 {
65 char d_type = *((char *) kbuf + kbuf->k.d_reclen - 1);
66 memmove (kbuf->u.d_name, kbuf->k.d_name,
67 strlen (kbuf->k.d_name) + 1);
68 kbuf->u.d_type = d_type;
69
70 kbuf = (void *) ((char *) kbuf + kbuf->k.d_reclen);
71 }
72 }
73 return retval;
74}
75# endif /* SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2) */
76#endif /* _DIRENT_MATCHES_DIRENT64 */
77