diff options
author | Siva Chandra Reddy <sivachandra@google.com> | 2022-01-27 23:47:50 +0000 |
---|---|---|
committer | Siva Chandra Reddy <sivachandra@google.com> | 2022-01-28 19:28:12 +0000 |
commit | 4abfe47e1fc8b4c7583d5bdcb20d102dd2a5efb1 (patch) | |
tree | 8745cb2877c466bc2d729775243e2276fbab2d77 /libc | |
parent | [gn build] Port f489e86a24d3 (diff) | |
download | llvm-project-4abfe47e1fc8b4c7583d5bdcb20d102dd2a5efb1.tar.gz llvm-project-4abfe47e1fc8b4c7583d5bdcb20d102dd2a5efb1.tar.bz2 llvm-project-4abfe47e1fc8b4c7583d5bdcb20d102dd2a5efb1.zip |
[libc] Add implementations of the POSIX creat and openat functions.
Reviewed By: michaelrj
Differential Revision: https://reviews.llvm.org/D118435
Diffstat (limited to 'libc')
-rw-r--r-- | libc/config/linux/x86_64/entrypoints.txt | 2 | ||||
-rw-r--r-- | libc/include/llvm-libc-macros/linux/fcntl-macros.h | 4 | ||||
-rw-r--r-- | libc/spec/posix.td | 10 | ||||
-rw-r--r-- | libc/src/fcntl/CMakeLists.txt | 14 | ||||
-rw-r--r-- | libc/src/fcntl/creat.h | 20 | ||||
-rw-r--r-- | libc/src/fcntl/linux/CMakeLists.txt | 26 | ||||
-rw-r--r-- | libc/src/fcntl/linux/creat.cpp | 30 | ||||
-rw-r--r-- | libc/src/fcntl/linux/openat.cpp | 40 | ||||
-rw-r--r-- | libc/src/fcntl/openat.h | 20 | ||||
-rw-r--r-- | libc/test/src/CMakeLists.txt | 1 | ||||
-rw-r--r-- | libc/test/src/fcntl/CMakeLists.txt | 34 | ||||
-rw-r--r-- | libc/test/src/fcntl/creat_test.cpp | 32 | ||||
-rw-r--r-- | libc/test/src/fcntl/openat_test.cpp | 43 | ||||
-rw-r--r-- | libc/test/src/fcntl/testdata/CMakeLists.txt | 1 |
14 files changed, 277 insertions, 0 deletions
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt index 997e3f6282e6..d230decc8f30 100644 --- a/libc/config/linux/x86_64/entrypoints.txt +++ b/libc/config/linux/x86_64/entrypoints.txt @@ -21,7 +21,9 @@ set(TARGET_LIBC_ENTRYPOINTS libc.src.errno.__errno_location # fcntl.h entrypoints + libc.src.fcntl.creat libc.src.fcntl.open + libc.src.fcntl.openat # string.h entrypoints libc.src.string.bcmp diff --git a/libc/include/llvm-libc-macros/linux/fcntl-macros.h b/libc/include/llvm-libc-macros/linux/fcntl-macros.h index e7ce8e847a9e..007f780b43b3 100644 --- a/libc/include/llvm-libc-macros/linux/fcntl-macros.h +++ b/libc/include/llvm-libc-macros/linux/fcntl-macros.h @@ -49,4 +49,8 @@ #define S_ISUID 04000 #define S_ISGID 02000 +// Special directory FD to indicate that the path argument to +// openat is relative to the current directory. +#define AT_FDCWD -100 + #endif // __LLVM_LIBC_MACROS_LINUX_FCNTL_MACROS_H diff --git a/libc/spec/posix.td b/libc/spec/posix.td index 28d8dfe0b5d4..de3e2d59aaec 100644 --- a/libc/spec/posix.td +++ b/libc/spec/posix.td @@ -115,10 +115,20 @@ def POSIX : StandardSpec<"POSIX"> { [], // Enumerations [ FunctionSpec< + "creat", + RetValSpec<IntType>, + [ArgSpec<ConstCharPtr>, ArgSpec<ModeTType>] + >, + FunctionSpec< "open", RetValSpec<IntType>, [ArgSpec<ConstCharPtr>, ArgSpec<IntType>, ArgSpec<VarArgType>] >, + FunctionSpec< + "openat", + RetValSpec<IntType>, + [ArgSpec<IntType>, ArgSpec<ConstCharPtr>, ArgSpec<IntType>, ArgSpec<VarArgType>] + >, ] >; diff --git a/libc/src/fcntl/CMakeLists.txt b/libc/src/fcntl/CMakeLists.txt index f5416e981d1f..0b9ee47c4f7c 100644 --- a/libc/src/fcntl/CMakeLists.txt +++ b/libc/src/fcntl/CMakeLists.txt @@ -3,8 +3,22 @@ if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS}) endif() add_entrypoint_object( + creat + ALIAS + DEPENDS + .${LIBC_TARGET_OS}.creat +) + +add_entrypoint_object( open ALIAS DEPENDS .${LIBC_TARGET_OS}.open ) + +add_entrypoint_object( + openat + ALIAS + DEPENDS + .${LIBC_TARGET_OS}.openat +) diff --git a/libc/src/fcntl/creat.h b/libc/src/fcntl/creat.h new file mode 100644 index 000000000000..0c1abda2870c --- /dev/null +++ b/libc/src/fcntl/creat.h @@ -0,0 +1,20 @@ +//===-- Implementation header of creat --------------------------*- 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_FCNTL_CREAT_H +#define LLVM_LIBC_SRC_FCNTL_CREAT_H + +#include <fcntl.h> + +namespace __llvm_libc { + +int creat(const char *path, int mode); + +} // namespace __llvm_libc + +#endif // LLVM_LIBC_SRC_FCNTL_CREAT_H diff --git a/libc/src/fcntl/linux/CMakeLists.txt b/libc/src/fcntl/linux/CMakeLists.txt index 3ed5d516e1af..17d7b4b76491 100644 --- a/libc/src/fcntl/linux/CMakeLists.txt +++ b/libc/src/fcntl/linux/CMakeLists.txt @@ -1,4 +1,17 @@ add_entrypoint_object( + creat + SRCS + creat.cpp + HDRS + ../creat.h + DEPENDS + libc.include.errno + libc.include.fcntl + libc.src.__support.OSUtil.osutil + libc.src.errno.__errno_location +) + +add_entrypoint_object( open SRCS open.cpp @@ -10,3 +23,16 @@ add_entrypoint_object( libc.src.__support.OSUtil.osutil libc.src.errno.__errno_location ) + +add_entrypoint_object( + openat + SRCS + openat.cpp + HDRS + ../openat.h + DEPENDS + libc.include.errno + libc.include.fcntl + libc.src.__support.OSUtil.osutil + libc.src.errno.__errno_location +) diff --git a/libc/src/fcntl/linux/creat.cpp b/libc/src/fcntl/linux/creat.cpp new file mode 100644 index 000000000000..50b5d5e0a9b3 --- /dev/null +++ b/libc/src/fcntl/linux/creat.cpp @@ -0,0 +1,30 @@ +//===-- Implementation of creat -------------------------------------------===// +// +// 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/creat.h" + +#include "src/__support/OSUtil/syscall.h" // For internal syscall function. +#include "src/__support/common.h" + +#include <errno.h> +#include <fcntl.h> +#include <sys/syscall.h> // For syscall numbers. + +namespace __llvm_libc { + +LLVM_LIBC_FUNCTION(int, creat, (const char *path, int mode_flags)) { + int fd = __llvm_libc::syscall(SYS_open, path, O_CREAT | O_WRONLY | O_TRUNC, + mode_flags); + if (fd > 0) + return fd; + + errno = -fd; + return -1; +} + +} // namespace __llvm_libc diff --git a/libc/src/fcntl/linux/openat.cpp b/libc/src/fcntl/linux/openat.cpp new file mode 100644 index 000000000000..b55fa92206f5 --- /dev/null +++ b/libc/src/fcntl/linux/openat.cpp @@ -0,0 +1,40 @@ +//===-- Implementation of openat ------------------------------------------===// +// +// 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/openat.h" + +#include "src/__support/OSUtil/syscall.h" // For internal syscall function. +#include "src/__support/common.h" + +#include <errno.h> +#include <fcntl.h> +#include <stdarg.h> +#include <sys/syscall.h> // For syscall numbers. + +namespace __llvm_libc { + +LLVM_LIBC_FUNCTION(int, openat, (int dfd, const char *path, int flags, ...)) { + mode_t mode_flags = 0; + // O_TMPFILE is a multi-bit flag so we test all bits by checking for equality + // with O_TMPFILE + if ((flags & O_CREAT) || (flags & O_TMPFILE) == O_TMPFILE) { + va_list varargs; + va_start(varargs, flags); + mode_flags = va_arg(varargs, mode_t); + va_end(varargs); + } + + int fd = __llvm_libc::syscall(SYS_openat, dfd, path, flags, mode_flags); + if (fd > 0) + return fd; + + errno = -fd; + return -1; +} + +} // namespace __llvm_libc diff --git a/libc/src/fcntl/openat.h b/libc/src/fcntl/openat.h new file mode 100644 index 000000000000..96a96de14049 --- /dev/null +++ b/libc/src/fcntl/openat.h @@ -0,0 +1,20 @@ +//===-- Implementation header of openat -------------------------*- 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_FCNTL_OPENAT_H +#define LLVM_LIBC_SRC_FCNTL_OPENAT_H + +#include <fcntl.h> + +namespace __llvm_libc { + +int openat(int dfd, const char *path, int flags, ...); + +} // namespace __llvm_libc + +#endif // LLVM_LIBC_SRC_FCNTL_OPENAT_H diff --git a/libc/test/src/CMakeLists.txt b/libc/test/src/CMakeLists.txt index 469f5a56e713..e10b9ec30646 100644 --- a/libc/test/src/CMakeLists.txt +++ b/libc/test/src/CMakeLists.txt @@ -35,6 +35,7 @@ add_subdirectory(string) add_subdirectory(stdlib) if(${LIBC_TARGET_OS} STREQUAL "linux") + add_subdirectory(fcntl) add_subdirectory(sys) add_subdirectory(unistd) endif() diff --git a/libc/test/src/fcntl/CMakeLists.txt b/libc/test/src/fcntl/CMakeLists.txt new file mode 100644 index 000000000000..877e00b9cc42 --- /dev/null +++ b/libc/test/src/fcntl/CMakeLists.txt @@ -0,0 +1,34 @@ +add_libc_testsuite(libc_fcntl_unittests) + +add_subdirectory(testdata) + +add_libc_unittest( + creat_test + SUITE + libc_fcntl_unittests + SRCS + creat_test.cpp + DEPENDS + libc.include.errno + libc.include.fcntl + libc.src.fcntl.creat + libc.src.fcntl.open + libc.src.unistd.close + libc.test.errno_setter_matcher +) + +add_libc_unittest( + openat_test + SUITE + libc_fcntl_unittests + SRCS + openat_test.cpp + DEPENDS + libc.include.errno + libc.include.fcntl + libc.src.fcntl.open + libc.src.fcntl.openat + libc.src.unistd.close + libc.src.unistd.read + libc.test.errno_setter_matcher +) diff --git a/libc/test/src/fcntl/creat_test.cpp b/libc/test/src/fcntl/creat_test.cpp new file mode 100644 index 000000000000..22cbd1bb996d --- /dev/null +++ b/libc/test/src/fcntl/creat_test.cpp @@ -0,0 +1,32 @@ +//===-- Unittest for creat ------------------------------------------------===// +// +// 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/creat.h" +#include "src/fcntl/open.h" +#include "src/unistd/close.h" +#include "test/ErrnoSetterMatcher.h" +#include "utils/UnitTest/Test.h" +#include "utils/testutils/FDReader.h" + +#include <errno.h> + +TEST(LlvmLibcCreatTest, CreatAndOpen) { + using __llvm_libc::testing::ErrnoSetterMatcher::Succeeds; + constexpr const char *TEST_FILE = "testdata/creat.test"; + int fd = __llvm_libc::creat(TEST_FILE, S_IRWXU); + ASSERT_EQ(errno, 0); + ASSERT_GT(fd, 0); + ASSERT_THAT(__llvm_libc::close(fd), Succeeds(0)); + + fd = __llvm_libc::open(TEST_FILE, O_RDONLY); + ASSERT_EQ(errno, 0); + ASSERT_GT(fd, 0); + ASSERT_THAT(__llvm_libc::close(fd), Succeeds(0)); + + // TODO: 'remove' the test file at the end. +} diff --git a/libc/test/src/fcntl/openat_test.cpp b/libc/test/src/fcntl/openat_test.cpp new file mode 100644 index 000000000000..b4c05f41ccaa --- /dev/null +++ b/libc/test/src/fcntl/openat_test.cpp @@ -0,0 +1,43 @@ +//===-- Unittests for openat ----------------------------------------------===// +// +// 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/fcntl/openat.h" +#include "src/unistd/close.h" +#include "src/unistd/read.h" +#include "test/ErrnoSetterMatcher.h" +#include "utils/UnitTest/Test.h" +#include "utils/testutils/FDReader.h" + +#include <errno.h> + +TEST(LlvmLibcUniStd, OpenAndReadTest) { + using __llvm_libc::testing::ErrnoSetterMatcher::Succeeds; + constexpr const char *TEST_DIR = "testdata"; + constexpr const char *TEST_FILE = "openat.test"; + int dir_fd = __llvm_libc::open(TEST_DIR, O_DIRECTORY); + ASSERT_EQ(errno, 0); + ASSERT_GT(dir_fd, 0); + constexpr const char TEST_MSG[] = "openat test"; + constexpr int TEST_MSG_SIZE = sizeof(TEST_MSG) - 1; + + int read_fd = __llvm_libc::openat(dir_fd, TEST_FILE, O_RDONLY); + ASSERT_EQ(errno, 0); + ASSERT_GT(read_fd, 0); + char read_buf[TEST_MSG_SIZE]; + ASSERT_THAT(__llvm_libc::read(read_fd, read_buf, TEST_MSG_SIZE), + Succeeds(TEST_MSG_SIZE)); + ASSERT_THAT(__llvm_libc::close(read_fd), Succeeds(0)); + ASSERT_THAT(__llvm_libc::close(dir_fd), Succeeds(0)); +} + +TEST(LlvmLibcUniStd, FailTest) { + using __llvm_libc::testing::ErrnoSetterMatcher::Fails; + EXPECT_THAT(__llvm_libc::openat(AT_FDCWD, "openat.test", O_RDONLY), + Fails(ENOENT)); +} diff --git a/libc/test/src/fcntl/testdata/CMakeLists.txt b/libc/test/src/fcntl/testdata/CMakeLists.txt new file mode 100644 index 000000000000..9c22c6dd1763 --- /dev/null +++ b/libc/test/src/fcntl/testdata/CMakeLists.txt @@ -0,0 +1 @@ +file(GENERATE OUTPUT openat.test CONTENT "openat test") |