@@ -5,7 +5,8 @@ use std::mem;
55use std:: os:: unix:: ffi:: OsStringExt ;
66use std:: os:: unix:: io:: { AsRawFd , FromRawFd , IntoRawFd , RawFd } ;
77use std:: path:: { Path , PathBuf } ;
8- use std:: sync:: atomic:: { AtomicI16 , AtomicI32 , AtomicI64 , Ordering } ;
8+
9+ use parking_lot:: { RwLock , RwLockReadGuard } ;
910
1011use crate :: list:: { open_dirfd, DirIter } ;
1112use crate :: metadata:: { self , Metadata } ;
@@ -36,18 +37,18 @@ pub const O_SEARCH: libc::c_int = 0;
3637///
3738/// Construct it either with ``Dir::cwd()`` or ``Dir::open(path)``
3839#[ derive( Debug ) ]
39- pub struct Dir ( AtomicRawFd ) ;
40+ pub struct Dir ( RwLock < RawFd > ) ;
4041
4142impl Dir {
4243 /// low level ctor, only used by builder and tests
4344 pub ( crate ) fn new ( fd : RawFd ) -> Self {
44- Dir ( AtomicRawFd :: new ( fd) )
45+ Dir ( RwLock :: new ( fd) )
4546 }
4647
4748 /// Gets the underlying RawFd from a Dir handle.
48- pub ( crate ) fn rawfd ( & self ) -> io:: Result < RawFd > {
49- let rawfd = self . 0 . load ( Ordering :: Acquire ) ;
50- if rawfd != -1 {
49+ pub ( crate ) fn rawfd ( & self ) -> io:: Result < RwLockReadGuard < RawFd > > {
50+ let rawfd = self . 0 . read ( ) ;
51+ if * rawfd != -1 {
5152 Ok ( rawfd)
5253 } else {
5354 Err ( io:: Error :: from_raw_os_error ( libc:: EBADF ) )
@@ -92,7 +93,7 @@ impl Dir {
9293 /// explicitly. Thats what 'is_dir()' is for. Returns 'true' when the underlying handles
9394 /// represents a directory and false otherwise.
9495 pub fn is_dir ( & self ) -> bool {
95- match fd_type ( self . 0 . load ( Ordering :: Acquire ) ) . unwrap_or ( FdType :: Other ) {
96+ match fd_type ( * self . 0 . read ( ) ) . unwrap_or ( FdType :: Other ) {
9697 FdType :: NormalDir | FdType :: OPathDir => true ,
9798 FdType :: Other => false ,
9899 }
@@ -113,7 +114,7 @@ impl Dir {
113114 /// Create a DirIter from a Dir
114115 /// Dir must not be a handle opened with O_PATH.
115116 pub fn list ( self ) -> io:: Result < DirIter > {
116- let fd = self . rawfd ( ) ?;
117+ let fd = * self . rawfd ( ) ?;
117118 std:: mem:: forget ( self ) ;
118119 open_dirfd ( fd)
119120 }
@@ -159,7 +160,7 @@ impl Dir {
159160 pub ( crate ) fn _sub_dir ( & self , path : & CStr , flags : libc:: c_int ) -> io:: Result < Dir > {
160161 Ok ( Dir :: new ( unsafe {
161162 libc_ok ( libc:: openat (
162- self . rawfd ( ) ?,
163+ * self . rawfd ( ) ?,
163164 path. as_ptr ( ) ,
164165 flags | O_DIRECTORY ,
165166 ) ) ?
@@ -175,7 +176,7 @@ impl Dir {
175176 let mut buf = vec ! [ 0u8 ; 4096 ] ;
176177 let res = unsafe {
177178 libc:: readlinkat (
178- self . rawfd ( ) ?,
179+ * self . rawfd ( ) ?,
179180 path. as_ptr ( ) ,
180181 buf. as_mut_ptr ( ) as * mut libc:: c_char ,
181182 buf. len ( ) ,
@@ -371,7 +372,7 @@ impl Dir {
371372 // promoted as they are in C this would break on Freebsd where
372373 // *mode_t* is an alias for `uint16_t`.
373374 let res = libc_ok ( libc:: openat (
374- self . rawfd ( ) ?,
375+ * self . rawfd ( ) ?,
375376 path. as_ptr ( ) ,
376377 flags | libc:: O_CLOEXEC | libc:: O_NOFOLLOW ,
377378 mode as libc:: c_uint ,
@@ -389,7 +390,7 @@ impl Dir {
389390
390391 fn _symlink ( & self , path : & CStr , link : & CStr ) -> io:: Result < ( ) > {
391392 unsafe {
392- let res = libc:: symlinkat ( link. as_ptr ( ) , self . rawfd ( ) ?, path. as_ptr ( ) ) ;
393+ let res = libc:: symlinkat ( link. as_ptr ( ) , * self . rawfd ( ) ?, path. as_ptr ( ) ) ;
393394 if res < 0 {
394395 Err ( io:: Error :: last_os_error ( ) )
395396 } else {
@@ -405,7 +406,7 @@ impl Dir {
405406
406407 fn _create_dir ( & self , path : & CStr , mode : libc:: mode_t ) -> io:: Result < ( ) > {
407408 unsafe {
408- libc_ok ( libc:: mkdirat ( self . rawfd ( ) ?, path. as_ptr ( ) , mode) ) ?;
409+ libc_ok ( libc:: mkdirat ( * self . rawfd ( ) ?, path. as_ptr ( ) , mode) ) ?;
409410 }
410411 Ok ( ( ) )
411412 }
@@ -448,7 +449,7 @@ impl Dir {
448449
449450 fn _unlink ( & self , path : & CStr , flags : libc:: c_int ) -> io:: Result < ( ) > {
450451 unsafe {
451- libc_ok ( libc:: unlinkat ( self . rawfd ( ) ?, path. as_ptr ( ) , flags) ) ?;
452+ libc_ok ( libc:: unlinkat ( * self . rawfd ( ) ?, path. as_ptr ( ) , flags) ) ?;
452453 }
453454 Ok ( ( ) )
454455 }
@@ -507,7 +508,7 @@ impl Dir {
507508 #[ cfg( feature = "proc_self_fd" ) ]
508509 pub fn recover_path ( & self ) -> io:: Result < PathBuf > {
509510 let fd = self . rawfd ( ) ?;
510- if fd != libc:: AT_FDCWD {
511+ if * fd != libc:: AT_FDCWD {
511512 read_link ( format ! ( "/proc/self/fd/{}" , fd) )
512513 } else {
513514 read_link ( "/proc/self/cwd" )
@@ -529,7 +530,7 @@ impl Dir {
529530 unsafe {
530531 let mut stat = mem:: zeroed ( ) ; // TODO(cehteh): uninit
531532 libc_ok ( libc:: fstatat (
532- self . rawfd ( ) ?,
533+ * self . rawfd ( ) ?,
533534 path. as_ptr ( ) ,
534535 & mut stat,
535536 flags,
@@ -542,7 +543,7 @@ impl Dir {
542543 pub fn self_metadata ( & self ) -> io:: Result < Metadata > {
543544 unsafe {
544545 let mut stat = mem:: zeroed ( ) ; // TODO(cehteh): uninit
545- libc_ok ( libc:: fstat ( self . rawfd ( ) ?, & mut stat) ) ?;
546+ libc_ok ( libc:: fstat ( * self . rawfd ( ) ?, & mut stat) ) ?;
546547 Ok ( metadata:: new ( stat) )
547548 }
548549 }
@@ -563,25 +564,26 @@ impl Dir {
563564 /// Creates a new independently owned handle to the underlying directory.
564565 /// The new handle has the same (Normal/O_PATH) semantics as the original handle.
565566 pub fn try_clone ( & self ) -> io:: Result < Self > {
566- Ok ( Dir :: new ( clone_dirfd ( self . rawfd ( ) ?) ?) )
567+ Ok ( Dir :: new ( clone_dirfd ( * self . rawfd ( ) ?) ?) )
567568 }
568569
569570 /// Creates a new 'Normal' independently owned handle to the underlying directory.
570571 pub fn clone_upgrade ( & self ) -> io:: Result < Self > {
571- Ok ( Dir :: new ( clone_dirfd_upgrade ( self . rawfd ( ) ?, 0 ) ?) )
572+ Ok ( Dir :: new ( clone_dirfd_upgrade ( * self . rawfd ( ) ?, 0 ) ?) )
572573 }
573574
574575 /// Creates a new 'O_PATH' restricted independently owned handle to the underlying directory.
575576 pub fn clone_downgrade ( & self ) -> io:: Result < Self > {
576- Ok ( Dir :: new ( clone_dirfd_downgrade ( self . rawfd ( ) ?) ?) )
577+ Ok ( Dir :: new ( clone_dirfd_downgrade ( * self . rawfd ( ) ?) ?) )
577578 }
578579
579580 /// Explicit closing of a file handle. The object stays alive but all operations on it will fail.
580581 pub fn close ( & self ) {
581- let fd = self . 0 . swap ( - 1 , Ordering :: AcqRel ) ;
582- if fd != libc:: AT_FDCWD && fd != -1 {
582+ let mut fd = self . 0 . write ( ) ;
583+ if * fd != libc:: AT_FDCWD && * fd != -1 {
583584 unsafe {
584- libc:: close ( fd) ;
585+ libc:: close ( * fd) ;
586+ * fd = -1 ;
585587 }
586588 }
587589 }
@@ -726,9 +728,9 @@ where
726728fn _rename ( old_dir : & Dir , old : & CStr , new_dir : & Dir , new : & CStr ) -> io:: Result < ( ) > {
727729 unsafe {
728730 libc_ok ( libc:: renameat (
729- old_dir. rawfd ( ) ?,
731+ * old_dir. rawfd ( ) ?,
730732 old. as_ptr ( ) ,
731- new_dir. rawfd ( ) ?,
733+ * new_dir. rawfd ( ) ?,
732734 new. as_ptr ( ) ,
733735 ) ) ?;
734736 }
@@ -766,9 +768,9 @@ fn _hardlink(
766768) -> io:: Result < ( ) > {
767769 unsafe {
768770 libc_ok ( libc:: linkat (
769- old_dir. rawfd ( ) ?,
771+ * old_dir. rawfd ( ) ?,
770772 old. as_ptr ( ) ,
771- new_dir. rawfd ( ) ?,
773+ * new_dir. rawfd ( ) ?,
772774 new. as_ptr ( ) ,
773775 flags,
774776 ) ) ?;
@@ -831,7 +833,7 @@ fn _rename_flags(
831833impl AsRawFd for Dir {
832834 #[ inline]
833835 fn as_raw_fd ( & self ) -> RawFd {
834- self . 0 . load ( Ordering :: Acquire )
836+ * self . 0 . read ( )
835837 }
836838}
837839
@@ -847,7 +849,7 @@ impl FromRawFd for Dir {
847849impl IntoRawFd for Dir {
848850 #[ inline]
849851 fn into_raw_fd ( self ) -> RawFd {
850- let result = self . 0 . load ( Ordering :: Acquire ) ;
852+ let result = * self . 0 . read ( ) ;
851853 mem:: forget ( self ) ;
852854 result
853855 }
@@ -864,26 +866,6 @@ pub(crate) fn to_cstr<P: AsPath>(path: P) -> io::Result<P::Buffer> {
864866 . ok_or_else ( || io:: Error :: new ( io:: ErrorKind :: InvalidInput , "nul byte in file name" ) )
865867}
866868
867- // For the esoteric platforms where c_int is not i32,
868- // make the RawFd/c_int atomic in a portable way
869- trait Atomic {
870- type T ;
871- }
872-
873- impl Atomic for i16 {
874- type T = AtomicI16 ;
875- }
876-
877- impl Atomic for i32 {
878- type T = AtomicI32 ;
879- }
880-
881- impl Atomic for i64 {
882- type T = AtomicI64 ;
883- }
884-
885- type AtomicRawFd = <RawFd as Atomic >:: T ;
886-
887869#[ cfg( test) ]
888870mod test {
889871 use std:: io:: Read ;
0 commit comments