unix,win: add uv_os_gethostname()

Fixes: https://github.com/libuv/libuv/issues/1315
PR-URL: https://github.com/libuv/libuv/pull/1342
Reviewed-By: Santiago Gimeno <santiago.gimeno@gmail.com>
Reviewed-By: Sam Roberts <vieuxtech@gmail.com>
This commit is contained in:
cjihrig 2017-05-12 13:41:22 -04:00
parent 4d0054145d
commit d8cd08bd98
9 changed files with 152 additions and 0 deletions

View File

@ -178,6 +178,7 @@ test_run_tests_SOURCES = test/blackhole-server.c \
test/test-get-memory.c \
test/test-get-passwd.c \
test/test-getaddrinfo.c \
test/test-gethostname.c \
test/test-getnameinfo.c \
test/test-getsockname.c \
test/test-handle-fileno.c \

View File

@ -104,6 +104,7 @@ test/test-get-loadavg.c
test/test-get-memory.c
test/test-get-passwd.c
test/test-getaddrinfo.c
test/test-gethostname.c
test/test-getsockname.c
test/test-homedir.c
test/test-hrtime.c

View File

@ -429,3 +429,14 @@ API
This function is not thread safe.
.. versionadded:: 1.12.0
.. c:function:: int uv_os_gethostname(char* buffer, size_t* size)
Returns the hostname as a null-terminated string in `buffer`, and sets
`size` to the string length of the hostname. When calling this function,
`size` must be set to the amount of storage available in `buffer`, including
the null terminator. If the hostname exceeds the storage available in
`buffer`, `UV_ENOBUFS` is returned, and `size` is set to the amount of
storage required to hold the value.
.. versionadded:: 1.12.0

View File

@ -1078,6 +1078,8 @@ UV_EXTERN int uv_os_getenv(const char* name, char* buffer, size_t* size);
UV_EXTERN int uv_os_setenv(const char* name, const char* value);
UV_EXTERN int uv_os_unsetenv(const char* name);
UV_EXTERN int uv_os_gethostname(char* buffer, size_t* size);
typedef enum {
UV_FS_UNKNOWN = -1,

View File

@ -28,6 +28,7 @@
#include <errno.h>
#include <assert.h>
#include <unistd.h>
#include <sys/param.h> /* MAXHOSTNAMELEN on Linux and the BSDs */
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
@ -42,6 +43,7 @@
#include <pwd.h>
#ifdef __sun
# include <netdb.h> /* MAXHOSTNAMELEN on Solaris */
# include <sys/filio.h>
# include <sys/types.h>
# include <sys/wait.h>
@ -80,6 +82,11 @@
#include <sys/ioctl.h>
#endif
/* Fallback for the maximum hostname length */
#ifndef MAXHOSTNAMELEN
# define MAXHOSTNAMELEN 256
#endif
static int uv__run_pending(uv_loop_t* loop);
/* Verify that uv_buf_t is ABI-compatible with struct iovec. */
@ -1285,3 +1292,33 @@ int uv_os_unsetenv(const char* name) {
return 0;
}
int uv_os_gethostname(char* buffer, size_t* size) {
/*
On some platforms, if the input buffer is not large enough, gethostname()
succeeds, but truncates the result. libuv can detect this and return ENOBUFS
instead by creating a large enough buffer and comparing the hostname length
to the size input.
*/
char buf[MAXHOSTNAMELEN + 1];
size_t len;
if (buffer == NULL || size == NULL || *size == 0)
return -EINVAL;
if (gethostname(buf, sizeof(buf)) != 0)
return -errno;
buf[sizeof(buf) - 1] = '\0'; /* Null terminate, just to be safe. */
len = strlen(buf);
if (len >= *size) {
*size = len + 1;
return -ENOBUFS;
}
memcpy(buffer, buf, len + 1);
*size = len;
return 0;
}

View File

@ -59,6 +59,14 @@
# define UNLEN 256
#endif
/*
Max hostname length. The Windows gethostname() documentation states that 256
bytes will always be large enough to hold the null-terminated hostname.
*/
#ifndef MAXHOSTNAMELEN
# define MAXHOSTNAMELEN 256
#endif
/* Maximum environment variable size, including the terminating null */
#define MAX_ENV_VAR_LENGTH 32767
@ -1540,3 +1548,29 @@ int uv_os_unsetenv(const char* name) {
return 0;
}
int uv_os_gethostname(char* buffer, size_t* size) {
char buf[MAXHOSTNAMELEN + 1];
size_t len;
if (buffer == NULL || size == NULL || *size == 0)
return UV_EINVAL;
uv__once_init(); /* Initialize winsock */
if (gethostname(buf, sizeof(buf)) != 0)
return uv_translate_sys_error(WSAGetLastError());
buf[sizeof(buf) - 1] = '\0'; /* Null terminate, just to be safe. */
len = strlen(buf);
if (len >= *size) {
*size = len + 1;
return UV_ENOBUFS;
}
memcpy(buffer, buf, len + 1);
*size = len;
return 0;
}

62
test/test-gethostname.c Normal file
View File

@ -0,0 +1,62 @@
/* Copyright libuv 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 <string.h>
#ifndef MAXHOSTNAMELEN
# define MAXHOSTNAMELEN 256
#endif
TEST_IMPL(gethostname) {
char buf[MAXHOSTNAMELEN + 1];
size_t size;
size_t enobufs_size;
int r;
/* Reject invalid inputs */
size = 1;
r = uv_os_gethostname(NULL, &size);
ASSERT(r == UV_EINVAL);
r = uv_os_gethostname(buf, NULL);
ASSERT(r == UV_EINVAL);
size = 0;
r = uv_os_gethostname(buf, &size);
ASSERT(r == UV_EINVAL);
/* Return UV_ENOBUFS if the buffer cannot hold the hostname */
enobufs_size = 1;
buf[0] = '\0';
r = uv_os_gethostname(buf, &enobufs_size);
ASSERT(r == UV_ENOBUFS);
ASSERT(buf[0] == '\0');
ASSERT(enobufs_size > 1);
/* Successfully get the hostname */
size = MAXHOSTNAMELEN + 1;
r = uv_os_gethostname(buf, &size);
ASSERT(r == 0);
ASSERT(size > 1 && size == strlen(buf));
ASSERT(size + 1 == enobufs_size);
return 0;
}

View File

@ -220,6 +220,7 @@ TEST_DECLARE (getaddrinfo_fail_sync)
TEST_DECLARE (getaddrinfo_basic)
TEST_DECLARE (getaddrinfo_basic_sync)
TEST_DECLARE (getaddrinfo_concurrent)
TEST_DECLARE (gethostname)
TEST_DECLARE (getnameinfo_basic_ip4)
TEST_DECLARE (getnameinfo_basic_ip4_sync)
TEST_DECLARE (getnameinfo_basic_ip6)
@ -655,6 +656,8 @@ TASK_LIST_START
TEST_ENTRY (getaddrinfo_basic_sync)
TEST_ENTRY (getaddrinfo_concurrent)
TEST_ENTRY (gethostname)
TEST_ENTRY (getnameinfo_basic_ip4)
TEST_ENTRY (getnameinfo_basic_ip4_sync)
TEST_ENTRY (getnameinfo_basic_ip6)

1
uv.gyp
View File

@ -357,6 +357,7 @@
'test/test-get-memory.c',
'test/test-get-passwd.c',
'test/test-getaddrinfo.c',
'test/test-gethostname.c',
'test/test-getnameinfo.c',
'test/test-getsockname.c',
'test/test-handle-fileno.c',