1
- #include "../git-compat-util.h"
2
- #include "dirent.h"
1
+ #include "../../git-compat-util.h"
3
2
4
3
struct DIR {
5
4
struct dirent dd_dir ; /* includes d_type */
6
5
HANDLE dd_handle ; /* FindFirstFile handle */
7
6
int dd_stat ; /* 0-based index */
8
- char dd_name [1 ]; /* extend struct */
9
7
};
10
8
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
+
11
21
DIR * opendir (const char * name )
12
22
{
13
- DWORD attrs = GetFileAttributesA (name );
23
+ char pattern [MAX_PATH ];
24
+ WIN32_FIND_DATAA fdata ;
25
+ HANDLE h ;
14
26
int len ;
15
- DIR * p ;
27
+ DIR * dir ;
16
28
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 ;
20
32
return NULL ;
21
33
}
22
-
23
- /* check if it's a directory */
24
- if (!(attrs & FILE_ATTRIBUTE_DIRECTORY )) {
25
- errno = ENOTDIR ;
26
- return NULL ;
27
- }
28
-
29
34
/* check that the pattern won't be too long for FindFirstFileA */
30
35
len = strlen (name );
31
- if (is_dir_sep (name [len - 1 ]))
32
- len -- ;
33
36
if (len + 2 >= MAX_PATH ) {
34
37
errno = ENAMETOOLONG ;
35
38
return NULL ;
36
39
}
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 );
40
54
return NULL ;
55
+ }
41
56
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 ;
49
63
}
50
64
51
65
struct dirent * readdir (DIR * dir )
52
66
{
53
- WIN32_FIND_DATAA buf ;
54
- HANDLE handle ;
55
-
56
- if (!dir || !dir -> dd_handle ) {
67
+ if (!dir ) {
57
68
errno = EBADF ; /* No set_errno for mingw */
58
69
return NULL ;
59
70
}
60
71
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 );
68
84
return NULL ;
69
85
}
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 ;
81
86
}
82
87
83
- /* We get here if `buf' contains valid data. */
84
- strcpy (dir -> dd_dir .d_name , buf .cFileName );
85
88
++ 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
-
94
89
return & dir -> dd_dir ;
95
90
}
96
91
@@ -101,8 +96,7 @@ int closedir(DIR *dir)
101
96
return -1 ;
102
97
}
103
98
104
- if (dir -> dd_handle != INVALID_HANDLE_VALUE )
105
- FindClose (dir -> dd_handle );
99
+ FindClose (dir -> dd_handle );
106
100
free (dir );
107
101
return 0 ;
108
102
}
0 commit comments