Skip to content

Commit 8334dd4

Browse files
committed
native: Stop using readdir()
This function is not threadsafe, and is deprecated in favor of the threadsafe readdir_r variant. Closes #12692
1 parent fe50c75 commit 8334dd4

File tree

3 files changed

+29
-11
lines changed

3 files changed

+29
-11
lines changed

src/libnative/io/file_unix.rs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use std::libc;
1919
use std::mem;
2020
use std::rt::rtio;
2121
use std::vec;
22+
use std::vec_ng::Vec;
2223

2324
use io::{IoResult, retry, keep_going};
2425

@@ -341,7 +342,7 @@ pub fn mkdir(p: &CString, mode: io::FilePermission) -> IoResult<()> {
341342

342343
pub fn readdir(p: &CString) -> IoResult<~[Path]> {
343344
use std::libc::{dirent_t};
344-
use std::libc::{opendir, readdir, closedir};
345+
use std::libc::{opendir, readdir_r, closedir};
345346

346347
fn prune(root: &CString, dirs: ~[Path]) -> ~[Path] {
347348
let root = unsafe { CString::new(root.with_ref(|p| p), false) };
@@ -353,23 +354,28 @@ pub fn readdir(p: &CString) -> IoResult<~[Path]> {
353354
}
354355

355356
extern {
356-
fn rust_list_dir_val(ptr: *dirent_t) -> *libc::c_char;
357+
fn rust_dirent_t_size() -> libc::c_int;
358+
fn rust_list_dir_val(ptr: *mut dirent_t) -> *libc::c_char;
357359
}
358360

361+
let size = unsafe { rust_dirent_t_size() };
362+
let mut buf = Vec::<u8>::with_capacity(size as uint);
363+
let ptr = buf.as_mut_slice().as_mut_ptr() as *mut dirent_t;
364+
359365
debug!("os::list_dir -- BEFORE OPENDIR");
360366

361367
let dir_ptr = p.with_ref(|buf| unsafe { opendir(buf) });
362368

363369
if dir_ptr as uint != 0 {
364370
let mut paths = ~[];
365371
debug!("os::list_dir -- opendir() SUCCESS");
366-
let mut entry_ptr = unsafe { readdir(dir_ptr) };
367-
while entry_ptr as uint != 0 {
372+
let mut entry_ptr = 0 as *mut dirent_t;
373+
while unsafe { readdir_r(dir_ptr, ptr, &mut entry_ptr) == 0 } {
374+
if entry_ptr.is_null() { break }
368375
let cstr = unsafe {
369376
CString::new(rust_list_dir_val(entry_ptr), false)
370377
};
371378
paths.push(Path::new(cstr));
372-
entry_ptr = unsafe { readdir(dir_ptr) };
373379
}
374380
assert_eq!(unsafe { closedir(dir_ptr) }, 0);
375381
Ok(prune(p, paths))

src/libstd/libc.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3657,13 +3657,16 @@ pub mod funcs {
36573657
pub unsafe fn opendir(dirname: *c_char) -> *DIR {
36583658
rust_opendir(dirname)
36593659
}
3660-
pub unsafe fn readdir(dirp: *DIR) -> *dirent_t {
3661-
rust_readdir(dirp)
3660+
pub unsafe fn readdir_r(dirp: *DIR,
3661+
entry: *mut dirent_t,
3662+
result: *mut *mut dirent_t) -> c_int {
3663+
rust_readdir_r(dirp, entry, result)
36623664
}
36633665

36643666
extern {
36653667
fn rust_opendir(dirname: *c_char) -> *DIR;
3666-
fn rust_readdir(dirp: *DIR) -> *dirent_t;
3668+
fn rust_readdir_r(dirp: *DIR, entry: *mut dirent_t,
3669+
result: *mut *mut dirent_t) -> c_int;
36673670
}
36683671

36693672
extern {

src/rt/rust_builtin.c

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -279,9 +279,14 @@ rust_opendir(char *dirname) {
279279
return opendir(dirname);
280280
}
281281

282-
struct dirent*
283-
rust_readdir(DIR *dirp) {
284-
return readdir(dirp);
282+
int
283+
rust_readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result) {
284+
return readdir_r(dirp, entry, result);
285+
}
286+
287+
int
288+
rust_dirent_t_size() {
289+
return sizeof(struct dirent);
285290
}
286291

287292
#else
@@ -294,6 +299,10 @@ void
294299
rust_readdir() {
295300
}
296301

302+
void
303+
rust_dirent_t_size() {
304+
}
305+
297306
#endif
298307

299308
uintptr_t

0 commit comments

Comments
 (0)