[libc-commits] [libc] dc2b01b - [libc] Add POSIX close, fsync, open, read and write functions.

Siva Chandra Reddy via libc-commits libc-commits at lists.llvm.org
Thu Jan 27 12:32:31 PST 2022


Author: Siva Chandra Reddy
Date: 2022-01-27T20:32:02Z
New Revision: dc2b01b3f7b0e89cb57a29542da2492276c61678

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

LOG: [libc] Add POSIX close, fsync, open, read and write functions.

They are implemented as simple syscall wrappers. The file creation
macros have been put in a header file as a temporary solution until we
have a cleaner approach to listing platform relevant macros.

Reviewed By: abrachet

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

Added: 
    libc/include/fcntl.h.def
    libc/include/llvm-libc-macros/CMakeLists.txt
    libc/include/llvm-libc-macros/fcntl-macros.h
    libc/include/llvm-libc-macros/linux/CMakeLists.txt
    libc/include/llvm-libc-macros/linux/fcntl-macros.h
    libc/include/llvm-libc-types/mode_t.h
    libc/src/fcntl/CMakeLists.txt
    libc/src/fcntl/linux/CMakeLists.txt
    libc/src/fcntl/linux/open.cpp
    libc/src/fcntl/open.h
    libc/src/unistd/close.h
    libc/src/unistd/fsync.h
    libc/src/unistd/linux/close.cpp
    libc/src/unistd/linux/fsync.cpp
    libc/src/unistd/linux/read.cpp
    libc/src/unistd/read.h
    libc/test/src/unistd/read_write_test.cpp

Modified: 
    libc/config/linux/api.td
    libc/config/linux/x86_64/entrypoints.txt
    libc/include/CMakeLists.txt
    libc/include/llvm-libc-types/CMakeLists.txt
    libc/spec/posix.td
    libc/src/CMakeLists.txt
    libc/src/unistd/CMakeLists.txt
    libc/src/unistd/linux/CMakeLists.txt
    libc/src/unistd/linux/write.cpp
    libc/test/src/unistd/CMakeLists.txt

Removed: 
    libc/test/src/unistd/write_test.cpp


