about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBrian Anderson <banderson@mozilla.com>2011-10-04 13:35:39 -0700
committerBrian Anderson <banderson@mozilla.com>2011-10-04 21:35:06 -0700
commita8ce543dc937043f2988a856c0c43339eadf8d69 (patch)
treec901752717bf2627bc987a4698a5c47918410366
parenta0a4d34e141a7a6445457e27fe18d875fb57d9d5 (diff)
Add std::os::get_exe_path
Need this to correctly determine sysroot in rustc
-rw-r--r--src/lib/ctypes.rs1
-rw-r--r--src/lib/linux_os.rs19
-rw-r--r--src/lib/macos_os.rs14
-rw-r--r--src/lib/win32_os.rs21
-rw-r--r--src/test/stdtest/os.rs15
5 files changed, 68 insertions, 2 deletions
diff --git a/src/lib/ctypes.rs b/src/lib/ctypes.rs
index f5d625f1880..7e876ed7602 100644
--- a/src/lib/ctypes.rs
+++ b/src/lib/ctypes.rs
@@ -2,3 +2,4 @@
 type size_t = uint;
 type ssize_t = int;
 
+type uint32_t = u32;
diff --git a/src/lib/linux_os.rs b/src/lib/linux_os.rs
index 7ce8c05b095..563d10092cb 100644
--- a/src/lib/linux_os.rs
+++ b/src/lib/linux_os.rs
@@ -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;
diff --git a/src/lib/macos_os.rs b/src/lib/macos_os.rs
index 2897551d80a..aaf682b23ba 100644
--- a/src/lib/macos_os.rs
+++ b/src/lib/macos_os.rs
@@ -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;
diff --git a/src/lib/win32_os.rs b/src/lib/win32_os.rs
index 7cd3f58cdca..560d9be8c8e 100644
--- a/src/lib/win32_os.rs
+++ b/src/lib/win32_os.rs
@@ -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;
diff --git a/src/test/stdtest/os.rs b/src/test/stdtest/os.rs
index 49ebb217dbf..2d17afddc95 100644
--- a/src/test/stdtest/os.rs
+++ b/src/test/stdtest/os.rs
@@ -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;