Imported Upstream version 4.0
[platform/upstream/make.git] / w32 / compat / dirent.c
1 /* Directory entry code for Window platforms.
2 Copyright (C) 1996-2013 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 <http://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
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 = (ino_t)-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 }