[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