Skip to content

Move rustrt::last_os_error into core #4900

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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