################################################################################
diff  --git a/libc/config/linux/api.td b/libc/config/linux/api.td
index 77e22287fe76..7bfa621fd98f 100644
--- a/libc/config/linux/api.td
+++ b/libc/config/linux/api.td
@@ -62,6 +62,10 @@ def AssertAPI : PublicAPI<"assert.h"> {
 def CTypeAPI : PublicAPI<"ctype.h"> {
 }
 
+def FCntlAPI : PublicAPI<"fcntl.h"> {
+  let Types = ["mode_t"];
+}
+
 def IntTypesAPI : PublicAPI<"inttypes.h"> {
   let Types = ["imaxdiv_t"];
 }

diff  --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 47066d598da7..997e3f6282e6 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -20,6 +20,9 @@ set(TARGET_LIBC_ENTRYPOINTS
     # errno.h entrypoints
     libc.src.errno.__errno_location
 
+    # fcntl.h entrypoints
+    libc.src.fcntl.open
+
     # string.h entrypoints
     libc.src.string.bcmp
     libc.src.string.bzero
@@ -81,6 +84,9 @@ set(TARGET_LIBC_ENTRYPOINTS
     libc.src.sys.mman.munmap
 
     # unistd.h entrypoints
+    libc.src.unistd.close
+    libc.src.unistd.fsync
+    libc.src.unistd.read
     libc.src.unistd.write
 )
 

diff  --git a/libc/include/CMakeLists.txt b/libc/include/CMakeLists.txt
index d3b813b87b49..d208f17ad699 100644
--- a/libc/include/CMakeLists.txt
+++ b/libc/include/CMakeLists.txt
@@ -1,3 +1,4 @@
+add_subdirectory(llvm-libc-macros)
 add_subdirectory(llvm-libc-types)
 
 add_header(
@@ -14,6 +15,16 @@ add_gen_header(
     .llvm_libc_common_h
 )
 
+add_gen_header(
+  fcntl
+  DEF_FILE fcntl.h.def
+  GEN_HDR fcntl.h
+  DEPENDS
+    .llvm_libc_common_h
+    .llvm-libc-macros.fcntl_macros
+    .llvm-libc-types.mode_t
+)
+
 add_gen_header(
   fenv
   DEF_FILE fenv.h.def

diff  --git a/libc/include/fcntl.h.def b/libc/include/fcntl.h.def
new file mode 100644
index 000000000000..83d4477d0064
--- /dev/null
+++ b/libc/include/fcntl.h.def
@@ -0,0 +1,17 @@
+//===-- C standard library header fcntl.h ---------------------------------===//
+//
+// 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_FCNTL_H
+#define LLVM_LIBC_FCNTL_H
+
+#include <__llvm-libc-common.h>
+#include <llvm-libc-macros/fcntl-macros.h>
+
+%%public_api()
+
+#endif // LLVM_LIBC_FCNTL_H 

diff  --git a/libc/include/llvm-libc-macros/CMakeLists.txt b/libc/include/llvm-libc-macros/CMakeLists.txt
new file mode 100644
index 000000000000..d6b59dbbb8e2
--- /dev/null
+++ b/libc/include/llvm-libc-macros/CMakeLists.txt
@@ -0,0 +1,9 @@
+add_subdirectory(linux)
+
+add_header(
+  fcntl_macros
+  HDR
+    fcntl-macros.h
+  DEPENDS
+    .linux.fcntl_macros
+)

diff  --git a/libc/include/llvm-libc-macros/fcntl-macros.h b/libc/include/llvm-libc-macros/fcntl-macros.h
new file mode 100644
index 000000000000..4d957e17cafe
--- /dev/null
+++ b/libc/include/llvm-libc-macros/fcntl-macros.h
@@ -0,0 +1,8 @@
+#ifndef __LLVM_LIBC_MACROS_FCNTL_MACROS_H
+#define __LLVM_LIBC_MACROS_FCNTL_MACROS_H
+
+#ifdef __unix__
+#include "linux/fcntl-macros.h"
+#endif
+
+#endif // __LLVM_LIBC_MACROS_FCNTL_MACROS_H

diff  --git a/libc/include/llvm-libc-macros/linux/CMakeLists.txt b/libc/include/llvm-libc-macros/linux/CMakeLists.txt
new file mode 100644
index 000000000000..bc06a8f6f48d
--- /dev/null
+++ b/libc/include/llvm-libc-macros/linux/CMakeLists.txt
@@ -0,0 +1,5 @@
+add_header(
+  fcntl_macros
+  HDR
+    fcntl-macros.h
+)

diff  --git a/libc/include/llvm-libc-macros/linux/fcntl-macros.h b/libc/include/llvm-libc-macros/linux/fcntl-macros.h
new file mode 100644
index 000000000000..e7ce8e847a9e
--- /dev/null
+++ b/libc/include/llvm-libc-macros/linux/fcntl-macros.h
@@ -0,0 +1,52 @@
+//===-- Definition of macros from fcntl.h ---------------------------------===//
+//
+// 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_MACROS_LINUX_FCNTL_MACROS_H
+#define __LLVM_LIBC_MACROS_LINUX_FCNTL_MACROS_H
+
+// File creation flags
+#define O_CLOEXEC 02000000
+#define O_CREAT 00000100
+#define O_DIRECTORY 00200000
+#define O_EXCL 00000200
+#define O_NOCTTY 00000400
+#define O_NOFOLLOW 00400000
+#define O_TRUNC 00001000
+#define O_TMPFILE (020000000 | O_DIRECTORY)
+
+// File status flags
+#define O_APPEND 00002000
+#define O_DSYNC 00010000
+#define O_NONBLOCK 00004000
+#define O_SYNC 04000000 | O_DSYNC
+
+// File access mode mask
+#define O_ACCMODE 00000003
+
+// File access mode flags
+#define O_RDONLY 00000000
+#define O_RDWR 00000002
+#define O_WRONLY 00000001
+
+// File mode flags
+#define S_IRWXU 0700
+#define S_IRUSR 0400
+#define S_IWUSR 0200
+#define S_IXUSR 0100
+#define S_IRWXG 070
+#define S_IRGRP 040
+#define S_IWGRP 020
+#define S_IXGRP 010
+#define S_IRWXO 07
+#define S_IROTH 04
+#define S_IWOTH 02
+#define S_IXOTH 01
+#define S_ISUID 04000
+#define S_ISGID 02000
+
+#endif // __LLVM_LIBC_MACROS_LINUX_FCNTL_MACROS_H

diff  --git a/libc/include/llvm-libc-types/CMakeLists.txt b/libc/include/llvm-libc-types/CMakeLists.txt
index 3c9bed7183b5..cf70d4472c8f 100644
--- a/libc/include/llvm-libc-types/CMakeLists.txt
+++ b/libc/include/llvm-libc-types/CMakeLists.txt
@@ -12,6 +12,7 @@ add_header(fenv_t HDR fenv_t.h)
 add_header(fexcept_t HDR fexcept_t.h)
 add_header(float_t HDR float_t.h)
 add_header(imaxdiv_t HDR imaxdiv_t.h)
+add_header(mode_t HDR mode_t.h)
 add_header(mtx_t HDR mtx_t.h)
 add_header(off_t HDR off_t.h)
 add_header(once_flag HDR once_flag.h)

diff  --git a/libc/include/llvm-libc-types/mode_t.h b/libc/include/llvm-libc-types/mode_t.h
new file mode 100644
index 000000000000..20037bb9ac8f
--- /dev/null
+++ b/libc/include/llvm-libc-types/mode_t.h
@@ -0,0 +1,14 @@
+//===-- Definition of mode_t type -----------------------------------------===//
+//
+// 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_TYPES_MODE_T_H
+#define __LLVM_LIBC_TYPES_MODE_T_H
+
+typedef unsigned mode_t;
+
+#endif // __LLVM_LIBC_TYPES_MODE_T_H

diff  --git a/libc/spec/posix.td b/libc/spec/posix.td
index e1fc63367c6a..28d8dfe0b5d4 100644
--- a/libc/spec/posix.td
+++ b/libc/spec/posix.td
@@ -17,6 +17,7 @@ def POSIX : StandardSpec<"POSIX"> {
   ConstType ConstCharPtr = ConstType<CharPtr>;
   ConstType ConstRestrictedCharPtr = ConstType<RestrictedCharPtr>;
 
+  NamedType ModeTType = NamedType<"mode_t">;
   NamedType OffTType = NamedType<"off_t">;
   NamedType SSizeTType = NamedType<"ssize_t">;
 
@@ -107,6 +108,20 @@ def POSIX : StandardSpec<"POSIX"> {
       []  // Functions
   >;
 
+  HeaderSpec FCntl = HeaderSpec<
+    "fcntl.h",
+    [], // Macros
+    [ModeTType],
+    [], // Enumerations
+    [
+      FunctionSpec<
+          "open",
+          RetValSpec<IntType>,
+          [ArgSpec<ConstCharPtr>, ArgSpec<IntType>, ArgSpec<VarArgType>]
+      >,
+    ]
+  >;
+
   HeaderSpec SysMMan = HeaderSpec<
       "sys/mman.h",
       [
@@ -202,6 +217,21 @@ def POSIX : StandardSpec<"POSIX"> {
     ],
     [], // Enumerations
     [
+        FunctionSpec<
+          "close",
+          RetValSpec<IntType>,
+          [ArgSpec<IntType>]
+        >,
+        FunctionSpec<
+          "fsync",
+          RetValSpec<IntType>,
+          [ArgSpec<IntType>]
+        >,
+        FunctionSpec<
+          "read",
+          RetValSpec<SSizeTType>,
+          [ArgSpec<IntType>, ArgSpec<VoidPtr>, ArgSpec<SizeTType>]
+        >,
         FunctionSpec<
           "write",
           RetValSpec<SSizeTType>,
@@ -280,6 +310,7 @@ def POSIX : StandardSpec<"POSIX"> {
   let Headers = [
     CType,
     Errno,
+    FCntl,
     SysMMan,
     Signal,
     UniStd,

diff  --git a/libc/src/CMakeLists.txt b/libc/src/CMakeLists.txt
index 7dfaac78b6c6..f16af6c94fc7 100644
--- a/libc/src/CMakeLists.txt
+++ b/libc/src/CMakeLists.txt
@@ -9,6 +9,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/src/fcntl/CMakeLists.txt b/libc/src/fcntl/CMakeLists.txt
new file mode 100644
index 000000000000..f5416e981d1f
--- /dev/null
+++ b/libc/src/fcntl/CMakeLists.txt
@@ -0,0 +1,10 @@
+if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
+  add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
+endif()
+
+add_entrypoint_object(
+  open
+  ALIAS
+  DEPENDS
+    .${LIBC_TARGET_OS}.open
+)

diff  --git a/libc/src/fcntl/linux/CMakeLists.txt b/libc/src/fcntl/linux/CMakeLists.txt
new file mode 100644
index 000000000000..3ed5d516e1af
--- /dev/null
+++ b/libc/src/fcntl/linux/CMakeLists.txt
@@ -0,0 +1,12 @@
+add_entrypoint_object(
+  open
+  SRCS
+    open.cpp
+  HDRS
+    ../open.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/open.cpp b/libc/src/fcntl/linux/open.cpp
new file mode 100644
index 000000000000..71872b2c93e2
--- /dev/null
+++ b/libc/src/fcntl/linux/open.cpp
@@ -0,0 +1,40 @@
+//===-- Implementation of open --------------------------------------------===//
+//
+// 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/__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, open, (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_open, path, flags, mode_flags);
+  if (fd > 0)
+    return fd;
+
+  errno = -fd;
+  return -1;
+}
+
+} // namespace __llvm_libc

diff  --git a/libc/src/fcntl/open.h b/libc/src/fcntl/open.h
new file mode 100644
index 000000000000..49cfb5012659
--- /dev/null
+++ b/libc/src/fcntl/open.h
@@ -0,0 +1,20 @@
+//===-- Implementation header of open ---------------------------*- 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_OPEN_H
+#define LLVM_LIBC_SRC_FCNTL_OPEN_H
+
+#include <fcntl.h>
+
+namespace __llvm_libc {
+
+int open(const char *path, int flags, ...);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_FCNTL_OPEN_H

diff  --git a/libc/src/unistd/CMakeLists.txt b/libc/src/unistd/CMakeLists.txt
index d0e5b14d6fd9..1d0ef0e33e9b 100644
--- a/libc/src/unistd/CMakeLists.txt
+++ b/libc/src/unistd/CMakeLists.txt
@@ -2,6 +2,27 @@ if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
   add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
 endif()
 
+add_entrypoint_object(
+  close
+  ALIAS
+  DEPENDS
+    .${LIBC_TARGET_OS}.close
+)
+
+add_entrypoint_object(
+  fsync
+  ALIAS
+  DEPENDS
+    .${LIBC_TARGET_OS}.fsync
+)
+
+add_entrypoint_object(
+  read
+  ALIAS
+  DEPENDS
+    .${LIBC_TARGET_OS}.read
+)
+
 add_entrypoint_object(
   write
   ALIAS

diff  --git a/libc/src/unistd/close.h b/libc/src/unistd/close.h
new file mode 100644
index 000000000000..56fce1172a16
--- /dev/null
+++ b/libc/src/unistd/close.h
@@ -0,0 +1,18 @@
+//===-- Implementation header for close -------------------------*- 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_CLOSE_H
+#define LLVM_LIBC_SRC_UNISTD_CLOSE_H
+
+namespace __llvm_libc {
+
+int close(int fd);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_UNISTD_CLOSE_H

diff  --git a/libc/src/unistd/fsync.h b/libc/src/unistd/fsync.h
new file mode 100644
index 000000000000..12e5d740b188
--- /dev/null
+++ b/libc/src/unistd/fsync.h
@@ -0,0 +1,18 @@
+//===-- Implementation header for fsync -------------------------*- 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_FSYNC_H
+#define LLVM_LIBC_SRC_UNISTD_FSYNC_H
+
+namespace __llvm_libc {
+
+int fsync(int fd);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_UNISTD_FSYNC_H

diff  --git a/libc/src/unistd/linux/CMakeLists.txt b/libc/src/unistd/linux/CMakeLists.txt
index 1c3fdf15a6a7..a9c429d45cd7 100644
--- a/libc/src/unistd/linux/CMakeLists.txt
+++ b/libc/src/unistd/linux/CMakeLists.txt
@@ -1,3 +1,42 @@
+add_entrypoint_object(
+  close
+  SRCS
+    close.cpp
+  HDRS
+    ../close.h
+  DEPENDS
+    libc.include.unistd
+    libc.include.sys_syscall
+    libc.src.__support.OSUtil.osutil
+    libc.src.errno.__errno_location
+)
+
+add_entrypoint_object(
+  fsync
+  SRCS
+    fsync.cpp
+  HDRS
+    ../fsync.h
+  DEPENDS
+    libc.include.unistd
+    libc.include.sys_syscall
+    libc.src.__support.OSUtil.osutil
+    libc.src.errno.__errno_location
+)
+
+add_entrypoint_object(
+  read
+  SRCS
+    read.cpp
+  HDRS
+    ../read.h
+  DEPENDS
+    libc.include.unistd
+    libc.include.sys_syscall
+    libc.src.__support.OSUtil.osutil
+    libc.src.errno.__errno_location
+)
+
 add_entrypoint_object(
   write
   SRCS

diff  --git a/libc/src/unistd/linux/close.cpp b/libc/src/unistd/linux/close.cpp
new file mode 100644
index 000000000000..5380c078ded7
--- /dev/null
+++ b/libc/src/unistd/linux/close.cpp
@@ -0,0 +1,28 @@
+//===-- Linux implementation of close -------------------------------------===//
+//
+// 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/close.h"
+
+#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
+#include "src/__support/common.h"
+
+#include <errno.h>
+#include <sys/syscall.h> // For syscall numbers.
+
+namespace __llvm_libc {
+
+LLVM_LIBC_FUNCTION(int, close, (int fd)) {
+  long ret = __llvm_libc::syscall(SYS_close, fd);
+  if (ret < 0) {
+    errno = -ret;
+    return -1;
+  }
+  return ret;
+}
+
+} // namespace __llvm_libc

diff  --git a/libc/src/unistd/linux/fsync.cpp b/libc/src/unistd/linux/fsync.cpp
new file mode 100644
index 000000000000..2ee9cc945bab
--- /dev/null
+++ b/libc/src/unistd/linux/fsync.cpp
@@ -0,0 +1,28 @@
+//===-- Linux implementation of fsync -------------------------------------===//
+//
+// 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/fsync.h"
+
+#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
+#include "src/__support/common.h"
+
+#include <errno.h>
+#include <sys/syscall.h> // For syscall numbers.
+
+namespace __llvm_libc {
+
+LLVM_LIBC_FUNCTION(int, fsync, (int fd)) {
+  long ret = __llvm_libc::syscall(SYS_fsync, fd);
+  if (ret < 0) {
+    errno = -ret;
+    return -1;
+  }
+  return ret;
+}
+
+} // namespace __llvm_libc

diff  --git a/libc/src/unistd/linux/read.cpp b/libc/src/unistd/linux/read.cpp
new file mode 100644
index 000000000000..309976374b99
--- /dev/null
+++ b/libc/src/unistd/linux/read.cpp
@@ -0,0 +1,28 @@
+//===-- Linux implementation of read --------------------------------------===//
+//
+// 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/read.h"
+
+#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
+#include "src/__support/common.h"
+
+#include <errno.h>
+#include <sys/syscall.h> // For syscall numbers.
+
+namespace __llvm_libc {
+
+LLVM_LIBC_FUNCTION(ssize_t, read, (int fd, void *buf, size_t count)) {
+  long ret = __llvm_libc::syscall(SYS_read, fd, buf, count);
+  if (ret < 0) {
+    errno = -ret;
+    return -1;
+  }
+  return ret;
+}
+
+} // namespace __llvm_libc

diff  --git a/libc/src/unistd/linux/write.cpp b/libc/src/unistd/linux/write.cpp
index 2de84c330fc5..68ff1fa3d848 100644
--- a/libc/src/unistd/linux/write.cpp
+++ b/libc/src/unistd/linux/write.cpp
@@ -12,7 +12,7 @@
 #include "src/__support/common.h"
 
 #include <errno.h>
-#include <sys/syscall.h>          // For syscall numbers.
+#include <sys/syscall.h> // For syscall numbers.
 
 namespace __llvm_libc {
 

diff  --git a/libc/src/unistd/read.h b/libc/src/unistd/read.h
new file mode 100644
index 000000000000..62602c82a906
--- /dev/null
+++ b/libc/src/unistd/read.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for read --------------------------*- 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_READ_H
+#define LLVM_LIBC_SRC_UNISTD_READ_H
+
+#include <unistd.h>
+
+namespace __llvm_libc {
+
+ssize_t read(int fd, void *buf, size_t count);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_UNISTD_READ_H

diff  --git a/libc/test/src/unistd/CMakeLists.txt b/libc/test/src/unistd/CMakeLists.txt
index 54e513504b3b..cba400b9dfb9 100644
--- a/libc/test/src/unistd/CMakeLists.txt
+++ b/libc/test/src/unistd/CMakeLists.txt
@@ -1,14 +1,18 @@
 add_libc_testsuite(libc_unistd_unittests)
 
 add_libc_unittest(
-  write_test
+  read_write_test
   SUITE
     libc_unistd_unittests
   SRCS
-    write_test.cpp
+    read_write_test.cpp
   DEPENDS
     libc.include.errno
     libc.include.unistd
+    libc.src.fcntl.open
+    libc.src.unistd.close
+    libc.src.unistd.fsync
+    libc.src.unistd.read
     libc.src.unistd.write
     libc.test.errno_setter_matcher
 )

diff  --git a/libc/test/src/unistd/read_write_test.cpp b/libc/test/src/unistd/read_write_test.cpp
new file mode 100644
index 000000000000..6b86cd1560ab
--- /dev/null
+++ b/libc/test/src/unistd/read_write_test.cpp
@@ -0,0 +1,59 @@
+//===-- Unittests for read and write --------------------------------------===//
+//
+// 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/close.h"
+#include "src/unistd/fsync.h"
+#include "src/unistd/read.h"
+#include "src/unistd/write.h"
+#include "test/ErrnoSetterMatcher.h"
+#include "utils/UnitTest/Test.h"
+#include "utils/testutils/FDReader.h"
+
+#include <errno.h>
+
+TEST(LlvmLibcUniStd, WriteAndReadBackTest) {
+  using __llvm_libc::testing::ErrnoSetterMatcher::Succeeds;
+  constexpr const char *TEST_FILE = "__unistd_read_write.test";
+  int write_fd = __llvm_libc::open(TEST_FILE, O_WRONLY | O_CREAT);
+  ASSERT_EQ(errno, 0);
+  ASSERT_GT(write_fd, 0);
+  constexpr const char HELLO[] = "hello";
+  constexpr int HELLO_SIZE = sizeof(HELLO);
+  ASSERT_THAT(__llvm_libc::write(write_fd, HELLO, HELLO_SIZE),
+              Succeeds(HELLO_SIZE));
+  ASSERT_THAT(__llvm_libc::fsync(write_fd), Succeeds(0));
+  ASSERT_THAT(__llvm_libc::close(write_fd), Succeeds(0));
+
+  int read_fd = __llvm_libc::open(TEST_FILE, O_RDONLY);
+  ASSERT_EQ(errno, 0);
+  ASSERT_GT(read_fd, 0);
+  char read_buf[10];
+  ASSERT_THAT(__llvm_libc::read(read_fd, read_buf, HELLO_SIZE),
+              Succeeds(HELLO_SIZE));
+  EXPECT_STREQ(read_buf, HELLO);
+  ASSERT_THAT(__llvm_libc::close(read_fd), Succeeds(0));
+
+  // TODO: 'remove' the test file after the test.
+}
+
+TEST(LlvmLibcUniStd, WriteFails) {
+  using __llvm_libc::testing::ErrnoSetterMatcher::Fails;
+
+  EXPECT_THAT(__llvm_libc::write(-1, "", 1), Fails(EBADF));
+  EXPECT_THAT(__llvm_libc::write(1, reinterpret_cast<const void *>(-1), 1),
+              Fails(EFAULT));
+}
+
+TEST(LlvmLibcUniStd, ReadFails) {
+  using __llvm_libc::testing::ErrnoSetterMatcher::Fails;
+
+  EXPECT_THAT(__llvm_libc::read(-1, nullptr, 1), Fails(EBADF));
+  EXPECT_THAT(__llvm_libc::read(0, reinterpret_cast<void *>(-1), 1),
+              Fails(EFAULT));
+}

diff  --git a/libc/test/src/unistd/write_test.cpp b/libc/test/src/unistd/write_test.cpp
deleted file mode 100644
index 43914e87ef65..000000000000
--- a/libc/test/src/unistd/write_test.cpp
+++ /dev/null
@@ -1,30 +0,0 @@
-//===-- Unittests for write -----------------------------------------------===//
-//
-// 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/write.h"
-#include "test/ErrnoSetterMatcher.h"
-#include "utils/UnitTest/Test.h"
-#include "utils/testutils/FDReader.h"
-
-#include <errno.h>
-
-TEST(LlvmLibcUniStd, WriteBasic) {
-  using __llvm_libc::testing::ErrnoSetterMatcher::Succeeds;
-  constexpr const char *HELLO = "hello";
-  __llvm_libc::testutils::FDReader reader;
-  EXPECT_THAT(__llvm_libc::write(reader.get_write_fd(), HELLO, 5), Succeeds(5));
-  EXPECT_TRUE(reader.match_written(HELLO));
-}
-
-TEST(LlvmLibcUniStd, WriteFails) {
-  using __llvm_libc::testing::ErrnoSetterMatcher::Fails;
-
-  EXPECT_THAT(__llvm_libc::write(-1, "", 1), Fails(EBADF));
-  EXPECT_THAT(__llvm_libc::write(1, reinterpret_cast<const void *>(-1), 1),
-              Fails(EFAULT));
-}


        


More information about the libc-commits mailing list