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