about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJeff Olson <olson.jeffery@gmail.com>2013-02-20 22:46:26 -0800
committerBrian Anderson <banderson@mozilla.com>2013-03-11 15:38:55 -0700
commita69a2acfba1c09d2ca47f454ecff7b571c324d57 (patch)
treed3b952b31d20c922ef23871a0c2d84d09c944910
parent53db6c7e2a11764a806e87c7268d31288fa9171d (diff)
downloadrust-a69a2acfba1c09d2ca47f454ecff7b571c324d57.tar.gz
rust-a69a2acfba1c09d2ca47f454ecff7b571c324d57.zip
rt/core: port os::list_dir to rust ref #4812
-rw-r--r--src/libcore/libc.rs33
-rw-r--r--src/libcore/os.rs96
-rw-r--r--src/libcore/ptr.rs6
-rw-r--r--src/libcore/unstable/exchange_alloc.rs15
-rw-r--r--src/rt/rust_builtin.cpp66
-rw-r--r--src/rt/rust_util.h32
-rw-r--r--src/rt/rustrt.def.in5
-rw-r--r--src/test/run-pass/conditional-compile.rs4
-rw-r--r--src/test/run-pass/morestack6.rs3
9 files changed, 174 insertions, 86 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>();
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<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) {
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<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?
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 @@ 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;
         }
     }
 }
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