11#include "../../git-compat-util.h"
22
3- struct DIR {
3+ typedef struct dirent_DIR {
4+ struct DIR base_dir ; /* extend base struct DIR */
45 struct dirent dd_dir ; /* includes d_type */
56 HANDLE dd_handle ; /* FindFirstFile handle */
67 int dd_stat ; /* 0-based index */
7- };
8+ char dd_name [MAX_PATH * 3 ]; /* file name (* 3 for UTF-8 conversion) */
9+ } dirent_DIR ;
10+
11+ DIR * (* opendir )(const char * dirname ) = dirent_opendir ;
812
913static inline void finddata2dirent (struct dirent * ent , WIN32_FIND_DATAW * fdata )
1014{
11- /* convert UTF-16 name to UTF-8 */
12- xwcstoutf (ent -> d_name , fdata -> cFileName , sizeof ( ent -> d_name ) );
15+ /* convert UTF-16 name to UTF-8 (d_name points to dirent_DIR.dd_name) */
16+ xwcstoutf (ent -> d_name , fdata -> cFileName , MAX_PATH * 3 );
1317
1418 /* Set file type, based on WIN32_FIND_DATA */
1519 if (fdata -> dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
@@ -18,41 +22,7 @@ static inline void finddata2dirent(struct dirent *ent, WIN32_FIND_DATAW *fdata)
1822 ent -> d_type = DT_REG ;
1923}
2024
21- DIR * opendir (const char * name )
22- {
23- wchar_t pattern [MAX_PATH + 2 ]; /* + 2 for '/' '*' */
24- WIN32_FIND_DATAW fdata ;
25- HANDLE h ;
26- int len ;
27- DIR * dir ;
28-
29- /* convert name to UTF-16 and check length < MAX_PATH */
30- if ((len = xutftowcs_path (pattern , name )) < 0 )
31- return NULL ;
32-
33- /* append optional '/' and wildcard '*' */
34- if (len && !is_dir_sep (pattern [len - 1 ]))
35- pattern [len ++ ] = '/' ;
36- pattern [len ++ ] = '*' ;
37- pattern [len ] = 0 ;
38-
39- /* open find handle */
40- h = FindFirstFileW (pattern , & fdata );
41- if (h == INVALID_HANDLE_VALUE ) {
42- DWORD err = GetLastError ();
43- errno = (err == ERROR_DIRECTORY ) ? ENOTDIR : err_win_to_posix (err );
44- return NULL ;
45- }
46-
47- /* initialize DIR structure and copy first dir entry */
48- dir = xmalloc (sizeof (DIR ));
49- dir -> dd_handle = h ;
50- dir -> dd_stat = 0 ;
51- finddata2dirent (& dir -> dd_dir , & fdata );
52- return dir ;
53- }
54-
55- struct dirent * readdir (DIR * dir )
25+ static struct dirent * dirent_readdir (dirent_DIR * dir )
5626{
5727 if (!dir ) {
5828 errno = EBADF ; /* No set_errno for mingw */
@@ -79,7 +49,7 @@ struct dirent *readdir(DIR *dir)
7949 return & dir -> dd_dir ;
8050}
8151
82- int closedir ( DIR * dir )
52+ static int dirent_closedir ( dirent_DIR * dir )
8353{
8454 if (!dir ) {
8555 errno = EBADF ;
@@ -90,3 +60,40 @@ int closedir(DIR *dir)
9060 free (dir );
9161 return 0 ;
9262}
63+
64+ DIR * dirent_opendir (const char * name )
65+ {
66+ wchar_t pattern [MAX_PATH + 2 ]; /* + 2 for '/' '*' */
67+ WIN32_FIND_DATAW fdata ;
68+ HANDLE h ;
69+ int len ;
70+ dirent_DIR * dir ;
71+
72+ /* convert name to UTF-16 and check length < MAX_PATH */
73+ if ((len = xutftowcs_path (pattern , name )) < 0 )
74+ return NULL ;
75+
76+ /* append optional '/' and wildcard '*' */
77+ if (len && !is_dir_sep (pattern [len - 1 ]))
78+ pattern [len ++ ] = '/' ;
79+ pattern [len ++ ] = '*' ;
80+ pattern [len ] = 0 ;
81+
82+ /* open find handle */
83+ h = FindFirstFileW (pattern , & fdata );
84+ if (h == INVALID_HANDLE_VALUE ) {
85+ DWORD err = GetLastError ();
86+ errno = (err == ERROR_DIRECTORY ) ? ENOTDIR : err_win_to_posix (err );
87+ return NULL ;
88+ }
89+
90+ /* initialize DIR structure and copy first dir entry */
91+ dir = xmalloc (sizeof (dirent_DIR ));
92+ dir -> base_dir .preaddir = (struct dirent * (* )(DIR * dir )) dirent_readdir ;
93+ dir -> base_dir .pclosedir = (int (* )(DIR * dir )) dirent_closedir ;
94+ dir -> dd_dir .d_name = dir -> dd_name ;
95+ dir -> dd_handle = h ;
96+ dir -> dd_stat = 0 ;
97+ finddata2dirent (& dir -> dd_dir , & fdata );
98+ return (DIR * ) dir ;
99+ }
0 commit comments