| /* Directory entry code for Window platforms. |
| Copyright (C) 1996-2016 Free Software Foundation, Inc. |
| This file is part of GNU Make. |
| |
| GNU Make is free software; you can redistribute it and/or modify it under the |
| terms of the GNU General Public License as published by the Free Software |
| Foundation; either version 3 of the License, or (at your option) any later |
| version. |
| |
| GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY |
| WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR |
| A PARTICULAR PURPOSE. See the GNU General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License along with |
| this program. If not, see <http://www.gnu.org/licenses/>. */ |
| |
| |
| #include <config.h> |
| #include <sys/types.h> |
| #include <sys/stat.h> |
| #include <errno.h> |
| #include <string.h> |
| #include <stdlib.h> |
| #include "dirent.h" |
| |
| |
| DIR* |
| opendir(const char* pDirName) |
| { |
| struct stat sb; |
| DIR* pDir; |
| char* pEndDirName; |
| int nBufferLen; |
| |
| /* sanity checks */ |
| if (!pDirName) { |
| errno = EINVAL; |
| return NULL; |
| } |
| if (stat(pDirName, &sb) != 0) { |
| errno = ENOENT; |
| return NULL; |
| } |
| if ((sb.st_mode & S_IFMT) != S_IFDIR) { |
| errno = ENOTDIR; |
| return NULL; |
| } |
| |
| /* allocate a DIR structure to return */ |
| pDir = (DIR *) malloc(sizeof (DIR)); |
| |
| if (!pDir) |
| return NULL; |
| |
| /* input directory name length */ |
| nBufferLen = strlen(pDirName); |
| |
| /* copy input directory name to DIR buffer */ |
| strcpy(pDir->dir_pDirectoryName, pDirName); |
| |
| /* point to end of the copied directory name */ |
| pEndDirName = &pDir->dir_pDirectoryName[nBufferLen - 1]; |
| |
| /* if directory name did not end in '/' or '\', add '/' */ |
| if ((*pEndDirName != '/') && (*pEndDirName != '\\')) { |
| pEndDirName++; |
| *pEndDirName = '/'; |
| } |
| |
| /* now append the wildcard character to the buffer */ |
| pEndDirName++; |
| *pEndDirName = '*'; |
| pEndDirName++; |
| *pEndDirName = '\0'; |
| |
| /* other values defaulted */ |
| pDir->dir_nNumFiles = 0; |
| pDir->dir_hDirHandle = INVALID_HANDLE_VALUE; |
| pDir->dir_ulCookie = __DIRENT_COOKIE; |
| |
| return pDir; |
| } |
| |
| void |
| closedir(DIR *pDir) |
| { |
| /* got a valid pointer? */ |
| if (!pDir) { |
| errno = EINVAL; |
| return; |
| } |
| |
| /* sanity check that this is a DIR pointer */ |
| if (pDir->dir_ulCookie != __DIRENT_COOKIE) { |
| errno = EINVAL; |
| return; |
| } |
| |
| /* close the WINDOWS32 directory handle */ |
| if (pDir->dir_hDirHandle != INVALID_HANDLE_VALUE) |
| FindClose(pDir->dir_hDirHandle); |
| |
| free(pDir); |
| |
| return; |
| } |
| |
| struct dirent * |
| readdir(DIR* pDir) |
| { |
| WIN32_FIND_DATA wfdFindData; |
| |
| if (!pDir) { |
| errno = EINVAL; |
| return NULL; |
| } |
| |
| /* sanity check that this is a DIR pointer */ |
| if (pDir->dir_ulCookie != __DIRENT_COOKIE) { |
| errno = EINVAL; |
| return NULL; |
| } |
| |
| if (pDir->dir_nNumFiles == 0) { |
| pDir->dir_hDirHandle = FindFirstFile(pDir->dir_pDirectoryName, &wfdFindData); |
| if (pDir->dir_hDirHandle == INVALID_HANDLE_VALUE) |
| return NULL; |
| } else if (!FindNextFile(pDir->dir_hDirHandle, &wfdFindData)) |
| return NULL; |
| |
| /* bump count for next call to readdir() or telldir() */ |
| pDir->dir_nNumFiles++; |
| |
| /* fill in struct dirent values */ |
| pDir->dir_sdReturn.d_ino = (ino_t)-1; |
| strcpy(pDir->dir_sdReturn.d_name, wfdFindData.cFileName); |
| |
| return &pDir->dir_sdReturn; |
| } |
| |
| void |
| rewinddir(DIR* pDir) |
| { |
| if (!pDir) { |
| errno = EINVAL; |
| return; |
| } |
| |
| /* sanity check that this is a DIR pointer */ |
| if (pDir->dir_ulCookie != __DIRENT_COOKIE) { |
| errno = EINVAL; |
| return; |
| } |
| |
| /* close the WINDOWS32 directory handle */ |
| if (pDir->dir_hDirHandle != INVALID_HANDLE_VALUE) |
| if (!FindClose(pDir->dir_hDirHandle)) |
| errno = EBADF; |
| |
| /* reset members which control readdir() */ |
| pDir->dir_hDirHandle = INVALID_HANDLE_VALUE; |
| pDir->dir_nNumFiles = 0; |
| |
| return; |
| } |
| |
| int |
| telldir(DIR* pDir) |
| { |
| if (!pDir) { |
| errno = EINVAL; |
| return -1; |
| } |
| |
| /* sanity check that this is a DIR pointer */ |
| if (pDir->dir_ulCookie != __DIRENT_COOKIE) { |
| errno = EINVAL; |
| return -1; |
| } |
| |
| /* return number of times readdir() called */ |
| return pDir->dir_nNumFiles; |
| } |
| |
| void |
| seekdir(DIR* pDir, long nPosition) |
| { |
| if (!pDir) |
| return; |
| |
| /* sanity check that this is a DIR pointer */ |
| if (pDir->dir_ulCookie != __DIRENT_COOKIE) |
| return; |
| |
| /* go back to beginning of directory */ |
| rewinddir(pDir); |
| |
| /* loop until we have found position we care about */ |
| for (--nPosition; nPosition && readdir(pDir); nPosition--); |
| |
| /* flag invalid nPosition value */ |
| if (nPosition) |
| errno = EINVAL; |
| |
| return; |
| } |