Skip to content

Commit f4dba95

Browse files
committed
auto merge of #5322 : brson/rust/4812, r=brson
Supersedes #5013
2 parents 878a310 + 7e59951 commit f4dba95

File tree

11 files changed

+382
-149
lines changed

11 files changed

+382
-149
lines changed

src/libcore/core.rc

+1
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ Implicitly, all crates behave as if they included the following prologue:
5858
#[cfg(target_os = "linux")]
5959
pub mod linkhack {
6060
#[link_args="-lrustrt -lrt"]
61+
#[link_args = "-lpthread"]
6162
extern {
6263
}
6364
}

src/libcore/libc.rs

+36-2
Original file line numberDiff line numberDiff line change
@@ -534,6 +534,8 @@ pub mod types {
534534

535535
pub type LPCWSTR = *WCHAR;
536536
pub type LPCSTR = *CHAR;
537+
pub type LPCTSTR = *CHAR;
538+
pub type LPTCH = *CHAR;
537539

538540
pub type LPWSTR = *mut WCHAR;
539541
pub type LPSTR = *mut CHAR;
@@ -792,6 +794,7 @@ pub mod consts {
792794

793795
pub const ERROR_SUCCESS : int = 0;
794796
pub const ERROR_INSUFFICIENT_BUFFER : int = 122;
797+
pub const INVALID_HANDLE_VALUE: int = -1;
795798
}
796799
}
797800

