[libc-commits] [libc] 4abfe47 - [libc] Add implementations of the POSIX creat and openat functions.

Siva Chandra Reddy via libc-commits libc-commits at lists.llvm.org
Fri Jan 28 11:28:28 PST 2022


Author: Siva Chandra Reddy
Date: 2022-01-28T19:28:12Z
New Revision: 4abfe47e1fc8b4c7583d5bdcb20d102dd2a5efb1

URL: https://github.com/llvm/llvm-project/commit/4abfe47e1fc8b4c7583d5bdcb20d102dd2a5efb1
DIFF: https://github.com/llvm/llvm-project/commit/4abfe47e1fc8b4c7583d5bdcb20d102dd2a5efb1.diff

LOG: [libc] Add implementations of the POSIX creat and openat functions.

Reviewed By: michaelrj

Differential Revision: https://reviews.llvm.org/D118435

Added: 
    libc/src/fcntl/creat.h
    libc/src/fcntl/linux/creat.cpp
    libc/src/fcntl/linux/openat.cpp
    libc/src/fcntl/openat.h
    libc/test/src/fcntl/CMakeLists.txt
    libc/test/src/fcntl/creat_test.cpp
    libc/test/src/fcntl/openat_test.cpp
    libc/test/src/fcntl/testdata/CMakeLists.txt

Modified: 
    libc/config/linux/x86_64/entrypoints.txt
    libc/include/llvm-libc-macros/linux/fcntl-macros.h
    libc/spec/posix.td
    libc/src/fcntl/CMakeLists.txt
    libc/src/fcntl/linux/CMakeLists.txt
    libc/test/src/CMakeLists.txt

Removed: 
    


################################################################################
diff  --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 997e3f6282e6d..d230decc8f30c 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 e7ce8e847a9ec..007f780b43b3f 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 28d8dfe0b5d4c..de3e2d59aaec5 100644
--- a/libc/spec/posix.td
+++ b/libc/spec/posix.td
@@ -114,11 +114,21 @@ def POSIX : StandardSpec<"POSIX"> {
     [ModeTType],
     [], // 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 f5416e981d1fa..0b9ee47c4f7c1 100644
--- a/libc/src/fcntl/CMakeLists.txt
+++ b/libc/src/fcntl/CMakeLists.txt
@@ -2,9 +2,23 @@ if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
   add_subdirectory(${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 0000000000000..0c1abda2870c7
--- /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 3ed5d516e1af3..17d7b4b76491f 100644
--- a/libc/src/fcntl/linux/CMakeLists.txt
+++ b/libc/src/fcntl/linux/CMakeLists.txt
@@ -1,3 +1,16 @@
+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
@@ -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 0000000000000..50b5d5e0a9b30
--- /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 0000000000000..b55fa92206f51
--- /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 0000000000000..96a96de140496
--- /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 469f5a56e7139..e10b9ec306469 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 0000000000000..877e00b9cc420
--- /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 0000000000000..22cbd1bb996d9
--- /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 0000000000000..b4c05f41ccaa9
--- /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 0000000000000..9c22c6dd17636
--- /dev/null
+++ b/libc/test/src/fcntl/testdata/CMakeLists.txt
@@ -0,0 +1 @@
+file(GENERATE OUTPUT openat.test CONTENT "openat test")


        


More information about the libc-commits mailing list