about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2014-03-04 17:27:43 -0800
committerAlex Crichton <alex@alexcrichton.com>2014-03-05 09:11:10 -0800
commit8334dd445fb10089a68808e7895f0c00d6fd0b3e (patch)
treee6886b691e2cd20d65211444b5993e55076fff2b
parentfe50c75d02c9b41bcda28596077b1122a89bee5d (diff)
downloadrust-8334dd445fb10089a68808e7895f0c00d6fd0b3e.tar.gz
rust-8334dd445fb10089a68808e7895f0c00d6fd0b3e.zip
native: Stop using readdir()
This function is not threadsafe, and is deprecated in favor of the threadsafe
readdir_r variant.

Closes #12692
-rw-r--r--src/libnative/io/file_unix.rs16
-rw-r--r--src/libstd/libc.rs9
-rw-r--r--src/rt/rust_builtin.c15
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::<u8>::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