1
Fork 0

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
This commit is contained in:
Alex Crichton 2015-02-20 09:46:56 -08:00
parent 522d09dfec
commit 756210a0b9
3 changed files with 76 additions and 25 deletions

View file

@ -18,7 +18,7 @@ use libc::{self, c_int, c_void, size_t, off_t, c_char, mode_t};
use mem;
use path::{Path, PathBuf};
use ptr;
use rc::Rc;
use sync::Arc;
use sys::fd::FileDesc;
use sys::{c, cvt, cvt_r};
use sys_common::FromInner;
@ -31,14 +31,18 @@ pub struct FileAttr {
}
pub struct ReadDir {
dirp: *mut libc::DIR,
root: Rc<PathBuf>,
dirp: Dir,
root: Arc<PathBuf>,
}
struct Dir(*mut libc::DIR);
unsafe impl Send for Dir {}
unsafe impl Sync for Dir {}
pub struct DirEntry {
buf: Vec<u8>,
dirent: *mut libc::dirent_t,
root: Rc<PathBuf>,
buf: Vec<u8>, // actually *mut libc::dirent_t
root: Arc<PathBuf>,
}
#[derive(Clone)]
@ -109,7 +113,7 @@ impl Iterator for ReadDir {
let mut entry_ptr = ptr::null_mut();
loop {
if unsafe { libc::readdir_r(self.dirp, ptr, &mut entry_ptr) != 0 } {
if unsafe { libc::readdir_r(self.dirp.0, ptr, &mut entry_ptr) != 0 } {
return Some(Err(Error::last_os_error()))
}
if entry_ptr.is_null() {
@ -118,7 +122,6 @@ impl Iterator for ReadDir {
let entry = DirEntry {
buf: buf,
dirent: entry_ptr,
root: self.root.clone()
};
if entry.name_bytes() == b"." || entry.name_bytes() == b".." {
@ -130,9 +133,9 @@ impl Iterator for ReadDir {
}
}
impl Drop for ReadDir {
impl Drop for Dir {
fn drop(&mut self) {
let r = unsafe { libc::closedir(self.dirp) };
let r = unsafe { libc::closedir(self.0) };
debug_assert_eq!(r, 0);
}
}
@ -147,9 +150,13 @@ impl DirEntry {
fn rust_list_dir_val(ptr: *mut libc::dirent_t) -> *const c_char;
}
unsafe {
CStr::from_ptr(rust_list_dir_val(self.dirent)).to_bytes()
CStr::from_ptr(rust_list_dir_val(self.dirent())).to_bytes()
}
}
fn dirent(&self) -> *mut libc::dirent_t {
self.buf.as_ptr() as *mut _
}
}
impl OpenOptions {
@ -279,14 +286,14 @@ pub fn mkdir(p: &Path) -> io::Result<()> {
}
pub fn readdir(p: &Path) -> io::Result<ReadDir> {
let root = Rc::new(p.to_path_buf());
let root = Arc::new(p.to_path_buf());
let p = try!(cstr(p));
unsafe {
let ptr = libc::opendir(p.as_ptr());
if ptr.is_null() {
Err(Error::last_os_error())
} else {
Ok(ReadDir { dirp: ptr, root: root })
Ok(ReadDir { dirp: Dir(ptr), root: root })
}
}
}