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:
parent
522d09dfec
commit
756210a0b9
3 changed files with 76 additions and 25 deletions
|
@ -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 })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue