rt/core: port os::list_dir to rust ref #4812
This commit is contained in:
parent
53db6c7e2a
commit
a69a2acfba
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 != ~".."
|
||||
}
|
||||
}
|
||||
|
@ -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| {
|
||||
|
@ -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>();
|
||||
|
@ -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) {
|
||||
|
@ -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?
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user