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 <limits.h>
      20  #include <stddef.h>
      21  #include <stdlib.h>
      22  #include <string.h>
      23  #include <dirent.h>
      24  #include <fcntl.h>
      25  #include <sys/types.h>
      26  #include <sys/stat.h>
      27  #include <unistd.h>
      28  #include <stdio.h>
      29  #include <hurd.h>
      30  #include <hurd/fd.h>
      31  #include <not-cancel.h>
      32  #include "dirstream.h"
      33  
      34  
      35  /* Open a directory stream on a file descriptor in Hurd internal form.
      36     We do no checking here on the descriptor.  */
      37  DIR *
      38  _hurd_fd_opendir (struct hurd_fd *d)
      39  {
      40    DIR *dirp;
      41  
      42    if (d == NULL)
      43      return __hurd_fail (EBADF), NULL;
      44  
      45    dirp = (DIR *) malloc (sizeof (DIR));
      46    if (dirp == NULL)
      47      return NULL;
      48  
      49    /* Set the descriptor to close on exec. */
      50    HURD_CRITICAL_BEGIN;
      51    __spin_lock (&d->port.lock);
      52    d->flags |= FD_CLOEXEC;
      53    __spin_unlock (&d->port.lock);
      54    HURD_CRITICAL_END;
      55  
      56    dirp->__fd = d;
      57    dirp->__data = dirp->__ptr = NULL;
      58    dirp->__entry_data = dirp->__entry_ptr = 0;
      59    dirp->__allocation = 0;
      60    dirp->__size = 0;
      61  
      62    __libc_lock_init (dirp->__lock);
      63  
      64    return dirp;
      65  }
      66  
      67  
      68  DIR *
      69  __opendirat (int dfd, const char *name)
      70  {
      71    if (name[0] == '\0')
      72      /* POSIX.1-1990 says an empty name gets ENOENT;
      73         but `open' might like it fine.  */
      74      return __hurd_fail (ENOENT), NULL;
      75  
      76    int flags = O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_CLOEXEC;
      77    int fd;
      78  #if IS_IN (rtld)
      79    assert (dfd == AT_FDCWD);
      80    fd = __open_nocancel (name, flags);
      81  #else
      82    fd = __openat_nocancel (dfd, name, flags);
      83  #endif
      84    if (fd < 0)
      85      return NULL;
      86  
      87    /* Extract the pointer to the descriptor structure.  */
      88    DIR *dirp = _hurd_fd_opendir (_hurd_fd_get (fd));
      89    if (dirp == NULL)
      90      __close (fd);
      91  
      92    return dirp;
      93  }
      94  
      95  
      96  /* Open a directory stream on NAME.  */
      97  DIR *
      98  __opendir (const char *name)
      99  {
     100  #if 0 /* TODO.  */
     101    return __opendirat (AT_FDCWD, name);
     102  #else
     103    if (name[0] == '\0')
     104      /* POSIX.1-1990 says an empty name gets ENOENT;
     105         but `open' might like it fine.  */
     106      return __hurd_fail (ENOENT), NULL;
     107  
     108    int fd = __open (name, O_RDONLY | O_NONBLOCK | O_DIRECTORY);
     109    if (fd < 0)
     110      return NULL;
     111  
     112    /* Extract the pointer to the descriptor structure.  */
     113    DIR *dirp = _hurd_fd_opendir (_hurd_fd_get (fd));
     114    if (dirp == NULL)
     115      __close (fd);
     116  
     117    return dirp;
     118  #endif
     119  }
     120  weak_alias (__opendir, opendir)