/* Directory entry code for Window platforms. | |
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, | |
2006 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 2, 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 | |
GNU Make; see the file COPYING. If not, write to the Free Software | |
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ | |
#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 = -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; | |
} |