about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2013-02-12 21:27:22 -0800
committerbors <bors@rust-lang.org>2013-02-12 21:27:22 -0800
commit6016214101d40c627f2c52412fb77d56254c901e (patch)
tree501c5e07c3e50246ca3c202d4935dc18552ff013 /src
parent27b3e01377ff9b25a38a76937c3d14cd9d0fb2b0 (diff)
parent2180fe25520727a747c5a73b4d582a120ad116bd (diff)
downloadrust-6016214101d40c627f2c52412fb77d56254c901e.tar.gz
rust-6016214101d40c627f2c52412fb77d56254c901e.zip
auto merge of #4900 : luqmana/rust/core_os_errors, r=graydon
Rewrote the last pull request (#4859) to not require on llvm for core.

Also fixes #2269.
Diffstat (limited to 'src')
-rw-r--r--src/libcore/os.rs144
-rw-r--r--src/rt/rust_builtin.cpp44
-rw-r--r--src/rt/rustrt.def.in1
-rw-r--r--src/test/auxiliary/anon-extern-mod-cross-crate-1.rs2
-rw-r--r--src/test/auxiliary/foreign_lib.rs2
-rw-r--r--src/test/run-fail/morestack2.rs4
-rw-r--r--src/test/run-pass/anon-extern-mod-cross-crate-2.rs2
-rw-r--r--src/test/run-pass/anon-extern-mod.rs4
-rw-r--r--src/test/run-pass/foreign-dupe.rs8
-rw-r--r--src/test/run-pass/invoke-external-foreign.rs2
-rw-r--r--src/test/run-pass/morestack6.rs4
11 files changed, 148 insertions, 69 deletions
diff --git a/src/libcore/os.rs b/src/libcore/os.rs
index 38469c35cfa..0efc17354dd 100644
--- a/src/libcore/os.rs
+++ b/src/libcore/os.rs
@@ -62,11 +62,10 @@ extern mod rustrt {
     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 last_os_error() -> ~str;
     unsafe fn rust_set_exit_status(code: libc::intptr_t);
 }
 
-pub const tmpbuf_sz : uint = 1000u;
+pub const TMPBUF_SZ : uint = 1000u;
 
 pub fn getcwd() -> Path {
     unsafe {
@@ -80,7 +79,7 @@ pub fn as_c_charp<T>(s: &str, f: fn(*c_char) -> T) -> T {
 
 pub fn fill_charp_buf(f: fn(*mut c_char, size_t) -> bool)
     -> Option<~str> {
-    let buf = vec::cast_to_mut(vec::from_elem(tmpbuf_sz, 0u8 as c_char));
+    let buf = vec::cast_to_mut(vec::from_elem(TMPBUF_SZ, 0u8 as c_char));
     do vec::as_mut_buf(buf) |b, sz| {
         if f(b, sz as size_t) {
             unsafe {
@@ -99,19 +98,19 @@ pub mod win32 {
     use str;
     use option::{None, Option};
     use option;
-    use os::tmpbuf_sz;
+    use os::TMPBUF_SZ;
     use libc::types::os::arch::extra::DWORD;
 
     pub fn fill_utf16_buf_and_decode(f: fn(*mut u16, DWORD) -> DWORD)
         -> Option<~str> {
         unsafe {
-            let mut n = tmpbuf_sz as DWORD;
+            let mut n = TMPBUF_SZ as DWORD;
             let mut res = None;
             let mut done = false;
             while !done {
                 let buf = vec::cast_to_mut(vec::from_elem(n as uint, 0u16));
                 do vec::as_mut_buf(buf) |b, _sz| {
-                    let k : DWORD = f(b, tmpbuf_sz as DWORD);
+                    let k : DWORD = f(b, TMPBUF_SZ as DWORD);
                     if k == (0 as DWORD) {
                         done = true;
                     } else if (k == n &&
@@ -387,11 +386,11 @@ pub fn self_exe_path() -> Option<Path> {
         unsafe {
             use libc::funcs::posix01::unistd::readlink;
 
-            let mut path_str = str::with_capacity(tmpbuf_sz);
+            let mut path_str = str::with_capacity(TMPBUF_SZ);
             let len = do str::as_c_str(path_str) |buf| {
                 let buf = buf as *mut c_char;
                 do as_c_charp("/proc/self/exe") |proc_self_buf| {
-                    readlink(proc_self_buf, buf, tmpbuf_sz as size_t)
+                    readlink(proc_self_buf, buf, TMPBUF_SZ as size_t)
                 }
             };
             if len == -1 {
@@ -766,11 +765,136 @@ pub fn remove_file(p: &Path) -> bool {
     }
 }
 
+#[cfg(unix)]
+pub fn errno() -> int {
+    #[cfg(target_os = "macos")]
+    #[cfg(target_os = "freebsd")]
+    fn errno_location() -> *c_int {
+        #[nolink]
+        extern {
+            unsafe fn __error() -> *c_int;
+        }
+        unsafe {
+            __error()
+        }
+    }
+
+    #[cfg(target_os = "linux")]
+    #[cfg(target_os = "android")]
+    fn errno_location() -> *c_int {
+        #[nolink]
+        extern {
+            unsafe fn __errno_location() -> *c_int;
+        }
+        unsafe {
+            __errno_location()
+        }
+    }
+
+    unsafe {
+        (*errno_location()) as int
+    }
+}
+
+#[cfg(windows)]
+pub fn errno() -> uint {
+    use libc::types::os::arch::extra::DWORD;
+
+    #[link_name = "kernel32"]
+    #[abi = "stdcall"]
+    extern {
+        unsafe fn GetLastError() -> DWORD;
+    }
+
+    unsafe {
+        GetLastError() as uint
+    }
+}
+
 /// Get a string representing the platform-dependent last error
 pub fn last_os_error() -> ~str {
-    unsafe {
-        rustrt::last_os_error()
+    #[cfg(unix)]
+    fn strerror() -> ~str {
+        #[cfg(target_os = "macos")]
+        #[cfg(target_os = "android")]
+        #[cfg(target_os = "freebsd")]
+        fn strerror_r(errnum: c_int, buf: *c_char, buflen: size_t) -> c_int {
+            #[nolink]
+            extern {
+                unsafe fn strerror_r(errnum: c_int, buf: *c_char,
+                                     buflen: size_t) -> c_int;
+            }
+            unsafe {
+                strerror_r(errnum, buf, buflen)
+            }
+        }
+
+        // GNU libc provides a non-compliant version of strerror_r by default
+        // and requires macros to instead use the POSIX compliant variant.
+        // So we just use __xpg_strerror_r which is always POSIX compliant
+        #[cfg(target_os = "linux")]
+        fn strerror_r(errnum: c_int, buf: *c_char, buflen: size_t) -> c_int {
+            #[nolink]
+            extern {
+                unsafe fn __xpg_strerror_r(errnum: c_int, buf: *c_char,
+                                           buflen: size_t) -> c_int;
+            }
+            unsafe {
+                __xpg_strerror_r(errnum, buf, buflen)
+            }
+        }
+
+        let mut buf = [0 as c_char, ..TMPBUF_SZ];
+        unsafe {
+            let err = strerror_r(errno() as c_int, &buf[0],
+                                 TMPBUF_SZ as size_t);
+            if err < 0 {
+                die!(~"strerror_r failure");
+            }
+
+            str::raw::from_c_str(&buf[0])
+        }
+    }
+
+    #[cfg(windows)]
+    fn strerror() -> ~str {
+        use libc::types::os::arch::extra::DWORD;
+        use libc::types::os::arch::extra::LPSTR;
+        use libc::types::os::arch::extra::LPVOID;
+
+        #[link_name = "kernel32"]
+        #[abi = "stdcall"]
+        extern {
+            unsafe fn FormatMessageA(flags: DWORD, lpSrc: LPVOID,
+                                     msgId: DWORD, langId: DWORD,
+                                     buf: LPSTR, nsize: DWORD,
+                                     args: *c_void) -> DWORD;
+        }
+
+        const FORMAT_MESSAGE_FROM_SYSTEM: DWORD = 0x00001000;
+        const FORMAT_MESSAGE_IGNORE_INSERTS: DWORD = 0x00000200;
+
+        let mut buf = [0 as c_char, ..TMPBUF_SZ];
+
+        // This value is calculated from the macro
+        // MAKELANGID(LANG_SYSTEM_DEFAULT, SUBLANG_SYS_DEFAULT)
+        let langId = 0x0800 as DWORD;
+        let err = errno() as DWORD;
+        unsafe {
+            let res = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM |
+                                     FORMAT_MESSAGE_IGNORE_INSERTS,
+                                     ptr::mut_null(), err, langId,
+                                     &mut buf[0], TMPBUF_SZ as DWORD,
+                                     ptr::null());
+            if res == 0 {
+                die!(fmt!("[%?] FormatMessage failure", errno()));
+            }
+
+            str::raw::from_c_str(&buf[0])
+        }
     }
+
+    strerror()
 }
 
 /**
diff --git a/src/rt/rust_builtin.cpp b/src/rt/rust_builtin.cpp
index 7c1d1a8ed16..86f371a30f3 100644
--- a/src/rt/rust_builtin.cpp
+++ b/src/rt/rust_builtin.cpp
@@ -52,50 +52,6 @@ timegm(struct tm *tm)
 }
 #endif
 
-
-extern "C" CDECL rust_str*
-last_os_error() {
-    rust_task *task = rust_get_current_task();
-
-    LOG(task, task, "last_os_error()");
-
-#if defined(__WIN32__)
-    LPTSTR buf;
-    DWORD err = GetLastError();
-    DWORD res = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
-                              FORMAT_MESSAGE_FROM_SYSTEM |
-                              FORMAT_MESSAGE_IGNORE_INSERTS,
-                              NULL, err,
-                              MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
-                              (LPTSTR) &buf, 0, NULL);
-    if (!res) {
-        task->fail();
-        return NULL;
-    }
-#elif defined(_GNU_SOURCE) && !defined(__ANDROID__)
-    char cbuf[BUF_BYTES];
-    char *buf = strerror_r(errno, cbuf, sizeof(cbuf));
-    if (!buf) {
-        task->fail();
-        return NULL;
-    }
-#else
-    char buf[BUF_BYTES];
-    int err = strerror_r(errno, buf, sizeof(buf));
-    if (err) {
-        task->fail();
-        return NULL;
-    }
-#endif
-
-    rust_str * st = make_str(task->kernel, buf, strlen(buf),
-                             "last_os_error");
-#ifdef __WIN32__
-    LocalFree((HLOCAL)buf);
-#endif
-    return st;
-}
-
 extern "C" CDECL rust_str *
 rust_getcwd() {
     rust_task *task = rust_get_current_task();
diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in
index 03b18d026ad..c554489c4b3 100644
--- a/src/rt/rustrt.def.in
+++ b/src/rt/rustrt.def.in
@@ -14,7 +14,6 @@ rust_gmtime
 rust_localtime
 rust_timegm
 rust_mktime
-last_os_error
 new_task
 precise_time_ns
 rand_free
diff --git a/src/test/auxiliary/anon-extern-mod-cross-crate-1.rs b/src/test/auxiliary/anon-extern-mod-cross-crate-1.rs
index bbe36f18d6c..bccbb8173aa 100644
--- a/src/test/auxiliary/anon-extern-mod-cross-crate-1.rs
+++ b/src/test/auxiliary/anon-extern-mod-cross-crate-1.rs
@@ -15,5 +15,5 @@
 
 #[crate_type = "lib"];
 extern {
-  fn last_os_error() -> ~str;
+  fn rust_get_argc() -> libc::c_int;
 }
diff --git a/src/test/auxiliary/foreign_lib.rs b/src/test/auxiliary/foreign_lib.rs
index eb3397a8a5f..1d9c1cdbf83 100644
--- a/src/test/auxiliary/foreign_lib.rs
+++ b/src/test/auxiliary/foreign_lib.rs
@@ -11,5 +11,5 @@
 #[link(name="foreign_lib", vers="0.0")];
 
 pub extern mod rustrt {
-    pub fn last_os_error() -> ~str;
+    pub fn rust_get_argc() -> libc::c_int;
 }
diff --git a/src/test/run-fail/morestack2.rs b/src/test/run-fail/morestack2.rs
index 58957aac203..8236489834d 100644
--- a/src/test/run-fail/morestack2.rs
+++ b/src/test/run-fail/morestack2.rs
@@ -18,7 +18,7 @@
 extern mod std;
 
 extern mod rustrt {
-    pub fn last_os_error() -> ~str;
+    pub fn rust_get_argc() -> libc::c_int;
 }
 
 fn getbig_call_c_and_fail(i: int) {
@@ -26,7 +26,7 @@ fn getbig_call_c_and_fail(i: int) {
         getbig_call_c_and_fail(i - 1);
     } else {
         unsafe {
-            rustrt::last_os_error();
+            rustrt::rust_get_argc();
             die!();
         }
     }
diff --git a/src/test/run-pass/anon-extern-mod-cross-crate-2.rs b/src/test/run-pass/anon-extern-mod-cross-crate-2.rs
index 939903b3b12..ed57b32b3d9 100644
--- a/src/test/run-pass/anon-extern-mod-cross-crate-2.rs
+++ b/src/test/run-pass/anon-extern-mod-cross-crate-2.rs
@@ -15,5 +15,5 @@ extern mod anonexternmod;
 use anonexternmod::*;
 
 pub fn main() {
-  last_os_error();
+  rust_get_argc();
 }
diff --git a/src/test/run-pass/anon-extern-mod.rs b/src/test/run-pass/anon-extern-mod.rs
index 525e6b9fbd6..6e73022fad2 100644
--- a/src/test/run-pass/anon-extern-mod.rs
+++ b/src/test/run-pass/anon-extern-mod.rs
@@ -11,11 +11,11 @@
 #[abi = "cdecl"]
 #[link_name = "rustrt"]
 extern {
-    fn last_os_error() -> ~str;
+    fn rust_get_argc() -> libc::c_int;
 }
 
 pub fn main() {
     unsafe {
-        let _ = last_os_error();
+        let _ = rust_get_argc();
     }
 }
diff --git a/src/test/run-pass/foreign-dupe.rs b/src/test/run-pass/foreign-dupe.rs
index 77ed95a8099..6230fe11363 100644
--- a/src/test/run-pass/foreign-dupe.rs
+++ b/src/test/run-pass/foreign-dupe.rs
@@ -14,18 +14,18 @@
 #[abi = "cdecl"]
 #[link_name = "rustrt"]
 extern mod rustrt1 {
-    pub fn last_os_error() -> ~str;
+    pub fn rust_get_argc() -> libc::c_int;
 }
 
 #[abi = "cdecl"]
 #[link_name = "rustrt"]
 extern mod rustrt2 {
-    pub fn last_os_error() -> ~str;
+    pub fn rust_get_argc() -> libc::c_int;
 }
 
 pub fn main() {
     unsafe {
-        rustrt1::last_os_error();
-        rustrt2::last_os_error();
+        rustrt1::rust_get_argc();
+        rustrt2::rust_get_argc();
     }
 }
diff --git a/src/test/run-pass/invoke-external-foreign.rs b/src/test/run-pass/invoke-external-foreign.rs
index cc50e06199d..69fce9e541e 100644
--- a/src/test/run-pass/invoke-external-foreign.rs
+++ b/src/test/run-pass/invoke-external-foreign.rs
@@ -18,5 +18,5 @@
 extern mod foreign_lib;
 
 pub fn main() {
-    let foo = foreign_lib::rustrt::last_os_error();
+    let foo = foreign_lib::rustrt::rust_get_argc();
 }
diff --git a/src/test/run-pass/morestack6.rs b/src/test/run-pass/morestack6.rs
index 9b852cbc635..d56d9c30b70 100644
--- a/src/test/run-pass/morestack6.rs
+++ b/src/test/run-pass/morestack6.rs
@@ -15,7 +15,7 @@ extern mod rustrt {
     pub fn debug_get_stk_seg() -> *u8;
 
     pub fn rust_get_sched_id() -> libc::intptr_t;
-    pub fn last_os_error() -> ~str;
+    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();
@@ -23,7 +23,7 @@ extern mod rustrt {
 }
 
 fn calllink01() { unsafe { rustrt::rust_get_sched_id(); } }
-fn calllink02() { unsafe { rustrt::last_os_error(); } }
+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(); } }