@@ -1115,6 +1118,7 @@ pub mod funcs {
11151118
pub mod string {
11161119
use libc::types::common::c95::c_void;
11171120
use libc::types::os::arch::c95::{c_char, c_int, size_t};
1121+
use libc::types::os::arch::c95::{wchar_t};
11181122

11191123
pub extern {
11201124
unsafe fn strcpy(dst: *c_char, src: *c_char) -> *c_char;
@@ -1138,6 +1142,7 @@ pub mod funcs {
11381142
unsafe fn strtok(s: *c_char, t: *c_char) -> *c_char;
11391143
unsafe fn strxfrm(s: *c_char, ct: *c_char, n: size_t)
11401144
-> size_t;
1145+
unsafe fn wcslen(buf: *wchar_t) -> size_t;
11411146

11421147
// These are fine to execute on the Rust stack. They must be,
11431148
// in fact, because LLVM generates calls to them!
@@ -1381,9 +1386,28 @@ pub mod funcs {
13811386
use libc::types::os::arch::c95::{c_char, c_int, c_long};
13821387

13831388
pub extern {
1389+
// default bindings for opendir and readdir in
1390+
// non-macos unix
1391+
#[cfg(target_os = "linux")]
1392+
#[cfg(target_os = "android")]
1393+
#[cfg(target_os = "freebsd")]
13841394
unsafe fn opendir(dirname: *c_char) -> *DIR;
1385-
unsafe fn closedir(dirp: *DIR) -> c_int;
1395+
#[cfg(target_os = "linux")]
1396+
#[cfg(target_os = "android")]
1397+
#[cfg(target_os = "freebsd")]
13861398
unsafe fn readdir(dirp: *DIR) -> *dirent_t;
1399+
// on OSX (particularly when running with a
1400+
// 64bit kernel), we have an issue where there
1401+
// are separate bindings for opendir and readdir,
1402+
// which we have to explicitly link, as below.
1403+
#[cfg(target_os = "macos")]
1404+
#[link_name = "opendir$INODE64"]
1405+
unsafe fn opendir(dirname: *c_char) -> *DIR;
1406+
#[cfg(target_os = "macos")]
1407+
#[link_name = "readdir$INODE64"]
1408+
unsafe fn readdir(dirp: *DIR) -> *dirent_t;
1409+
1410+
unsafe fn closedir(dirp: *DIR) -> c_int;
13871411
unsafe fn rewinddir(dirp: *DIR);
13881412
unsafe fn seekdir(dirp: *DIR, loc: c_long);
13891413
unsafe fn telldir(dirp: *DIR) -> c_long;
@@ -1594,8 +1618,9 @@ pub mod funcs {
15941618

15951619
pub mod kernel32 {
15961620
use libc::types::os::arch::extra::{BOOL, DWORD, HMODULE};
1597-
use libc::types::os::arch::extra::{LPCWSTR, LPWSTR};
1621+
use libc::types::os::arch::extra::{LPCWSTR, LPWSTR, LPTCH};
15981622
use libc::types::os::arch::extra::{LPSECURITY_ATTRIBUTES};
1623+
use libc::types::os::arch::extra::{HANDLE};
15991624

16001625
#[abi = "stdcall"]
16011626
pub extern {
@@ -1605,6 +1630,8 @@ pub mod funcs {
16051630
-> DWORD;
16061631
unsafe fn SetEnvironmentVariableW(n: LPCWSTR, v: LPCWSTR)
16071632
-> BOOL;
1633+
unsafe fn GetEnvironmentStringsA() -> LPTCH;
1634+
unsafe fn FreeEnvironmentStringsA(env_ptr: LPTCH) -> BOOL;
16081635

16091636
unsafe fn GetModuleFileNameW(hModule: HMODULE,
16101637
lpFilename: LPWSTR,
@@ -1623,6 +1650,13 @@ pub mod funcs {
16231650
unsafe fn SetCurrentDirectoryW(lpPathName: LPCWSTR) -> BOOL;
16241651

16251652
unsafe fn GetLastError() -> DWORD;
1653+
unsafe fn FindFirstFileW(fileName: *u16,
1654+
findFileData: HANDLE)
1655+
-> HANDLE;
1656+
unsafe fn FindNextFileW(findFile: HANDLE,
1657+
findFileData: HANDLE)
1658+
-> BOOL;
1659+
unsafe fn FindClose(findFile: HANDLE) -> BOOL;
16261660
}
16271661
}
16281662

src/libcore/os.rs

+156-20
Original file line numberDiff line numberDiff line change
@@ -58,20 +58,25 @@ pub mod rustrt {
5858
pub extern {
5959
unsafe fn rust_get_argc() -> c_int;
6060
unsafe fn rust_get_argv() -> **c_char;
61-
unsafe fn rust_getcwd() -> ~str;
6261
unsafe fn rust_path_is_dir(path: *libc::c_char) -> c_int;
6362
unsafe fn rust_path_exists(path: *libc::c_char) -> c_int;
64-
unsafe fn rust_list_files2(&&path: ~str) -> ~[~str];
6563
unsafe fn rust_process_wait(handle: c_int) -> c_int;
6664
unsafe fn rust_set_exit_status(code: libc::intptr_t);
6765
}
6866
}
6967

7068
pub const TMPBUF_SZ : uint = 1000u;
69+
const BUF_BYTES : uint = 2048u;
7170

7271
pub fn getcwd() -> Path {
72+
let buf = [0 as libc::c_char, ..BUF_BYTES];
7373
unsafe {
74-
Path(rustrt::rust_getcwd())
74+
if(0 as *libc::c_char == libc::getcwd(
75+
&buf[0],
76+
BUF_BYTES as libc::size_t)) {
77+
fail!();
78+
}
79+
Path(str::raw::from_c_str(&buf[0]))
7580
}
7681
}
7782

@@ -164,20 +169,68 @@ fn with_env_lock<T>(f: &fn() -> T) -> T {
164169
}
165170

166171
pub fn env() -> ~[(~str,~str)] {
167-
extern {
168-
unsafe fn rust_env_pairs() -> ~[~str];
169-
}
170-
171172
unsafe {
172-
do with_env_lock {
173+
#[cfg(windows)]
174+
unsafe fn get_env_pairs() -> ~[~str] {
175+
use libc::types::os::arch::extra::LPTCH;
176+
use libc::funcs::extra::kernel32::{
177+
GetEnvironmentStringsA,
178+
FreeEnvironmentStringsA
179+
};
180+
let ch = GetEnvironmentStringsA();
181+
if (ch as uint == 0) {
182+
fail!(fmt!("os::env() failure getting env string from OS: %s",
183+
os::last_os_error()));
184+
}
185+
let mut curr_ptr: uint = ch as uint;
186+
let mut result = ~[];
187+
while(*(curr_ptr as *libc::c_char) != 0 as libc::c_char) {
188+
let env_pair = str::raw::from_c_str(
189+
curr_ptr as *libc::c_char);
190+
result.push(env_pair);
191+
curr_ptr +=
192+
libc::strlen(curr_ptr as *libc::c_char) as uint
193+
+ 1;
194+
}
195+
FreeEnvironmentStringsA(ch);
196+
result
197+
}
198+
#[cfg(unix)]
199+
unsafe fn get_env_pairs() -> ~[~str] {
200+
extern mod rustrt {
201+
unsafe fn rust_env_pairs() -> **libc::c_char;
202+
}
203+
let environ = rustrt::rust_env_pairs();
204+
if (environ as uint == 0) {
205+
fail!(fmt!("os::env() failure getting env string from OS: %s",
206+
os::last_os_error()));
207+
}
208+
let mut result = ~[];
209+
ptr::array_each(environ, |e| {
210+
let env_pair = str::raw::from_c_str(e);
211+
log(debug, fmt!("get_env_pairs: %s",
212+
env_pair));
213+
result.push(env_pair);
214+
});
215+
result
216+
}
217+
218+
fn env_convert(input: ~[~str]) -> ~[(~str, ~str)] {
173219
let mut pairs = ~[];
174-
for vec::each(rust_env_pairs()) |p| {
175-
let vs = str::splitn_char(*p, '=', 1u);
176-
fail_unless!(vec::len(vs) == 2u);
220+
for input.each |p| {
221+
let vs = str::splitn_char(*p, '=', 1);
222+
log(debug,
223+
fmt!("splitting: len: %u",
224+
vs.len()));
225+
fail_unless!(vs.len() == 2);
177226
pairs.push((copy vs[0], copy vs[1]));
178227
}
179228
pairs
180229
}
230+
do with_env_lock {
231+
let unparsed_environ = get_env_pairs();
232+
env_convert(unparsed_environ)
233+
}
181234
}
182235
}
183236

@@ -615,13 +668,97 @@ pub fn make_dir(p: &Path, mode: c_int) -> bool {
615668
#[allow(non_implicitly_copyable_typarams)]
616669
pub fn list_dir(p: &Path) -> ~[~str] {
617670
unsafe {
618-
#[cfg(unix)]
619-
fn star(p: &Path) -> Path { copy *p }
620-
671+
#[cfg(target_os = "linux")]
672+
#[cfg(target_os = "android")]
673+
#[cfg(target_os = "freebsd")]
674+
#[cfg(target_os = "macos")]
675+
unsafe fn get_list(p: &Path) -> ~[~str] {
676+
use libc::{DIR, dirent_t};
677+
use libc::{opendir, readdir, closedir};
678+
extern mod rustrt {
679+
unsafe fn rust_list_dir_val(ptr: *dirent_t)
680+
-> *libc::c_char;
681+
}
682+
let input = p.to_str();
683+
let mut strings = ~[];
684+
let input_ptr = ::cast::transmute(&input[0]);
685+
log(debug, "os::list_dir -- BEFORE OPENDIR");
686+
let dir_ptr = opendir(input_ptr);
687+
if (dir_ptr as uint != 0) {
688+
log(debug, "os::list_dir -- opendir() SUCCESS");
689+
let mut entry_ptr = readdir(dir_ptr);
690+
while (entry_ptr as uint != 0) {
691+
strings.push(
692+
str::raw::from_c_str(
693+
rustrt::rust_list_dir_val(
694+
entry_ptr)));
695+
entry_ptr = readdir(dir_ptr);
696+
}
697+
closedir(dir_ptr);
698+
}
699+
else {
700+
log(debug, "os::list_dir -- opendir() FAILURE");
701+
}
702+
log(debug,
703+
fmt!("os::list_dir -- AFTER -- #: %?",
704+
strings.len()));
705+
strings
706+
}
621707
#[cfg(windows)]
622-
fn star(p: &Path) -> Path { p.push("*") }
623-
624-
do rustrt::rust_list_files2(star(p).to_str()).filtered |filename| {
708+
unsafe fn get_list(p: &Path) -> ~[~str] {
709+
use libc::types::os::arch::extra::{LPCTSTR, HANDLE, BOOL};
710+
use libc::consts::os::extra::INVALID_HANDLE_VALUE;
711+
use libc::wcslen;
712+
use libc::funcs::extra::kernel32::{
713+
FindFirstFileW,
714+
FindNextFileW,
715+
FindClose,
716+
};
717+
use os::win32::{
718+
as_utf16_p
719+
};
720+
use unstable::exchange_alloc::{malloc_raw, free_raw};
721+
#[nolink]
722+
extern mod rustrt {
723+
unsafe fn rust_list_dir_wfd_size() -> libc::size_t;
724+
unsafe fn rust_list_dir_wfd_fp_buf(wfd: *libc::c_void)
725+
-> *u16;
726+
}
727+
fn star(p: &Path) -> Path { p.push("*") }
728+
do as_utf16_p(star(p).to_str()) |path_ptr| {
729+
let mut strings = ~[];
730+
let wfd_ptr = malloc_raw(
731+
rustrt::rust_list_dir_wfd_size() as uint);
732+
let find_handle =
733+
FindFirstFileW(
734+
path_ptr,
735+
::cast::transmute(wfd_ptr));
736+
if find_handle as int != INVALID_HANDLE_VALUE {
737+
let mut more_files = 1 as libc::c_int;
738+
while more_files != 0 {
739+
let fp_buf = rustrt::rust_list_dir_wfd_fp_buf(
740+
wfd_ptr);
741+
if fp_buf as uint == 0 {
742+
fail!(~"os::list_dir() failure:"+
743+
~" got null ptr from wfd");
744+
}
745+
else {
746+
let fp_vec = vec::from_buf(
747+
fp_buf, wcslen(fp_buf) as uint);
748+
let fp_str = str::from_utf16(fp_vec);
749+
strings.push(fp_str);
750+
}
751+
more_files = FindNextFileW(
752+
find_handle,
753+
::cast::transmute(wfd_ptr));
754+
}
755+
FindClose(find_handle);
756+
free_raw(wfd_ptr);
757+
}
758+
strings
759+
}
760+
}
761+
do get_list(p).filtered |filename| {
625762
*filename != ~"." && *filename != ~".."
626763
}
627764
}
@@ -1274,9 +1411,8 @@ mod tests {
12741411
setenv(~"USERPROFILE", ~"/home/PaloAlto");
12751412
fail_unless!(os::homedir() == Some(Path("/home/MountainView")));
12761413
1277-
option::iter(&oldhome, |s| setenv(~"HOME", *s));
1278-
option::iter(&olduserprofile,
1279-
|s| setenv(~"USERPROFILE", *s));
1414+
oldhome.each(|s| {setenv(~"HOME", *s);true});
1415+
olduserprofile.each(|s| {setenv(~"USERPROFILE", *s);true});
12801416
}
12811417
12821418
#[test]

0 commit comments

Comments
 (0)