aboutsummaryrefslogtreecommitdiff
path: root/libc
diff options
context:
space:
mode:
authorSiva Chandra Reddy <sivachandra@google.com>2022-01-27 23:47:50 +0000
committerSiva Chandra Reddy <sivachandra@google.com>2022-01-28 19:28:12 +0000
commit4abfe47e1fc8b4c7583d5bdcb20d102dd2a5efb1 (patch)
tree8745cb2877c466bc2d729775243e2276fbab2d77 /libc
parent[gn build] Port f489e86a24d3 (diff)
downloadllvm-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.txt2
-rw-r--r--libc/include/llvm-libc-macros/linux/fcntl-macros.h4
-rw-r--r--libc/spec/posix.td10
-rw-r--r--libc/src/fcntl/CMakeLists.txt14
-rw-r--r--libc/src/fcntl/creat.h20
-rw-r--r--libc/src/fcntl/linux/CMakeLists.txt26
-rw-r--r--libc/src/fcntl/linux/creat.cpp30
-rw-r--r--libc/src/fcntl/linux/openat.cpp40
-rw-r--r--libc/src/fcntl/openat.h20
-rw-r--r--libc/test/src/CMakeLists.txt1
-rw-r--r--libc/test/src/fcntl/CMakeLists.txt34
-rw-r--r--libc/test/src/fcntl/creat_test.cpp32
-rw-r--r--libc/test/src/fcntl/openat_test.cpp43
-rw-r--r--libc/test/src/fcntl/testdata/CMakeLists.txt1
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")