diff --git a/msvs/libuv-test.vcxproj b/msvs/libuv-test.vcxproj
index 7d1922a3..e38b11b7 100644
--- a/msvs/libuv-test.vcxproj
+++ b/msvs/libuv-test.vcxproj
@@ -147,6 +147,7 @@
+
diff --git a/test/runner-unix.c b/test/runner-unix.c
index 7af10c45..9f74d16e 100644
--- a/test/runner-unix.c
+++ b/test/runner-unix.c
@@ -37,10 +37,6 @@
#include
#include
-#define PATHMAX 1024
-static char executable_path[PATHMAX] = { '\0' };
-
-
#ifdef __APPLE__
#include /* _NSGetExecutablePath */
diff --git a/test/runner-win.c b/test/runner-win.c
index a91b7d5f..09458a6b 100644
--- a/test/runner-win.c
+++ b/test/runner-win.c
@@ -47,6 +47,8 @@ void platform_init(int argc, char **argv) {
/* Disable stdio output buffering. */
setvbuf(stdout, NULL, _IONBF, 0);
setvbuf(stderr, NULL, _IONBF, 0);
+
+ strcpy(executable_path, argv[0]);
}
diff --git a/test/runner.c b/test/runner.c
index f7caff79..00214c77 100644
--- a/test/runner.c
+++ b/test/runner.c
@@ -24,6 +24,7 @@
#include "runner.h"
#include "task.h"
+char executable_path[PATHMAX] = { '\0' };
/* Start a specific process declared by TEST_ENTRY or TEST_HELPER. */
/* Returns the exit code of the specific process. */
diff --git a/test/runner.h b/test/runner.h
index a6af951f..11d49802 100644
--- a/test/runner.h
+++ b/test/runner.h
@@ -79,6 +79,8 @@ int run_task(task_entry_t *test, int timeout, int benchmark_output);
#define TEST_HELPER HELPER_ENTRY
#define BENCHMARK_HELPER HELPER_ENTRY
+#define PATHMAX 1024
+extern char executable_path[PATHMAX];
/*
* Include platform-dependent definitions
diff --git a/test/test-get-currentexe.c b/test/test-get-currentexe.c
new file mode 100644
index 00000000..880d9cd6
--- /dev/null
+++ b/test/test-get-currentexe.c
@@ -0,0 +1,53 @@
+/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "../uv.h"
+#include "task.h"
+#include
+
+#define PATHMAX 1024
+extern char executable_path[];
+
+TEST_IMPL(get_currentexe) {
+ char buffer[PATHMAX];
+ size_t size;
+ char* match;
+ int r;
+
+ size = sizeof(buffer) / sizeof(buffer[0]);
+ r = uv_get_exepath(buffer, &size);
+ ASSERT(!r);
+
+ match = strstr(buffer, executable_path);
+ /* Verify that the path returned from uv_get_exepath is a subdirectory of executable_path */
+ ASSERT(match && !strcmp(match, executable_path));
+ ASSERT(size == strlen(buffer));
+
+ /* Negative tests */
+ size = sizeof(buffer) / sizeof(buffer[0]);
+ r = uv_get_exepath(NULL, &size);
+ ASSERT(r == -1);
+
+ r = uv_get_exepath(buffer, NULL);
+ ASSERT(r == -1);
+
+ return 0;
+}
diff --git a/test/test-list.h b/test/test-list.h
index 499d6503..f5f633cb 100644
--- a/test/test-list.h
+++ b/test/test-list.h
@@ -38,6 +38,7 @@ TEST_DECLARE (async_ref)
TEST_DECLARE (prepare_ref)
TEST_DECLARE (check_ref)
TEST_DECLARE (async)
+TEST_DECLARE (get_currentexe)
TEST_DECLARE (fail_always)
TEST_DECLARE (pass_always)
HELPER_DECLARE (echo_server)
@@ -80,6 +81,8 @@ TASK_LIST_START
TEST_ENTRY (async)
+ TEST_ENTRY (get_currentexe)
+
#if 0
/* These are for testing the test runner. */
TEST_ENTRY (fail_always)
diff --git a/uv-unix.c b/uv-unix.c
index c92e6492..2bd9df7d 100644
--- a/uv-unix.c
+++ b/uv-unix.c
@@ -31,7 +31,11 @@
#include
#include
#include
+#include /* PATH_MAX */
+#if defined(__APPLE__)
+#include /* _NSGetExecutablePath */
+#endif
static uv_err_t last_err;
static uv_alloc_cb alloc_cb;
@@ -1204,3 +1208,34 @@ int64_t uv_timer_get_repeat(uv_handle_t* handle) {
return (int64_t)(1000 * handle->timer_watcher.repeat);
}
+int uv_get_exepath(char* buffer, size_t* size) {
+ if (!buffer || !size) {
+ return -1;
+ }
+
+#if defined(__APPLE__)
+ uint32_t usize = *size;
+ int result = _NSGetExecutablePath(buffer, &usize);
+ if (result) return result;
+
+ char *path = (char*)malloc(2 * PATH_MAX);
+ char *fullpath = realpath(buffer, path);
+ if (fullpath == NULL) {
+ free(path);
+ return -1;
+ }
+
+ strncpy(buffer, fullpath, *size);
+ free(fullpath);
+ *size = strlen(buffer);
+ return 0;
+#elif defined(__linux__)
+ *size = readlink("/proc/self/exe", buffer, *size - 1);
+ if (*size <= 0) return -1;
+ buffer[*size] = '\0';
+ return 0;
+#else
+ assert(0 && "implement me");
+ /* Need to return argv[0] */
+#endif
+}
diff --git a/uv-win.c b/uv-win.c
index c25bb706..6db7a021 100644
--- a/uv-win.c
+++ b/uv-win.c
@@ -1626,3 +1626,18 @@ void uv_ref() {
void uv_unref() {
uv_refs_--;
}
+
+int uv_get_exepath(char* buffer, size_t* size) {
+ if (!buffer || !size) {
+ return -1;
+ }
+
+ *size = GetModuleFileName(NULL, buffer, *size - 1);
+ if (*size <= 0) {
+ uv_set_sys_error(GetLastError());
+ return -1;
+ }
+
+ buffer[*size] = '\0';
+ return 0;
+}
diff --git a/uv.h b/uv.h
index 0b4984bf..d29e659c 100644
--- a/uv.h
+++ b/uv.h
@@ -291,6 +291,9 @@ int uv_close(uv_handle_t* handle);
/* Utility */
struct sockaddr_in uv_ip4_addr(char* ip, int port);
+/* Gets the executable path */
+int uv_get_exepath(char* buffer, size_t* size);
+
#ifdef __cplusplus
}
#endif