Add std::os::get_exe_path

Need this to correctly determine sysroot in rustc
This commit is contained in:
Brian Anderson 2011-10-04 13:35:39 -07:00
parent a0a4d34e14
commit a8ce543dc9
5 changed files with 68 additions and 2 deletions

View file

@ -2,3 +2,4 @@
type size_t = uint;
type ssize_t = int;
type uint32_t = u32;

View file

@ -1,5 +1,3 @@
// FIXME Somehow merge stuff duplicated here and macosx_os.rs. Made difficult
// by https://github.com/graydon/rust/issues#issue/268
native "cdecl" mod libc = "" {
@ -28,6 +26,8 @@ native "cdecl" mod libc = "" {
fn unsetenv(n: str::sbuf) -> int;
fn pipe(buf: *mutable int) -> int;
fn waitpid(pid: int, &status: int, options: int) -> int;
fn readlink(path: str::sbuf, buf: str::sbuf,
bufsize: ctypes::size_t) -> ctypes::ssize_t;
}
mod libc_constants {
@ -78,6 +78,21 @@ native "rust" mod rustrt {
fn getcwd() -> str { ret rustrt::rust_getcwd(); }
/// Returns the directory containing the running program
/// followed by a path separator
fn get_exe_path() -> option::t<fs::path> {
let bufsize = 1023u;
let path = str::unsafe_from_bytes(vec::init_elt(0u8, bufsize));
ret str::as_buf("/proc/self/exe", { |proc_self_buf|
str::as_buf(path, { |path_buf|
if libc::readlink(proc_self_buf, path_buf, bufsize) != -1 {
option::some(fs::dirname(path) + fs::path_sep())
} else {
option::none
}
})
});
}
// Local Variables:
// mode: rust;

View file

@ -25,6 +25,8 @@ native "cdecl" mod libc = "" {
fn unsetenv(n: str::sbuf) -> int;
fn pipe(buf: *mutable int) -> int;
fn waitpid(pid: int, &status: int, options: int) -> int;
fn _NSGetExecutablePath(buf: str::sbuf,
bufsize: *mutable ctypes::uint32_t) -> int;
}
mod libc_constants {
@ -75,6 +77,18 @@ native "rust" mod rustrt {
fn getcwd() -> str { ret rustrt::rust_getcwd(); }
fn get_exe_path() -> option::t<fs::path> {
// FIXME: This doesn't handle the case where the buffer is too small
let bufsize = 1023u32;
let path = str::unsafe_from_bytes(vec::init_elt(0u8, bufsize as uint));
ret str::as_buf(path, { |path_buf|
if libc::_NSGetExecutablePath(path_buf, ptr::addr_of(bufsize)) == 0 {
option::some(fs::dirname(path) + fs::path_sep())
} else {
option::none
}
});
}
// Local Variables:
// mode: rust;

View file

@ -39,10 +39,17 @@ mod libc_constants {
}
}
type DWORD = u32;
type HMODULE = uint;
type LPTSTR = str::sbuf;
native "x86stdcall" mod kernel32 {
fn GetEnvironmentVariableA(n: str::sbuf, v: str::sbuf, nsize: uint) ->
uint;
fn SetEnvironmentVariableA(n: str::sbuf, v: str::sbuf) -> int;
fn GetModuleFileNameA(hModule: HMODULE,
lpFilename: LPTSTR,
nSize: DWORD) -> DWORD;
}
fn exec_suffix() -> str { ret ".exe"; }
@ -81,6 +88,20 @@ fn waitpid(pid: int) -> int { ret rustrt::rust_process_wait(pid); }
fn getcwd() -> str { ret rustrt::rust_getcwd(); }
fn get_exe_path() -> option::t<fs::path> {
// FIXME: This doesn't handle the case where the buffer is too small
let bufsize = 1023u;
let path = str::unsafe_from_bytes(vec::init_elt(0u8, bufsize));
ret str::as_buf(path, { |path_buf|
if kernel32::GetModuleFileNameA(0u, path_buf,
bufsize as u32) != 0u32 {
option::some(fs::dirname(path) + fs::path_sep())
} else {
option::none
}
});
}
// Local Variables:
// mode: rust;
// fill-column: 78;

View file

@ -28,6 +28,21 @@ fn test_getenv_big() {
assert (getenv("NAME3") == option::some(s));
}
#[test]
fn get_exe_path() {
let path = std::os::get_exe_path();
assert option::is_some(path);
let path = option::get(path);
log path;
// Hard to test this function
if std::os::target_os() != "win32" {
assert std::str::starts_with(path, std::fs::path_sep());
} else {
assert path[1] == ':' as u8;
}
}
// Local Variables:
// mode: rust;
// fill-column: 78;