(root)/
make-4.4/
src/
w32/
compat/
dirent.c
       1  /* Directory entry code for Window platforms.
       2  Copyright (C) 1996-2022 Free Software Foundation, Inc.
       3  This file is part of GNU Make.
       4  
       5  GNU Make is free software; you can redistribute it and/or modify it under the
       6  terms of the GNU General Public License as published by the Free Software
       7  Foundation; either version 3 of the License, or (at your option) any later
       8  version.
       9  
      10  GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
      11  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
      12  A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
      13  
      14  You should have received a copy of the GNU General Public License along with
      15  this program.  If not, see <https://www.gnu.org/licenses/>.  */
      16  
      17  
      18  #include <config.h>
      19  #include <sys/types.h>
      20  #include <sys/stat.h>
      21  #include <errno.h>
      22  #include <string.h>
      23  #include <stdlib.h>
      24  #include "dirent.h"
      25  
      26  #ifndef __MINGW32__
      27  DIR*
      28  opendir(const char* pDirName)
      29  {
      30          struct stat sb;
      31          DIR*    pDir;
      32          char*   pEndDirName;
      33          size_t  nBufferLen;
      34  
      35          /* sanity checks */
      36          if (!pDirName) {
      37                  errno = EINVAL;
      38                  return NULL;
      39          }
      40          if (stat(pDirName, &sb) != 0) {
      41                  errno = ENOENT;
      42                  return NULL;
      43          }
      44          if ((sb.st_mode & S_IFMT) != S_IFDIR) {
      45                  errno = ENOTDIR;
      46                  return NULL;
      47          }
      48  
      49          /* allocate a DIR structure to return */
      50          pDir = (DIR *) malloc(sizeof (DIR));
      51  
      52          if (!pDir)
      53                  return NULL;
      54  
      55          /* input directory name length */
      56          nBufferLen = strlen(pDirName);
      57  
      58          /* copy input directory name to DIR buffer */
      59          strcpy(pDir->dir_pDirectoryName, pDirName);
      60  
      61          /* point to end of the copied directory name */
      62          pEndDirName = &pDir->dir_pDirectoryName[nBufferLen - 1];
      63  
      64          /* if directory name did not end in '/' or '\', add '/' */
      65          if ((*pEndDirName != '/') && (*pEndDirName != '\\')) {
      66                  pEndDirName++;
      67                  *pEndDirName = '/';
      68          }
      69  
      70          /* now append the wildcard character to the buffer */
      71          pEndDirName++;
      72          *pEndDirName = '*';
      73          pEndDirName++;
      74          *pEndDirName = '\0';
      75  
      76          /* other values defaulted */
      77          pDir->dir_nNumFiles = 0;
      78          pDir->dir_hDirHandle = INVALID_HANDLE_VALUE;
      79          pDir->dir_ulCookie = __DIRENT_COOKIE;
      80  
      81          return pDir;
      82  }
      83  
      84  void
      85  closedir(DIR *pDir)
      86  {
      87          /* got a valid pointer? */
      88          if (!pDir) {
      89                  errno = EINVAL;
      90                  return;
      91          }
      92  
      93          /* sanity check that this is a DIR pointer */
      94          if (pDir->dir_ulCookie != __DIRENT_COOKIE) {
      95                  errno = EINVAL;
      96                  return;
      97          }
      98  
      99          /* close the WINDOWS32 directory handle */
     100          if (pDir->dir_hDirHandle != INVALID_HANDLE_VALUE)
     101                  FindClose(pDir->dir_hDirHandle);
     102  
     103          free(pDir);
     104  
     105          return;
     106  }
     107  
     108  struct dirent *
     109  readdir(DIR* pDir)
     110  {
     111          WIN32_FIND_DATA wfdFindData;
     112  
     113          if (!pDir) {
     114                  errno = EINVAL;
     115                  return NULL;
     116          }
     117  
     118          /* sanity check that this is a DIR pointer */
     119          if (pDir->dir_ulCookie != __DIRENT_COOKIE) {
     120                  errno = EINVAL;
     121                  return NULL;
     122          }
     123  
     124          if (pDir->dir_nNumFiles == 0) {
     125                  pDir->dir_hDirHandle = FindFirstFile(pDir->dir_pDirectoryName, &wfdFindData);
     126                  if (pDir->dir_hDirHandle == INVALID_HANDLE_VALUE)
     127                          return NULL;
     128          } else if (!FindNextFile(pDir->dir_hDirHandle, &wfdFindData))
     129                          return NULL;
     130  
     131          /* bump count for next call to readdir() */
     132          pDir->dir_nNumFiles++;
     133  
     134          /* fill in struct dirent values */
     135          pDir->dir_sdReturn.d_ino = (ino_t)-1;
     136          strcpy(pDir->dir_sdReturn.d_name, wfdFindData.cFileName);
     137  
     138          if (wfdFindData.dwFileAttributes & FILE_ATTRIBUTE_DEVICE)
     139            pDir->dir_sdReturn.d_type = DT_CHR;
     140          else if (wfdFindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
     141            pDir->dir_sdReturn.d_type = DT_DIR;
     142          else
     143            pDir->dir_sdReturn.d_type = DT_REG;
     144  
     145          return &pDir->dir_sdReturn;
     146  }
     147  
     148  void
     149  rewinddir(DIR* pDir)
     150  {
     151          if (!pDir) {
     152                  errno = EINVAL;
     153                  return;
     154          }
     155  
     156          /* sanity check that this is a DIR pointer */
     157          if (pDir->dir_ulCookie != __DIRENT_COOKIE) {
     158                  errno = EINVAL;
     159                  return;
     160          }
     161  
     162          /* close the WINDOWS32 directory handle */
     163          if (pDir->dir_hDirHandle != INVALID_HANDLE_VALUE)
     164                  if (!FindClose(pDir->dir_hDirHandle))
     165                          errno = EBADF;
     166  
     167          /* reset members which control readdir() */
     168          pDir->dir_hDirHandle = INVALID_HANDLE_VALUE;
     169          pDir->dir_nNumFiles = 0;
     170  
     171          return;
     172  }
     173  
     174  void
     175  seekdir(DIR* pDir, long nPosition)
     176  {
     177          if (!pDir)
     178                  return;
     179  
     180          /* sanity check that this is a DIR pointer */
     181          if (pDir->dir_ulCookie != __DIRENT_COOKIE)
     182                  return;
     183  
     184          /* go back to beginning of directory */
     185          rewinddir(pDir);
     186  
     187          /* loop until we have found position we care about */
     188          for (--nPosition; nPosition && readdir(pDir); nPosition--);
     189  
     190          /* flag invalid nPosition value */
     191          if (nPosition)
     192                  errno = EINVAL;
     193  
     194          return;
     195  }
     196  #endif  /* !__MINGW32__ */