[libc-commits] [libc] b838516 - [libc] Add implementations of POSIX mkdir, mkdirat, rmdir, unlink and unlinkat.
Siva Chandra Reddy via libc-commits
libc-commits at lists.llvm.org
Mon Jan 31 21:17:27 PST 2022
Author: Siva Chandra Reddy
Date: 2022-02-01T05:17:10Z
New Revision: b8385162c2f9a53354ce98d4893946f0a9e8c406
URL: https://github.com/llvm/llvm-project/commit/b8385162c2f9a53354ce98d4893946f0a9e8c406
DIFF: https://github.com/llvm/llvm-project/commit/b8385162c2f9a53354ce98d4893946f0a9e8c406.diff
LOG: [libc] Add implementations of POSIX mkdir, mkdirat, rmdir, unlink and unlinkat.
Reviewed By: michaelrj
Differential Revision: https://reviews.llvm.org/D118641
Added:
libc/include/sys/stat.h.def
libc/src/sys/stat/CMakeLists.txt
libc/src/sys/stat/linux/CMakeLists.txt
libc/src/sys/stat/linux/mkdir.cpp
libc/src/sys/stat/linux/mkdirat.cpp
libc/src/sys/stat/mkdir.h
libc/src/sys/stat/mkdirat.h
libc/src/unistd/linux/rmdir.cpp
libc/src/unistd/linux/unlink.cpp
libc/src/unistd/linux/unlinkat.cpp
libc/src/unistd/rmdir.h
libc/src/unistd/unlink.h
libc/src/unistd/unlinkat.h
libc/test/src/sys/stat/CMakeLists.txt
libc/test/src/sys/stat/mkdirat_test.cpp
libc/test/src/sys/stat/testdata/CMakeLists.txt
libc/test/src/unistd/rmdir_test.cpp
libc/test/src/unistd/testdata/CMakeLists.txt
libc/test/src/unistd/unlink_test.cpp
libc/test/src/unistd/unlinkat_test.cpp
Modified:
libc/config/linux/api.td
libc/config/linux/x86_64/entrypoints.txt
libc/include/CMakeLists.txt
libc/include/llvm-libc-macros/linux/fcntl-macros.h
libc/spec/posix.td
libc/src/sys/CMakeLists.txt
libc/src/unistd/CMakeLists.txt
libc/src/unistd/linux/CMakeLists.txt
libc/test/src/sys/CMakeLists.txt
libc/test/src/unistd/CMakeLists.txt
Removed:
################################################################################
diff --git a/libc/config/linux/api.td b/libc/config/linux/api.td
index 7bfa621fd98f0..69c663f388b2c 100644
--- a/libc/config/linux/api.td
+++ b/libc/config/linux/api.td
@@ -242,3 +242,7 @@ def ThreadsAPI : PublicAPI<"threads.h"> {
def UniStdAPI : PublicAPI<"unistd.h"> {
let Types = ["size_t", "ssize_t"];
}
+
+def SysStatAPI : PublicAPI<"sys/stat.h"> {
+ let Types = ["mode_t"];
+}
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index d230decc8f30c..aa3d69a48a546 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -85,10 +85,17 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.sys.mman.mmap
libc.src.sys.mman.munmap
+ # sys/stat.h entrypoints
+ libc.src.sys.stat.mkdir
+ libc.src.sys.stat.mkdirat
+
# unistd.h entrypoints
libc.src.unistd.close
libc.src.unistd.fsync
libc.src.unistd.read
+ libc.src.unistd.rmdir
+ libc.src.unistd.unlink
+ libc.src.unistd.unlinkat
libc.src.unistd.write
)
diff --git a/libc/include/CMakeLists.txt b/libc/include/CMakeLists.txt
index d208f17ad699a..bb713815ffbc9 100644
--- a/libc/include/CMakeLists.txt
+++ b/libc/include/CMakeLists.txt
@@ -167,6 +167,15 @@ add_gen_header(
.llvm-libc-types.ssize_t
)
+add_gen_header(
+ sys_stat
+ DEF_FILE sys/stat.h.def
+ GEN_HDR sys/stat.h
+ DEPENDS
+ .llvm_libc_common_h
+ .llvm-libc-types.mode_t
+)
+
add_gen_header(
sys_syscall
DEF_FILE sys/syscall.h.def
diff --git a/libc/include/llvm-libc-macros/linux/fcntl-macros.h b/libc/include/llvm-libc-macros/linux/fcntl-macros.h
index 007f780b43b3f..46655c2d12eb0 100644
--- a/libc/include/llvm-libc-macros/linux/fcntl-macros.h
+++ b/libc/include/llvm-libc-macros/linux/fcntl-macros.h
@@ -53,4 +53,8 @@
// openat is relative to the current directory.
#define AT_FDCWD -100
+// Special flag to the function unlinkat to indicate that it
+// has to perform the equivalent of "rmdir" on the path argument.
+#define AT_REMOVEDIR 0x200
+
#endif // __LLVM_LIBC_MACROS_LINUX_FCNTL_MACROS_H
diff --git a/libc/include/sys/stat.h.def b/libc/include/sys/stat.h.def
new file mode 100644
index 0000000000000..f925208d8db13
--- /dev/null
+++ b/libc/include/sys/stat.h.def
@@ -0,0 +1,16 @@
+//===-- POSIX header stat.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_SYS_STAT_H
+#define LLVM_LIBC_SYS_STAT_H
+
+#include <__llvm-libc-common.h>
+
+%%public_api()
+
+#endif // LLVM_LIBC_SYS_STAT_H
diff --git a/libc/spec/posix.td b/libc/spec/posix.td
index de3e2d59aaec5..dc9a3ee773a93 100644
--- a/libc/spec/posix.td
+++ b/libc/spec/posix.td
@@ -242,6 +242,21 @@ def POSIX : StandardSpec<"POSIX"> {
RetValSpec<SSizeTType>,
[ArgSpec<IntType>, ArgSpec<VoidPtr>, ArgSpec<SizeTType>]
>,
+ FunctionSpec<
+ "rmdir",
+ RetValSpec<IntType>,
+ [ArgSpec<ConstCharPtr>]
+ >,
+ FunctionSpec<
+ "unlink",
+ RetValSpec<IntType>,
+ [ArgSpec<ConstCharPtr>]
+ >,
+ FunctionSpec<
+ "unlinkat",
+ RetValSpec<IntType>,
+ [ArgSpec<IntType>, ArgSpec<ConstCharPtr>, ArgSpec<IntType>]
+ >,
FunctionSpec<
"write",
RetValSpec<SSizeTType>,
@@ -317,12 +332,32 @@ def POSIX : StandardSpec<"POSIX"> {
]
>;
+ HeaderSpec SysStat = HeaderSpec<
+ "sys/stat.h",
+ [], // Macros
+ [ModeTType], // Types
+ [], // Enumerations
+ [
+ FunctionSpec<
+ "mkdir",
+ RetValSpec<IntType>,
+ [ArgSpec<ConstCharPtr>, ArgSpec<ModeTType>]
+ >,
+ FunctionSpec<
+ "mkdirat",
+ RetValSpec<IntType>,
+ [ArgSpec<IntType>, ArgSpec<ConstCharPtr>, ArgSpec<ModeTType>]
+ >,
+ ]
+ >;
+
let Headers = [
CType,
Errno,
FCntl,
- SysMMan,
Signal,
+ SysMMan,
+ SysStat,
UniStd,
String
];
diff --git a/libc/src/sys/CMakeLists.txt b/libc/src/sys/CMakeLists.txt
index 03c59bfc4a0bb..4c7e82097bf64 100644
--- a/libc/src/sys/CMakeLists.txt
+++ b/libc/src/sys/CMakeLists.txt
@@ -1 +1,2 @@
add_subdirectory(mman)
+add_subdirectory(stat)
diff --git a/libc/src/sys/stat/CMakeLists.txt b/libc/src/sys/stat/CMakeLists.txt
new file mode 100644
index 0000000000000..44bc48a8af5d6
--- /dev/null
+++ b/libc/src/sys/stat/CMakeLists.txt
@@ -0,0 +1,17 @@
+if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
+ add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
+endif()
+
+add_entrypoint_object(
+ mkdir
+ ALIAS
+ DEPENDS
+ .${LIBC_TARGET_OS}.mkdir
+)
+
+add_entrypoint_object(
+ mkdirat
+ ALIAS
+ DEPENDS
+ .${LIBC_TARGET_OS}.mkdirat
+)
diff --git a/libc/src/sys/stat/linux/CMakeLists.txt b/libc/src/sys/stat/linux/CMakeLists.txt
new file mode 100644
index 0000000000000..5a818837ae15f
--- /dev/null
+++ b/libc/src/sys/stat/linux/CMakeLists.txt
@@ -0,0 +1,25 @@
+add_entrypoint_object(
+ mkdir
+ SRCS
+ mkdir.cpp
+ HDRS
+ ../mkdir.h
+ DEPENDS
+ libc.include.sys_stat
+ libc.include.sys_syscall
+ libc.src.__support.OSUtil.osutil
+ libc.src.errno.__errno_location
+)
+
+add_entrypoint_object(
+ mkdirat
+ SRCS
+ mkdirat.cpp
+ HDRS
+ ../mkdirat.h
+ DEPENDS
+ libc.include.sys_stat
+ libc.include.sys_syscall
+ libc.src.__support.OSUtil.osutil
+ libc.src.errno.__errno_location
+)
diff --git a/libc/src/sys/stat/linux/mkdir.cpp b/libc/src/sys/stat/linux/mkdir.cpp
new file mode 100644
index 0000000000000..3477e1a5cbe8f
--- /dev/null
+++ b/libc/src/sys/stat/linux/mkdir.cpp
@@ -0,0 +1,36 @@
+//===-- Linux implementation of mkdir -------------------------------------===//
+//
+// 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/sys/stat/mkdir.h"
+
+#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
+#include "src/__support/common.h"
+
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/syscall.h> // For syscall numbers.
+
+namespace __llvm_libc {
+
+LLVM_LIBC_FUNCTION(int, mkdir, (const char *path, mode_t mode)) {
+#ifdef SYS_mkdir
+ long ret = __llvm_libc::syscall(SYS_mkdir, path, mode);
+#elif defined(SYS_unlinkat)
+ long ret = __llvm_libc::syscall(SYS_mkdirat, AT_FDCWD, path, mode);
+#else
+#error "mkdir and mkdirat syscalls not available."
+#endif
+
+ if (ret < 0) {
+ errno = -ret;
+ return -1;
+ }
+ return 0;
+}
+
+} // namespace __llvm_libc
diff --git a/libc/src/sys/stat/linux/mkdirat.cpp b/libc/src/sys/stat/linux/mkdirat.cpp
new file mode 100644
index 0000000000000..07cd337c6221a
--- /dev/null
+++ b/libc/src/sys/stat/linux/mkdirat.cpp
@@ -0,0 +1,34 @@
+//===-- Linux implementation of mkdirat -----------------------------------===//
+//
+// 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/sys/stat/mkdirat.h"
+
+#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
+#include "src/__support/common.h"
+
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/syscall.h> // For syscall numbers.
+
+namespace __llvm_libc {
+
+LLVM_LIBC_FUNCTION(int, mkdirat, (int dfd, const char *path, mode_t mode)) {
+#ifdef SYS_unlinkat
+ long ret = __llvm_libc::syscall(SYS_mkdirat, dfd, path, mode);
+#else
+#error "mkdirat syscalls not available."
+#endif
+
+ if (ret < 0) {
+ errno = -ret;
+ return -1;
+ }
+ return 0;
+}
+
+} // namespace __llvm_libc
diff --git a/libc/src/sys/stat/mkdir.h b/libc/src/sys/stat/mkdir.h
new file mode 100644
index 0000000000000..535423acff788
--- /dev/null
+++ b/libc/src/sys/stat/mkdir.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for mkdir -------------------------*- 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_SYS_STAT_MKDIR_H
+#define LLVM_LIBC_SRC_SYS_STAT_MKDIR_H
+
+#include <sys/stat.h>
+
+namespace __llvm_libc {
+
+int mkdir(const char *path, mode_t mode);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_SYS_STAT_MKDIR_H
diff --git a/libc/src/sys/stat/mkdirat.h b/libc/src/sys/stat/mkdirat.h
new file mode 100644
index 0000000000000..883709cb21585
--- /dev/null
+++ b/libc/src/sys/stat/mkdirat.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for mkdirat -----------------------*- 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_SYS_STAT_MKDIRAT_H
+#define LLVM_LIBC_SRC_SYS_STAT_MKDIRAT_H
+
+#include <sys/stat.h>
+
+namespace __llvm_libc {
+
+int mkdirat(int dfd, const char *path, mode_t mode);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_SYS_STAT_MKDIRAT_H
diff --git a/libc/src/unistd/CMakeLists.txt b/libc/src/unistd/CMakeLists.txt
index 1d0ef0e33e9b0..70210ebd5b790 100644
--- a/libc/src/unistd/CMakeLists.txt
+++ b/libc/src/unistd/CMakeLists.txt
@@ -23,6 +23,27 @@ add_entrypoint_object(
.${LIBC_TARGET_OS}.read
)
+add_entrypoint_object(
+ rmdir
+ ALIAS
+ DEPENDS
+ .${LIBC_TARGET_OS}.rmdir
+)
+
+add_entrypoint_object(
+ unlink
+ ALIAS
+ DEPENDS
+ .${LIBC_TARGET_OS}.unlink
+)
+
+add_entrypoint_object(
+ unlinkat
+ ALIAS
+ DEPENDS
+ .${LIBC_TARGET_OS}.unlinkat
+)
+
add_entrypoint_object(
write
ALIAS
diff --git a/libc/src/unistd/linux/CMakeLists.txt b/libc/src/unistd/linux/CMakeLists.txt
index a9c429d45cd76..c08bd18477683 100644
--- a/libc/src/unistd/linux/CMakeLists.txt
+++ b/libc/src/unistd/linux/CMakeLists.txt
@@ -37,6 +37,45 @@ add_entrypoint_object(
libc.src.errno.__errno_location
)
+add_entrypoint_object(
+ rmdir
+ SRCS
+ rmdir.cpp
+ HDRS
+ ../rmdir.h
+ DEPENDS
+ libc.include.unistd
+ libc.include.sys_syscall
+ libc.src.__support.OSUtil.osutil
+ libc.src.errno.__errno_location
+)
+
+add_entrypoint_object(
+ unlink
+ SRCS
+ unlink.cpp
+ HDRS
+ ../unlink.h
+ DEPENDS
+ libc.include.unistd
+ libc.include.sys_syscall
+ libc.src.__support.OSUtil.osutil
+ libc.src.errno.__errno_location
+)
+
+add_entrypoint_object(
+ unlinkat
+ SRCS
+ unlinkat.cpp
+ HDRS
+ ../unlinkat.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/rmdir.cpp b/libc/src/unistd/linux/rmdir.cpp
new file mode 100644
index 0000000000000..220330aecde5a
--- /dev/null
+++ b/libc/src/unistd/linux/rmdir.cpp
@@ -0,0 +1,35 @@
+//===-- Linux implementation of rmdir -------------------------------------===//
+//
+// 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/rmdir.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, rmdir, (const char *path)) {
+#ifdef SYS_rmdir
+ long ret = __llvm_libc::syscall(SYS_rmdir, path);
+#elif defined(SYS_unlinkat)
+ long ret = __llvm_libc::syscall(SYS_unlinkat, AT_FDCWD, path, 0);
+#else
+#error "rmdir and unlinkat syscalls not available."
+#endif
+
+ if (ret < 0) {
+ errno = -ret;
+ return -1;
+ }
+ return 0;
+}
+
+} // namespace __llvm_libc
diff --git a/libc/src/unistd/linux/unlink.cpp b/libc/src/unistd/linux/unlink.cpp
new file mode 100644
index 0000000000000..f02f745e79f5b
--- /dev/null
+++ b/libc/src/unistd/linux/unlink.cpp
@@ -0,0 +1,35 @@
+//===-- Linux implementation of unlink ------------------------------------===//
+//
+// 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/unlink.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, unlink, (const char *path)) {
+#ifdef SYS_unlink
+ long ret = __llvm_libc::syscall(SYS_unlink, path);
+#elif defined(SYS_unlinkat)
+ long ret = __llvm_libc::syscall(SYS_unlinkat, AT_FDCWD, path, 0);
+#else
+#error "Unlink syscalls not available."
+#endif
+
+ if (ret < 0) {
+ errno = -ret;
+ return -1;
+ }
+ return 0;
+}
+
+} // namespace __llvm_libc
diff --git a/libc/src/unistd/linux/unlinkat.cpp b/libc/src/unistd/linux/unlinkat.cpp
new file mode 100644
index 0000000000000..54d3c103bd7c1
--- /dev/null
+++ b/libc/src/unistd/linux/unlinkat.cpp
@@ -0,0 +1,33 @@
+//===-- Linux implementation of unlinkat ----------------------------------===//
+//
+// 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/unlinkat.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, unlinkat, (int dfd, const char *path, int flags)) {
+#ifdef SYS_unlinkat
+ long ret = __llvm_libc::syscall(SYS_unlinkat, dfd, path, flags);
+#else
+#error "unlinkat syscall not available."
+#endif
+
+ if (ret < 0) {
+ errno = -ret;
+ return -1;
+ }
+ return 0;
+}
+
+} // namespace __llvm_libc
diff --git a/libc/src/unistd/rmdir.h b/libc/src/unistd/rmdir.h
new file mode 100644
index 0000000000000..5fe7fac23af78
--- /dev/null
+++ b/libc/src/unistd/rmdir.h
@@ -0,0 +1,18 @@
+//===-- Implementation header for rmdir -------------------------*- 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_RMDIR_H
+#define LLVM_LIBC_SRC_UNISTD_RMDIR_H
+
+namespace __llvm_libc {
+
+int rmdir(const char *path);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_UNISTD_RMDIR_H
diff --git a/libc/src/unistd/unlink.h b/libc/src/unistd/unlink.h
new file mode 100644
index 0000000000000..1119bfad7dbc5
--- /dev/null
+++ b/libc/src/unistd/unlink.h
@@ -0,0 +1,18 @@
+//===-- Implementation header for unlink ------------------------*- 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_UNLINK_H
+#define LLVM_LIBC_SRC_UNISTD_UNLINK_H
+
+namespace __llvm_libc {
+
+int unlink(const char *path);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_UNISTD_UNLINK_H
diff --git a/libc/src/unistd/unlinkat.h b/libc/src/unistd/unlinkat.h
new file mode 100644
index 0000000000000..b32d7b537851d
--- /dev/null
+++ b/libc/src/unistd/unlinkat.h
@@ -0,0 +1,18 @@
+//===-- Implementation header for unlinkat ----------------------*- 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_UNLINKAT_H
+#define LLVM_LIBC_SRC_UNISTD_UNLINKAT_H
+
+namespace __llvm_libc {
+
+int unlinkat(int dfd, const char *path, int flags);
+
+} // namespace __llvm_libc
+
+#endif // LLVM_LIBC_SRC_UNISTD_UNLINKAT_H
diff --git a/libc/test/src/sys/CMakeLists.txt b/libc/test/src/sys/CMakeLists.txt
index 03c59bfc4a0bb..4c7e82097bf64 100644
--- a/libc/test/src/sys/CMakeLists.txt
+++ b/libc/test/src/sys/CMakeLists.txt
@@ -1 +1,2 @@
add_subdirectory(mman)
+add_subdirectory(stat)
diff --git a/libc/test/src/sys/stat/CMakeLists.txt b/libc/test/src/sys/stat/CMakeLists.txt
new file mode 100644
index 0000000000000..eec671a77af4a
--- /dev/null
+++ b/libc/test/src/sys/stat/CMakeLists.txt
@@ -0,0 +1,17 @@
+add_libc_testsuite(libc_sys_stat_unittests)
+
+add_subdirectory(testdata)
+
+add_libc_unittest(
+ mkdirat_test
+ SUITE
+ libc_sys_stat_unittests
+ SRCS
+ mkdirat_test.cpp
+ DEPENDS
+ libc.include.errno
+ libc.include.fcntl
+ libc.include.sys_stat
+ libc.src.sys.stat.mkdirat
+ libc.src.unistd.rmdir
+)
diff --git a/libc/test/src/sys/stat/mkdirat_test.cpp b/libc/test/src/sys/stat/mkdirat_test.cpp
new file mode 100644
index 0000000000000..4a45fe2ffb885
--- /dev/null
+++ b/libc/test/src/sys/stat/mkdirat_test.cpp
@@ -0,0 +1,29 @@
+//===-- Unittests for mkdirat ---------------------------------------------===//
+//
+// 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/sys/stat/mkdirat.h"
+#include "src/unistd/rmdir.h"
+#include "test/ErrnoSetterMatcher.h"
+#include "utils/UnitTest/Test.h"
+#include "utils/testutils/FDReader.h"
+
+#include <errno.h>
+#include <fcntl.h>
+
+TEST(LlvmLibcMkdiratTest, CreateAndRemove) {
+ using __llvm_libc::testing::ErrnoSetterMatcher::Succeeds;
+ constexpr const char *TEST_DIR = "testdata/rmdir.testdir";
+ ASSERT_THAT(__llvm_libc::mkdirat(AT_FDCWD, TEST_DIR, S_IRWXU), Succeeds(0));
+ ASSERT_THAT(__llvm_libc::rmdir(TEST_DIR), Succeeds(0));
+}
+
+TEST(LlvmLibcMkdiratTest, BadPath) {
+ using __llvm_libc::testing::ErrnoSetterMatcher::Fails;
+ ASSERT_THAT(__llvm_libc::mkdirat(AT_FDCWD, "non-existent-dir/test", S_IRWXU),
+ Fails(ENOENT));
+}
diff --git a/libc/test/src/sys/stat/testdata/CMakeLists.txt b/libc/test/src/sys/stat/testdata/CMakeLists.txt
new file mode 100644
index 0000000000000..25d6247c1d975
--- /dev/null
+++ b/libc/test/src/sys/stat/testdata/CMakeLists.txt
@@ -0,0 +1,2 @@
+# This directory will be used to create test files and delete them
+# from tests.
diff --git a/libc/test/src/unistd/CMakeLists.txt b/libc/test/src/unistd/CMakeLists.txt
index cba400b9dfb97..abaec098af346 100644
--- a/libc/test/src/unistd/CMakeLists.txt
+++ b/libc/test/src/unistd/CMakeLists.txt
@@ -1,5 +1,7 @@
add_libc_testsuite(libc_unistd_unittests)
+add_subdirectory(testdata)
+
add_libc_unittest(
read_write_test
SUITE
@@ -16,3 +18,45 @@ add_libc_unittest(
libc.src.unistd.write
libc.test.errno_setter_matcher
)
+
+add_libc_unittest(
+ rmdir_test
+ SUITE
+ libc_unistd_unittests
+ SRCS
+ rmdir_test.cpp
+ DEPENDS
+ libc.include.errno
+ libc.include.fcntl
+ libc.src.sys.stat.mkdir
+ libc.src.unistd.rmdir
+)
+
+add_libc_unittest(
+ unlink_test
+ SUITE
+ libc_unistd_unittests
+ SRCS
+ unlink_test.cpp
+ DEPENDS
+ libc.include.errno
+ libc.include.unistd
+ libc.src.fcntl.open
+ libc.src.unistd.close
+ libc.src.unistd.unlink
+)
+
+add_libc_unittest(
+ unlinkat_test
+ SUITE
+ libc_unistd_unittests
+ SRCS
+ unlinkat_test.cpp
+ DEPENDS
+ libc.include.errno
+ libc.include.unistd
+ libc.src.fcntl.open
+ libc.src.fcntl.openat
+ libc.src.unistd.close
+ libc.src.unistd.unlinkat
+)
diff --git a/libc/test/src/unistd/rmdir_test.cpp b/libc/test/src/unistd/rmdir_test.cpp
new file mode 100644
index 0000000000000..5e07849df5ea2
--- /dev/null
+++ b/libc/test/src/unistd/rmdir_test.cpp
@@ -0,0 +1,28 @@
+//===-- Unittests for rmdir -----------------------------------------------===//
+//
+// 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/sys/stat/mkdir.h"
+#include "src/unistd/rmdir.h"
+#include "test/ErrnoSetterMatcher.h"
+#include "utils/UnitTest/Test.h"
+#include "utils/testutils/FDReader.h"
+
+#include <errno.h>
+#include <fcntl.h>
+
+TEST(LlvmLibcRmdirTest, CreateAndRemove) {
+ using __llvm_libc::testing::ErrnoSetterMatcher::Succeeds;
+ constexpr const char *TEST_DIR = "testdata/rmdir.testdir";
+ ASSERT_THAT(__llvm_libc::mkdir(TEST_DIR, S_IRWXU), Succeeds(0));
+ ASSERT_THAT(__llvm_libc::rmdir(TEST_DIR), Succeeds(0));
+}
+
+TEST(LlvmLibcRmdirTest, RemoveNonExistentDir) {
+ using __llvm_libc::testing::ErrnoSetterMatcher::Fails;
+ ASSERT_THAT(__llvm_libc::rmdir("testdata/non-existent-dir"), Fails(ENOENT));
+}
diff --git a/libc/test/src/unistd/testdata/CMakeLists.txt b/libc/test/src/unistd/testdata/CMakeLists.txt
new file mode 100644
index 0000000000000..25d6247c1d975
--- /dev/null
+++ b/libc/test/src/unistd/testdata/CMakeLists.txt
@@ -0,0 +1,2 @@
+# This directory will be used to create test files and delete them
+# from tests.
diff --git a/libc/test/src/unistd/unlink_test.cpp b/libc/test/src/unistd/unlink_test.cpp
new file mode 100644
index 0000000000000..be358cf5eeac3
--- /dev/null
+++ b/libc/test/src/unistd/unlink_test.cpp
@@ -0,0 +1,31 @@
+//===-- Unittests for unlink ----------------------------------------------===//
+//
+// 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/unlink.h"
+#include "test/ErrnoSetterMatcher.h"
+#include "utils/UnitTest/Test.h"
+#include "utils/testutils/FDReader.h"
+
+#include <errno.h>
+
+TEST(LlvmLibcUnlinkTest, CreateAndUnlink) {
+ using __llvm_libc::testing::ErrnoSetterMatcher::Succeeds;
+ constexpr const char *TEST_FILE = "testdata/unlink.test";
+ int write_fd = __llvm_libc::open(TEST_FILE, O_WRONLY | O_CREAT, S_IRWXU);
+ ASSERT_EQ(errno, 0);
+ ASSERT_GT(write_fd, 0);
+ ASSERT_THAT(__llvm_libc::close(write_fd), Succeeds(0));
+ ASSERT_THAT(__llvm_libc::unlink(TEST_FILE), Succeeds(0));
+}
+
+TEST(LlvmLibcUnlinkTest, UnlinkNonExistentFile) {
+ using __llvm_libc::testing::ErrnoSetterMatcher::Fails;
+ ASSERT_THAT(__llvm_libc::unlink("testdata/non-existent-file"), Fails(ENOENT));
+}
diff --git a/libc/test/src/unistd/unlinkat_test.cpp b/libc/test/src/unistd/unlinkat_test.cpp
new file mode 100644
index 0000000000000..8ce10c95d1c49
--- /dev/null
+++ b/libc/test/src/unistd/unlinkat_test.cpp
@@ -0,0 +1,45 @@
+//===-- Unittests for unlinkat --------------------------------------------===//
+//
+// 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/unlinkat.h"
+#include "test/ErrnoSetterMatcher.h"
+#include "utils/UnitTest/Test.h"
+#include "utils/testutils/FDReader.h"
+
+#include <errno.h>
+
+TEST(LlvmLibcUnlinkatTest, CreateAndDeleteTest) {
+ 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);
+ int write_fd =
+ __llvm_libc::openat(dir_fd, TEST_FILE, O_WRONLY | O_CREAT, S_IRWXU);
+ ASSERT_EQ(errno, 0);
+ ASSERT_GT(write_fd, 0);
+ ASSERT_THAT(__llvm_libc::close(write_fd), Succeeds(0));
+ ASSERT_THAT(__llvm_libc::unlinkat(dir_fd, TEST_FILE, 0), Succeeds(0));
+ ASSERT_THAT(__llvm_libc::close(dir_fd), Succeeds(0));
+}
+
+TEST(LlvmLibcUnlinkatTest, UnlinkatNonExistentFile) {
+ constexpr const char *TEST_DIR = "testdata";
+ int dir_fd = __llvm_libc::open(TEST_DIR, O_DIRECTORY);
+ ASSERT_EQ(errno, 0);
+ ASSERT_GT(dir_fd, 0);
+ using __llvm_libc::testing::ErrnoSetterMatcher::Fails;
+ using __llvm_libc::testing::ErrnoSetterMatcher::Succeeds;
+ ASSERT_THAT(__llvm_libc::unlinkat(dir_fd, "non-existent-file", 0),
+ Fails(ENOENT));
+ ASSERT_THAT(__llvm_libc::close(dir_fd), Succeeds(0));
+}
More information about the libc-commits
mailing list