about summary refs log tree commit diff
path: root/src/libcore
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 /src/libcore
parent53db6c7e2a11764a806e87c7268d31288fa9171d (diff)
downloadrust-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.rs33
-rw-r--r--src/libcore/os.rs96
-rw-r--r--src/libcore/ptr.rs6
-rw-r--r--src/libcore/unstable/exchange_alloc.rs15
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>();