unix,win: introduce uv_exepath2
Fixes: https://github.com/libuv/libuv/issues/4911 Signed-off-by: Juan José Arboleda <soyjuanarbol@gmail.com>
This commit is contained in:
parent
12d1ed1380
commit
b05665a380
@ -522,6 +522,17 @@ API
|
||||
Gets the executable path. You *must* call `uv_setup_args` before calling
|
||||
this function.
|
||||
|
||||
.. c:function:: int uv_exepath2(char* buffer, size_t* size)
|
||||
|
||||
Like :c:func:`uv_exepath`, but returns :c:macro:`UV_ENOBUFS` if ``buffer``
|
||||
is too small and sets ``*size`` to the required length (including NUL). On
|
||||
success, ``*size`` is set to the path length *excluding* the NUL byte.
|
||||
Returns :c:macro:`UV_ENOTSUP` on unsupported platforms.
|
||||
|
||||
You *must* call :c:func:`uv_setup_args` before using this function.
|
||||
|
||||
.. versionadded:: 1.52.0
|
||||
|
||||
.. c:function:: int uv_cwd(char* buffer, size_t* size)
|
||||
|
||||
Gets the current working directory, and stores it in `buffer`. If the
|
||||
|
||||
@ -1824,6 +1824,7 @@ UV_EXTERN int uv_if_indextoiid(unsigned int ifindex,
|
||||
size_t* size);
|
||||
|
||||
UV_EXTERN int uv_exepath(char* buffer, size_t* size);
|
||||
UV_EXTERN int uv_exepath2(char* buffer, size_t* size);
|
||||
|
||||
UV_EXTERN int uv_cwd(char* buffer, size_t* size);
|
||||
|
||||
|
||||
@ -57,7 +57,7 @@ uint64_t uv__hrtime(uv_clocktype_t type) {
|
||||
* or through some libc APIs. The below approach is to parse the argv[0]'s pattern
|
||||
* and use it in conjunction with PATH environment variable to craft one.
|
||||
*/
|
||||
int uv_exepath(char* buffer, size_t* size) {
|
||||
int uv__exepath(char* buffer, size_t* size, int return_enobufs) {
|
||||
int res;
|
||||
char args[UV__PATH_MAX];
|
||||
size_t cached_len;
|
||||
@ -73,6 +73,12 @@ int uv_exepath(char* buffer, size_t* size) {
|
||||
*size -= 1;
|
||||
if (*size > cached_len)
|
||||
*size = cached_len;
|
||||
|
||||
if (return_enobufs && cached_len > *size) {
|
||||
uv_mutex_unlock(&process_title_mutex);
|
||||
return UV_ENOBUFS;
|
||||
}
|
||||
|
||||
memcpy(buffer, original_exepath, *size);
|
||||
buffer[*size] = '\0';
|
||||
uv_mutex_unlock(&process_title_mutex);
|
||||
|
||||
@ -63,7 +63,7 @@ uint64_t uv__hrtime(uv_clocktype_t type) {
|
||||
}
|
||||
|
||||
|
||||
int uv_exepath(char* buffer, size_t* size) {
|
||||
int uv__exepath(char* buffer, size_t* size, int return_enobufs) {
|
||||
/* realpath(exepath) may be > PATH_MAX so double it to be on the safe side. */
|
||||
char abspath[PATH_MAX * 2 + 1];
|
||||
char exepath[PATH_MAX + 1];
|
||||
@ -84,6 +84,10 @@ int uv_exepath(char* buffer, size_t* size) {
|
||||
if (abspath_size == 0)
|
||||
return UV_EIO;
|
||||
|
||||
/* Return ENOBUFS if resize is requested and buffer is too small. */
|
||||
if (return_enobufs && *size < abspath_size)
|
||||
return UV_ENOBUFS;
|
||||
|
||||
*size -= 1;
|
||||
if (*size > abspath_size)
|
||||
*size = abspath_size;
|
||||
|
||||
@ -61,7 +61,8 @@ int uv__platform_loop_init(uv_loop_t* loop) {
|
||||
void uv__platform_loop_delete(uv_loop_t* loop) {
|
||||
}
|
||||
|
||||
int uv_exepath(char* buffer, size_t* size) {
|
||||
|
||||
int uv__exepath(char* buffer, size_t* size, int return_enobufs) {
|
||||
char abspath[PATH_MAX * 2 + 1];
|
||||
int mib[4];
|
||||
size_t abspath_size;
|
||||
@ -82,6 +83,9 @@ int uv_exepath(char* buffer, size_t* size) {
|
||||
abspath_size -= 1;
|
||||
*size -= 1;
|
||||
|
||||
if (return_enobufs && *size < abspath_size)
|
||||
return UV_ENOBUFS;
|
||||
|
||||
if (*size > abspath_size)
|
||||
*size = abspath_size;
|
||||
|
||||
@ -91,6 +95,7 @@ int uv_exepath(char* buffer, size_t* size) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
uint64_t uv_get_free_memory(void) {
|
||||
int freecount;
|
||||
size_t size = sizeof(freecount);
|
||||
|
||||
@ -33,7 +33,7 @@ void uv_loadavg(double avg[3]) {
|
||||
}
|
||||
|
||||
|
||||
int uv_exepath(char* buffer, size_t* size) {
|
||||
int uv__exepath(char* buffer, size_t* size, int return_enobufs) {
|
||||
char abspath[B_PATH_NAME_LENGTH];
|
||||
status_t status;
|
||||
ssize_t abspath_len;
|
||||
@ -46,10 +46,16 @@ int uv_exepath(char* buffer, size_t* size) {
|
||||
if (status != B_OK)
|
||||
return UV__ERR(status);
|
||||
|
||||
abspath_len = uv__strscpy(buffer, abspath, *size);
|
||||
abspath_len = strlen(abspath);
|
||||
*size -= 1;
|
||||
if (abspath_len >= 0 && *size > (size_t)abspath_len)
|
||||
*size = (size_t)abspath_len;
|
||||
if (return_enobufs && *size < (size_t) abspath_len) {
|
||||
*size = (size_t)abspath_len + 1;
|
||||
return UV_ENOBUFS;
|
||||
}
|
||||
|
||||
abspath_len = uv__strscpy(buffer, abspath, *size);
|
||||
if (abspath_len >= 0 && *size > (size_t) abspath_len)
|
||||
*size = (size_t) abspath_len;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -36,7 +36,7 @@
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
|
||||
int uv_exepath(char* buffer, size_t* size) {
|
||||
int uv__exepath(char* buffer, size_t* size, int return_enobufs) {
|
||||
kern_return_t err;
|
||||
/* XXX in current Hurd, strings are char arrays of 1024 elements */
|
||||
string_t exepath;
|
||||
@ -45,6 +45,9 @@ int uv_exepath(char* buffer, size_t* size) {
|
||||
if (buffer == NULL || size == NULL || *size == 0)
|
||||
return UV_EINVAL;
|
||||
|
||||
if (return_enobufs)
|
||||
return UV_ENOTSUP;
|
||||
|
||||
if (*size - 1 > 0) {
|
||||
/* XXX limited length of buffer in current Hurd, this API will probably
|
||||
* evolve in the future */
|
||||
|
||||
@ -63,13 +63,14 @@ void uv_loadavg(double avg[3]) {
|
||||
}
|
||||
|
||||
|
||||
int uv_exepath(char* buffer, size_t* size) {
|
||||
int uv__exepath(char* buffer, size_t* size, int return_enobufs) {
|
||||
/* Intermediate buffer, retrieving partial path name does not work
|
||||
* As of NetBSD-8(beta), vnode->path translator does not handle files
|
||||
* with longer names than 31 characters.
|
||||
*/
|
||||
char int_buf[PATH_MAX];
|
||||
size_t int_size;
|
||||
size_t required;
|
||||
int mib[4];
|
||||
|
||||
if (buffer == NULL || size == NULL || *size == 0)
|
||||
@ -84,6 +85,14 @@ int uv_exepath(char* buffer, size_t* size) {
|
||||
if (sysctl(mib, 4, int_buf, &int_size, NULL, 0))
|
||||
return UV__ERR(errno);
|
||||
|
||||
/* Determine required size. */
|
||||
required = strlen(int_buf) + 1;
|
||||
if (return_enobufs && *size < required) {
|
||||
/* Set new size. */
|
||||
*size = required;
|
||||
return UV_ENOBUFS;
|
||||
}
|
||||
|
||||
/* Copy string from the intermediate buffer to outer one with appropriate
|
||||
* length.
|
||||
*/
|
||||
@ -91,7 +100,7 @@ int uv_exepath(char* buffer, size_t* size) {
|
||||
uv__strscpy(buffer, int_buf, *size);
|
||||
|
||||
/* Set new size. */
|
||||
*size = strlen(buffer);
|
||||
*size = required;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -58,7 +58,7 @@ void uv_loadavg(double avg[3]) {
|
||||
}
|
||||
|
||||
|
||||
int uv_exepath(char* buffer, size_t* size) {
|
||||
int uv__exepath(char* buffer, size_t* size, int return_enobufs) {
|
||||
int mib[4];
|
||||
char **argsbuf = NULL;
|
||||
size_t argsbuf_size = 100U;
|
||||
@ -96,6 +96,11 @@ int uv_exepath(char* buffer, size_t* size) {
|
||||
|
||||
*size -= 1;
|
||||
exepath_size = strlen(argsbuf[0]);
|
||||
if (return_enobufs && *size < exepath_size) {
|
||||
*size = exepath_size;
|
||||
return UV_ENOBUFS;
|
||||
}
|
||||
|
||||
if (*size > exepath_size)
|
||||
*size = exepath_size;
|
||||
|
||||
|
||||
@ -152,14 +152,16 @@ static int getexe(char* buf, size_t len) {
|
||||
* or through some libc APIs. The below approach is to parse the argv[0]'s pattern
|
||||
* and use it in conjunction with PATH environment variable to craft one.
|
||||
*/
|
||||
int uv_exepath(char* buffer, size_t* size) {
|
||||
int uv__exepath(char* buffer, size_t* size, int return_enobufs) {
|
||||
int res;
|
||||
char args[PATH_MAX];
|
||||
int pid;
|
||||
|
||||
if (buffer == NULL || size == NULL || *size == 0)
|
||||
return UV_EINVAL;
|
||||
|
||||
if (return_enobufs)
|
||||
return UV_ENOTSUP;
|
||||
|
||||
res = getexe(args, sizeof(args));
|
||||
if (res < 0)
|
||||
return UV_EINVAL;
|
||||
|
||||
@ -25,21 +25,32 @@
|
||||
#include <stddef.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int uv_exepath(char* buffer, size_t* size) {
|
||||
|
||||
int uv__exepath(char* buffer, size_t* size, int return_enobufs) {
|
||||
char tmp[4096];
|
||||
ssize_t n;
|
||||
|
||||
if (buffer == NULL || size == NULL || *size == 0)
|
||||
return UV_EINVAL;
|
||||
|
||||
n = *size - 1;
|
||||
if (n > 0)
|
||||
n = readlink("/proc/self/exe", buffer, n);
|
||||
|
||||
n = readlink("/proc/self/exe", tmp, sizeof(tmp) - 1);
|
||||
if (n == -1)
|
||||
return UV__ERR(errno);
|
||||
|
||||
tmp[n] = '\0';
|
||||
|
||||
if (return_enobufs && *size < (size_t) n) {
|
||||
*size = (size_t) n + 1;
|
||||
return UV_ENOBUFS;
|
||||
}
|
||||
|
||||
n = uv__strscpy(buffer, tmp, *size);
|
||||
if (n < 0) /* Trucated but still ok */
|
||||
n = *size - 1;
|
||||
|
||||
buffer[n] = '\0';
|
||||
*size = n;
|
||||
|
||||
*size = (size_t) n;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -63,11 +63,14 @@ void uv_loadavg(double avg[3]) {
|
||||
}
|
||||
|
||||
|
||||
int uv_exepath(char* buffer, size_t* size) {
|
||||
int uv__exepath(char* buffer, size_t* size, int return_enobufs) {
|
||||
char path[PATH_MAX];
|
||||
if (buffer == NULL || size == NULL || *size == 0)
|
||||
return UV_EINVAL;
|
||||
|
||||
if (return_enobufs)
|
||||
return UV_ENOTSUP;
|
||||
|
||||
realpath(_cmdname(NULL), path);
|
||||
strlcpy(buffer, path, *size);
|
||||
*size = strlen(buffer);
|
||||
|
||||
@ -380,7 +380,7 @@ uint64_t uv__hrtime(uv_clocktype_t type) {
|
||||
* of the function, but this function could be called by multiple consumers and
|
||||
* we don't want to potentially create a race condition in the use of snprintf.
|
||||
*/
|
||||
int uv_exepath(char* buffer, size_t* size) {
|
||||
int uv__exepath(char* buffer, size_t* size, int return_enobufs) {
|
||||
ssize_t res;
|
||||
char buf[128];
|
||||
|
||||
@ -396,6 +396,11 @@ int uv_exepath(char* buffer, size_t* size) {
|
||||
if (res == -1)
|
||||
return UV__ERR(errno);
|
||||
|
||||
if (return_enobufs && *size < (size_t) res) {
|
||||
*size = (size_t) res;
|
||||
return UV_ENOBUFS;
|
||||
}
|
||||
|
||||
buffer[res] = '\0';
|
||||
*size = res;
|
||||
return 0;
|
||||
|
||||
@ -1055,6 +1055,17 @@ uint64_t uv_metrics_idle_time(uv_loop_t* loop) {
|
||||
return idle_time;
|
||||
}
|
||||
|
||||
|
||||
int uv_exepath(char *buffer, size_t *size) {
|
||||
return uv__exepath(buffer, size, /*return_enobufs*/0);
|
||||
}
|
||||
|
||||
|
||||
int uv_exepath2(char *buffer, size_t *size) {
|
||||
return uv__exepath(buffer, size, /*return_enobufs*/1);
|
||||
}
|
||||
|
||||
|
||||
/* OS390 needs a different implementation, already provided in os390.c. */
|
||||
#ifndef __MVS__
|
||||
void uv_free_interface_addresses(uv_interface_address_t* addresses,
|
||||
|
||||
@ -211,6 +211,12 @@ void uv__fs_poll_close(uv_fs_poll_t* handle);
|
||||
|
||||
int uv__getaddrinfo_translate_error(int sys_err); /* EAI_* error. */
|
||||
|
||||
int uv__exepath(char* buffer, size_t* size, int return_enobufs);
|
||||
|
||||
int uv_exepath(char *buffer, size_t *size);
|
||||
|
||||
int uv_exepath2(char *buffer, size_t *size);
|
||||
|
||||
enum uv__work_kind {
|
||||
UV__WORK_CPU,
|
||||
UV__WORK_FAST_IO,
|
||||
|
||||
@ -94,9 +94,10 @@ void uv__util_init(void) {
|
||||
}
|
||||
|
||||
|
||||
int uv_exepath(char* buffer, size_t* size_ptr) {
|
||||
int uv__exepath(char* buffer, size_t* size_ptr, int return_enobufs) {
|
||||
size_t utf8_len, utf16_buffer_len, utf16_len;
|
||||
WCHAR* utf16_buffer;
|
||||
int required_utf8_len;
|
||||
int err;
|
||||
|
||||
if (buffer == NULL || size_ptr == NULL || *size_ptr == 0) {
|
||||
@ -122,6 +123,23 @@ int uv_exepath(char* buffer, size_t* size_ptr) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Determine how many UTF-8 bytes are needed. */
|
||||
required_utf8_len = WideCharToMultiByte(CP_UTF8, 0,
|
||||
utf16_buffer, (int)utf16_len,
|
||||
NULL, 0, NULL, NULL);
|
||||
/* Just return error if return enobufs is requested */
|
||||
if (return_enobufs && required_utf8_len <= 0) {
|
||||
err = GetLastError();
|
||||
uv__free(utf16_buffer);
|
||||
return uv_translate_sys_error(err);
|
||||
}
|
||||
|
||||
if (return_enobufs && *size_ptr < (size_t) required_utf8_len + 1) {
|
||||
*size_ptr = (size_t) required_utf8_len + 1;
|
||||
uv__free(utf16_buffer);
|
||||
return UV_ENOBUFS;
|
||||
}
|
||||
|
||||
/* Convert to UTF-8 */
|
||||
utf8_len = *size_ptr - 1; /* Reserve space for NUL */
|
||||
err = uv_utf16_to_wtf8(utf16_buffer, utf16_len, &buffer, &utf8_len);
|
||||
|
||||
@ -289,6 +289,7 @@ TEST_DECLARE (eintr_handling)
|
||||
TEST_DECLARE (get_currentexe)
|
||||
TEST_DECLARE (process_title)
|
||||
TEST_DECLARE (process_title_big_argv)
|
||||
TEST_DECLARE (exepath2_enobufs)
|
||||
TEST_DECLARE (process_title_threadsafe)
|
||||
TEST_DECLARE (cwd_and_chdir)
|
||||
TEST_DECLARE (get_memory)
|
||||
@ -942,6 +943,7 @@ TASK_LIST_START
|
||||
|
||||
TEST_ENTRY (process_title)
|
||||
TEST_ENTRY (process_title_big_argv)
|
||||
TEST_ENTRY (exepath2_enobufs)
|
||||
TEST_ENTRY (process_title_threadsafe)
|
||||
|
||||
TEST_ENTRY (cwd_and_chdir)
|
||||
|
||||
@ -83,6 +83,22 @@ static void exit_cb(uv_process_t* process, int64_t status, int signo) {
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(exepath2_enobufs) {
|
||||
int r;
|
||||
char smallbuf[2];
|
||||
size_t small_size;
|
||||
|
||||
/* Test uv_exepath2
|
||||
* Refs: https://github.com/libuv/libuv/issues/4911 */
|
||||
small_size = sizeof(smallbuf);
|
||||
r = uv_exepath2(smallbuf, &small_size);
|
||||
ASSERT(r == UV_ENOBUFS || r == UV_ENOTSUP);
|
||||
ASSERT_GE(small_size, sizeof(smallbuf));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
TEST_IMPL(process_title_big_argv) {
|
||||
uv_process_options_t options;
|
||||
uv_process_t process;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user