diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt --- a/libc/config/linux/aarch64/entrypoints.txt +++ b/libc/config/linux/aarch64/entrypoints.txt @@ -111,6 +111,9 @@ libc.src.sys.stat.mkdir libc.src.sys.stat.mkdirat + # sys/utsname.h entrypoints + libc.src.sys.utsname.uname + # unistd.h entrypoints libc.src.unistd.access libc.src.unistd.chdir diff --git a/libc/config/linux/api.td b/libc/config/linux/api.td --- a/libc/config/linux/api.td +++ b/libc/config/linux/api.td @@ -278,3 +278,7 @@ def SysSendfileAPI : PublicAPI<"sys/sendfile.h"> { let Types = ["off_t", "size_t", "ssize_t"]; } + +def SysUtsNameAPI : PublicAPI<"sys/utsname.h"> { + let Types = ["struct utsname"]; +} diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt --- a/libc/config/linux/x86_64/entrypoints.txt +++ b/libc/config/linux/x86_64/entrypoints.txt @@ -111,6 +111,9 @@ libc.src.sys.stat.mkdir libc.src.sys.stat.mkdirat + # sys/utsname.h entrypoints + libc.src.sys.utsname.uname + # unistd.h entrypoints libc.src.unistd.access libc.src.unistd.chdir diff --git a/libc/include/CMakeLists.txt b/libc/include/CMakeLists.txt --- a/libc/include/CMakeLists.txt +++ b/libc/include/CMakeLists.txt @@ -233,6 +233,15 @@ ../config/${LIBC_TARGET_OS}/syscall_numbers.h.inc ) +add_gen_header( + sys_utsname + DEF_FILE sys/utsname.h.def + GEN_HDR sys/utsname.h + DEPENDS + .llvm_libc_common_h + .llvm-libc-types.struct_utsname +) + if(NOT LLVM_LIBC_FULL_BUILD) # We don't install headers in non-fullbuild mode. return() diff --git a/libc/include/llvm-libc-types/CMakeLists.txt b/libc/include/llvm-libc-types/CMakeLists.txt --- a/libc/include/llvm-libc-types/CMakeLists.txt +++ b/libc/include/llvm-libc-types/CMakeLists.txt @@ -35,6 +35,7 @@ add_header(struct_dirent HDR struct_dirent.h DEPENDS .ino_t .off_t) add_header(struct_sigaction HDR struct_sigaction.h) add_header(struct_tm HDR struct_tm.h) +add_header(struct_utsname HDR struct_utsname.h) add_header(thrd_start_t HDR thrd_start_t.h) add_header(thrd_t HDR thrd_t.h DEPENDS .__thread_type) add_header(time_t HDR time_t.h) diff --git a/libc/include/llvm-libc-types/struct_utsname.h b/libc/include/llvm-libc-types/struct_utsname.h new file mode 100644 --- /dev/null +++ b/libc/include/llvm-libc-types/struct_utsname.h @@ -0,0 +1,32 @@ +//===-- Definition of struct utsname --------------------------------------===// +// +// 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_TYPES_STRUCT_UTSNAME_H__ +#define __LLVM_LIBC_TYPES_STRUCT_UTSNAME_H__ + +#ifdef __unix__ +#define __UTS_NAME_LENGTH 65 +#else +// Arbitray default. Should be specialized for each platform. +#define __UTS_NAME_LENGTH 1024 +#endif + +struct utsname { + char sysname[__UTS_NAME_LENGTH]; + char nodename[__UTS_NAME_LENGTH]; + char release[__UTS_NAME_LENGTH]; + char version[__UTS_NAME_LENGTH]; + char machine[__UTS_NAME_LENGTH]; +#ifdef __unix__ + char domainname[__UTS_NAME_LENGTH]; +#endif +}; + +#undef __UTS_NAME_LENGTH + +#endif // __LLVM_LIBC_TYPES_STRUCT_UTSNAME_H__ diff --git a/libc/include/sys/utsname.h.def b/libc/include/sys/utsname.h.def new file mode 100644 --- /dev/null +++ b/libc/include/sys/utsname.h.def @@ -0,0 +1,16 @@ +//===-- Linux sys/utsname.h -----------------------------------------------===// +// +// 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_SYS_UTSNAME_H +#define LLVM_LIBC_SYS_UTSNAME_H + +#include <__llvm-libc-common.h> + +%%public_api() + +#endif // LLVM_LIBC_SYS_UTSNAME_H diff --git a/libc/spec/posix.td b/libc/spec/posix.td --- a/libc/spec/posix.td +++ b/libc/spec/posix.td @@ -499,6 +499,22 @@ ] >; + NamedType StructUtsName = NamedType<"struct utsname">; + PtrType StructUtsNamePtr = PtrType; + HeaderSpec SysUtsName = HeaderSpec< + "sys/utsname.h", + [], // Macros + [StructUtsName], // Types + [], // Enumerations + [ + FunctionSpec< + "uname", + RetValSpec, + [ArgSpec] + >, + ] + >; + HeaderSpec PThread = HeaderSpec< "pthread.h", [], // Macros @@ -765,6 +781,7 @@ StdLib, SysMMan, SysStat, + SysUtsName, UniStd, String ]; diff --git a/libc/src/sys/CMakeLists.txt b/libc/src/sys/CMakeLists.txt --- a/libc/src/sys/CMakeLists.txt +++ b/libc/src/sys/CMakeLists.txt @@ -1,3 +1,4 @@ add_subdirectory(mman) add_subdirectory(sendfile) add_subdirectory(stat) +add_subdirectory(utsname) diff --git a/libc/src/sys/utsname/CMakeLists.txt b/libc/src/sys/utsname/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/libc/src/sys/utsname/CMakeLists.txt @@ -0,0 +1,10 @@ +if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS}) + add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS}) +endif() + +add_entrypoint_object( + uname + ALIAS + DEPENDS + .${LIBC_TARGET_OS}.uname +) diff --git a/libc/src/sys/utsname/linux/CMakeLists.txt b/libc/src/sys/utsname/linux/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/libc/src/sys/utsname/linux/CMakeLists.txt @@ -0,0 +1,13 @@ +add_entrypoint_object( + uname + SRCS + uname.cpp + HDRS + ../uname.h + DEPENDS + libc.include.sys_utsname + libc.include.sys_syscall + libc.src.__support.OSUtil.osutil + libc.src.errno.errno +) + diff --git a/libc/src/sys/utsname/linux/uname.cpp b/libc/src/sys/utsname/linux/uname.cpp new file mode 100644 --- /dev/null +++ b/libc/src/sys/utsname/linux/uname.cpp @@ -0,0 +1,29 @@ +//===-- Linux implementation of uname -------------------------------------===// +// +// 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/sys/utsname/uname.h" + +#include "src/__support/OSUtil/syscall.h" // For internal syscall function. +#include "src/__support/common.h" + +#include +#include // For syscall numbers. +#include + +namespace __llvm_libc { + +LLVM_LIBC_FUNCTION(int, uname, (struct utsname * name)) { + long ret = __llvm_libc::syscall(SYS_uname, name); + + if (ret >= 0) + return 1; + errno = -ret; + return -1; +} + +} // namespace __llvm_libc diff --git a/libc/src/sys/utsname/uname.h b/libc/src/sys/utsname/uname.h new file mode 100644 --- /dev/null +++ b/libc/src/sys/utsname/uname.h @@ -0,0 +1,20 @@ +//===-- Implementation header for uname -------------------------*- 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_SYS_UTSNAME_UNAME_H +#define LLVM_LIBC_SRC_SYS_UTSNAME_UNAME_H + +#include + +namespace __llvm_libc { + +int uname(struct utsname *name); + +} // namespace __llvm_libc + +#endif // LLVM_LIBC_SRC_SYS_UTSNAME_UNAME_H diff --git a/libc/test/src/sys/CMakeLists.txt b/libc/test/src/sys/CMakeLists.txt --- a/libc/test/src/sys/CMakeLists.txt +++ b/libc/test/src/sys/CMakeLists.txt @@ -1,3 +1,4 @@ add_subdirectory(mman) add_subdirectory(sendfile) add_subdirectory(stat) +add_subdirectory(utsname) diff --git a/libc/test/src/sys/utsname/CMakeLists.txt b/libc/test/src/sys/utsname/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/libc/test/src/sys/utsname/CMakeLists.txt @@ -0,0 +1,15 @@ +add_libc_testsuite(libc_sys_utsname_unittests) + +add_libc_unittest( + uname_test + SUITE + libc_sys_utsname_unittests + SRCS + uname_test.cpp + DEPENDS + libc.include.errno + libc.include.sys_utsname + libc.src.__support.common + libc.src.sys.utsname.uname + libc.test.errno_setter_matcher +) diff --git a/libc/test/src/sys/utsname/uname_test.cpp b/libc/test/src/sys/utsname/uname_test.cpp new file mode 100644 --- /dev/null +++ b/libc/test/src/sys/utsname/uname_test.cpp @@ -0,0 +1,26 @@ +//===-- Unittests for uname -----------------------------------------------===// +// +// 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/__support/CPP/string_view.h" +#include "src/__support/architectures.h" +#include "src/sys/utsname/uname.h" +#include "test/ErrnoSetterMatcher.h" +#include "utils/UnitTest/Test.h" + +#include +#include + +TEST(LlvmLibcUnameTest, GetMachineName) { + struct utsname names; + ASSERT_GE(__llvm_libc::uname(&names), 0); +#ifdef LLVM_LIBC_ARCH_X86_64 + ASSERT_STREQ(names.machine, "x86_64"); +#elif defined(LLVM_LIBC_ARCH_AARCH64) + ASSERT_STREQ(names.machine, "aarch64"); +#endif +}