@@ -54,6 +54,16 @@ extern "C"
54
54
# define RCUTILS_PATH_DELIMITER "/"
55
55
#endif // _WIN32
56
56
57
+ typedef struct rcutils_dir_iter_state_t
58
+ {
59
+ #ifdef _WIN32
60
+ HANDLE handle ;
61
+ WIN32_FIND_DATA data ;
62
+ #else
63
+ DIR * dir ;
64
+ #endif
65
+ } rcutils_dir_iter_state_t ;
66
+
57
67
bool
58
68
rcutils_get_cwd (char * buffer , size_t max_length )
59
69
{
@@ -337,6 +347,7 @@ rcutils_calculate_directory_size_with_recursion(
337
347
{
338
348
dir_list_t * dir_list = NULL ;
339
349
rcutils_ret_t ret = RCUTILS_RET_OK ;
350
+ rcutils_dir_iter_t * iter = NULL ;
340
351
341
352
if (NULL == directory_path ) {
342
353
RCUTILS_SAFE_FWRITE_TO_STDERR ("directory_path is NULL !" );
@@ -371,89 +382,146 @@ rcutils_calculate_directory_size_with_recursion(
371
382
372
383
* size = 0 ;
373
384
374
- #ifdef _WIN32
375
- HANDLE handle = INVALID_HANDLE_VALUE ;
376
- char * dir_path = NULL ;
377
-
378
385
do {
379
- dir_path = rcutils_join_path (dir_list -> path , "*" , allocator );
380
- if (NULL == dir_path ) {
381
- RCUTILS_SAFE_FWRITE_TO_STDERR ("Failed to duplicate directory path !\n" );
382
- ret = RCUTILS_RET_BAD_ALLOC ;
383
- goto fail ;
384
- }
385
-
386
- WIN32_FIND_DATA data ;
387
- handle = FindFirstFile (dir_path , & data );
388
- if (INVALID_HANDLE_VALUE == handle ) {
389
- RCUTILS_SAFE_FWRITE_TO_STDERR_WITH_FORMAT_STRING (
390
- "Can't open directory %s. Error code: %lu\n" , dir_list -> path , GetLastError ());
386
+ iter = rcutils_dir_iter_start (dir_list -> path , allocator );
387
+ if (NULL == iter ) {
391
388
ret = RCUTILS_RET_ERROR ;
392
389
goto fail ;
393
390
}
394
391
395
392
do {
396
- ret = check_and_calculate_size (data . cFileName , size , max_depth , dir_list , allocator );
393
+ ret = check_and_calculate_size (iter -> entry_name , size , max_depth , dir_list , allocator );
397
394
if (RCUTILS_RET_OK != ret ) {
398
395
goto fail ;
399
396
}
400
- } while (FindNextFile ( handle , & data ));
397
+ } while (rcutils_dir_iter_next ( iter ));
401
398
402
- FindClose (handle );
403
- allocator .deallocate (dir_path , allocator .state );
399
+ rcutils_dir_iter_end (iter );
404
400
405
401
remove_first_dir_from_list (& dir_list , allocator );
406
402
} while (dir_list );
407
403
408
404
return ret ;
409
405
410
406
fail :
411
- if (NULL != dir_path ) {
412
- allocator .deallocate (dir_path , allocator .state );
407
+ rcutils_dir_iter_end (iter );
408
+ free_dir_list (dir_list , allocator );
409
+ return ret ;
410
+ }
411
+
412
+ rcutils_dir_iter_t *
413
+ rcutils_dir_iter_start (const char * directory_path , const rcutils_allocator_t allocator )
414
+ {
415
+ RCUTILS_CHECK_ARGUMENT_FOR_NULL (directory_path , NULL );
416
+ RCUTILS_CHECK_ALLOCATOR_WITH_MSG (
417
+ & allocator , "allocator is invalid" , return NULL );
418
+
419
+ rcutils_dir_iter_t * iter = (rcutils_dir_iter_t * )allocator .zero_allocate (
420
+ 1 , sizeof (rcutils_dir_iter_t ), allocator .state );
421
+ if (NULL == iter ) {
422
+ return NULL ;
413
423
}
424
+ iter -> allocator = allocator ;
414
425
415
- if (INVALID_HANDLE_VALUE != handle ) {
416
- FindClose (handle );
426
+ rcutils_dir_iter_state_t * state = (rcutils_dir_iter_state_t * )allocator .zero_allocate (
427
+ 1 , sizeof (rcutils_dir_iter_state_t ), allocator .state );
428
+ if (NULL == state ) {
429
+ RCUTILS_SET_ERROR_MSG (
430
+ "Failed to allocate memory.\n" );
431
+ goto rcutils_dir_iter_start_fail ;
417
432
}
418
- free_dir_list (dir_list , allocator );
419
- return ret ;
420
- #else
421
- DIR * dir = NULL ;
433
+ iter -> state = (void * )state ;
422
434
423
- struct dirent * entry ;
424
- do {
425
- dir = opendir (dir_list -> path );
426
- if (NULL == dir ) {
427
- RCUTILS_SAFE_FWRITE_TO_STDERR_WITH_FORMAT_STRING (
428
- "Can't open directory %s. Error code: %d\n" , dir_list -> path , errno );
429
- ret = RCUTILS_RET_ERROR ;
430
- goto fail ;
435
+ #ifdef _WIN32
436
+ char * search_path = rcutils_join_path (directory_path , "*" , allocator );
437
+ if (NULL == search_path ) {
438
+ goto rcutils_dir_iter_start_fail ;
439
+ }
440
+ state -> handle = FindFirstFile (search_path , & state -> data );
441
+ allocator .deallocate (search_path , allocator .state );
442
+ if (INVALID_HANDLE_VALUE == state -> handle ) {
443
+ DWORD error = GetLastError ();
444
+ if (ERROR_FILE_NOT_FOUND != error || !rcutils_is_directory (directory_path )) {
445
+ RCUTILS_SET_ERROR_MSG_WITH_FORMAT_STRING (
446
+ "Can't open directory %s. Error code: %d\n" , directory_path , error );
447
+ goto rcutils_dir_iter_start_fail ;
431
448
}
449
+ } else {
450
+ iter -> entry_name = state -> data .cFileName ;
451
+ }
452
+ #else
453
+ state -> dir = opendir (directory_path );
454
+ if (NULL == state -> dir ) {
455
+ RCUTILS_SET_ERROR_MSG_WITH_FORMAT_STRING (
456
+ "Can't open directory %s. Error code: %d\n" , directory_path , errno );
457
+ goto rcutils_dir_iter_start_fail ;
458
+ }
459
+
460
+ errno = 0 ;
461
+ struct dirent * entry = readdir (state -> dir );
462
+ if (NULL != entry ) {
463
+ iter -> entry_name = entry -> d_name ;
464
+ } else if (0 != errno ) {
465
+ RCUTILS_SET_ERROR_MSG_WITH_FORMAT_STRING (
466
+ "Can't iterate directory %s. Error code: %d\n" , directory_path , errno );
467
+ goto rcutils_dir_iter_start_fail ;
468
+ }
469
+ #endif
432
470
433
- // Scan in specified path
434
- // If found directory, add to dir_list
435
- // If found file, calculate file size
436
- while (NULL != (entry = readdir (dir ))) {
437
- ret = check_and_calculate_size (entry -> d_name , size , max_depth , dir_list , allocator );
438
- if (RCUTILS_RET_OK != ret ) {
439
- goto fail ;
440
- }
441
- }
471
+ return iter ;
442
472
443
- closedir (dir );
473
+ rcutils_dir_iter_start_fail :
474
+ rcutils_dir_iter_end (iter );
475
+ return NULL ;
476
+ }
444
477
445
- remove_first_dir_from_list (& dir_list , allocator );
446
- } while (dir_list );
478
+ bool
479
+ rcutils_dir_iter_next (rcutils_dir_iter_t * iter )
480
+ {
481
+ RCUTILS_CHECK_ARGUMENT_FOR_NULL (iter , false);
482
+ rcutils_dir_iter_state_t * state = (rcutils_dir_iter_state_t * )iter -> state ;
483
+ RCUTILS_CHECK_FOR_NULL_WITH_MSG (state , "iter is invalid" , false);
447
484
448
- return ret ;
485
+ #ifdef _WIN32
486
+ if (FindNextFile (state -> handle , & state -> data )) {
487
+ iter -> entry_name = state -> data .cFileName ;
488
+ return true;
489
+ }
490
+ FindClose (state -> handle );
491
+ #else
492
+ struct dirent * entry = readdir (state -> dir );
493
+ if (NULL != entry ) {
494
+ iter -> entry_name = entry -> d_name ;
495
+ return true;
496
+ }
497
+ #endif
449
498
450
- fail :
451
- if (NULL != dir ) {
452
- closedir (dir );
499
+ iter -> entry_name = NULL ;
500
+ return false;
501
+ }
502
+
503
+ void
504
+ rcutils_dir_iter_end (rcutils_dir_iter_t * iter )
505
+ {
506
+ if (NULL == iter ) {
507
+ return ;
453
508
}
454
- free_dir_list (dir_list , allocator );
455
- return ret ;
509
+
510
+ rcutils_allocator_t allocator = iter -> allocator ;
511
+ rcutils_dir_iter_state_t * state = (rcutils_dir_iter_state_t * )iter -> state ;
512
+ if (NULL != state ) {
513
+ #ifdef _WIN32
514
+ FindClose (state -> handle );
515
+ #else
516
+ if (NULL != state -> dir ) {
517
+ closedir (state -> dir );
518
+ }
456
519
#endif
520
+
521
+ allocator .deallocate (state , allocator .state );
522
+ }
523
+
524
+ allocator .deallocate (iter , allocator .state );
457
525
}
458
526
459
527
size_t
0 commit comments