1- #include "../git-compat-util.h"
2- #include "dirent.h"
1+ #include "../../git-compat-util.h"
32
43struct DIR {
54 struct dirent dd_dir ; /* includes d_type */
65 HANDLE dd_handle ; /* FindFirstFile handle */
76 int dd_stat ; /* 0-based index */
8- char dd_name [1 ]; /* extend struct */
97};
108
9+ static inline void finddata2dirent (struct dirent * ent , WIN32_FIND_DATAA * fdata )
10+ {
11+ /* copy file name from WIN32_FIND_DATA to dirent */
12+ memcpy (ent -> d_name , fdata -> cFileName , sizeof (ent -> d_name ));
13+
14+ /* Set file type, based on WIN32_FIND_DATA */
15+ if (fdata -> dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
16+ ent -> d_type = DT_DIR ;
17+ else
18+ ent -> d_type = DT_REG ;
19+ }
20+
1121DIR * opendir (const char * name )
1222{
13- DWORD attrs = GetFileAttributesA (name );
23+ char pattern [MAX_PATH ];
24+ WIN32_FIND_DATAA fdata ;
25+ HANDLE h ;
1426 int len ;
15- DIR * p ;
27+ DIR * dir ;
1628
17- /* check for valid path */
18- if (attrs == INVALID_FILE_ATTRIBUTES ) {
19- errno = ENOENT ;
29+ /* check that name is not NULL */
30+ if (! name ) {
31+ errno = EINVAL ;
2032 return NULL ;
2133 }
22-
23- /* check if it's a directory */
24- if (!(attrs & FILE_ATTRIBUTE_DIRECTORY )) {
25- errno = ENOTDIR ;
26- return NULL ;
27- }
28-
2934 /* check that the pattern won't be too long for FindFirstFileA */
3035 len = strlen (name );
31- if (is_dir_sep (name [len - 1 ]))
32- len -- ;
3336 if (len + 2 >= MAX_PATH ) {
3437 errno = ENAMETOOLONG ;
3538 return NULL ;
3639 }
37-
38- p = malloc (sizeof (DIR ) + len + 2 );
39- if (!p )
40+ /* copy name to temp buffer */
41+ memcpy (pattern , name , len + 1 );
42+
43+ /* append optional '/' and wildcard '*' */
44+ if (len && !is_dir_sep (pattern [len - 1 ]))
45+ pattern [len ++ ] = '/' ;
46+ pattern [len ++ ] = '*' ;
47+ pattern [len ] = 0 ;
48+
49+ /* open find handle */
50+ h = FindFirstFileA (pattern , & fdata );
51+ if (h == INVALID_HANDLE_VALUE ) {
52+ DWORD err = GetLastError ();
53+ errno = (err == ERROR_DIRECTORY ) ? ENOTDIR : err_win_to_posix (err );
4054 return NULL ;
55+ }
4156
42- memset (p , 0 , sizeof (DIR ) + len + 2 );
43- strcpy (p -> dd_name , name );
44- p -> dd_name [len ] = '/' ;
45- p -> dd_name [len + 1 ] = '*' ;
46-
47- p -> dd_handle = INVALID_HANDLE_VALUE ;
48- return p ;
57+ /* initialize DIR structure and copy first dir entry */
58+ dir = xmalloc (sizeof (DIR ));
59+ dir -> dd_handle = h ;
60+ dir -> dd_stat = 0 ;
61+ finddata2dirent (& dir -> dd_dir , & fdata );
62+ return dir ;
4963}
5064
5165struct dirent * readdir (DIR * dir )
5266{
53- WIN32_FIND_DATAA buf ;
54- HANDLE handle ;
55-
56- if (!dir || !dir -> dd_handle ) {
67+ if (!dir ) {
5768 errno = EBADF ; /* No set_errno for mingw */
5869 return NULL ;
5970 }
6071
61- if (dir -> dd_handle == INVALID_HANDLE_VALUE && dir -> dd_stat == 0 ) {
62- DWORD lasterr ;
63- handle = FindFirstFileA (dir -> dd_name , & buf );
64- lasterr = GetLastError ();
65- dir -> dd_handle = handle ;
66- if (handle == INVALID_HANDLE_VALUE && (lasterr != ERROR_NO_MORE_FILES )) {
67- errno = err_win_to_posix (lasterr );
72+ /* if first entry, dirent has already been set up by opendir */
73+ if (dir -> dd_stat ) {
74+ /* get next entry and convert from WIN32_FIND_DATA to dirent */
75+ WIN32_FIND_DATAA fdata ;
76+ if (FindNextFileA (dir -> dd_handle , & fdata )) {
77+ finddata2dirent (& dir -> dd_dir , & fdata );
78+ } else {
79+ DWORD lasterr = GetLastError ();
80+ /* POSIX says you shouldn't set errno when readdir can't
81+ find any more files; so, if another error we leave it set. */
82+ if (lasterr != ERROR_NO_MORE_FILES )
83+ errno = err_win_to_posix (lasterr );
6884 return NULL ;
6985 }
70- } else if (dir -> dd_handle == INVALID_HANDLE_VALUE ) {
71- return NULL ;
72- } else if (!FindNextFileA (dir -> dd_handle , & buf )) {
73- DWORD lasterr = GetLastError ();
74- FindClose (dir -> dd_handle );
75- dir -> dd_handle = INVALID_HANDLE_VALUE ;
76- /* POSIX says you shouldn't set errno when readdir can't
77- find any more files; so, if another error we leave it set. */
78- if (lasterr != ERROR_NO_MORE_FILES )
79- errno = err_win_to_posix (lasterr );
80- return NULL ;
8186 }
8287
83- /* We get here if `buf' contains valid data. */
84- strcpy (dir -> dd_dir .d_name , buf .cFileName );
8588 ++ dir -> dd_stat ;
86-
87- /* Set file type, based on WIN32_FIND_DATA */
88- dir -> dd_dir .d_type = 0 ;
89- if (buf .dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
90- dir -> dd_dir .d_type |= DT_DIR ;
91- else
92- dir -> dd_dir .d_type |= DT_REG ;
93-
9489 return & dir -> dd_dir ;
9590}
9691
@@ -101,8 +96,7 @@ int closedir(DIR *dir)
10196 return -1 ;
10297 }
10398
104- if (dir -> dd_handle != INVALID_HANDLE_VALUE )
105- FindClose (dir -> dd_handle );
99+ FindClose (dir -> dd_handle );
106100 free (dir );
107101 return 0 ;
108102}
0 commit comments