(root)/
glibc-2.38/
sysdeps/
mach/
hurd/
readdir64.c
       1  /* Copyright (C) 2001-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 <dirent.h>
      19  #include <stddef.h>
      20  #include <hurd.h>
      21  #include <hurd/fs.h>
      22  #include <hurd/fd.h>
      23  #include "dirstream.h"
      24  
      25  /* Read a directory entry from DIRP.  */
      26  struct dirent64 *
      27  __readdir64 (DIR *dirp)
      28  {
      29    struct dirent64 *dp;
      30  
      31    if (dirp == NULL)
      32      return __hurd_fail (EINVAL), NULL;
      33  
      34    __libc_lock_lock (dirp->__lock);
      35  
      36    do
      37      {
      38        if (dirp->__ptr - dirp->__data >= dirp->__size)
      39  	{
      40  	  /* We've emptied out our buffer.  Refill it.  */
      41  
      42  	  char *data = dirp->__data;
      43  	  mach_msg_type_number_t data_size = dirp->__size;
      44  	  int nentries;
      45  	  error_t err;
      46  
      47  	  if (err = HURD_FD_PORT_USE (dirp->__fd,
      48  				      __dir_readdir (port,
      49  						     &data, &data_size,
      50  						     dirp->__entry_ptr,
      51  						     -1, 0, &nentries)))
      52  	    {
      53  	      __hurd_fail (err);
      54  	      dp = NULL;
      55  	      break;
      56  	    }
      57  
      58  	  dirp->__size = data_size;
      59  	  /* DATA now corresponds to entry index DIRP->__entry_ptr.  */
      60  	  dirp->__entry_data = dirp->__entry_ptr;
      61  
      62  	  if (data != dirp->__data)
      63  	    {
      64  	      /* The data was passed out of line, so our old buffer is no
      65  		 longer useful.  Deallocate the old buffer and reset our
      66  		 information for the new buffer.  */
      67  	      if (dirp->__data != NULL)
      68  		{
      69  		  err = __vm_deallocate (__mach_task_self (),
      70  					 (vm_address_t) dirp->__data,
      71  					 dirp->__allocation);
      72  		  assert_perror (err);
      73  		}
      74  	      dirp->__data = data;
      75  	      dirp->__allocation = round_page (dirp->__size);
      76  	    }
      77  
      78  	  /* Reset the pointer into the buffer.  */
      79  	  dirp->__ptr = dirp->__data;
      80  
      81  	  if (nentries == 0)
      82  	    {
      83  	      /* End of file.  */
      84  	      dp = NULL;
      85  	      break;
      86  	    }
      87  
      88  	  /* We trust the filesystem to return correct data and so we
      89  	     ignore NENTRIES.  */
      90  	}
      91  
      92        dp = (struct dirent64 *) dirp->__ptr;
      93        dirp->__ptr += dp->d_reclen;
      94        ++dirp->__entry_ptr;
      95  
      96        /* Loop to ignore deleted files.  */
      97      } while (dp->d_fileno == 0);
      98  
      99    __libc_lock_unlock (dirp->__lock);
     100  
     101    return dp;
     102  }
     103  
     104  libc_hidden_def (__readdir64)
     105  weak_alias (__readdir64, readdir64)