2828
2929#[ allow( missing_doc) ] ;
3030
31- use c_str:: { CString , ToCStr } ;
31+ #[ cfg( unix) ]
32+ use c_str:: CString ;
3233use clone:: Clone ;
3334use container:: Container ;
3435use io;
@@ -56,6 +57,11 @@ pub fn close(fd: c_int) -> c_int {
5657 }
5758}
5859
60+ // On Windows, wide character version of function must be used to support
61+ // unicode, so functions should be split into at least two versions,
62+ // which are for Windows and for non-Windows, if necessary.
63+ // See https://github.com/mozilla/rust/issues/9822 for more information.
64+
5965pub mod rustrt {
6066 use libc:: { c_char, c_int} ;
6167 use libc;
@@ -64,11 +70,19 @@ pub mod rustrt {
6470 pub fn rust_path_is_dir ( path : * libc:: c_char ) -> c_int ;
6571 pub fn rust_path_exists ( path : * libc:: c_char ) -> c_int ;
6672 }
73+
74+ // Uses _wstat instead of stat.
75+ #[ cfg( windows) ]
76+ extern {
77+ pub fn rust_path_is_dir_u16 ( path : * u16 ) -> c_int ;
78+ pub fn rust_path_exists_u16 ( path : * u16 ) -> c_int ;
79+ }
6780}
6881
6982pub static TMPBUF_SZ : uint = 1000 u;
7083static BUF_BYTES : uint = 2048 u;
7184
85+ #[ cfg( unix) ]
7286pub fn getcwd ( ) -> Path {
7387 #[ fixed_stack_segment] ; #[ inline( never) ] ;
7488 let mut buf = [ 0 as libc:: c_char , ..BUF_BYTES ] ;
@@ -83,6 +97,22 @@ pub fn getcwd() -> Path {
8397 }
8498}
8599
100+ #[ cfg( windows) ]
101+ pub fn getcwd ( ) -> Path {
102+ #[ fixed_stack_segment] ; #[ inline( never) ] ;
103+ use libc:: DWORD ;
104+ use libc:: GetCurrentDirectoryW ;
105+ let mut buf = [ 0 as u16 , ..BUF_BYTES ] ;
106+ do buf. as_mut_buf |buf, len| {
107+ unsafe {
108+ if libc:: GetCurrentDirectoryW ( len as DWORD , buf) == 0 as DWORD {
109+ fail2 ! ( ) ;
110+ }
111+ }
112+ }
113+ Path :: new ( str:: from_utf16 ( buf) )
114+ }
115+
86116#[ cfg ( windows) ]
87117pub mod win32 {
88118 use libc;
@@ -613,6 +643,7 @@ pub fn walk_dir(p: &Path, f: &fn(&Path) -> bool) -> bool {
613643 })
614644}
615645
646+ #[cfg(unix)]
616647/// Indicates whether a path represents a directory
617648pub fn path_is_dir(p: &Path) -> bool {
618649 #[fixed_stack_segment]; #[inline(never)];
@@ -623,6 +654,18 @@ pub fn path_is_dir(p: &Path) -> bool {
623654 }
624655}
625656
657+
658+ #[cfg(windows)]
659+ pub fn path_is_dir(p: &Path) -> bool {
660+ #[fixed_stack_segment]; #[inline(never)];
661+ unsafe {
662+ do os::win32::as_utf16_p(p.as_str().unwrap()) |buf| {
663+ rustrt::rust_path_is_dir_u16(buf) != 0 as c_int
664+ }
665+ }
666+ }
667+
668+ #[cfg(unix)]
626669/// Indicates whether a path exists
627670pub fn path_exists(p: &Path) -> bool {
628671 #[fixed_stack_segment]; #[inline(never)];
@@ -633,6 +676,16 @@ pub fn path_exists(p: &Path) -> bool {
633676 }
634677}
635678
679+ #[cfg(windows)]
680+ pub fn path_exists(p: &Path) -> bool {
681+ #[fixed_stack_segment]; #[inline(never)];
682+ unsafe {
683+ do os::win32::as_utf16_p(p.as_str().unwrap()) |buf| {
684+ rustrt::rust_path_exists_u16(buf) != 0 as c_int
685+ }
686+ }
687+ }
688+
636689/**
637690 * Convert a relative path to an absolute path
638691 *
@@ -1922,15 +1975,47 @@ mod tests {
19221975
19231976 #[test]
19241977 fn path_is_dir() {
1978+ use rt::io::file::open;
1979+ use rt::io::{OpenOrCreate, Read};
1980+
19251981 assert!((os::path_is_dir(&Path::new("."))));
19261982 assert!((!os::path_is_dir(&Path::new("test/stdtest/fs.rs"))));
1983+
1984+ let mut dirpath = os::tmpdir();
1985+ dirpath.push(format!("rust-test-{}/test-\uac00\u4e00\u30fc\u4f60\u597d",
1986+ rand::random::<u32>())); // 가一ー你好
1987+ debug2!("path_is_dir dirpath: {}", dirpath.display());
1988+
1989+ let mkdir_result = os::mkdir_recursive(&dirpath, (S_IRUSR | S_IWUSR | S_IXUSR) as i32);
1990+ debug2!("path_is_dir mkdir_result: {}", mkdir_result);
1991+
1992+ assert!((os::path_is_dir(&dirpath)));
1993+
1994+ let mut filepath = dirpath;
1995+ filepath.push("unicode-file-\uac00\u4e00\u30fc\u4f60\u597d.rs");
1996+ debug2!("path_is_dir filepath: {}", filepath.display());
1997+
1998+ open(&filepath, OpenOrCreate, Read); // ignore return; touch only
1999+ assert!((!os::path_is_dir(&filepath)));
2000+
2001+ assert!((!os::path_is_dir(&Path::new(
2002+ "test/unicode-bogus-dir-\uac00\u4e00\u30fc\u4f60\u597d"))));
19272003 }
19282004
19292005 #[test]
19302006 fn path_exists() {
19312007 assert!((os::path_exists(&Path::new("."))));
19322008 assert!((!os::path_exists(&Path::new(
19332009 "test/nonexistent-bogus-path"))));
2010+
2011+ let mut dirpath = os::tmpdir();
2012+ dirpath.push(format!("rust-test-{}/test-\uac01\u4e01\u30fc\u518d\u89c1",
2013+ rand::random::<u32>())); // 각丁ー再见
2014+
2015+ os::mkdir_recursive(&dirpath, (S_IRUSR | S_IWUSR | S_IXUSR) as i32);
2016+ assert!((os::path_exists(&dirpath)));
2017+ assert!((!os::path_exists(&Path::new(
2018+ "test/unicode-bogus-path-\uac01\u4e01\u30fc\u518d\u89c1"))));
19342019 }
19352020
19362021 #[test]
0 commit comments