about summary refs log tree commit diff
path: root/src/libstd/sys/windows
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2015-02-20 09:46:56 -0800
committerAlex Crichton <alex@alexcrichton.com>2015-02-20 11:51:22 -0800
commit756210a0b95f807e95189f1c608d8343ad68e66d (patch)
tree1815d5416407cbd46560e1d1f81b7ea908684a82 /src/libstd/sys/windows
parent522d09dfecbeca1595f25ac58c6d0178bbd21d7d (diff)
downloadrust-756210a0b95f807e95189f1c608d8343ad68e66d.tar.gz
rust-756210a0b95f807e95189f1c608d8343ad68e66d.zip
std: Ensure fs::{DirEntry, ReadDir} are Send/Sync
The windows/unix modules were currently inconsistent about the traits being
implemented for `DirEntry` and there isn't much particular reason why the traits
*couldn't* be implemented for `ReadDir` and `DirEntry`, so this commit ensures
that they are implemented.

Closes #22577
Diffstat (limited to 'src/libstd/sys/windows')
-rw-r--r--src/libstd/sys/windows/fs2.rs39
1 files changed, 27 insertions, 12 deletions
diff --git a/src/libstd/sys/windows/fs2.rs b/src/libstd/sys/windows/fs2.rs
index 8abcd90efe8..117f819eeeb 100644
--- a/src/libstd/sys/windows/fs2.rs
+++ b/src/libstd/sys/windows/fs2.rs
@@ -19,6 +19,7 @@ use libc::{self, HANDLE};
 use mem;
 use path::{Path, PathBuf};
 use ptr;
+use sync::Arc;
 use sys::handle::Handle as RawHandle;
 use sys::{c, cvt};
 use vec::Vec;
@@ -27,12 +28,20 @@ pub struct File { handle: RawHandle }
 pub struct FileAttr { data: c::WIN32_FILE_ATTRIBUTE_DATA }
 
 pub struct ReadDir {
-    handle: libc::HANDLE,
-    root: PathBuf,
+    handle: FindNextFileHandle,
+    root: Arc<PathBuf>,
     first: Option<libc::WIN32_FIND_DATAW>,
 }
 
-pub struct DirEntry { path: PathBuf }
+struct FindNextFileHandle(libc::HANDLE);
+
+unsafe impl Send for FindNextFileHandle {}
+unsafe impl Sync for FindNextFileHandle {}
+
+pub struct DirEntry {
+    root: Arc<PathBuf>,
+    data: libc::WIN32_FIND_DATAW,
+}
 
 #[derive(Clone, Default)]
 pub struct OpenOptions {
@@ -61,7 +70,7 @@ impl Iterator for ReadDir {
         unsafe {
             let mut wfd = mem::zeroed();
             loop {
-                if libc::FindNextFileW(self.handle, &mut wfd) == 0 {
+                if libc::FindNextFileW(self.handle.0, &mut wfd) == 0 {
                     if libc::GetLastError() ==
                         c::ERROR_NO_MORE_FILES as libc::DWORD {
                         return None
@@ -77,15 +86,15 @@ impl Iterator for ReadDir {
     }
 }
 
-impl Drop for ReadDir {
+impl Drop for FindNextFileHandle {
     fn drop(&mut self) {
-        let r = unsafe { libc::FindClose(self.handle) };
+        let r = unsafe { libc::FindClose(self.0) };
         debug_assert!(r != 0);
     }
 }
 
 impl DirEntry {
-    fn new(root: &Path, wfd: &libc::WIN32_FIND_DATAW) -> Option<DirEntry> {
+    fn new(root: &Arc<PathBuf>, wfd: &libc::WIN32_FIND_DATAW) -> Option<DirEntry> {
         match &wfd.cFileName[0..3] {
             // check for '.' and '..'
             [46, 0, ..] |
@@ -93,13 +102,15 @@ impl DirEntry {
             _ => {}
         }
 
-        let filename = super::truncate_utf16_at_nul(&wfd.cFileName);
-        let filename: OsString = OsStringExt::from_wide(filename);
-        Some(DirEntry { path: root.join(&filename) })
+        Some(DirEntry {
+            root: root.clone(),
+            data: *wfd,
+        })
     }
 
     pub fn path(&self) -> PathBuf {
-        self.path.clone()
+        let filename = super::truncate_utf16_at_nul(&self.data.cFileName);
+        self.root.join(&<OsString as OsStringExt>::from_wide(filename))
     }
 }
 
@@ -312,7 +323,11 @@ pub fn readdir(p: &Path) -> io::Result<ReadDir> {
         let mut wfd = mem::zeroed();
         let find_handle = libc::FindFirstFileW(path.as_ptr(), &mut wfd);
         if find_handle != libc::INVALID_HANDLE_VALUE {
-            Ok(ReadDir { handle: find_handle, root: root, first: Some(wfd) })
+            Ok(ReadDir {
+                handle: FindNextFileHandle(find_handle),
+                root: Arc::new(root),
+                first: Some(wfd),
+            })
         } else {
             Err(Error::last_os_error())
         }