From 8334dd445fb10089a68808e7895f0c00d6fd0b3e Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 4 Mar 2014 17:27:43 -0800 Subject: [PATCH] native: Stop using readdir() This function is not threadsafe, and is deprecated in favor of the threadsafe readdir_r variant. Closes #12692 --- src/libnative/io/file_unix.rs | 16 +++++++++++----- src/libstd/libc.rs | 9 ++++++--- src/rt/rust_builtin.c | 15 ++++++++++++--- 3 files changed, 29 insertions(+), 11 deletions(-) diff --git a/src/libnative/io/file_unix.rs b/src/libnative/io/file_unix.rs index 4b6d1813ffa..cf9ada97a32 100644 --- a/src/libnative/io/file_unix.rs +++ b/src/libnative/io/file_unix.rs @@ -19,6 +19,7 @@ use std::libc; use std::mem; use std::rt::rtio; use std::vec; +use std::vec_ng::Vec; use io::{IoResult, retry, keep_going}; @@ -341,7 +342,7 @@ pub fn mkdir(p: &CString, mode: io::FilePermission) -> IoResult<()> { pub fn readdir(p: &CString) -> IoResult<~[Path]> { use std::libc::{dirent_t}; - use std::libc::{opendir, readdir, closedir}; + use std::libc::{opendir, readdir_r, closedir}; fn prune(root: &CString, dirs: ~[Path]) -> ~[Path] { let root = unsafe { CString::new(root.with_ref(|p| p), false) }; @@ -353,9 +354,14 @@ pub fn readdir(p: &CString) -> IoResult<~[Path]> { } extern { - fn rust_list_dir_val(ptr: *dirent_t) -> *libc::c_char; + fn rust_dirent_t_size() -> libc::c_int; + fn rust_list_dir_val(ptr: *mut dirent_t) -> *libc::c_char; } + let size = unsafe { rust_dirent_t_size() }; + let mut buf = Vec::::with_capacity(size as uint); + let ptr = buf.as_mut_slice().as_mut_ptr() as *mut dirent_t; + debug!("os::list_dir -- BEFORE OPENDIR"); let dir_ptr = p.with_ref(|buf| unsafe { opendir(buf) }); @@ -363,13 +369,13 @@ pub fn readdir(p: &CString) -> IoResult<~[Path]> { if dir_ptr as uint != 0 { let mut paths = ~[]; debug!("os::list_dir -- opendir() SUCCESS"); - let mut entry_ptr = unsafe { readdir(dir_ptr) }; - while entry_ptr as uint != 0 { + let mut entry_ptr = 0 as *mut dirent_t; + while unsafe { readdir_r(dir_ptr, ptr, &mut entry_ptr) == 0 } { + if entry_ptr.is_null() { break } let cstr = unsafe { CString::new(rust_list_dir_val(entry_ptr), false) }; paths.push(Path::new(cstr)); - entry_ptr = unsafe { readdir(dir_ptr) }; } assert_eq!(unsafe { closedir(dir_ptr) }, 0); Ok(prune(p, paths)) diff --git a/src/libstd/libc.rs b/src/libstd/libc.rs index ef641bbb665..7096765d9fc 100644 --- a/src/libstd/libc.rs +++ b/src/libstd/libc.rs @@ -3657,13 +3657,16 @@ pub mod funcs { pub unsafe fn opendir(dirname: *c_char) -> *DIR { rust_opendir(dirname) } - pub unsafe fn readdir(dirp: *DIR) -> *dirent_t { - rust_readdir(dirp) + pub unsafe fn readdir_r(dirp: *DIR, + entry: *mut dirent_t, + result: *mut *mut dirent_t) -> c_int { + rust_readdir_r(dirp, entry, result) } extern { fn rust_opendir(dirname: *c_char) -> *DIR; - fn rust_readdir(dirp: *DIR) -> *dirent_t; + fn rust_readdir_r(dirp: *DIR, entry: *mut dirent_t, + result: *mut *mut dirent_t) -> c_int; } extern { diff --git a/src/rt/rust_builtin.c b/src/rt/rust_builtin.c index 81eba2984da..6ba121c5d2d 100644 --- a/src/rt/rust_builtin.c +++ b/src/rt/rust_builtin.c @@ -279,9 +279,14 @@ rust_opendir(char *dirname) { return opendir(dirname); } -struct dirent* -rust_readdir(DIR *dirp) { - return readdir(dirp); +int +rust_readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result) { + return readdir_r(dirp, entry, result); +} + +int +rust_dirent_t_size() { + return sizeof(struct dirent); } #else @@ -294,6 +299,10 @@ void rust_readdir() { } +void +rust_dirent_t_size() { +} + #endif uintptr_t