Skip to content

Commit

Permalink
auto merge of rust-lang#4900 : luqmana/rust/core_os_errors, r=graydon
Browse files Browse the repository at this point in the history
Rewrote the last pull request (rust-lang#4859) to not require on llvm for core.

Also fixes rust-lang#2269.
  • Loading branch information
bors committed Feb 13, 2013
2 parents 27b3e01 + 2180fe2 commit 6016214
Show file tree
Hide file tree
Showing 11 changed files with 148 additions and 69 deletions.
144 changes: 134 additions & 10 deletions src/libcore/os.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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 {
Expand All @@ -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 &&
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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()
}
/**
Expand Down
44 changes: 0 additions & 44 deletions src/rt/rust_builtin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
1 change: 0 additions & 1 deletion src/rt/rustrt.def.in
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ rust_gmtime
rust_localtime
rust_timegm
rust_mktime
last_os_error
new_task
precise_time_ns
rand_free
Expand Down
2 changes: 1 addition & 1 deletion src/test/auxiliary/anon-extern-mod-cross-crate-1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,5 @@

#[crate_type = "lib"];
extern {
fn last_os_error() -> ~str;
fn rust_get_argc() -> libc::c_int;
}
2 changes: 1 addition & 1 deletion src/test/auxiliary/foreign_lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
4 changes: 2 additions & 2 deletions src/test/run-fail/morestack2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,15 @@
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) {
if i != 0 {
getbig_call_c_and_fail(i - 1);
} else {
unsafe {
rustrt::last_os_error();
rustrt::rust_get_argc();
die!();
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/test/run-pass/anon-extern-mod-cross-crate-2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,5 @@ extern mod anonexternmod;
use anonexternmod::*;

pub fn main() {
last_os_error();
rust_get_argc();
}
4 changes: 2 additions & 2 deletions src/test/run-pass/anon-extern-mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
}
8 changes: 4 additions & 4 deletions src/test/run-pass/foreign-dupe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
}
2 changes: 1 addition & 1 deletion src/test/run-pass/invoke-external-foreign.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
4 changes: 2 additions & 2 deletions src/test/run-pass/morestack6.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@ 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();
pub fn rust_get_task();
}

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(); } }
Expand Down

0 comments on commit 6016214

Please sign in to comment.