diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt index 840d4cec14bbf..0cafd1c9bac4a 100644 --- a/libc/config/linux/aarch64/entrypoints.txt +++ b/libc/config/linux/aarch64/entrypoints.txt @@ -332,6 +332,7 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.unistd.getcwd libc.src.unistd.getentropy libc.src.unistd.geteuid + libc.src.unistd.gethostname libc.src.unistd.getpid libc.src.unistd.getppid libc.src.unistd.getsid diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt index 653282c7d3935..a0d09423369d6 100644 --- a/libc/config/linux/riscv/entrypoints.txt +++ b/libc/config/linux/riscv/entrypoints.txt @@ -336,6 +336,7 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.unistd.getcwd libc.src.unistd.getentropy libc.src.unistd.geteuid + libc.src.unistd.gethostname libc.src.unistd.getpid libc.src.unistd.getppid libc.src.unistd.getsid diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt index 1fef16f190af6..457f1bcb2d7a3 100644 --- a/libc/config/linux/x86_64/entrypoints.txt +++ b/libc/config/linux/x86_64/entrypoints.txt @@ -338,6 +338,7 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.unistd.getcwd libc.src.unistd.getentropy libc.src.unistd.geteuid + libc.src.unistd.gethostname libc.src.unistd.getpid libc.src.unistd.getppid libc.src.unistd.getsid diff --git a/libc/include/unistd.yaml b/libc/include/unistd.yaml index 051e92b006741..3ba3ec71c25ce 100644 --- a/libc/include/unistd.yaml +++ b/libc/include/unistd.yaml @@ -141,6 +141,13 @@ functions: return_type: uid_t arguments: - type: void + - name: gethostname + standards: + - POSIX + return_type: int + arguments: + - type: char * + - type: size_t - name: getopt standards: - POSIX diff --git a/libc/src/unistd/CMakeLists.txt b/libc/src/unistd/CMakeLists.txt index b1a1716aa85c6..c66a3a4d0ed76 100644 --- a/libc/src/unistd/CMakeLists.txt +++ b/libc/src/unistd/CMakeLists.txt @@ -111,6 +111,13 @@ add_entrypoint_object( .${LIBC_TARGET_OS}.getcwd ) +add_entrypoint_object( + gethostname + ALIAS + DEPENDS + .${LIBC_TARGET_OS}.gethostname +) + add_entrypoint_object( getpid ALIAS diff --git a/libc/src/unistd/gethostname.h b/libc/src/unistd/gethostname.h new file mode 100644 index 0000000000000..cf67bdbd5c320 --- /dev/null +++ b/libc/src/unistd/gethostname.h @@ -0,0 +1,21 @@ +//===-- Implementation header for gethostname -------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SRC_UNISTD_GETHOSTNAME_H +#define LLVM_LIBC_SRC_UNISTD_GETHOSTNAME_H + +#include "hdr/types/size_t.h" +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { + +int gethostname(char *name, size_t len); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_UNISTD_GETHOSTNAME_H diff --git a/libc/src/unistd/linux/CMakeLists.txt b/libc/src/unistd/linux/CMakeLists.txt index 382a61fea8b66..2d510f32d287d 100644 --- a/libc/src/unistd/linux/CMakeLists.txt +++ b/libc/src/unistd/linux/CMakeLists.txt @@ -194,6 +194,20 @@ add_entrypoint_object( libc.src.errno.errno ) +add_entrypoint_object( + gethostname + SRCS + gethostname.cpp + HDRS + ../gethostname.h + DEPENDS + libc.hdr.types.size_t + libc.include.sys_syscall + libc.include.sys_utsname + libc.src.__support.OSUtil.osutil + libc.src.errno.errno +) + add_entrypoint_object( geteuid SRCS diff --git a/libc/src/unistd/linux/gethostname.cpp b/libc/src/unistd/linux/gethostname.cpp new file mode 100644 index 0000000000000..60a12a4d6f8ea --- /dev/null +++ b/libc/src/unistd/linux/gethostname.cpp @@ -0,0 +1,53 @@ +//===-- Linux implementation of gethostname -------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "src/unistd/gethostname.h" + +#include "hdr/types/size_t.h" +#include "src/__support/OSUtil/syscall.h" // For internal syscall function. +#include "src/__support/common.h" +#include "src/__support/libc_errno.h" +#include "src/__support/macros/config.h" +#include "src/string/string_utils.h" + +#include // For syscall numbers. +#include + +namespace LIBC_NAMESPACE_DECL { + +LLVM_LIBC_FUNCTION(int, gethostname, (char *name, size_t size)) { + // Check for invalid pointer + if (name == nullptr) { + libc_errno = EFAULT; + return -1; + } + + // Because there is no SYS_gethostname syscall, we use uname to get the + // hostname. + utsname unameData; + int ret = LIBC_NAMESPACE::syscall_impl(SYS_uname, &unameData); + if (ret < 0) { + libc_errno = static_cast(-ret); + return -1; + } + + // Guarantee that the name will be null terminated. + // The amount of bytes copied is min(size + 1, strlen(nodename) + 1) + // +1 to account for the null terminator (the last copied byte is a NULL). + internal::strlcpy(name, unameData.nodename, size + 1); + + // Checks if the length of the hostname was greater than or equal to size + if (internal::string_length(unameData.nodename) >= size) { + libc_errno = ENAMETOOLONG; + return -1; + } + + return 0; +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/test/src/unistd/CMakeLists.txt b/libc/test/src/unistd/CMakeLists.txt index 9aec6150af0ec..6630a7ef15e53 100644 --- a/libc/test/src/unistd/CMakeLists.txt +++ b/libc/test/src/unistd/CMakeLists.txt @@ -408,6 +408,18 @@ add_libc_unittest( libc.test.UnitTest.ErrnoSetterMatcher ) +add_libc_unittest( + gethostname_test + SUITE + libc_unistd_unittests + SRCS + gethostname_test.cpp + DEPENDS + libc.src.unistd.gethostname + libc.src.errno.errno + libc.test.UnitTest.ErrnoCheckingTest +) + add_libc_unittest( getpid_test SUITE diff --git a/libc/test/src/unistd/gethostname_test.cpp b/libc/test/src/unistd/gethostname_test.cpp new file mode 100644 index 0000000000000..a0e57ff0df333 --- /dev/null +++ b/libc/test/src/unistd/gethostname_test.cpp @@ -0,0 +1,31 @@ +//===-- Unittests for gethostname -----------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "src/unistd/gethostname.h" + +#include "test/UnitTest/ErrnoCheckingTest.h" +#include "test/UnitTest/Test.h" + +using LlvmLibcGetHostNameTest = LIBC_NAMESPACE::testing::ErrnoCheckingTest; + +TEST(LlvmLibcGetHostNameTest, GetCurrHostName) { + char hostbuffer[1024]; + int ret = LIBC_NAMESPACE::gethostname(hostbuffer, sizeof(hostbuffer)); + ASSERT_NE(ret, -1); + ASSERT_ERRNO_SUCCESS(); + + ret = LIBC_NAMESPACE::gethostname(hostbuffer, 0); + ASSERT_EQ(ret, -1); + ASSERT_ERRNO_EQ(ENAMETOOLONG); + + // test for invalid pointer + char *nptr = nullptr; + ret = LIBC_NAMESPACE::gethostname(nptr, 1); + ASSERT_EQ(ret, -1); + ASSERT_ERRNO_EQ(EFAULT); +}