@@ -34,6 +34,17 @@ use libc::c_char;
3434use libc:: dirfd;
3535#[ cfg( any( target_os = "linux" , target_os = "emscripten" ) ) ]
3636use 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;
3748#[ cfg( not( any(
3849 target_os = "linux" ,
3950 target_os = "emscripten" ,
@@ -60,9 +71,7 @@ use libc::{
6071 lstat as lstat64, off_t as off64_t, open as open64, stat as stat64,
6172} ;
6273#[ 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} ;
6675
6776pub use crate :: sys_common:: fs:: try_exists;
6877
@@ -202,6 +211,7 @@ struct InnerReadDir {
202211pub struct ReadDir {
203212 inner : Arc < InnerReadDir > ,
204213 #[ cfg( not( any(
214+ target_os = "linux" ,
205215 target_os = "solaris" ,
206216 target_os = "illumos" ,
207217 target_os = "fuchsia" ,
@@ -218,11 +228,11 @@ unsafe impl Sync for Dir {}
218228pub struct DirEntry {
219229 entry : dirent64 ,
220230 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.
225234 #[ cfg( any(
235+ target_os = "linux" ,
226236 target_os = "solaris" ,
227237 target_os = "illumos" ,
228238 target_os = "fuchsia" ,
@@ -449,6 +459,7 @@ impl Iterator for ReadDir {
449459 type Item = io:: Result < DirEntry > ;
450460
451461 #[ cfg( any(
462+ target_os = "linux" ,
452463 target_os = "solaris" ,
453464 target_os = "fuchsia" ,
454465 target_os = "redox" ,
@@ -457,12 +468,13 @@ impl Iterator for ReadDir {
457468 fn next ( & mut self ) -> Option < io:: Result < DirEntry > > {
458469 unsafe {
459470 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.
464476 super :: os:: set_errno ( 0 ) ;
465- let entry_ptr = libc :: readdir ( self . inner . dirp . 0 ) ;
477+ let entry_ptr = readdir64 ( self . inner . dirp . 0 ) ;
466478 if entry_ptr. is_null ( ) {
467479 // null can mean either the end is reached or an error occurred.
468480 // So we had to clear errno beforehand to check for an error now.
@@ -486,6 +498,7 @@ impl Iterator for ReadDir {
486498 }
487499
488500 #[ cfg( not( any(
501+ target_os = "linux" ,
489502 target_os = "solaris" ,
490503 target_os = "fuchsia" ,
491504 target_os = "redox" ,
@@ -652,6 +665,7 @@ impl DirEntry {
652665 }
653666
654667 #[ cfg( not( any(
668+ target_os = "linux" ,
655669 target_os = "solaris" ,
656670 target_os = "illumos" ,
657671 target_os = "fuchsia" ,
@@ -661,6 +675,7 @@ impl DirEntry {
661675 unsafe { CStr :: from_ptr ( self . entry . d_name . as_ptr ( ) ) }
662676 }
663677 #[ cfg( any(
678+ target_os = "linux" ,
664679 target_os = "solaris" ,
665680 target_os = "illumos" ,
666681 target_os = "fuchsia" ,
@@ -1071,6 +1086,7 @@ pub fn readdir(p: &Path) -> io::Result<ReadDir> {
10711086 Ok ( ReadDir {
10721087 inner : Arc :: new ( inner) ,
10731088 #[ cfg( not( any(
1089+ target_os = "linux" ,
10741090 target_os = "solaris" ,
10751091 target_os = "illumos" ,
10761092 target_os = "fuchsia" ,
@@ -1606,6 +1622,7 @@ mod remove_dir_impl {
16061622 ReadDir {
16071623 inner : Arc :: new ( InnerReadDir { dirp, root : dummy_root } ) ,
16081624 #[ cfg( not( any(
1625+ target_os = "linux" ,
16091626 target_os = "solaris" ,
16101627 target_os = "illumos" ,
16111628 target_os = "fuchsia" ,
0 commit comments