(root)/
glibc-2.38/
sysdeps/
mach/
hurd/
readdir.c
       1  /* Copyright (C) 1993-2023 Free Software Foundation, Inc.
       2     This file is part of the GNU C Library.
       3  
       4     The GNU C Library is free software; you can redistribute it and/or
       5     modify it under the terms of the GNU Lesser General Public
       6     License as published by the Free Software Foundation; either
       7     version 2.1 of the License, or (at your option) any later version.
       8  
       9     The GNU C Library is distributed in the hope that it will be useful,
      10     but WITHOUT ANY WARRANTY; without even the implied warranty of
      11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12     Lesser General Public License for more details.
      13  
      14     You should have received a copy of the GNU Lesser General Public
      15     License along with the GNU C Library; if not, see
      16     <https://www.gnu.org/licenses/>.  */
      17  
      18  #include <errno.h>
      19  #include <stddef.h>
      20  #include <dirent.h>
      21  #include <unistd.h>
      22  #include <endian.h>
      23  #include <assert.h>
      24  #include <hurd.h>
      25  
      26  /* Read a directory entry from DIRP.  */
      27  struct dirent *
      28  __readdir (DIR *dirp)
      29  {
      30    struct dirent64 *entry64 = __readdir64 (dirp);
      31  
      32    if (sizeof (struct dirent64) == sizeof (struct dirent))
      33      /* We should in fact just be an alias to readdir64 on this machine.  */
      34      return (struct dirent *) entry64;
      35  
      36    /* These are all compile-time constants.  We know that d_ino is the first
      37       member and that the layout of the following members matches exactly in
      38       both structures.  */
      39    assert (offsetof (struct dirent, d_ino) == 0);
      40    assert (offsetof (struct dirent64, d_ino) == 0);
      41  # define MATCH(memb)							      \
      42    assert (offsetof (struct dirent64, memb) - sizeof (entry64->d_ino)	      \
      43  	  == offsetof (struct dirent, memb) - sizeof (ino_t))
      44    MATCH (d_reclen);
      45    MATCH (d_type);
      46    MATCH (d_namlen);
      47  # undef MATCH
      48  
      49    if (entry64 == NULL)
      50      return NULL;
      51  
      52    struct dirent *const entry = ((void *) (&entry64->d_ino + 1)
      53  				- sizeof entry->d_ino);
      54    const ino_t d_ino = entry64->d_ino;
      55    if (d_ino != entry64->d_ino)
      56      return __hurd_fail (EOVERFLOW), NULL;
      57  # if BYTE_ORDER != BIG_ENDIAN	/* We just skipped over the zero high word.  */
      58    entry->d_ino = d_ino;	/* ... or the nonzero low word, swap it.  */
      59  # endif
      60    entry->d_reclen -= sizeof entry64->d_ino - sizeof entry->d_ino;
      61    return entry;
      62  }
      63  
      64  weak_alias (__readdir, readdir)