diff --git a/src/libcore/libc.rs b/src/libcore/libc.rs index 9a45ffc5b2e..7f293b98e24 100644 --- a/src/libcore/libc.rs +++ b/src/libcore/libc.rs @@ -534,6 +534,7 @@ pub mod extra { pub type LPCWSTR = *WCHAR; pub type LPCSTR = *CHAR; + pub type LPCTSTR = *CHAR; pub type LPTCH = *CHAR; pub type LPWSTR = *mut WCHAR; @@ -793,6 +794,7 @@ pub mod extra { pub const ERROR_SUCCESS : int = 0; pub const ERROR_INSUFFICIENT_BUFFER : int = 122; + pub const INVALID_HANDLE_VALUE: int = -1; } } @@ -1116,6 +1118,7 @@ unsafe fn strtoul(s: *c_char, endp: **c_char, base: c_int) pub mod string { use libc::types::common::c95::c_void; use libc::types::os::arch::c95::{c_char, c_int, size_t}; + use libc::types::os::arch::c95::{wchar_t}; pub extern { unsafe fn strcpy(dst: *c_char, src: *c_char) -> *c_char; @@ -1139,6 +1142,7 @@ unsafe fn strncmp(cs: *c_char, ct: *c_char, n: size_t) unsafe fn strtok(s: *c_char, t: *c_char) -> *c_char; unsafe fn strxfrm(s: *c_char, ct: *c_char, n: size_t) -> size_t; + unsafe fn wcslen(buf: *wchar_t) -> size_t; // These are fine to execute on the Rust stack. They must be, // in fact, because LLVM generates calls to them! @@ -1382,9 +1386,28 @@ pub mod dirent { use libc::types::os::arch::c95::{c_char, c_int, c_long}; pub extern { + // default bindings for opendir and readdir in + // non-macos unix + #[cfg(target_os = "linux")] + #[cfg(target_os = "android")] + #[cfg(target_os = "freebsd")] unsafe fn opendir(dirname: *c_char) -> *DIR; - unsafe fn closedir(dirp: *DIR) -> c_int; + #[cfg(target_os = "linux")] + #[cfg(target_os = "android")] + #[cfg(target_os = "freebsd")] unsafe fn readdir(dirp: *DIR) -> *dirent_t; + // on OSX (particularly when running with a + // 64bit kernel), we have an issue where there + // are separate bindings for opendir and readdir, + // which we have to explicitly link, as below. + #[cfg(target_os = "macos")] + #[link_name = "opendir$INODE64"] + unsafe fn opendir(dirname: *c_char) -> *DIR; + #[cfg(target_os = "macos")] + #[link_name = "readdir$INODE64"] + unsafe fn readdir(dirp: *DIR) -> *dirent_t; + + unsafe fn closedir(dirp: *DIR) -> c_int; unsafe fn rewinddir(dirp: *DIR); unsafe fn seekdir(dirp: *DIR, loc: c_long); unsafe fn telldir(dirp: *DIR) -> c_long; @@ -1597,6 +1620,7 @@ pub mod kernel32 { use libc::types::os::arch::extra::{BOOL, DWORD, HMODULE}; use libc::types::os::arch::extra::{LPCWSTR, LPWSTR, LPTCH}; use libc::types::os::arch::extra::{LPSECURITY_ATTRIBUTES}; + use libc::types::os::arch::extra::{HANDLE}; #[abi = "stdcall"] pub extern { @@ -1626,6 +1650,13 @@ unsafe fn CopyFileW(lpExistingFileName: LPCWSTR, unsafe fn SetCurrentDirectoryW(lpPathName: LPCWSTR) -> BOOL; unsafe fn GetLastError() -> DWORD; + unsafe fn FindFirstFileW(fileName: *u16, + findFileData: HANDLE) + -> HANDLE; + unsafe fn FindNextFileW(findFile: HANDLE, + findFileData: HANDLE) + -> BOOL; + unsafe fn FindClose(findFile: HANDLE) -> BOOL; } } diff --git a/src/libcore/os.rs b/src/libcore/os.rs index a1793cc5efa..24d5df7140e 100644 --- a/src/libcore/os.rs +++ b/src/libcore/os.rs @@ -58,10 +58,8 @@ pub mod rustrt { pub extern { unsafe fn rust_get_argc() -> c_int; unsafe fn rust_get_argv() -> **c_char; - unsafe fn rust_getcwd() -> ~str; unsafe fn rust_path_is_dir(path: *libc::c_char) -> c_int; unsafe fn rust_path_exists(path: *libc::c_char) -> c_int; - unsafe fn rust_list_files2(&&path: ~str) -> ~[~str]; unsafe fn rust_process_wait(handle: c_int) -> c_int; unsafe fn rust_set_exit_status(code: libc::intptr_t); } @@ -670,13 +668,95 @@ fn mkdir(p: &Path, mode: c_int) -> bool { #[allow(non_implicitly_copyable_typarams)] pub fn list_dir(p: &Path) -> ~[~str] { unsafe { - #[cfg(unix)] - fn star(p: &Path) -> Path { copy *p } - + #[cfg(target_os = "linux")] + #[cfg(target_os = "android")] + #[cfg(target_os = "freebsd")] + #[cfg(target_os = "macos")] + unsafe fn get_list(p: &Path) -> ~[~str] { + use libc::{DIR, dirent_t}; + use libc::{opendir, readdir, closedir}; + extern mod rustrt { + unsafe fn rust_list_dir_val(ptr: *dirent_t) + -> *libc::c_char; + } + let input = p.to_str(); + let mut strings = ~[]; + let input_ptr = ::cast::transmute(&input[0]); + log(debug, "os::list_dir -- BEFORE OPENDIR"); + let dir_ptr = opendir(input_ptr); + if (dir_ptr as uint != 0) { + log(debug, "os::list_dir -- opendir() SUCCESS"); + let mut entry_ptr = readdir(dir_ptr); + while (entry_ptr as uint != 0) { + strings.push( + str::raw::from_c_str( + rustrt::rust_list_dir_val( + entry_ptr))); + entry_ptr = readdir(dir_ptr); + } + closedir(dir_ptr); + } + else { + log(debug, "os::list_dir -- opendir() FAILURE"); + } + log(debug, fmt!("os::list_dir -- AFTER ITERATION -- # of results: %?", strings.len())); + strings + } #[cfg(windows)] - fn star(p: &Path) -> Path { p.push("*") } - - do rustrt::rust_list_files2(star(p).to_str()).filtered |filename| { + unsafe fn get_list(p: &Path) -> ~[~str] { + use libc::types::os::arch::extra::{LPCTSTR, HANDLE, BOOL}; + use libc::consts::os::extra::INVALID_HANDLE_VALUE; + use libc::wcslen; + use libc::funcs::extra::kernel32::{ + FindFirstFileW, + FindNextFileW, + FindClose, + }; + use os::win32::{ + as_utf16_p + }; + use private::exchange_alloc::{malloc_raw, free_raw}; + #[nolink] + extern mod rustrt { + unsafe fn rust_list_dir_wfd_size() -> libc::size_t; + unsafe fn rust_list_dir_wfd_fp_buf(wfd: *libc::c_void) + -> *u16; + } + fn star(p: &Path) -> Path { p.push("*") } + do as_utf16_p(star(p).to_str()) |path_ptr| { + let mut strings = ~[]; + let wfd_ptr = malloc_raw( + rustrt::rust_list_dir_wfd_size() as uint); + let find_handle = + FindFirstFileW( + path_ptr, + ::cast::transmute(wfd_ptr)); + if find_handle as int != INVALID_HANDLE_VALUE { + let mut more_files = 1 as libc::c_int; + while more_files != 0 { + let fp_buf = rustrt::rust_list_dir_wfd_fp_buf( + wfd_ptr); + if fp_buf as uint == 0 { + fail!(~"os::list_dir() failure:"+ + ~" got null ptr from wfd"); + } + else { + let fp_vec = vec::from_buf( + fp_buf, wcslen(fp_buf) as uint); + let fp_str = str::from_utf16(fp_vec); + strings.push(fp_str); + } + more_files = FindNextFileW( + find_handle, + ::cast::transmute(wfd_ptr)); + } + FindClose(find_handle); + free_raw(wfd_ptr); + } + strings + } + } + do get_list(p).filtered |filename| { *filename != ~"." && *filename != ~".." } } diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 042720e1b4e..9f8ddc92a77 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -18,9 +18,9 @@ #[cfg(test)] use vec; #[cfg(test)] use str; -#[cfg(test)] use uint; -#[cfg(test)] use debug; #[cfg(notest)] use cmp::{Eq, Ord}; +use debug; +use uint; pub mod libc_ { use libc::c_void; @@ -504,6 +504,7 @@ pub fn test_ptr_array_each() { } #[test] #[should_fail] + #[ignore(cfg(windows))] pub fn test_ptr_array_each_with_len_null_ptr() { unsafe { ptr::array_each_with_len(0 as **libc::c_char, 1, |e| { @@ -513,6 +514,7 @@ pub fn test_ptr_array_each_with_len_null_ptr() { } #[test] #[should_fail] + #[ignore(cfg(windows))] pub fn test_ptr_array_each_null_ptr() { unsafe { ptr::array_each(0 as **libc::c_char, |e| { diff --git a/src/libcore/unstable/exchange_alloc.rs b/src/libcore/unstable/exchange_alloc.rs index a2815cebc51..3b4d86ba86b 100644 --- a/src/libcore/unstable/exchange_alloc.rs +++ b/src/libcore/unstable/exchange_alloc.rs @@ -41,6 +41,17 @@ pub unsafe fn malloc(td: *TypeDesc, size: uint) -> *c_void { return transmute(box); } } +/** +Thin wrapper around libc::malloc, none of the box header +stuff in exchange_alloc::malloc +*/ +pub unsafe fn malloc_raw(size: uint) -> *c_void { + let p = c_malloc(size as size_t); + if p.is_null() { + fail!(~"Failure in malloc_raw: result ptr is null"); + } + p +} pub unsafe fn free(ptr: *c_void) { let exchange_count = &mut *rust_get_exchange_count_ptr(); @@ -49,6 +60,10 @@ pub unsafe fn free(ptr: *c_void) { fail_unless!(ptr.is_not_null()); c_free(ptr); } +///Thin wrapper around libc::free, as with exchange_alloc::malloc_raw +pub unsafe fn free_raw(ptr: *c_void) { + c_free(ptr); +} fn get_box_size(body_size: uint, body_align: uint) -> uint { let header_size = size_of::(); diff --git a/src/rt/rust_builtin.cpp b/src/rt/rust_builtin.cpp index 2c9c4a70681..a621d61cdf7 100644 --- a/src/rt/rust_builtin.cpp +++ b/src/rt/rust_builtin.cpp @@ -247,49 +247,43 @@ debug_get_stk_seg() { return task->stk; } -extern "C" CDECL rust_vec_box* -rust_list_files(rust_str *path) { - rust_task *task = rust_get_current_task(); - array_list strings; +extern "C" CDECL char* #if defined(__WIN32__) - WIN32_FIND_DATA FindFileData; - HANDLE hFind = FindFirstFile((char*)path->body.data, &FindFileData); - if (hFind != INVALID_HANDLE_VALUE) { - do { - rust_str *str = make_str(task->kernel, FindFileData.cFileName, - strlen(FindFileData.cFileName), - "list_files_str"); - strings.push(str); - } while (FindNextFile(hFind, &FindFileData)); - FindClose(hFind); - } +rust_list_dir_val(WIN32_FIND_DATA* entry_ptr) { + return entry_ptr->cFileName; +} #else - DIR *dirp = opendir((char*)path->body.data); - if (dirp) { - struct dirent *dp; - while ((dp = readdir(dirp))) { - rust_vec_box *str = make_str(task->kernel, dp->d_name, - strlen(dp->d_name), - "list_files_str"); - strings.push(str); - } - closedir(dirp); - } +rust_list_dir_val(dirent* entry_ptr) { + return entry_ptr->d_name; +} #endif - rust_vec_box *vec = (rust_vec_box *) - task->kernel->malloc(vec_size(strings.size()), - "list_files_vec"); - size_t alloc_sz = sizeof(rust_vec*) * strings.size(); - vec->body.fill = vec->body.alloc = alloc_sz; - memcpy(&vec->body.data[0], strings.data(), alloc_sz); - return vec; +extern "C" CDECL size_t +#if defined(__WIN32__) +rust_list_dir_wfd_size() { + return sizeof(WIN32_FIND_DATAW); } +#else +rust_list_dir_wfd_size() { + return 0; +} +#endif -extern "C" CDECL rust_vec_box* -rust_list_files2(rust_str **path) { - return rust_list_files(*path); +extern "C" CDECL void* +#if defined(__WIN32__) +rust_list_dir_wfd_fp_buf(WIN32_FIND_DATAW* wfd) { + if(wfd == NULL) { + return 0; + } + else { + return wfd->cFileName; + } } +#else +rust_list_dir_wfd_fp_buf(void* wfd) { + return 0; +} +#endif extern "C" CDECL int rust_path_is_dir(char *path) { diff --git a/src/rt/rust_util.h b/src/rt/rust_util.h index fbedb9bc6ef..101d04c8804 100644 --- a/src/rt/rust_util.h +++ b/src/rt/rust_util.h @@ -79,38 +79,6 @@ inline void reserve_vec_exact(rust_vec_box** vpp, typedef rust_vec_box rust_str; -inline rust_str * -make_str(rust_kernel* kernel, const char* c, size_t strlen, - const char* name) { - size_t str_fill = strlen + 1; - size_t str_alloc = str_fill; - rust_str *str = (rust_str *) - kernel->malloc(vec_size(str_fill), name); - str->header.td = &str_body_tydesc; - str->body.fill = str_fill; - str->body.alloc = str_alloc; - memcpy(&str->body.data, c, strlen); - str->body.data[strlen] = '\0'; - return str; -} - -inline rust_vec_box * -make_str_vec(rust_kernel* kernel, size_t nstrs, char **strs) { - rust_vec_box *v = (rust_vec_box *) - kernel->malloc(vec_size(nstrs), - "str vec interior"); - // FIXME: should have a real td (Issue #2639) - v->header.td = NULL; - v->body.fill = v->body.alloc = sizeof(rust_vec_box*) * nstrs; - for (size_t i = 0; i < nstrs; ++i) { - rust_str *str = make_str(kernel, strs[i], - strlen(strs[i]), - "str"); - ((rust_str**)&v->body.data)[i] = str; - } - return v; -} - inline size_t get_box_size(size_t body_size, size_t body_align) { size_t header_size = sizeof(rust_opaque_box); // FIXME (#2699): This alignment calculation is suspicious. Is it right? diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in index ddbd4729782..284f827bc75 100644 --- a/src/rt/rustrt.def.in +++ b/src/rt/rustrt.def.in @@ -32,8 +32,9 @@ rust_path_exists rust_get_stdin rust_get_stdout rust_get_stderr -rust_list_files -rust_list_files2 +rust_list_dir_val +rust_list_dir_wfd_size +rust_list_dir_wfd_fp_buf rust_log_console_on rust_log_console_off rust_process_wait diff --git a/src/test/run-pass/conditional-compile.rs b/src/test/run-pass/conditional-compile.rs index 0a579916e93..fa6f59999f8 100644 --- a/src/test/run-pass/conditional-compile.rs +++ b/src/test/run-pass/conditional-compile.rs @@ -112,8 +112,8 @@ pub mod rustrt { #[abi = "cdecl"] pub extern { #[cfg(bogus)] - pub fn rust_getcwd() -> ~str; - pub fn rust_getcwd() -> ~str; + pub fn rust_get_stdin() -> ~str; + pub fn rust_get_stdin() -> ~str; } } } diff --git a/src/test/run-pass/morestack6.rs b/src/test/run-pass/morestack6.rs index 9d210f2580b..7e0b4b47846 100644 --- a/src/test/run-pass/morestack6.rs +++ b/src/test/run-pass/morestack6.rs @@ -17,7 +17,6 @@ mod rustrt { pub fn rust_get_sched_id() -> libc::intptr_t; pub fn rust_get_argc() -> libc::c_int; - pub fn rust_getcwd() -> ~str; pub fn get_task_id() -> libc::intptr_t; pub fn rust_sched_threads(); pub fn rust_get_task(); @@ -26,7 +25,6 @@ mod rustrt { fn calllink01() { unsafe { rustrt::rust_get_sched_id(); } } fn calllink02() { unsafe { rustrt::rust_get_argc(); } } -fn calllink03() { unsafe { rustrt::rust_getcwd(); } } fn calllink08() { unsafe { rustrt::get_task_id(); } } fn calllink09() { unsafe { rustrt::rust_sched_threads(); } } fn calllink10() { unsafe { rustrt::rust_get_task(); } } @@ -59,7 +57,6 @@ pub fn main() { let fns = ~[ calllink01, calllink02, - calllink03, calllink08, calllink09, calllink10