diff options
| author | Jeff Olson <olson.jeffery@gmail.com> | 2013-02-20 22:46:26 -0800 |
|---|---|---|
| committer | Brian Anderson <banderson@mozilla.com> | 2013-03-11 15:38:55 -0700 |
| commit | a69a2acfba1c09d2ca47f454ecff7b571c324d57 (patch) | |
| tree | d3b952b31d20c922ef23871a0c2d84d09c944910 /src/libcore | |
| parent | 53db6c7e2a11764a806e87c7268d31288fa9171d (diff) | |
| download | rust-a69a2acfba1c09d2ca47f454ecff7b571c324d57.tar.gz rust-a69a2acfba1c09d2ca47f454ecff7b571c324d57.zip | |
rt/core: port os::list_dir to rust ref #4812
Diffstat (limited to 'src/libcore')
| -rw-r--r-- | src/libcore/libc.rs | 33 | ||||
| -rw-r--r-- | src/libcore/os.rs | 96 | ||||
| -rw-r--r-- | src/libcore/ptr.rs | 6 | ||||
| -rw-r--r-- | src/libcore/unstable/exchange_alloc.rs | 15 |
4 files changed, 139 insertions, 11 deletions
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 types { 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 consts { pub const ERROR_SUCCESS : int = 0; pub const ERROR_INSUFFICIENT_BUFFER : int = 122; + pub const INVALID_HANDLE_VALUE: int = -1; } } @@ -1116,6 +1118,7 @@ pub mod funcs { 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 @@ pub mod funcs { 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 funcs { 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 funcs { 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 @@ pub mod funcs { 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 @@ pub fn make_dir(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 @@ use sys; #[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 mod ptr_tests { } #[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 mod ptr_tests { } #[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::<BoxHeaderRepr>(); |
