@@ -34,6 +34,17 @@ use libc::c_char;
34
34
use libc:: dirfd;
35
35
#[ cfg( any( target_os = "linux" , target_os = "emscripten" ) ) ]
36
36
use libc:: fstatat64;
37
+ #[ cfg( any(
38
+ target_os = "solaris" ,
39
+ target_os = "fuchsia" ,
40
+ target_os = "redox" ,
41
+ target_os = "illumos"
42
+ ) ) ]
43
+ use libc:: readdir as readdir64;
44
+ #[ cfg( target_os = "linux" ) ]
45
+ use libc:: readdir64;
46
+ #[ cfg( any( target_os = "emscripten" , target_os = "l4re" ) ) ]
47
+ use libc:: readdir64_r;
37
48
#[ cfg( not( any(
38
49
target_os = "linux" ,
39
50
target_os = "emscripten" ,
@@ -60,9 +71,7 @@ use libc::{
60
71
lstat as lstat64, off_t as off64_t, open as open64, stat as stat64,
61
72
} ;
62
73
#[ cfg( any( target_os = "linux" , target_os = "emscripten" , target_os = "l4re" ) ) ]
63
- use libc:: {
64
- dirent64, fstat64, ftruncate64, lseek64, lstat64, off64_t, open64, readdir64_r, stat64,
65
- } ;
74
+ use libc:: { dirent64, fstat64, ftruncate64, lseek64, lstat64, off64_t, open64, stat64} ;
66
75
67
76
pub use crate :: sys_common:: fs:: try_exists;
68
77
@@ -202,6 +211,7 @@ struct InnerReadDir {
202
211
pub struct ReadDir {
203
212
inner : Arc < InnerReadDir > ,
204
213
#[ cfg( not( any(
214
+ target_os = "linux" ,
205
215
target_os = "solaris" ,
206
216
target_os = "illumos" ,
207
217
target_os = "fuchsia" ,
@@ -218,11 +228,11 @@ unsafe impl Sync for Dir {}
218
228
pub struct DirEntry {
219
229
entry : dirent64 ,
220
230
dir : Arc < InnerReadDir > ,
221
- // We need to store an owned copy of the entry name
222
- // on Solaris and Fuchsia because a) it uses a zero-length
223
- // array to store the name, b) its lifetime between readdir
224
- // calls is not guaranteed.
231
+ // We need to store an owned copy of the entry name on platforms that use
232
+ // readdir() (not readdir_r()), because a) struct dirent may use a flexible
233
+ // array to store the name, b) it lives only until the next readdir() call.
225
234
#[ cfg( any(
235
+ target_os = "linux" ,
226
236
target_os = "solaris" ,
227
237
target_os = "illumos" ,
228
238
target_os = "fuchsia" ,
@@ -449,6 +459,7 @@ impl Iterator for ReadDir {
449
459
type Item = io:: Result < DirEntry > ;
450
460
451
461
#[ cfg( any(
462
+ target_os = "linux" ,
452
463
target_os = "solaris" ,
453
464
target_os = "fuchsia" ,
454
465
target_os = "redox" ,
@@ -457,12 +468,13 @@ impl Iterator for ReadDir {
457
468
fn next ( & mut self ) -> Option < io:: Result < DirEntry > > {
458
469
unsafe {
459
470
loop {
460
- // Although readdir_r(3) would be a correct function to use here because
461
- // of the thread safety, on Illumos and Fuchsia the readdir(3C) function
462
- // is safe to use in threaded applications and it is generally preferred
463
- // over the readdir_r(3C) function.
471
+ // As of POSIX.1-2017, readdir() is not required to be thread safe; only
472
+ // readdir_r() is. However, readdir_r() cannot correctly handle platforms
473
+ // with unlimited or variable NAME_MAX. Many modern platforms guarantee
474
+ // thread safety for readdir() as long an individual DIR* is not accessed
475
+ // concurrently, which is sufficient for Rust.
464
476
super :: os:: set_errno ( 0 ) ;
465
- let entry_ptr = libc :: readdir ( self . inner . dirp . 0 ) ;
477
+ let entry_ptr = readdir64 ( self . inner . dirp . 0 ) ;
466
478
if entry_ptr. is_null ( ) {
467
479
// null can mean either the end is reached or an error occurred.
468
480
// So we had to clear errno beforehand to check for an error now.
@@ -486,6 +498,7 @@ impl Iterator for ReadDir {
486
498
}
487
499
488
500
#[ cfg( not( any(
501
+ target_os = "linux" ,
489
502
target_os = "solaris" ,
490
503
target_os = "fuchsia" ,
491
504
target_os = "redox" ,
@@ -652,6 +665,7 @@ impl DirEntry {
652
665
}
653
666
654
667
#[ cfg( not( any(
668
+ target_os = "linux" ,
655
669
target_os = "solaris" ,
656
670
target_os = "illumos" ,
657
671
target_os = "fuchsia" ,
@@ -661,6 +675,7 @@ impl DirEntry {
661
675
unsafe { CStr :: from_ptr ( self . entry . d_name . as_ptr ( ) ) }
662
676
}
663
677
#[ cfg( any(
678
+ target_os = "linux" ,
664
679
target_os = "solaris" ,
665
680
target_os = "illumos" ,
666
681
target_os = "fuchsia" ,
@@ -1071,6 +1086,7 @@ pub fn readdir(p: &Path) -> io::Result<ReadDir> {
1071
1086
Ok ( ReadDir {
1072
1087
inner : Arc :: new ( inner) ,
1073
1088
#[ cfg( not( any(
1089
+ target_os = "linux" ,
1074
1090
target_os = "solaris" ,
1075
1091
target_os = "illumos" ,
1076
1092
target_os = "fuchsia" ,
@@ -1606,6 +1622,7 @@ mod remove_dir_impl {
1606
1622
ReadDir {
1607
1623
inner : Arc :: new ( InnerReadDir { dirp, root : dummy_root } ) ,
1608
1624
#[ cfg( not( any(
1625
+ target_os = "linux" ,
1609
1626
target_os = "solaris" ,
1610
1627
target_os = "illumos" ,
1611
1628
target_os = "fuchsia" ,
0 commit comments