[libc-commits] [libc] [libc] Add chown and getgid implementations (PR #166434)
Shubh Pachchigar via libc-commits
libc-commits at lists.llvm.org
Tue Nov 4 13:33:41 PST 2025
https://github.com/shubhe25p updated https://github.com/llvm/llvm-project/pull/166434
>From 1a041ef1596b86f657aa2559c2c05ad894302359 Mon Sep 17 00:00:00 2001
From: "shubh at DOE" <shubhp at mbm3a24.local>
Date: Tue, 4 Nov 2025 13:32:48 -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 | 28 +++++++++++++
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, 281 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 <sys/types.h>
+
+#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..84a8eba2cb2e6
--- /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 "hdr/types/gid_t.h"
+#include "hdr/types/uid_t.h"
+#include "src/__support/macros/config.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..c2dacc6456e27 100644
--- a/libc/src/unistd/linux/CMakeLists.txt
+++ b/libc/src/unistd/linux/CMakeLists.txt
@@ -25,6 +25,20 @@ 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.sys_syscall
+ libc.src.__support.OSUtil.osutil
+ libc.src.errno.errno
+)
+
add_entrypoint_object(
close
SRCS
@@ -276,6 +290,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 <sys/syscall.h> // 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<int>(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 <sys/syscall.h> // For syscall numbers.
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(gid_t, getgid, ()) {
+ return LIBC_NAMESPACE::syscall_impl<gid_t>(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..8b1f783273624
--- /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/getgid.h"
+#include "src/unistd/getuid.h"
+#include "src/unistd/unlink.h"
+
+#include "test/UnitTest/ErrnoCheckingTest.h"
+#include "test/UnitTest/ErrnoSetterMatcher.h"
+#include "test/UnitTest/Test.h"
+
+#include "hdr/fcntl_macros.h"
+#include <sys/stat.h>
+
+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();
+}
More information about the libc-commits
mailing list