From b838a3ec0315b40b05de515d2d50837ff376a642 Mon Sep 17 00:00:00 2001 From: "shubh@DOE" Date: Tue, 4 Nov 2025 11:32:00 -0800 Subject: [PATCH] [libc] Add chown and getgid implementations Implements chown and getgid per the POSIX specification and adds corresponding unit tests. getgid is added as it is required by the chown unit tests. --- libc/config/linux/x86_64/entrypoints.txt | 2 + libc/hdr/types/CMakeLists.txt | 8 ++++ libc/hdr/types/gid_t.h | 22 ++++++++++ libc/include/unistd.yaml | 15 +++++++ libc/src/unistd/CMakeLists.txt | 14 +++++++ libc/src/unistd/chown.h | 22 ++++++++++ libc/src/unistd/getgid.h | 22 ++++++++++ libc/src/unistd/linux/CMakeLists.txt | 29 ++++++++++++++ libc/src/unistd/linux/chown.cpp | 29 ++++++++++++++ libc/src/unistd/linux/getgid.cpp | 23 +++++++++++ libc/test/src/unistd/CMakeLists.txt | 30 ++++++++++++++ libc/test/src/unistd/chown_test.cpp | 51 ++++++++++++++++++++++++ libc/test/src/unistd/getgid_test.cpp | 15 +++++++ 13 files changed, 282 insertions(+) create mode 100644 libc/hdr/types/gid_t.h create mode 100644 libc/src/unistd/chown.h create mode 100644 libc/src/unistd/getgid.h create mode 100644 libc/src/unistd/linux/chown.cpp create mode 100644 libc/src/unistd/linux/getgid.cpp create mode 100644 libc/test/src/unistd/chown_test.cpp create mode 100644 libc/test/src/unistd/getgid_test.cpp diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt index 7a8d74a4e5da9..a44e2041e57f2 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 # unistd.h entrypoints libc.src.unistd.access libc.src.unistd.chdir + libc.src.unistd.chown libc.src.unistd.close libc.src.unistd.dup libc.src.unistd.dup2 @@ -344,6 +345,7 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.unistd.getppid libc.src.unistd.getsid libc.src.unistd.gettid + libc.src.unistd.getgid libc.src.unistd.getuid libc.src.unistd.isatty libc.src.unistd.link diff --git a/libc/hdr/types/CMakeLists.txt b/libc/hdr/types/CMakeLists.txt index 225843924c243..433c47b174766 100644 --- a/libc/hdr/types/CMakeLists.txt +++ b/libc/hdr/types/CMakeLists.txt @@ -479,3 +479,11 @@ add_proxy_header_library( libc.include.llvm-libc-types.struct_rlimit libc.include.sys_resource ) + +add_proxy_header_library( + gid_t + HDRS + gid_t.h + FULL_BUILD_DEPENDS + libc.include.llvm-libc-types.gid_t +) diff --git a/libc/hdr/types/gid_t.h b/libc/hdr/types/gid_t.h new file mode 100644 index 0000000000000..bc274aaa9a8a8 --- /dev/null +++ b/libc/hdr/types/gid_t.h @@ -0,0 +1,22 @@ +//===-- Proxy for gid_t ---------------------------------------------------===// +// +// 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_HDR_TYPES_GID_T_H +#define LLVM_LIBC_HDR_TYPES_GID_T_H + +#ifdef LIBC_FULL_BUILD + +#include "include/llvm-libc-types/gid_t.h" + +#else // Overlay mode + +#include + +#endif // LLVM_LIBC_FULL_BUILD + +#endif // LLVM_LIBC_HDR_TYPES_GID_T_H diff --git a/libc/include/unistd.yaml b/libc/include/unistd.yaml index 2ff86eafaf550..0e5b22e627b67 100644 --- a/libc/include/unistd.yaml +++ b/libc/include/unistd.yaml @@ -3,6 +3,7 @@ header_template: unistd.h.def macros: [] types: - type_name: uid_t + - type_name: gid_t - type_name: ssize_t - type_name: size_t - type_name: pid_t @@ -54,6 +55,14 @@ functions: return_type: int arguments: - type: const char * + - name: chown + standards: + - POSIX + return_type: int + arguments: + - type: const char * + - type: uid_t + - type: gid_t - name: close standards: - POSIX @@ -195,6 +204,12 @@ functions: return_type: uid_t arguments: - type: void + - name: getgid + standards: + - POSIX + return_type: gid_t + arguments: + - type: void - name: isatty standards: - POSIX diff --git a/libc/src/unistd/CMakeLists.txt b/libc/src/unistd/CMakeLists.txt index 78c3bf8442fab..337480cbbf928 100644 --- a/libc/src/unistd/CMakeLists.txt +++ b/libc/src/unistd/CMakeLists.txt @@ -27,6 +27,13 @@ add_entrypoint_object( .${LIBC_TARGET_OS}.chdir ) +add_entrypoint_object( + chown + ALIAS + DEPENDS + .${LIBC_TARGET_OS}.chown +) + add_entrypoint_object( close ALIAS @@ -160,6 +167,13 @@ add_entrypoint_object( .${LIBC_TARGET_OS}.getuid ) +add_entrypoint_object( + getgid + ALIAS + DEPENDS + .${LIBC_TARGET_OS}.getgid +) + add_entrypoint_object( isatty ALIAS diff --git a/libc/src/unistd/chown.h b/libc/src/unistd/chown.h new file mode 100644 index 0000000000000..e5cae67c7f344 --- /dev/null +++ b/libc/src/unistd/chown.h @@ -0,0 +1,22 @@ +//===-- Implementation header for chown -------------------------*- 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_CHOWN_H +#define LLVM_LIBC_SRC_UNISTD_CHOWN_H + +#include "src/__support/macros/config.h" +#include "hdr/types/uid_t.h" +#include "hdr/types/gid_t.h" + +namespace LIBC_NAMESPACE_DECL { + +int chown(const char *path, uid_t owner, gid_t group); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_UNISTD_CHOWN_H diff --git a/libc/src/unistd/getgid.h b/libc/src/unistd/getgid.h new file mode 100644 index 0000000000000..eed0b20d688b1 --- /dev/null +++ b/libc/src/unistd/getgid.h @@ -0,0 +1,22 @@ +//===-- Implementation header for getgid ------------------------*- 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_GETGID_H +#define LLVM_LIBC_SRC_UNISTD_GETGID_H + +#include "hdr/types/gid_t.h" +#include "hdr/unistd_macros.h" +#include "src/__support/macros/config.h" + +namespace LIBC_NAMESPACE_DECL { + +gid_t getgid(); + +} // namespace LIBC_NAMESPACE_DECL + +#endif // LLVM_LIBC_SRC_UNISTD_GETGID_H diff --git a/libc/src/unistd/linux/CMakeLists.txt b/libc/src/unistd/linux/CMakeLists.txt index 4eb3c7d3d7fae..ee2acf3ff2109 100644 --- a/libc/src/unistd/linux/CMakeLists.txt +++ b/libc/src/unistd/linux/CMakeLists.txt @@ -25,6 +25,21 @@ add_entrypoint_object( libc.src.errno.errno ) +add_entrypoint_object( + chown + SRCS + chown.cpp + HDRS + ../chown.h + DEPENDS + libc.hdr.types.uid_t + libc.hdr.types.gid_t + libc.include.unistd + libc.include.sys_syscall + libc.src.__support.OSUtil.osutil + libc.src.errno.errno +) + add_entrypoint_object( close SRCS @@ -276,6 +291,20 @@ add_entrypoint_object( libc.src.errno.errno ) +add_entrypoint_object( + getgid + SRCS + getgid.cpp + HDRS + ../getgid.h + DEPENDS + libc.hdr.types.gid_t + libc.hdr.fcntl_macros + libc.include.unistd + libc.include.sys_syscall + libc.src.__support.OSUtil.osutil +) + add_entrypoint_object( getuid SRCS diff --git a/libc/src/unistd/linux/chown.cpp b/libc/src/unistd/linux/chown.cpp new file mode 100644 index 0000000000000..c7bf1703ffe57 --- /dev/null +++ b/libc/src/unistd/linux/chown.cpp @@ -0,0 +1,29 @@ +//===-- Linux implementation of chown -------------------------------------===// +// +// 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/chown.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 // For syscall numbers. + +namespace LIBC_NAMESPACE_DECL { + +LLVM_LIBC_FUNCTION(int, chown, (const char *path, uid_t owner, gid_t group)) { + int ret = LIBC_NAMESPACE::syscall_impl(SYS_chown, path, owner, group); + if (ret < 0) { + libc_errno = -ret; + return -1; + } + return 0; +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/unistd/linux/getgid.cpp b/libc/src/unistd/linux/getgid.cpp new file mode 100644 index 0000000000000..1656fd601d843 --- /dev/null +++ b/libc/src/unistd/linux/getgid.cpp @@ -0,0 +1,23 @@ +//===-- Linux implementation of getgid ------------------------------------===// +// +// 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/getgid.h" + +#include "src/__support/OSUtil/syscall.h" // For internal syscall function. +#include "src/__support/common.h" +#include "src/__support/macros/config.h" + +#include // For syscall numbers. + +namespace LIBC_NAMESPACE_DECL { + +LLVM_LIBC_FUNCTION(gid_t, getgid, ()) { + return LIBC_NAMESPACE::syscall_impl(SYS_getgid); +} + +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/test/src/unistd/CMakeLists.txt b/libc/test/src/unistd/CMakeLists.txt index 44f28fff9ad39..07070535459ec 100644 --- a/libc/test/src/unistd/CMakeLists.txt +++ b/libc/test/src/unistd/CMakeLists.txt @@ -36,6 +36,26 @@ add_libc_unittest( libc.test.UnitTest.ErrnoSetterMatcher ) +add_libc_unittest( + chown_test + SUITE + libc_unistd_unittests + SRCS + chown_test.cpp + DEPENDS + libc.hdr.fcntl_macros + libc.include.unistd + libc.src.errno.errno + libc.src.unistd.chown + libc.src.unistd.close + libc.src.unistd.unlink + libc.src.fcntl.open + libc.src.unistd.getuid + libc.src.unistd.getgid + libc.test.UnitTest.ErrnoCheckingTest + libc.test.UnitTest.ErrnoSetterMatcher +) + add_libc_unittest( dup_test SUITE @@ -437,6 +457,16 @@ add_libc_unittest( libc.test.UnitTest.ErrnoCheckingTest ) +add_libc_unittest( + getgid_test + SUITE + libc_unistd_unittests + SRCS + getgid_test.cpp + DEPENDS + libc.src.unistd.getgid +) + add_libc_unittest( getpid_test SUITE diff --git a/libc/test/src/unistd/chown_test.cpp b/libc/test/src/unistd/chown_test.cpp new file mode 100644 index 0000000000000..caa1c3deb6a76 --- /dev/null +++ b/libc/test/src/unistd/chown_test.cpp @@ -0,0 +1,51 @@ +//===-- Unittests for chown -----------------------------------------------===// +// +// 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/fcntl/open.h" +#include "src/unistd/chown.h" +#include "src/unistd/close.h" +#include "src/unistd/unlink.h" +#include "src/unistd/getuid.h" +#include "src/unistd/getgid.h" + +#include "test/UnitTest/ErrnoCheckingTest.h" +#include "test/UnitTest/ErrnoSetterMatcher.h" +#include "test/UnitTest/Test.h" + +#include "hdr/fcntl_macros.h" +#include + +using LlvmLibcChownTest = LIBC_NAMESPACE::testing::ErrnoCheckingTest; + +TEST_F(LlvmLibcChownTest, ChownSuccess) { + using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds; + uid_t my_uid = LIBC_NAMESPACE::getuid(); + gid_t my_gid = LIBC_NAMESPACE::getgid(); + constexpr const char *FILENAME = "chown.test"; + auto TEST_FILE = libc_make_test_file_path(FILENAME); + + // Create a test file. + int write_fd = LIBC_NAMESPACE::open(TEST_FILE, O_WRONLY | O_CREAT, S_IRWXU); + ASSERT_ERRNO_SUCCESS(); + ASSERT_GT(write_fd, 0); + + // Change the ownership of the file. + ASSERT_THAT(LIBC_NAMESPACE::chown(TEST_FILE, my_uid, my_gid), Succeeds(0)); + + // Close the file descriptor. + ASSERT_THAT(LIBC_NAMESPACE::close(write_fd), Succeeds(0)); + + // Clean up the test file. + ASSERT_THAT(LIBC_NAMESPACE::unlink(TEST_FILE), Succeeds(0)); +} + +TEST_F(LlvmLibcChownTest, ChownNonExistentFile) { + using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Fails; + ASSERT_THAT(LIBC_NAMESPACE::chown("non-existent-file", 1000, 1000), + Fails(ENOENT)); +} diff --git a/libc/test/src/unistd/getgid_test.cpp b/libc/test/src/unistd/getgid_test.cpp new file mode 100644 index 0000000000000..77dbad2f18e00 --- /dev/null +++ b/libc/test/src/unistd/getgid_test.cpp @@ -0,0 +1,15 @@ +//===-- Unittests for getgid ----------------------------------------------===// +// +// 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/getgid.h" +#include "test/UnitTest/Test.h" + +TEST(LlvmLibcGetGidTest, SmokeTest) { + // getgid always succeeds. So, we just call it as a smoke test. + LIBC_NAMESPACE::getgid(); +}