about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2013-03-11 16:39:43 -0700
committerbors <bors@rust-lang.org>2013-03-11 16:39:43 -0700
commitf4dba956ecec4667e6153691a6245dbac4a5f072 (patch)
tree2b85849db853691cb6d410c30ed7e23df8d129cf /src
parent878a31066d9f5cbe7e81433c64cbd00e6b024551 (diff)
parent7e5995197fa41002fd0ea78bf08208247e20ad51 (diff)
downloadrust-f4dba956ecec4667e6153691a6245dbac4a5f072.tar.gz
rust-f4dba956ecec4667e6153691a6245dbac4a5f072.zip
auto merge of #5322 : brson/rust/4812, r=brson
Supersedes #5013
Diffstat (limited to 'src')
-rw-r--r--src/libcore/core.rc1
-rw-r--r--src/libcore/libc.rs38
-rw-r--r--src/libcore/os.rs176
-rw-r--r--src/libcore/ptr.rs134
-rw-r--r--src/libcore/unstable/exchange_alloc.rs15
-rw-r--r--src/libcore/vec.rs1
-rw-r--r--src/rt/rust_builtin.cpp120
-rw-r--r--src/rt/rust_util.h32
-rw-r--r--src/rt/rustrt.def.in7
-rw-r--r--src/test/run-pass/conditional-compile.rs4
-rw-r--r--src/test/run-pass/morestack6.rs3
11 files changed, 382 insertions, 149 deletions
diff --git a/src/libcore/core.rc b/src/libcore/core.rc
index db1dc1e28aa..7b12bae7467 100644
--- a/src/libcore/core.rc
+++ b/src/libcore/core.rc
@@ -58,6 +58,7 @@ Implicitly, all crates behave as if they included the following prologue:
 #[cfg(target_os = "linux")]
 pub mod linkhack {
     #[link_args="-lrustrt -lrt"]
+    #[link_args = "-lpthread"]
     extern {
     }
 }
diff --git a/src/libcore/libc.rs b/src/libcore/libc.rs
index b59824969bb..7f293b98e24 100644
--- a/src/libcore/libc.rs
+++ b/src/libcore/libc.rs
@@ -534,6 +534,8 @@ pub mod types {
 
                 pub type LPCWSTR = *WCHAR;
                 pub type LPCSTR = *CHAR;
+                pub type LPCTSTR = *CHAR;
+                pub type LPTCH = *CHAR;
 
                 pub type LPWSTR = *mut WCHAR;
                 pub type LPSTR = *mut CHAR;
@@ -792,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;
         }
     }
 
