(root)/
sed-4.9/
gnulib-tests/
readdir.c
       1  /* Read the next entry of a directory.
       2     Copyright (C) 2011-2022 Free Software Foundation, Inc.
       3  
       4     This file is free software: you can redistribute it and/or modify
       5     it under the terms of the GNU Lesser General Public License as
       6     published by the Free Software Foundation; either version 2.1 of the
       7     License, or (at your option) any later version.
       8  
       9     This file 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
      12     GNU Lesser General Public License for more details.
      13  
      14     You should have received a copy of the GNU Lesser General Public License
      15     along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
      16  
      17  #include <config.h>
      18  
      19  /* Specification.  */
      20  #include <dirent.h>
      21  
      22  #include <errno.h>
      23  #include <stddef.h>
      24  
      25  #include "dirent-private.h"
      26  
      27  /* Don't assume that UNICODE is not defined.  */
      28  #undef FindNextFile
      29  #define FindNextFile FindNextFileA
      30  
      31  struct dirent *
      32  readdir (DIR *dirp)
      33  {
      34    char type;
      35    struct dirent *result;
      36  
      37    /* There is no need to add code to produce entries for "." and "..".
      38       According to the POSIX:2008 section "4.12 Pathname Resolution"
      39       <https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html>
      40       "." and ".." are syntactic entities.
      41       POSIX also says:
      42         "If entries for dot or dot-dot exist, one entry shall be returned
      43          for dot and one entry shall be returned for dot-dot; otherwise,
      44          they shall not be returned."  */
      45  
      46    switch (dirp->status)
      47      {
      48      case -2:
      49        /* End of directory already reached.  */
      50        return NULL;
      51      case -1:
      52        break;
      53      case 0:
      54        if (!FindNextFile (dirp->current, &dirp->entry))
      55          {
      56            switch (GetLastError ())
      57              {
      58              case ERROR_NO_MORE_FILES:
      59                dirp->status = -2;
      60                return NULL;
      61              default:
      62                errno = EIO;
      63                return NULL;
      64              }
      65          }
      66        break;
      67      default:
      68        errno = dirp->status;
      69        return NULL;
      70      }
      71  
      72    dirp->status = 0;
      73  
      74    if (dirp->entry.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
      75      type = DT_DIR;
      76    else if (dirp->entry.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
      77      type = DT_LNK;
      78    else if ((dirp->entry.dwFileAttributes
      79              & ~(FILE_ATTRIBUTE_READONLY
      80                  | FILE_ATTRIBUTE_HIDDEN
      81                  | FILE_ATTRIBUTE_SYSTEM
      82                  | FILE_ATTRIBUTE_ARCHIVE
      83                  | FILE_ATTRIBUTE_NORMAL
      84                  | FILE_ATTRIBUTE_TEMPORARY
      85                  | FILE_ATTRIBUTE_SPARSE_FILE
      86                  | FILE_ATTRIBUTE_COMPRESSED
      87                  | FILE_ATTRIBUTE_NOT_CONTENT_INDEXED
      88                  | FILE_ATTRIBUTE_ENCRYPTED)) == 0)
      89      /* Devices like COM1, LPT1, NUL would also have the attributes 0x20 but
      90         they cannot occur here.  */
      91      type = DT_REG;
      92    else
      93      type = DT_UNKNOWN;
      94  
      95    /* Reuse the memory of dirp->entry for the result.  */
      96    result =
      97      (struct dirent *)
      98      ((char *) dirp->entry.cFileName - offsetof (struct dirent, d_name[0]));
      99    result->d_type = type;
     100  
     101    return result;
     102  }