[libc] Add chown and getgid implementations (#166434)

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. This PR will address #165785

Co-authored-by: shubh@DOE <shubhp@mbm3a24.local>
This commit is contained in:
Shubh Pachchigar
2025-11-04 16:18:53 -08:00
committed by GitHub
parent 2b4ac66297
commit 0fd029858a
13 changed files with 281 additions and 0 deletions

View File

@@ -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

View File

@@ -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
)

22
libc/hdr/types/gid_t.h Normal file
View File

@@ -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

View File

@@ -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

View File

@@ -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

22
libc/src/unistd/chown.h Normal file
View File

@@ -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

22
libc/src/unistd/getgid.h Normal file
View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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));
}

View File

@@ -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();
}