@@ -1115,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;
@@ -1138,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!
@@ -1381,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;
@@ -1594,8 +1618,9 @@ pub mod funcs {
 
         pub mod kernel32 {
             use libc::types::os::arch::extra::{BOOL, DWORD, HMODULE};
-            use libc::types::os::arch::extra::{LPCWSTR, LPWSTR};
+            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 {
@@ -1605,6 +1630,8 @@ pub mod funcs {
                                                -> DWORD;
                 unsafe fn SetEnvironmentVariableW(n: LPCWSTR, v: LPCWSTR)
                                                -> BOOL;
+                unsafe fn GetEnvironmentStringsA() -> LPTCH;
+                unsafe fn FreeEnvironmentStringsA(env_ptr: LPTCH) -> BOOL;
 
                 unsafe fn GetModuleFileNameW(hModule: HMODULE,
                                              lpFilename: LPWSTR,
@@ -1623,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 ba16c14a85a..aa4a6feb76f 100644
--- a/src/libcore/os.rs
+++ b/src/libcore/os.rs
@@ -58,20 +58,25 @@ 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);
     }
 }
 
 pub const TMPBUF_SZ : uint = 1000u;
+const BUF_BYTES : uint = 2048u;
 
 pub fn getcwd() -> Path {
+    let buf = [0 as libc::c_char, ..BUF_BYTES];
     unsafe {
-        Path(rustrt::rust_getcwd())
+        if(0 as *libc::c_char == libc::getcwd(
+            &buf[0],
+            BUF_BYTES as libc::size_t)) {
+            fail!();
+        }
+        Path(str::raw::from_c_str(&buf[0]))
     }
 }
 
@@ -164,20 +169,68 @@ fn with_env_lock<T>(f: &fn() -> T) -> T {
 }
 
 pub fn env() -> ~[(~str,~str)] {
-    extern {
-        unsafe fn rust_env_pairs() -> ~[~str];
-    }
-
     unsafe {
-        do with_env_lock {
+        #[cfg(windows)]
+        unsafe fn get_env_pairs() -> ~[~str] {
+            use libc::types::os::arch::extra::LPTCH;
+            use libc::funcs::extra::kernel32::{
+                GetEnvironmentStringsA,
+                FreeEnvironmentStringsA
+            };
+            let ch = GetEnvironmentStringsA();
+            if (ch as uint == 0) {
+                fail!(fmt!("os::env() failure getting env string from OS: %s",
+                           os::last_os_error()));
+            }
+            let mut curr_ptr: uint = ch as uint;
+            let mut result = ~[];
+            while(*(curr_ptr as *libc::c_char) != 0 as libc::c_char) {
+                let env_pair = str::raw::from_c_str(
+                    curr_ptr as *libc::c_char);
+                result.push(env_pair);
+                curr_ptr +=
+                    libc::strlen(curr_ptr as *libc::c_char) as uint
+                    + 1;
+            }
+            FreeEnvironmentStringsA(ch);
+            result
+        }
+        #[cfg(unix)]
+        unsafe fn get_env_pairs() -> ~[~str] {
+            extern mod rustrt {
+                unsafe fn rust_env_pairs() -> **libc::c_char;
+            }
+            let environ = rustrt::rust_env_pairs();
+            if (environ as uint == 0) {
+                fail!(fmt!("os::env() failure getting env string from OS: %s",
+                           os::last_os_error()));
+            }
+            let mut result = ~[];
+            ptr::array_each(environ, |e| {
+                let env_pair = str::raw::from_c_str(e);
+                log(debug, fmt!("get_env_pairs: %s",
+                                env_pair));
+                result.push(env_pair);
+            });
+            result
+        }
+
+        fn env_convert(input: ~[~str]) -> ~[(~str, ~str)] {
             let mut pairs = ~[];
-            for vec::each(rust_env_pairs()) |p| {
-                let vs = str::splitn_char(*p, '=', 1u);
-                fail_unless!(vec::len(vs) == 2u);
+            for input.each |p| {
+                let vs = str::splitn_char(*p, '=', 1);
+                log(debug,
+                    fmt!("splitting: len: %u",
+                    vs.len()));
+                fail_unless!(vs.len() == 2);
                 pairs.push((copy vs[0], copy vs[1]));
             }
             pairs
         }
+        do with_env_lock {
+            let unparsed_environ = get_env_pairs();
+            env_convert(unparsed_environ)
+        }
     }
 }
 
@@ -615,13 +668,97 @@ 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 -- #: %?",
+                     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 unstable::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 != ~".."
         }
     }
@@ -1274,9 +1411,8 @@ mod tests {
         setenv(~"USERPROFILE", ~"/home/PaloAlto");
         fail_unless!(os::homedir() == Some(Path("/home/MountainView")));
 
-        option::iter(&oldhome, |s| setenv(~"HOME", *s));
-        option::iter(&olduserprofile,
-                               |s| setenv(~"USERPROFILE", *s));
+        oldhome.each(|s| {setenv(~"HOME", *s);true});
+        olduserprofile.each(|s| {setenv(~"USERPROFILE", *s);true});
     }
 
     #[test]
diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs
index b66c1c4696f..ace70d7f061 100644
--- a/src/libcore/ptr.rs
+++ b/src/libcore/ptr.rs
@@ -19,6 +19,8 @@ use sys;
 #[cfg(test)] use vec;
 #[cfg(test)] use str;
 #[cfg(notest)] use cmp::{Eq, Ord};
+use debug;
+use uint;
 
 pub mod libc_ {
     use libc::c_void;
@@ -181,6 +183,46 @@ pub pure fn ref_eq<T>(thing: &a/T, other: &b/T) -> bool {
     to_uint(thing) == to_uint(other)
 }
 
+/**
+  Given a **T (pointer to an array of pointers),
+  iterate through each *T, up to the provided `len`,
+  passing to the provided callback function
+
+  SAFETY NOTE: Pointer-arithmetic. Dragons be here.
+*/
+pub unsafe fn array_each_with_len<T>(arr: **T, len: uint, cb: &fn(*T)) {
+    log(debug, "array_each_with_len: before iterate");
+    if (arr as uint == 0) {
+        fail!(~"ptr::array_each_with_len failure: arr input is null pointer");
+    }
+    //let start_ptr = *arr;
+    uint::iterate(0, len, |e| {
+        let n = offset(arr, e);
+        cb(*n);
+        true
+    });
+    log(debug, "array_each_with_len: after iterate");
+}
+
+/**
+  Given a null-pointer-terminated **T (pointer to
+  an array of pointers), iterate through each *T,
+  passing to the provided callback function
+
+  SAFETY NOTE: This will only work with a null-terminated
+  pointer array. Barely less-dodgey Pointer Arithmetic.
+  Dragons be here.
+*/
+pub unsafe fn array_each<T>(arr: **T, cb: &fn(*T)) {
+    if (arr as uint == 0) {
+        fail!(~"ptr::array_each_with_len failure: arr input is null pointer");
+    }
+    let len = buf_len(arr);
+    log(debug, fmt!("array_each inferred len: %u",
+                    len));
+    array_each_with_len(arr, len, cb);
+}
+
 pub trait Ptr<T> {
     pure fn is_null(&self) -> bool;
     pure fn is_not_null(&self) -> bool;
@@ -389,3 +431,95 @@ pub fn test_is_null() {
    fail_unless!(!mq.is_null());
    fail_unless!(mq.is_not_null());
 }
+
+#[cfg(test)]
+pub mod ptr_tests {
+    use debug;
+    use ptr;
+    use str;
+    use libc;
+    use vec;
+    #[test]
+    pub fn test_ptr_array_each_with_len() {
+        unsafe {
+            let one = ~"oneOne";
+            let two = ~"twoTwo";
+            let three = ~"threeThree";
+            let arr: ~[*i8] = ~[
+                ::cast::transmute(&one[0]),
+                ::cast::transmute(&two[0]),
+                ::cast::transmute(&three[0]),
+            ];
+            let expected_arr = [
+                one, two, three
+            ];
+            let arr_ptr = &arr[0];
+            let mut ctr = 0;
+            let mut iteration_count = 0;
+            ptr::array_each_with_len(arr_ptr, vec::len(arr),
+                |e| {
+                let actual = str::raw::from_c_str(e);
+                let expected = copy expected_arr[ctr];
+                log(debug,
+                    fmt!("test_ptr_array_each e: %s, a: %s",
+                         expected, actual));
+                fail_unless!(actual == expected);
+                ctr += 1;
+                iteration_count += 1;
+            });
+            fail_unless!(iteration_count == 3u);
+        }
+    }
+    #[test]
+    pub fn test_ptr_array_each() {
+        unsafe {
+            let one = ~"oneOne";
+            let two = ~"twoTwo";
+            let three = ~"threeThree";
+            let arr: ~[*i8] = ~[
+                ::cast::transmute(&one[0]),
+                ::cast::transmute(&two[0]),
+                ::cast::transmute(&three[0]),
+                // fake a null terminator
+                0 as *i8
+            ];
+            let expected_arr = [
+                one, two, three
+            ];
+            let arr_ptr = &arr[0];
+            let mut ctr = 0;
+            let mut iteration_count = 0;
+            ptr::array_each(arr_ptr, |e| {
+                let actual = str::raw::from_c_str(e);
+                let expected = copy expected_arr[ctr];
+                log(debug,
+                    fmt!("test_ptr_array_each e: %s, a: %s",
+                         expected, actual));
+                fail_unless!(actual == expected);
+                ctr += 1;
+                iteration_count += 1;
+            });
+            fail_unless!(iteration_count == 3);
+        }
+    }
+    #[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| {
+                str::raw::from_c_str(e);
+            });
+        }
+    }
+    #[test]
+    #[should_fail]
+    #[ignore(cfg(windows))]
+    pub fn test_ptr_array_each_null_ptr() {
+        unsafe {
+            ptr::array_each(0 as **libc::c_char, |e| {
+                str::raw::from_c_str(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/libcore/vec.rs b/src/libcore/vec.rs
index 697bfe63b18..68dca608a48 100644
--- a/src/libcore/vec.rs
+++ b/src/libcore/vec.rs
@@ -2692,6 +2692,7 @@ mod tests {
 
     #[test]
     #[should_fail]
+    #[ignore(cfg(windows))]
     fn test_last_empty() {
         let a: ~[int] = ~[];
         a.last();
diff --git a/src/rt/rust_builtin.cpp b/src/rt/rust_builtin.cpp
index 1243d824603..a621d61cdf7 100644
--- a/src/rt/rust_builtin.cpp
+++ b/src/rt/rust_builtin.cpp
@@ -52,64 +52,18 @@ timegm(struct tm *tm)
 }
 #endif
 
-extern "C" CDECL rust_str *
-rust_getcwd() {
-    rust_task *task = rust_get_current_task();
-    LOG(task, task, "rust_getcwd()");
-
-    char cbuf[BUF_BYTES];
-
-#if defined(__WIN32__)
-    if (!_getcwd(cbuf, sizeof(cbuf))) {
-#else
-        if (!getcwd(cbuf, sizeof(cbuf))) {
-#endif
-        task->fail();
-        return NULL;
-    }
-
-    return make_str(task->kernel, cbuf, strlen(cbuf), "rust_str(getcwd)");
-}
-
 #if defined(__WIN32__)
-extern "C" CDECL rust_vec_box *
+extern "C" CDECL char**
 rust_env_pairs() {
-    rust_task *task = rust_get_current_task();
-    size_t envc = 0;
-    LPTCH ch = GetEnvironmentStringsA();
-    LPTCH c;
-    for (c = ch; *c; c += strlen(c) + 1) {
-        ++envc;
-    }
-    c = ch;
-    rust_vec_box *v = (rust_vec_box *)
-        task->kernel->malloc(vec_size<rust_vec_box*>(envc),
-                       "str vec interior");
-    v->body.fill = v->body.alloc = sizeof(rust_vec*) * envc;
-    for (size_t i = 0; i < envc; ++i) {
-        size_t n = strlen(c);
-        rust_str *str = make_str(task->kernel, c, n, "str");
-        ((rust_str**)&v->body.data)[i] = str;
-        c += n + 1;
-    }
-    if (ch) {
-        FreeEnvironmentStrings(ch);
-    }
-    return v;
+    return 0;
 }
 #else
-extern "C" CDECL rust_vec_box *
+extern "C" CDECL char**
 rust_env_pairs() {
-    rust_task *task = rust_get_current_task();
 #ifdef __APPLE__
     char **environ = *_NSGetEnviron();
 #endif
-    char **e = environ;
-    size_t envc = 0;
-    while (*e) {
-        ++envc; ++e;
-    }
-    return make_str_vec(task->kernel, envc, environ);
+    return environ;
 }
 #endif
 
@@ -293,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 fca10ac3ef4..284f827bc75 100644
--- a/src/rt/rustrt.def.in
+++ b/src/rt/rustrt.def.in
@@ -29,12 +29,12 @@ rust_new_task_in_sched
 rust_num_threads
 rust_path_is_dir
 rust_path_exists
-rust_getcwd
 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
@@ -43,7 +43,6 @@ rust_sched_current_nonlazy_threads
 rust_sched_threads
 rust_set_exit_status
 rust_start
-rust_getcwd
 rust_env_pairs
 rust_task_yield
 rust_task_is_unwinding
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