Skip to content

Commit 85dff76

Browse files
author
Siva Chandra Reddy
committed
[libc] Add linux implementation of POSIX fchmodat function.
Reviewed By: michaelrj Differential Revision: https://reviews.llvm.org/D132533
1 parent 23245a9 commit 85dff76

File tree

10 files changed

+167
-2
lines changed

10 files changed

+167
-2
lines changed

libc/config/linux/aarch64/entrypoints.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ set(TARGET_LIBC_ENTRYPOINTS
103103
# sys/stat.h entrypoints
104104
libc.src.sys.stat.chmod
105105
libc.src.sys.stat.fchmod
106+
libc.src.sys.stat.fchmodat
106107
libc.src.sys.stat.mkdir
107108
libc.src.sys.stat.mkdirat
108109

libc/config/linux/x86_64/entrypoints.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ set(TARGET_LIBC_ENTRYPOINTS
103103
# sys/stat.h entrypoints
104104
libc.src.sys.stat.chmod
105105
libc.src.sys.stat.fchmod
106+
libc.src.sys.stat.fchmodat
106107
libc.src.sys.stat.mkdir
107108
libc.src.sys.stat.mkdirat
108109

libc/spec/posix.td

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -406,12 +406,17 @@ def POSIX : StandardSpec<"POSIX"> {
406406
FunctionSpec<
407407
"chmod",
408408
RetValSpec<IntType>,
409-
[ArgSpec<ConstCharPtr>]
409+
[ArgSpec<ConstCharPtr>, ArgSpec<ModeTType>]
410410
>,
411411
FunctionSpec<
412412
"fchmod",
413413
RetValSpec<IntType>,
414-
[ArgSpec<IntType>]
414+
[ArgSpec<IntType>, ArgSpec<ModeTType>]
415+
>,
416+
FunctionSpec<
417+
"fchmodat",
418+
RetValSpec<IntType>,
419+
[ArgSpec<IntType>, ArgSpec<ConstCharPtr>, ArgSpec<ModeTType>, ArgSpec<IntType>]
415420
>,
416421
FunctionSpec<
417422
"mkdir",

libc/src/sys/stat/CMakeLists.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,13 @@ add_entrypoint_object(
99
.${LIBC_TARGET_OS}.chmod
1010
)
1111

12+
add_entrypoint_object(
13+
fchmodat
14+
ALIAS
15+
DEPENDS
16+
.${LIBC_TARGET_OS}.fchmodat
17+
)
18+
1219
add_entrypoint_object(
1320
fchmod
1421
ALIAS

libc/src/sys/stat/fchmodat.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//===-- Implementation header for fchmodat ----------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_LIBC_SRC_SYS_STAT_FCHMODAT_H
10+
#define LLVM_LIBC_SRC_SYS_STAT_FCHMODAT_H
11+
12+
#include <sys/stat.h>
13+
14+
namespace __llvm_libc {
15+
16+
int fchmodat(int dirfd, const char *path, mode_t mode, int flags);
17+
18+
} // namespace __llvm_libc
19+
20+
#endif // LLVM_LIBC_SRC_SYS_STAT_FCHMODAT_H

libc/src/sys/stat/linux/CMakeLists.txt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,19 @@ add_entrypoint_object(
2525
libc.src.errno.errno
2626
)
2727

28+
add_entrypoint_object(
29+
fchmodat
30+
SRCS
31+
fchmodat.cpp
32+
HDRS
33+
../fchmod.h
34+
DEPENDS
35+
libc.include.sys_stat
36+
libc.include.sys_syscall
37+
libc.src.__support.OSUtil.osutil
38+
libc.src.errno.errno
39+
)
40+
2841
add_entrypoint_object(
2942
mkdir
3043
SRCS

libc/src/sys/stat/linux/fchmodat.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
//===-- Linux implementation of fchmodat ----------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "src/sys/stat/fchmodat.h"
10+
11+
#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
12+
#include "src/__support/common.h"
13+
14+
#include <errno.h>
15+
#include <sys/stat.h>
16+
#include <sys/syscall.h> // For syscall numbers.
17+
18+
namespace __llvm_libc {
19+
20+
LLVM_LIBC_FUNCTION(int, fchmodat,
21+
(int dirfd, const char *path, mode_t mode, int flags)) {
22+
long ret = __llvm_libc::syscall(SYS_fchmodat, dirfd, path, mode, flags);
23+
if (ret < 0) {
24+
errno = -ret;
25+
return -1;
26+
}
27+
return 0;
28+
}
29+
30+
} // namespace __llvm_libc

libc/test/src/sys/stat/CMakeLists.txt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,22 @@ add_libc_unittest(
1818
libc.src.unistd.write
1919
)
2020

21+
add_libc_unittest(
22+
fchmodat_test
23+
SUITE
24+
libc_sys_stat_unittests
25+
SRCS
26+
fchmodat_test.cpp
27+
DEPENDS
28+
libc.include.errno
29+
libc.include.fcntl
30+
libc.include.sys_stat
31+
libc.src.fcntl.open
32+
libc.src.sys.stat.fchmodat
33+
libc.src.unistd.close
34+
libc.src.unistd.write
35+
)
36+
2137
add_libc_unittest(
2238
fchmod_test
2339
SUITE
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
//===-- Unittests for fchmodat --------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "src/fcntl/open.h"
10+
#include "src/sys/stat/fchmodat.h"
11+
#include "src/unistd/close.h"
12+
#include "src/unistd/write.h"
13+
#include "test/ErrnoSetterMatcher.h"
14+
#include "utils/UnitTest/Test.h"
15+
#include "utils/testutils/FDReader.h"
16+
17+
#include <errno.h>
18+
#include <fcntl.h>
19+
#include <sys/stat.h>
20+
21+
TEST(LlvmLibcFchmodatTest, ChangeAndOpen) {
22+
using __llvm_libc::testing::ErrnoSetterMatcher::Fails;
23+
using __llvm_libc::testing::ErrnoSetterMatcher::Succeeds;
24+
25+
// The test file is initially writable. We open it for writing and ensure
26+
// that it indeed can be opened for writing. Next, we close the file and
27+
// make it readonly using chmod. We test that chmod actually succeeded by
28+
// trying to open the file for writing and failing.
29+
constexpr const char *TEST_FILE = "testdata/fchmodat.test";
30+
constexpr const char *TEST_DIR = "testdata";
31+
constexpr const char *TEST_FILE_BASENAME = "fchmodat.test";
32+
const char WRITE_DATA[] = "fchmodat test";
33+
constexpr ssize_t WRITE_SIZE = ssize_t(sizeof(WRITE_DATA));
34+
errno = 0;
35+
36+
int fd = __llvm_libc::open(TEST_FILE, O_CREAT | O_WRONLY, S_IRWXU);
37+
ASSERT_GT(fd, 0);
38+
ASSERT_EQ(errno, 0);
39+
ASSERT_EQ(__llvm_libc::write(fd, WRITE_DATA, sizeof(WRITE_DATA)), WRITE_SIZE);
40+
ASSERT_THAT(__llvm_libc::close(fd), Succeeds(0));
41+
42+
int dirfd = __llvm_libc::open(TEST_DIR, O_DIRECTORY);
43+
ASSERT_GT(dirfd, 0);
44+
ASSERT_EQ(errno, 0);
45+
46+
EXPECT_THAT(__llvm_libc::fchmodat(dirfd, TEST_FILE_BASENAME, S_IRUSR, 0),
47+
Succeeds(0));
48+
49+
// Opening for writing should fail.
50+
EXPECT_EQ(__llvm_libc::open(TEST_FILE, O_APPEND | O_WRONLY), -1);
51+
EXPECT_NE(errno, 0);
52+
errno = 0;
53+
// But opening for reading should succeed.
54+
fd = __llvm_libc::open(TEST_FILE, O_APPEND | O_RDONLY);
55+
EXPECT_GT(fd, 0);
56+
EXPECT_EQ(errno, 0);
57+
58+
EXPECT_THAT(__llvm_libc::close(fd), Succeeds(0));
59+
EXPECT_THAT(__llvm_libc::fchmodat(dirfd, TEST_FILE_BASENAME, S_IRWXU, 0),
60+
Succeeds(0));
61+
62+
EXPECT_THAT(__llvm_libc::close(dirfd), Succeeds(0));
63+
}
64+
65+
TEST(LlvmLibcFchmodatTest, NonExistentFile) {
66+
errno = 0;
67+
using __llvm_libc::testing::ErrnoSetterMatcher::Fails;
68+
ASSERT_THAT(__llvm_libc::fchmodat(AT_FDCWD, "non-existent-file", S_IRUSR, 0),
69+
Fails(ENOENT));
70+
errno = 0;
71+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# This directory will be used to create test files.
22

33
file(GENERATE OUTPUT chmod.test CONTENT "chmod test")
4+
file(GENERATE OUTPUT fchmodat.test CONTENT "fchmodat test")
45
file(GENERATE OUTPUT fchmod.test CONTENT "fchmod test")

0 commit comments

Comments
 (0)