@@ -62,11 +62,10 @@ extern mod rustrt {
6262 unsafe fn rust_path_exists ( path : * libc:: c_char ) -> c_int ;
6363 unsafe fn rust_list_files2 ( & & path: ~str ) -> ~[ ~str ] ;
6464 unsafe fn rust_process_wait ( handle : c_int ) -> c_int ;
65- unsafe fn last_os_error ( ) -> ~str ;
6665 unsafe fn rust_set_exit_status ( code : libc:: intptr_t ) ;
6766}
6867
69- pub const tmpbuf_sz : uint = 1000 u;
68+ pub const TMPBUF_SZ : uint = 1000 u;
7069
7170pub fn getcwd ( ) -> Path {
7271 unsafe {
@@ -80,7 +79,7 @@ pub fn as_c_charp<T>(s: &str, f: fn(*c_char) -> T) -> T {
8079
8180pub fn fill_charp_buf ( f : fn ( * mut c_char , size_t ) -> bool )
8281 -> Option < ~str > {
83- let buf = vec:: cast_to_mut ( vec:: from_elem ( tmpbuf_sz , 0u8 as c_char ) ) ;
82+ let buf = vec:: cast_to_mut ( vec:: from_elem ( TMPBUF_SZ , 0u8 as c_char ) ) ;
8483 do vec:: as_mut_buf ( buf) |b, sz| {
8584 if f ( b, sz as size_t ) {
8685 unsafe {
@@ -99,19 +98,19 @@ pub mod win32 {
9998 use str;
10099 use option:: { None , Option } ;
101100 use option;
102- use os:: tmpbuf_sz ;
101+ use os:: TMPBUF_SZ ;
103102 use libc:: types:: os:: arch:: extra:: DWORD ;
104103
105104 pub fn fill_utf16_buf_and_decode ( f : fn ( * mut u16 , DWORD ) -> DWORD )
106105 -> Option < ~str > {
107106 unsafe {
108- let mut n = tmpbuf_sz as DWORD ;
107+ let mut n = TMPBUF_SZ as DWORD ;
109108 let mut res = None ;
110109 let mut done = false ;
111110 while !done {
112111 let buf = vec:: cast_to_mut ( vec:: from_elem ( n as uint , 0u16 ) ) ;
113112 do vec:: as_mut_buf ( buf) |b, _sz| {
114- let k : DWORD = f ( b, tmpbuf_sz as DWORD ) ;
113+ let k : DWORD = f ( b, TMPBUF_SZ as DWORD ) ;
115114 if k == ( 0 as DWORD ) {
116115 done = true ;
117116 } else if ( k == n &&
@@ -387,11 +386,11 @@ pub fn self_exe_path() -> Option<Path> {
387386 unsafe {
388387 use libc:: funcs:: posix01:: unistd:: readlink;
389388
390- let mut path_str = str:: with_capacity ( tmpbuf_sz ) ;
389+ let mut path_str = str:: with_capacity ( TMPBUF_SZ ) ;
391390 let len = do str:: as_c_str ( path_str) |buf| {
392391 let buf = buf as * mut c_char ;
393392 do as_c_charp( "/proc/self/exe" ) |proc_self_buf| {
394- readlink ( proc_self_buf, buf, tmpbuf_sz as size_t )
393+ readlink ( proc_self_buf, buf, TMPBUF_SZ as size_t )
395394 }
396395 } ;
397396 if len == -1 {
@@ -766,11 +765,136 @@ pub fn remove_file(p: &Path) -> bool {
766765 }
767766}
768767
768+ #[ cfg( unix) ]
769+ pub fn errno ( ) -> int {
770+ #[ cfg( target_os = "macos" ) ]
771+ #[ cfg( target_os = "freebsd" ) ]
772+ fn errno_location ( ) -> * c_int {
773+ #[ nolink]
774+ extern {
775+ unsafe fn __error ( ) -> * c_int ;
776+ }
777+ unsafe {
778+ __error ( )
779+ }
780+ }
781+
782+ #[ cfg( target_os = "linux" ) ]
783+ #[ cfg( target_os = "android" ) ]
784+ fn errno_location ( ) -> * c_int {
785+ #[ nolink]
786+ extern {
787+ unsafe fn __errno_location ( ) -> * c_int ;
788+ }
789+ unsafe {
790+ __errno_location ( )
791+ }
792+ }
793+
794+ unsafe {
795+ ( * errno_location ( ) ) as int
796+ }
797+ }
798+
799+ #[ cfg( windows) ]
800+ pub fn errno ( ) -> uint {
801+ use libc:: types:: os:: arch:: extra:: DWORD ;
802+
803+ #[ link_name = "kernel32" ]
804+ #[ abi = "stdcall" ]
805+ extern {
806+ unsafe fn GetLastError ( ) -> DWORD ;
807+ }
808+
809+ unsafe {
810+ GetLastError ( ) as uint
811+ }
812+ }
813+
769814/// Get a string representing the platform-dependent last error
770815pub fn last_os_error( ) -> ~str {
771- unsafe {
772- rustrt:: last_os_error ( )
816+ #[ cfg( unix) ]
817+ fn strerror ( ) -> ~str {
818+ #[ cfg( target_os = "macos" ) ]
819+ #[ cfg( target_os = "android" ) ]
820+ #[ cfg( target_os = "freebsd" ) ]
821+ fn strerror_r ( errnum : c_int , buf : * c_char , buflen : size_t ) -> c_int {
822+ #[ nolink]
823+ extern {
824+ unsafe fn strerror_r ( errnum : c_int , buf : * c_char ,
825+ buflen : size_t ) -> c_int ;
826+ }
827+ unsafe {
828+ strerror_r ( errnum, buf, buflen)
829+ }
830+ }
831+
832+ // GNU libc provides a non-compliant version of strerror_r by default
833+ // and requires macros to instead use the POSIX compliant variant.
834+ // So we just use __xpg_strerror_r which is always POSIX compliant
835+ #[ cfg( target_os = "linux" ) ]
836+ fn strerror_r ( errnum : c_int , buf : * c_char , buflen : size_t ) -> c_int {
837+ #[ nolink]
838+ extern {
839+ unsafe fn __xpg_strerror_r ( errnum : c_int , buf : * c_char ,
840+ buflen : size_t ) -> c_int ;
841+ }
842+ unsafe {
843+ __xpg_strerror_r ( errnum, buf, buflen)
844+ }
845+ }
846+
847+ let mut buf = [ 0 as c_char , ..TMPBUF_SZ ] ;
848+ unsafe {
849+ let err = strerror_r ( errno ( ) as c_int , & buf[ 0 ] ,
850+ TMPBUF_SZ as size_t ) ;
851+ if err < 0 {
852+ die ! ( ~"strerror_r failure");
853+ }
854+
855+ str::raw::from_c_str(&buf[0])
856+ }
857+ }
858+
859+ #[cfg(windows)]
860+ fn strerror() -> ~str {
861+ use libc::types::os::arch::extra::DWORD;
862+ use libc::types::os::arch::extra::LPSTR;
863+ use libc::types::os::arch::extra::LPVOID;
864+
865+ #[link_name = " kernel32"]
866+ #[abi = " stdcall"]
867+ extern {
868+ unsafe fn FormatMessageA(flags: DWORD, lpSrc: LPVOID,
869+ msgId: DWORD, langId: DWORD,
870+ buf: LPSTR, nsize: DWORD,
871+ args: *c_void) -> DWORD;
872+ }
873+
874+ const FORMAT_MESSAGE_FROM_SYSTEM: DWORD = 0x00001000;
875+ const FORMAT_MESSAGE_IGNORE_INSERTS: DWORD = 0x00000200;
876+
877+ let mut buf = [0 as c_char, ..TMPBUF_SZ];
878+
879+ // This value is calculated from the macro
880+ // MAKELANGID(LANG_SYSTEM_DEFAULT, SUBLANG_SYS_DEFAULT)
881+ let langId = 0x0800 as DWORD;
882+ let err = errno() as DWORD;
883+ unsafe {
884+ let res = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM |
885+ FORMAT_MESSAGE_IGNORE_INSERTS,
886+ ptr::mut_null(), err, langId,
887+ &mut buf[0], TMPBUF_SZ as DWORD,
888+ ptr::null());
889+ if res == 0 {
890+ die!(fmt!(" [ %?] FormatMessage failure", errno()));
891+ }
892+
893+ str::raw::from_c_str(&buf[0])
894+ }
773895 }
896+
897+ strerror()
774898}
775899
776900/**
0 commit comments