[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