[libc-commits] [libc] Implement gethostname (PR #128142)

Zaky Hermawan via libc-commits libc-commits at lists.llvm.org
Thu Feb 20 23:25:20 PST 2025


https://github.com/ZakyHermawan created https://github.com/llvm/llvm-project/pull/128142

The implementation is based on the specifications from: https://man7.org/linux/man-pages/man2/gethostname.2.html

Closes https://github.com/llvm/llvm-project/issues/126602


>From c44b475213378bbb63e4bfbbc0b6d0bf05003055 Mon Sep 17 00:00:00 2001
From: ZakyHermawan <zaky.hermawan9615 at gmail.com>
Date: Fri, 21 Feb 2025 14:10:54 +0700
Subject: [PATCH] Implement gethostname

Matching the behavior of glibc version 2.2 and later.

If the size of the array name is not large enough, then anything might happen.
In this case, what happens to the array name
will be determined by the implementation of LIBC_NAMESPACE_DECL::strncpy

Signed-off-by: ZakyHermawan <zaky.hermawan9615 at gmail.com>
---
 libc/config/linux/aarch64/entrypoints.txt |  1 +
 libc/config/linux/riscv/entrypoints.txt   |  1 +
 libc/config/linux/x86_64/entrypoints.txt  |  1 +
 libc/include/unistd.yaml                  |  7 +++
 libc/src/unistd/CMakeLists.txt            |  7 +++
 libc/src/unistd/gethostname.h             | 22 ++++++++
 libc/src/unistd/linux/CMakeLists.txt      | 16 ++++++
 libc/src/unistd/linux/gethostname.cpp     | 62 +++++++++++++++++++++++
 libc/test/src/unistd/CMakeLists.txt       | 11 ++++
 libc/test/src/unistd/gethostname_test.cpp | 28 ++++++++++
 10 files changed, 156 insertions(+)
 create mode 100644 libc/src/unistd/gethostname.h
 create mode 100644 libc/src/unistd/linux/gethostname.cpp
 create mode 100644 libc/test/src/unistd/gethostname_test.cpp

diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index aac4017a0d845..6450e41b76dfe 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -327,6 +327,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 6b006f0ecca89..10119b5f76d58 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -324,6 +324,7 @@ set(TARGET_LIBC_ENTRYPOINTS
     libc.src.unistd.ftruncate
     libc.src.unistd.getcwd
     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 35661004663c9..c4c2e1449ef97 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -326,6 +326,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..ef1b2d5381de6
--- /dev/null
+++ b/libc/src/unistd/gethostname.h
@@ -0,0 +1,22 @@
+//===-- 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 "hdr/unistd_macros.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 368593a3bb7b5..6ea8068a6f39c 100644
--- a/libc/src/unistd/linux/CMakeLists.txt
+++ b/libc/src/unistd/linux/CMakeLists.txt
@@ -193,6 +193,22 @@ 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
+    libc.src.string.strlen
+    libc.src.string.strncpy
+)
+
 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..617d0197c73c7
--- /dev/null
+++ b/libc/src/unistd/linux/gethostname.cpp
@@ -0,0 +1,62 @@
+//===-- 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/macros/config.h"
+
+#include "src/string/strlen.h"
+#include "src/string/strncpy.h"
+#include "src/errno/libc_errno.h"
+
+#include <sys/syscall.h> // For syscall numbers.
+#include <sys/utsname.h>
+
+namespace LIBC_NAMESPACE_DECL {
+
+// Matching the behavior of glibc version 2.2 and later.
+// Copies up to len bytes from the returned nodename field into name.
+LLVM_LIBC_FUNCTION(int, gethostname, (char *name, size_t len)) {
+  
+  // Check for invalid pointer
+  if (name == nullptr) {
+    libc_errno = EFAULT;
+    return -1;
+  }
+
+  struct utsname unameData;
+  int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_uname, &unameData);
+
+  // Checks if the length of the nodename was greater than or equal to len, and if it is,
+  // then the function returns -1 with errno set to ENAMETOOLONG.
+  // In this case, a terminating null byte is not included in the returned name.
+  if (strlen(unameData.nodename) >= len)
+  {
+    strncpy(name, unameData.nodename, len);
+    libc_errno = ENAMETOOLONG;
+    return -1;
+  }
+
+  // If the size of the array name is not large enough (less than the size of nodename with null termination), then anything might happen.
+  // In this case, what happens to the array name will be determined by the implementation of LIBC_NAMESPACE_DECL::strncpy
+  strncpy(name, unameData.nodename, len);
+
+  if (ret < 0) {
+    libc_errno = static_cast<int>(-ret);
+    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 d1f3050e6cccf..0f01104044e34 100644
--- a/libc/test/src/unistd/CMakeLists.txt
+++ b/libc/test/src/unistd/CMakeLists.txt
@@ -374,6 +374,17 @@ add_libc_unittest(
     libc.src.unistd.unlinkat
 )
 
+add_libc_unittest(
+  gethostname_test
+  SUITE
+    libc_unistd_unittests
+  SRCS
+    gethostname_test.cpp
+  DEPENDS
+    libc.src.unistd.gethostname
+    libc.src.errno.errno
+)
+
 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..777f9664e7ee6
--- /dev/null
+++ b/libc/test/src/unistd/gethostname_test.cpp
@@ -0,0 +1,28 @@
+//===-- 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/errno/libc_errno.h"
+#include "src/unistd/gethostname.h"
+#include "test/UnitTest/Test.h"
+
+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);
+}



More information about the libc-commits mailing list