1#include <sys/types.h>
2#include <sys/stat.h>
3#include <errno.h>
4#include <string.h>
5#include <stdlib.h>
6#include "dirent.h"
7
8
9DIR*
10opendir(const char* pDirName)
11{
12	struct stat sb;
13	DIR*	pDir;
14	char*	pEndDirName;
15	int	nBufferLen;
16
17	/* sanity checks */
18	if (!pDirName) {
19		errno = EINVAL;
20		return NULL;
21	}
22	if (stat(pDirName, &sb) != 0) {
23		errno = ENOENT;
24		return NULL;
25	}
26	if ((sb.st_mode & S_IFMT) != S_IFDIR) {
27		errno = ENOTDIR;
28		return NULL;
29	}
30
31	/* allocate a DIR structure to return */
32	pDir = (DIR *) malloc(sizeof (DIR));
33
34	if (!pDir)
35		return NULL;
36
37	/* input directory name length */
38	nBufferLen = strlen(pDirName);
39
40	/* copy input directory name to DIR buffer */
41	strcpy(pDir->dir_pDirectoryName, pDirName);
42
43	/* point to end of the copied directory name */
44	pEndDirName = &pDir->dir_pDirectoryName[nBufferLen - 1];
45
46	/* if directory name did not end in '/' or '\', add '/' */
47	if ((*pEndDirName != '/') && (*pEndDirName != '\\')) {
48		pEndDirName++;
49		*pEndDirName = '/';
50	}
51
52	/* now append the wildcard character to the buffer */
53	pEndDirName++;
54	*pEndDirName = '*';
55	pEndDirName++;
56	*pEndDirName = '\0';
57
58	/* other values defaulted */
59	pDir->dir_nNumFiles = 0;
60	pDir->dir_hDirHandle = INVALID_HANDLE_VALUE;
61	pDir->dir_ulCookie = __DIRENT_COOKIE;
62
63	return pDir;
64}
65
66void
67closedir(DIR *pDir)
68{
69	/* got a valid pointer? */
70	if (!pDir) {
71		errno = EINVAL;
72		return;
73	}
74
75	/* sanity check that this is a DIR pointer */
76	if (pDir->dir_ulCookie != __DIRENT_COOKIE) {
77		errno = EINVAL;
78		return;
79	}
80
81	/* close the WINDOWS32 directory handle */
82	if (pDir->dir_hDirHandle != INVALID_HANDLE_VALUE)
83		FindClose(pDir->dir_hDirHandle);
84
85	free(pDir);
86
87	return;
88}
89
90struct dirent *
91readdir(DIR* pDir)
92{
93	WIN32_FIND_DATA wfdFindData;
94
95	if (!pDir) {
96		errno = EINVAL;
97		return NULL;
98	}
99
100	/* sanity check that this is a DIR pointer */
101	if (pDir->dir_ulCookie != __DIRENT_COOKIE) {
102		errno = EINVAL;
103		return NULL;
104	}
105
106	if (pDir->dir_nNumFiles == 0) {
107		pDir->dir_hDirHandle = FindFirstFile(pDir->dir_pDirectoryName, &wfdFindData);
108		if (pDir->dir_hDirHandle == INVALID_HANDLE_VALUE)
109			return NULL;
110	} else if (!FindNextFile(pDir->dir_hDirHandle, &wfdFindData))
111			return NULL;
112
113	/* bump count for next call to readdir() or telldir() */
114	pDir->dir_nNumFiles++;
115
116	/* fill in struct dirent values */
117	pDir->dir_sdReturn.d_ino = -1;
118	strcpy(pDir->dir_sdReturn.d_name, wfdFindData.cFileName);
119
120	return &pDir->dir_sdReturn;
121}
122
123void
124rewinddir(DIR* pDir)
125{
126	if (!pDir) {
127		errno = EINVAL;
128		return;
129	}
130
131	/* sanity check that this is a DIR pointer */
132	if (pDir->dir_ulCookie != __DIRENT_COOKIE) {
133		errno = EINVAL;
134		return;
135	}
136
137	/* close the WINDOWS32 directory handle */
138	if (pDir->dir_hDirHandle != INVALID_HANDLE_VALUE)
139		if (!FindClose(pDir->dir_hDirHandle))
140			errno = EBADF;
141
142	/* reset members which control readdir() */
143	pDir->dir_hDirHandle = INVALID_HANDLE_VALUE;
144	pDir->dir_nNumFiles = 0;
145
146	return;
147}
148
149int
150telldir(DIR* pDir)
151{
152	if (!pDir) {
153		errno = EINVAL;
154		return -1;
155	}
156
157	/* sanity check that this is a DIR pointer */
158	if (pDir->dir_ulCookie != __DIRENT_COOKIE) {
159		errno = EINVAL;
160		return -1;
161	}
162
163	/* return number of times readdir() called */
164	return pDir->dir_nNumFiles;
165}
166
167void
168seekdir(DIR* pDir, long nPosition)
169{
170	if (!pDir)
171		return;
172
173	/* sanity check that this is a DIR pointer */
174	if (pDir->dir_ulCookie != __DIRENT_COOKIE)
175		return;
176
177	/* go back to beginning of directory */
178	rewinddir(pDir);
179
180	/* loop until we have found position we care about */
181	for (--nPosition; nPosition && readdir(pDir); nPosition--);
182
183	/* flag invalid nPosition value */
184	if (nPosition)
185		errno = EINVAL;
186
187	return;
188}
189