1717
1818#include "flb_tests_internal.h"
1919
20+ #ifdef _WIN32
21+ # define FLB_UNLINK _unlink
22+ # define FLB_RMDIR _rmdir
23+ #else
24+ # define FLB_UNLINK unlink
25+ # define FLB_RMDIR rmdir
26+ #endif
27+
2028static int mkpath (const char * p ) {
29+ #if FLB_SYSTEM_WINDOWS
30+ if (_mkdir (p ) == 0 ) {
31+ return 0 ;
32+ }
33+ #else
2134 if (mkdir (p , 0777 ) == 0 ) {
2235 return 0 ;
2336 }
37+ #endif
2438 if (errno == EEXIST ) {
2539 return 0 ;
2640 }
2741 return -1 ;
2842}
2943
30- static void tmpdir_for (char * out , size_t n , const char * name ) {
44+ static void join_path (char * out , size_t cap , const char * a , const char * b )
45+ {
46+ #ifdef _WIN32
47+ _snprintf (out , cap , "%s\\%s" , a , b );
48+ #else
49+ snprintf (out , cap , "%s/%s" , a , b );
50+ #endif
51+ out [cap - 1 ] = '\0' ;
52+ }
53+
54+ static void tmpdir_for (char * out , size_t n , const char * name )
55+ {
56+ #ifdef _WIN32
57+ DWORD pid = GetCurrentProcessId ();
58+ _snprintf (out , n , "C:\\Windows\\Temp\\flb-dlq-%s-%lu" , name , (unsigned long ) pid );
59+ #else
3160 snprintf (out , n , "/tmp/flb-dlq-%s-%ld" , name , (long ) getpid ());
61+ #endif
62+ out [n - 1 ] = '\0' ;
3263 mkpath (out );
3364}
3465
@@ -90,35 +121,71 @@ static int buf_contains(const void *hay, size_t hlen,
90121 return 0 ;
91122}
92123
93- /* find the most recent *.flb file in dir; write full path into out */
94- static int find_latest_flb (const char * dir , char * out , size_t out_sz )
124+ #if FLB_SYSTEM_WINDOWS
125+ static int find_latest_flb_win32 (const char * dir , char * out , size_t out_sz )
95126{
127+ WIN32_FIND_DATAA ffd ;
128+ HANDLE h = INVALID_HANDLE_VALUE ;
129+ char pattern [1024 ];
130+ ULONGLONG best_ts = 0ULL ;
131+ char best_name [MAX_PATH ] = {0 };
132+
133+ _snprintf (pattern , sizeof (pattern ), "%s\\*.flb" , dir );
134+ pattern [sizeof (pattern )- 1 ] = '\0' ;
135+
136+ h = FindFirstFileA (pattern , & ffd );
137+ if (h == INVALID_HANDLE_VALUE ) {
138+ return -1 ;
139+ }
140+
141+ do {
142+ if (ffd .dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) {
143+ continue ;
144+ }
145+ ULONGLONG ts = (((ULONGLONG )ffd .ftLastWriteTime .dwHighDateTime ) << 32 ) |
146+ (ULONGLONG )ffd .ftLastWriteTime .dwLowDateTime ;
147+ if (ts >= best_ts ) {
148+ best_ts = ts ;
149+ strncpy (best_name , ffd .cFileName , sizeof (best_name )- 1 );
150+ best_name [sizeof (best_name )- 1 ] = '\0' ;
151+ }
152+ } while (FindNextFileA (h , & ffd ));
153+
154+ FindClose (h );
155+
156+ if (best_name [0 ] == '\0' ) {
157+ return -1 ;
158+ }
159+
160+ join_path (out , out_sz , dir , best_name );
161+ return 0 ;
162+ }
163+ #else
164+ static int find_latest_flb_unix (const char * dir , char * out , size_t out_sz )
165+ {
166+ DIR * d = opendir (dir );
96167 struct dirent * e ;
97168 time_t best_t = 0 ;
98169 char best_path [1024 ] = {0 };
99170 struct stat st ;
100171 char full [1024 ];
101- size_t len = 0 ;
102- DIR * d = opendir (dir );
103172
104- if (!d ) {
105- return -1 ;
106- }
173+ if (!d ) return -1 ;
107174
108175 while ((e = readdir (d )) != NULL ) {
109- len = strlen (e -> d_name );
176+ size_t len = strlen (e -> d_name );
110177 if (len < 5 ) {
111178 continue ;
112179 }
113180 if (strcmp (e -> d_name + (len - 4 ), ".flb" ) != 0 ) {
114181 continue ;
115182 }
116183
117- snprintf (full , sizeof (full ), "%s/%s" , dir , e -> d_name );
184+ join_path (full , sizeof (full ), dir , e -> d_name );
118185 if (stat (full , & st ) == 0 ) {
119186 if (st .st_mtime >= best_t ) {
120187 best_t = st .st_mtime ;
121- strncpy (best_path , full , sizeof (best_path ) - 1 );
188+ strncpy (best_path , full , sizeof (best_path )- 1 );
122189 }
123190 }
124191 }
@@ -131,6 +198,17 @@ static int find_latest_flb(const char *dir, char *out, size_t out_sz)
131198 out [out_sz - 1 ] = '\0' ;
132199 return 0 ;
133200}
201+ #endif
202+
203+ /* find the most recent *.flb file in dir; write full path into out */
204+ static int find_latest_flb (const char * dir , char * out , size_t out_sz )
205+ {
206+ #if FLB_SYSTEM_WINDOWS
207+ return find_latest_flb_win32 (dir , out , out_sz );
208+ #else
209+ return find_latest_flb_unix (dir , out , out_sz );
210+ #endif
211+ }
134212
135213static void free_ctx (struct flb_config * ctx )
136214{
@@ -195,37 +273,85 @@ static void rmdir_stream_dir(const char *root, const char *stream_name)
195273}
196274
197275/* Minimal POSIX rm -rf for the whole temp tree after CIO is gone */
198- static void rm_rf_best_effort (const char * root )
276+ #if FLB_SYSTEM_WINDOWS
277+ static void rm_rf_best_effort_win32 (const char * root )
278+ {
279+ WIN32_FIND_DATAA ffd ;
280+ HANDLE h = INVALID_HANDLE_VALUE ;
281+ char pattern [1024 ], p [1024 ];
282+
283+ _snprintf (pattern , sizeof (pattern ), "%s\\*" ,
284+ root ? root : "" );
285+ pattern [sizeof (pattern )- 1 ] = '\0' ;
286+
287+ h = FindFirstFileA (pattern , & ffd );
288+ if (h == INVALID_HANDLE_VALUE ) {
289+ /* try removing root itself */
290+ (void ) FLB_RMDIR (root );
291+ return ;
292+ }
293+
294+ do {
295+ const char * name = ffd .cFileName ;
296+ if (!strcmp (name , "." ) || !strcmp (name , ".." )) continue ;
297+
298+ join_path (p , sizeof (p ), root , name );
299+
300+ if (ffd .dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) {
301+ rm_rf_best_effort_win32 (p );
302+ }
303+ else {
304+ /* clear read-only if needed */
305+ if (ffd .dwFileAttributes & FILE_ATTRIBUTE_READONLY ) {
306+ SetFileAttributesA (p ,
307+ ffd .dwFileAttributes & ~FILE_ATTRIBUTE_READONLY );
308+ }
309+ (void ) DeleteFileA (p );
310+ }
311+ } while (FindNextFileA (h , & ffd ));
312+
313+ FindClose (h );
314+ (void ) FLB_RMDIR (root );
315+ }
316+ #else
317+ static void rm_rf_best_effort_unix (const char * root )
199318{
200- DIR * d ;
319+ DIR * d = opendir ( root ) ;
201320 struct dirent * e ;
202321 char p [1024 ];
203322 struct stat st ;
204323
205- if (!root ) { return ; }
206-
207- d = opendir (root );
208324 if (!d ) {
209- (void ) rmdir (root );
325+ (void ) FLB_RMDIR (root );
210326 return ;
211327 }
212328 while ((e = readdir (d )) != NULL ) {
213- if (!strcmp (e -> d_name , "." ) || !strcmp (e -> d_name , ".." )) {
329+ if (!strcmp (e -> d_name , "." ) || !strcmp (e -> d_name , ".." )) {
214330 continue ;
215331 }
216- snprintf (p , sizeof (p ), "%s/%s" , root , e -> d_name );
332+ join_path (p , sizeof (p ), root , e -> d_name );
217333 if (lstat (p , & st ) != 0 ) {
218334 continue ;
219335 }
220336 if (S_ISDIR (st .st_mode )) {
221- rm_rf_best_effort (p );
337+ rm_rf_best_effort_unix (p );
222338 }
223339 else {
224- (void ) unlink (p );
340+ (void ) FLB_UNLINK (p );
225341 }
226342 }
227343 closedir (d );
228- (void ) rmdir (root );
344+ (void ) FLB_RMDIR (root );
345+ }
346+ #endif
347+
348+ static void rm_rf_best_effort (const char * root )
349+ {
350+ #if FLB_SYSTEM_WINDOWS
351+ rm_rf_best_effort_win32 (root );
352+ #else
353+ rm_rf_best_effort_unix (root );
354+ #endif
229355}
230356
231357static void test_cleanup_with_cio (struct flb_config * ctx , const char * root )
0 commit comments