Skip to content

Commit a69a2ac

Browse files
olsonjefferybrson
authored andcommitted
rt/core: port os::list_dir to rust ref rust-lang#4812
1 parent 53db6c7 commit a69a2ac

File tree

9 files changed

+174
-86
lines changed

9 files changed

+174
-86
lines changed

src/libcore/libc.rs

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -534,6 +534,7 @@ pub mod types {
534534

535535
pub type LPCWSTR = *WCHAR;
536536
pub type LPCSTR = *CHAR;
537+
pub type LPCTSTR = *CHAR;
537538
pub type LPTCH = *CHAR;
538539

539540
pub type LPWSTR = *mut WCHAR;
@@ -793,6 +794,7 @@ pub mod consts {
793794

794795
pub const ERROR_SUCCESS : int = 0;
795796
pub const ERROR_INSUFFICIENT_BUFFER : int = 122;
797+
pub const INVALID_HANDLE_VALUE: int = -1;
796798
}
797799
}
798800

@@ -1116,6 +1118,7 @@ pub mod funcs {
11161118
pub mod string {
11171119
use libc::types::common::c95::c_void;
11181120
use libc::types::os::arch::c95::{c_char, c_int, size_t};
1121+
use libc::types::os::arch::c95::{wchar_t};
11191122

11201123
pub extern {
11211124
unsafe fn strcpy(dst: *c_char, src: *c_char) -> *c_char;
@@ -1139,6 +1142,7 @@ pub mod funcs {
11391142
unsafe fn strtok(s: *c_char, t: *c_char) -> *c_char;
11401143
unsafe fn strxfrm(s: *c_char, ct: *c_char, n: size_t)
11411144
-> size_t;
1145+
unsafe fn wcslen(buf: *wchar_t) -> size_t;
11421146

11431147
// These are fine to execute on the Rust stack. They must be,
11441148
// in fact, because LLVM generates calls to them!
@@ -1382,9 +1386,28 @@ pub mod funcs {
13821386
use libc::types::os::arch::c95::{c_char, c_int, c_long};
13831387

13841388
pub extern {
1389+
// default bindings for opendir and readdir in
1390+
// non-macos unix
1391+
#[cfg(target_os = "linux")]
1392+
#[cfg(target_os = "android")]
1393+
#[cfg(target_os = "freebsd")]
13851394
unsafe fn opendir(dirname: *c_char) -> *DIR;
1386-
unsafe fn closedir(dirp: *DIR) -> c_int;
1395+
#[cfg(target_os = "linux")]
1396+
#[cfg(target_os = "android")]
1397+
#[cfg(target_os = "freebsd")]
13871398
unsafe fn readdir(dirp: *DIR) -> *dirent_t;
1399+
// on OSX (particularly when running with a
1400+
// 64bit kernel), we have an issue where there
1401+
// are separate bindings for opendir and readdir,
1402+
// which we have to explicitly link, as below.
1403+
#[cfg(target_os = "macos")]
1404+
#[link_name = "opendir$INODE64"]
1405+
unsafe fn opendir(dirname: *c_char) -> *DIR;
1406+
#[cfg(target_os = "macos")]
1407+
#[link_name = "readdir$INODE64"]
1408+
unsafe fn readdir(dirp: *DIR) -> *dirent_t;
1409+
1410+
unsafe fn closedir(dirp: *DIR) -> c_int;
13881411
unsafe fn rewinddir(dirp: *DIR);
13891412
unsafe fn seekdir(dirp: *DIR, loc: c_long);
13901413
unsafe fn telldir(dirp: *DIR) -> c_long;
@@ -1597,6 +1620,7 @@ pub mod funcs {
15971620
use libc::types::os::arch::extra::{BOOL, DWORD, HMODULE};
15981621
use libc::types::os::arch::extra::{LPCWSTR, LPWSTR, LPTCH};
15991622
use libc::types::os::arch::extra::{LPSECURITY_ATTRIBUTES};
1623+
use libc::types::os::arch::extra::{HANDLE};
16001624

16011625
#[abi = "stdcall"]
16021626
pub extern {
@@ -1626,6 +1650,13 @@ pub mod funcs {
16261650
unsafe fn SetCurrentDirectoryW(lpPathName: LPCWSTR) -> BOOL;
16271651

16281652
unsafe fn GetLastError() -> DWORD;
1653+
unsafe fn FindFirstFileW(fileName: *u16,
1654+
findFileData: HANDLE)
1655+
-> HANDLE;
1656+
unsafe fn FindNextFileW(findFile: HANDLE,
1657+
findFileData: HANDLE)
1658+
-> BOOL;
1659+
unsafe fn FindClose(findFile: HANDLE) -> BOOL;
16291660
}
16301661
}
16311662

src/libcore/os.rs

Lines changed: 88 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,8 @@ pub mod rustrt {
5858
pub extern {
5959
unsafe fn rust_get_argc() -> c_int;
6060
unsafe fn rust_get_argv() -> **c_char;
61-
unsafe fn rust_getcwd() -> ~str;
6261
unsafe fn rust_path_is_dir(path: *libc::c_char) -> c_int;
6362
unsafe fn rust_path_exists(path: *libc::c_char) -> c_int;
64-
unsafe fn rust_list_files2(&&path: ~str) -> ~[~str];
6563
unsafe fn rust_process_wait(handle: c_int) -> c_int;
6664
unsafe fn rust_set_exit_status(code: libc::intptr_t);
6765
}
@@ -670,13 +668,95 @@ pub fn make_dir(p: &Path, mode: c_int) -> bool {
670668
#[allow(non_implicitly_copyable_typarams)]
671669
pub fn list_dir(p: &Path) -> ~[~str] {
672670
unsafe {
673-
#[cfg(unix)]
674-
fn star(p: &Path) -> Path { copy *p }
675-
671+
#[cfg(target_os = "linux")]
672+
#[cfg(target_os = "android")]
673+
#[cfg(target_os = "freebsd")]
674+
#[cfg(target_os = "macos")]
675+
unsafe fn get_list(p: &Path) -> ~[~str] {
676+
use libc::{DIR, dirent_t};
677+
use libc::{opendir, readdir, closedir};
678+
extern mod rustrt {
679+
unsafe fn rust_list_dir_val(ptr: *dirent_t)
680+
-> *libc::c_char;
681+
}
682+
let input = p.to_str();
683+
let mut strings = ~[];
684+
let input_ptr = ::cast::transmute(&input[0]);
685+
log(debug, "os::list_dir -- BEFORE OPENDIR");
686+
let dir_ptr = opendir(input_ptr);
687+
if (dir_ptr as uint != 0) {
688+
log(debug, "os::list_dir -- opendir() SUCCESS");
689+
let mut entry_ptr = readdir(dir_ptr);
690+
while (entry_ptr as uint != 0) {
691+
strings.push(
692+
str::raw::from_c_str(
693+
rustrt::rust_list_dir_val(
694+
entry_ptr)));
695+
entry_ptr = readdir(dir_ptr);
696+
}
697+
closedir(dir_ptr);
698+
}
699+
else {
700+
log(debug, "os::list_dir -- opendir() FAILURE");
701+
}
702+
log(debug, fmt!("os::list_dir -- AFTER ITERATION -- # of results: %?", strings.len()));
703+
strings
704+
}
676705
#[cfg(windows)]
677-
fn star(p: &Path) -> Path { p.push("*") }
678-
679-
do rustrt::rust_list_files2(star(p).to_str()).filtered |filename| {
706+
unsafe fn get_list(p: &Path) -> ~[~str] {
707+
use libc::types::os::arch::extra::{LPCTSTR, HANDLE, BOOL};
708+
use libc::consts::os::extra::INVALID_HANDLE_VALUE;
709+
use libc::wcslen;
710+
use libc::funcs::extra::kernel32::{
711+
FindFirstFileW,
712+
FindNextFileW,
713+
FindClose,
714+
};
715+
use os::win32::{
716+
as_utf16_p
717+
};
718+
use private::exchange_alloc::{malloc_raw, free_raw};
719+
#[nolink]
720+
extern mod rustrt {
721+
unsafe fn rust_list_dir_wfd_size() -> libc::size_t;
722+
unsafe fn rust_list_dir_wfd_fp_buf(wfd: *libc::c_void)
723+
-> *u16;
724+
}
725+
fn star(p: &Path) -> Path { p.push("*") }
726+
do as_utf16_p(star(p).to_str()) |path_ptr| {
727+
let mut strings = ~[];
728+
let wfd_ptr = malloc_raw(
729+
rustrt::rust_list_dir_wfd_size() as uint);
730+
let find_handle =
731+
FindFirstFileW(
732+
path_ptr,
733+
::cast::transmute(wfd_ptr));
734+
if find_handle as int != INVALID_HANDLE_VALUE {
735+
let mut more_files = 1 as libc::c_int;
736+
while more_files != 0 {
737+
let fp_buf = rustrt::rust_list_dir_wfd_fp_buf(
738+
wfd_ptr);
739+
if fp_buf as uint == 0 {
740+
fail!(~"os::list_dir() failure:"+
741+
~" got null ptr from wfd");
742+
}
743+
else {
744+
let fp_vec = vec::from_buf(
745+
fp_buf, wcslen(fp_buf) as uint);
746+
let fp_str = str::from_utf16(fp_vec);
747+
strings.push(fp_str);
748+
}
749+
more_files = FindNextFileW(
750+
find_handle,
751+
::cast::transmute(wfd_ptr));
752+
}
753+
FindClose(find_handle);
754+
free_raw(wfd_ptr);
755+
}
756+
strings
757+
}
758+
}
759+
do get_list(p).filtered |filename| {
680760
*filename != ~"." && *filename != ~".."
681761
}
682762
}

src/libcore/ptr.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ use sys;
1818

1919
#[cfg(test)] use vec;
2020
#[cfg(test)] use str;
21-
#[cfg(test)] use uint;
22-
#[cfg(test)] use debug;
2321
#[cfg(notest)] use cmp::{Eq, Ord};
22+
use debug;
23+
use uint;
2424

2525
pub mod libc_ {
2626
use libc::c_void;
@@ -504,6 +504,7 @@ pub mod ptr_tests {
504504
}
505505
#[test]
506506
#[should_fail]
507+
#[ignore(cfg(windows))]
507508
pub fn test_ptr_array_each_with_len_null_ptr() {
508509
unsafe {
509510
ptr::array_each_with_len(0 as **libc::c_char, 1, |e| {
@@ -513,6 +514,7 @@ pub mod ptr_tests {
513514
}
514515
#[test]
515516
#[should_fail]
517+
#[ignore(cfg(windows))]
516518
pub fn test_ptr_array_each_null_ptr() {
517519
unsafe {
518520
ptr::array_each(0 as **libc::c_char, |e| {

src/libcore/unstable/exchange_alloc.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,17 @@ pub unsafe fn malloc(td: *TypeDesc, size: uint) -> *c_void {
4141
return transmute(box);
4242
}
4343
}
44+
/**
45+
Thin wrapper around libc::malloc, none of the box header
46+
stuff in exchange_alloc::malloc
47+
*/
48+
pub unsafe fn malloc_raw(size: uint) -> *c_void {
49+
let p = c_malloc(size as size_t);
50+
if p.is_null() {
51+
fail!(~"Failure in malloc_raw: result ptr is null");
52+
}
53+
p
54+
}
4455

4556
pub unsafe fn free(ptr: *c_void) {
4657
let exchange_count = &mut *rust_get_exchange_count_ptr();
@@ -49,6 +60,10 @@ pub unsafe fn free(ptr: *c_void) {
4960
fail_unless!(ptr.is_not_null());
5061
c_free(ptr);
5162
}
63+
///Thin wrapper around libc::free, as with exchange_alloc::malloc_raw
64+
pub unsafe fn free_raw(ptr: *c_void) {
65+
c_free(ptr);
66+
}
5267

5368
fn get_box_size(body_size: uint, body_align: uint) -> uint {
5469
let header_size = size_of::<BoxHeaderRepr>();

src/rt/rust_builtin.cpp

Lines changed: 30 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -247,49 +247,43 @@ debug_get_stk_seg() {
247247
return task->stk;
248248
}
249249

250-
extern "C" CDECL rust_vec_box*
251-
rust_list_files(rust_str *path) {
252-
rust_task *task = rust_get_current_task();
253-
array_list<rust_str*> strings;
250+
extern "C" CDECL char*
254251
#if defined(__WIN32__)
255-
WIN32_FIND_DATA FindFileData;
256-
HANDLE hFind = FindFirstFile((char*)path->body.data, &FindFileData);
257-
if (hFind != INVALID_HANDLE_VALUE) {
258-
do {
259-
rust_str *str = make_str(task->kernel, FindFileData.cFileName,
260-
strlen(FindFileData.cFileName),
261-
"list_files_str");
262-
strings.push(str);
263-
} while (FindNextFile(hFind, &FindFileData));
264-
FindClose(hFind);
265-
}
252+
rust_list_dir_val(WIN32_FIND_DATA* entry_ptr) {
253+
return entry_ptr->cFileName;
254+
}
266255
#else
267-
DIR *dirp = opendir((char*)path->body.data);
268-
if (dirp) {
269-
struct dirent *dp;
270-
while ((dp = readdir(dirp))) {
271-
rust_vec_box *str = make_str(task->kernel, dp->d_name,
272-
strlen(dp->d_name),
273-
"list_files_str");
274-
strings.push(str);
275-
}
276-
closedir(dirp);
277-
}
256+
rust_list_dir_val(dirent* entry_ptr) {
257+
return entry_ptr->d_name;
258+
}
278259
#endif
279260

280-
rust_vec_box *vec = (rust_vec_box *)
281-
task->kernel->malloc(vec_size<rust_vec_box*>(strings.size()),
282-
"list_files_vec");
283-
size_t alloc_sz = sizeof(rust_vec*) * strings.size();
284-
vec->body.fill = vec->body.alloc = alloc_sz;
285-
memcpy(&vec->body.data[0], strings.data(), alloc_sz);
286-
return vec;
261+
extern "C" CDECL size_t
262+
#if defined(__WIN32__)
263+
rust_list_dir_wfd_size() {
264+
return sizeof(WIN32_FIND_DATAW);
265+
}
266+
#else
267+
rust_list_dir_wfd_size() {
268+
return 0;
287269
}
270+
#endif
288271

289-
extern "C" CDECL rust_vec_box*
290-
rust_list_files2(rust_str **path) {
291-
return rust_list_files(*path);
272+
extern "C" CDECL void*
273+
#if defined(__WIN32__)
274+
rust_list_dir_wfd_fp_buf(WIN32_FIND_DATAW* wfd) {
275+
if(wfd == NULL) {
276+
return 0;
277+
}
278+
else {
279+
return wfd->cFileName;
280+
}
292281
}
282+
#else
283+
rust_list_dir_wfd_fp_buf(void* wfd) {
284+
return 0;
285+
}
286+
#endif
293287

294288
extern "C" CDECL int
295289
rust_path_is_dir(char *path) {

src/rt/rust_util.h

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -79,38 +79,6 @@ inline void reserve_vec_exact(rust_vec_box** vpp,
7979

8080
typedef rust_vec_box rust_str;
8181

82-
inline rust_str *
83-
make_str(rust_kernel* kernel, const char* c, size_t strlen,
84-
const char* name) {
85-
size_t str_fill = strlen + 1;
86-
size_t str_alloc = str_fill;
87-
rust_str *str = (rust_str *)
88-
kernel->malloc(vec_size<char>(str_fill), name);
89-
str->header.td = &str_body_tydesc;
90-
str->body.fill = str_fill;
91-
str->body.alloc = str_alloc;
92-
memcpy(&str->body.data, c, strlen);
93-
str->body.data[strlen] = '\0';
94-
return str;
95-
}
96-
97-
inline rust_vec_box *
98-
make_str_vec(rust_kernel* kernel, size_t nstrs, char **strs) {
99-
rust_vec_box *v = (rust_vec_box *)
100-
kernel->malloc(vec_size<rust_vec_box*>(nstrs),
101-
"str vec interior");
102-
// FIXME: should have a real td (Issue #2639)
103-
v->header.td = NULL;
104-
v->body.fill = v->body.alloc = sizeof(rust_vec_box*) * nstrs;
105-
for (size_t i = 0; i < nstrs; ++i) {
106-
rust_str *str = make_str(kernel, strs[i],
107-
strlen(strs[i]),
108-
"str");
109-
((rust_str**)&v->body.data)[i] = str;
110-
}
111-
return v;
112-
}
113-
11482
inline size_t get_box_size(size_t body_size, size_t body_align) {
11583
size_t header_size = sizeof(rust_opaque_box);
11684
// FIXME (#2699): This alignment calculation is suspicious. Is it right?

src/rt/rustrt.def.in

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,9 @@ rust_path_exists
3232
rust_get_stdin
3333
rust_get_stdout
3434
rust_get_stderr
35-
rust_list_files
36-
rust_list_files2
35+
rust_list_dir_val
36+
rust_list_dir_wfd_size
37+
rust_list_dir_wfd_fp_buf
3738
rust_log_console_on
3839
rust_log_console_off
3940
rust_process_wait

src/test/run-pass/conditional-compile.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,8 @@ mod test_foreign_items {
112112
#[abi = "cdecl"]
113113
pub extern {
114114
#[cfg(bogus)]
115-
pub fn rust_getcwd() -> ~str;
116-
pub fn rust_getcwd() -> ~str;
115+
pub fn rust_get_stdin() -> ~str;
116+
pub fn rust_get_stdin() -> ~str;
117117
}
118118
}
119119
}

0 commit comments

Comments
 (0)