rt/core: port os::list_dir to rust ref #4812

This commit is contained in:
Jeff Olson 2013-02-20 22:46:26 -08:00 committed by Brian Anderson
parent 53db6c7e2a
commit a69a2acfba
9 changed files with 174 additions and 86 deletions

View File

@ -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;
}
}

View File

@ -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 != ~".."
}
}

View File

@ -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| {

View File

@ -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>();

View File

@ -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<rust_str*> 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<rust_vec_box*>(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) {

View File

@ -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<char>(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<rust_vec_box*>(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?

View File

@ -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

View File

@ -112,8 +112,8 @@ mod test_foreign_items {
#[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;
}
}
}

View File

@ -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