Home | History | Annotate | Download | only in compat
      1 /* Directory entry code for Window platforms.
      2 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
      3 2006 Free Software Foundation, Inc.
      4 This file is part of GNU Make.
      5 
      6 GNU Make is free software; you can redistribute it and/or modify it under the
      7 terms of the GNU General Public License as published by the Free Software
      8 Foundation; either version 2, or (at your option) any later 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 GNU Make; see the file COPYING.  If not, write to the Free Software
     16 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
     17 
     18 
     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 
     27 DIR*
     28 opendir(const char* pDirName)
     29 {
     30 	struct stat sb;
     31 	DIR*	pDir;
     32 	char*	pEndDirName;
     33 	int	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() or telldir() */
    132 	pDir->dir_nNumFiles++;
    133 
    134 	/* fill in struct dirent values */
    135 	pDir->dir_sdReturn.d_ino = -1;
    136 	strcpy(pDir->dir_sdReturn.d_name, wfdFindData.cFileName);
    137 
    138 	return &pDir->dir_sdReturn;
    139 }
    140 
    141 void
    142 rewinddir(DIR* pDir)
    143 {
    144 	if (!pDir) {
    145 		errno = EINVAL;
    146 		return;
    147 	}
    148 
    149 	/* sanity check that this is a DIR pointer */
    150 	if (pDir->dir_ulCookie != __DIRENT_COOKIE) {
    151 		errno = EINVAL;
    152 		return;
    153 	}
    154 
    155 	/* close the WINDOWS32 directory handle */
    156 	if (pDir->dir_hDirHandle != INVALID_HANDLE_VALUE)
    157 		if (!FindClose(pDir->dir_hDirHandle))
    158 			errno = EBADF;
    159 
    160 	/* reset members which control readdir() */
    161 	pDir->dir_hDirHandle = INVALID_HANDLE_VALUE;
    162 	pDir->dir_nNumFiles = 0;
    163 
    164 	return;
    165 }
    166 
    167 int
    168 telldir(DIR* pDir)
    169 {
    170 	if (!pDir) {
    171 		errno = EINVAL;
    172 		return -1;
    173 	}
    174 
    175 	/* sanity check that this is a DIR pointer */
    176 	if (pDir->dir_ulCookie != __DIRENT_COOKIE) {
    177 		errno = EINVAL;
    178 		return -1;
    179 	}
    180 
    181 	/* return number of times readdir() called */
    182 	return pDir->dir_nNumFiles;
    183 }
    184 
    185 void
    186 seekdir(DIR* pDir, long nPosition)
    187 {
    188 	if (!pDir)
    189 		return;
    190 
    191 	/* sanity check that this is a DIR pointer */
    192 	if (pDir->dir_ulCookie != __DIRENT_COOKIE)
    193 		return;
    194 
    195 	/* go back to beginning of directory */
    196 	rewinddir(pDir);
    197 
    198 	/* loop until we have found position we care about */
    199 	for (--nPosition; nPosition && readdir(pDir); nPosition--);
    200 
    201 	/* flag invalid nPosition value */
    202 	if (nPosition)
    203 		errno = EINVAL;
    204 
    205 	return;
    206 }
    207