(root)/
tar-1.35/
gnu/
readdir.c
       1  /* Read the next entry of a directory.
       2     Copyright (C) 2011-2023 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  #if GNULIB_defined_DIR
      26  # include "dirent-private.h"
      27  #endif
      28  
      29  /* Don't assume that UNICODE is not defined.  */
      30  #undef FindNextFile
      31  #define FindNextFile FindNextFileA
      32  
      33  struct dirent *
      34  readdir (DIR *dirp)
      35  #undef readdir
      36  {
      37  #if HAVE_DIRENT_H                       /* equivalent to HAVE_READDIR */
      38    return readdir (dirp->real_dirp);
      39  #else
      40    char type;
      41    struct dirent *result;
      42  
      43    /* There is no need to add code to produce entries for "." and "..".
      44       According to the POSIX:2008 section "4.12 Pathname Resolution"
      45       <https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html>
      46       "." and ".." are syntactic entities.
      47       POSIX also says:
      48         "If entries for dot or dot-dot exist, one entry shall be returned
      49          for dot and one entry shall be returned for dot-dot; otherwise,
      50          they shall not be returned."  */
      51  
      52    switch (dirp->status)
      53      {
      54      case -2:
      55        /* End of directory already reached.  */
      56        return NULL;
      57      case -1:
      58        break;
      59      case 0:
      60        if (!FindNextFile (dirp->current, &dirp->entry))
      61          {
      62            switch (GetLastError ())
      63              {
      64              case ERROR_NO_MORE_FILES:
      65                dirp->status = -2;
      66                return NULL;
      67              default:
      68                errno = EIO;
      69                return NULL;
      70              }
      71          }
      72        break;
      73      default:
      74        errno = dirp->status;
      75        return NULL;
      76      }
      77  
      78    dirp->status = 0;
      79  
      80    if (dirp->entry.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
      81      type = DT_DIR;
      82    else if (dirp->entry.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
      83      type = DT_LNK;
      84    else if ((dirp->entry.dwFileAttributes
      85              & ~(FILE_ATTRIBUTE_READONLY
      86                  | FILE_ATTRIBUTE_HIDDEN
      87                  | FILE_ATTRIBUTE_SYSTEM
      88                  | FILE_ATTRIBUTE_ARCHIVE
      89                  | FILE_ATTRIBUTE_NORMAL
      90                  | FILE_ATTRIBUTE_TEMPORARY
      91                  | FILE_ATTRIBUTE_SPARSE_FILE
      92                  | FILE_ATTRIBUTE_COMPRESSED
      93                  | FILE_ATTRIBUTE_NOT_CONTENT_INDEXED
      94                  | FILE_ATTRIBUTE_ENCRYPTED)) == 0)
      95      /* Devices like COM1, LPT1, NUL would also have the attributes 0x20 but
      96         they cannot occur here.  */
      97      type = DT_REG;
      98    else
      99      type = DT_UNKNOWN;
     100  
     101    /* Reuse the memory of dirp->entry for the result.  */
     102    result =
     103      (struct dirent *)
     104      ((char *) dirp->entry.cFileName - offsetof (struct dirent, d_name[0]));
     105    result->d_type = type;
     106  
     107    return result;
     108  #endif
     109  }