[libc-commits] [libc] de9ad51 - [libc] Implement mkfifo (#223566)

via libc-commits libc-commits at lists.llvm.org
Tue Sep 15 17:59:27 PDT 2026


Author: Michael Jones
Date: 2026-09-15T17:59:22-07:00
New Revision: de9ad513460a1a5439b0b8d6d5c7a51a3634bc20

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

LOG: [libc] Implement mkfifo (#223566)

Implements the mkfifo function from POSIX, and tests.

Fixes: #220758
Assisted-by: Automated Tooling, Human Reviewed

Added: 
    libc/src/__support/OSUtil/linux/syscall_wrappers/mknodat.h
    libc/src/sys/stat/linux/mkfifo.cpp
    libc/src/sys/stat/mkfifo.h
    libc/test/src/sys/stat/mkfifo_test.cpp

Modified: 
    libc/config/linux/aarch64/entrypoints.txt
    libc/config/linux/riscv/entrypoints.txt
    libc/config/linux/x86_64/entrypoints.txt
    libc/include/sys/stat.yaml
    libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt
    libc/src/sys/stat/CMakeLists.txt
    libc/src/sys/stat/linux/CMakeLists.txt
    libc/test/src/sys/stat/CMakeLists.txt

Removed: 
    


################################################################################
diff  --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index bc76076582fc1..588845ea95831 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -353,6 +353,7 @@ set(TARGET_LIBC_ENTRYPOINTS
     libc.src.sys.stat.lstat
     libc.src.sys.stat.mkdir
     libc.src.sys.stat.mkdirat
+    libc.src.sys.stat.mkfifo
     libc.src.sys.stat.stat
     libc.src.sys.stat.umask
     libc.src.sys.stat.utimensat

diff  --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index 77c06949c1425..580d242fac20b 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -384,6 +384,7 @@ set(TARGET_LIBC_ENTRYPOINTS
     libc.src.sys.stat.lstat
     libc.src.sys.stat.mkdir
     libc.src.sys.stat.mkdirat
+    libc.src.sys.stat.mkfifo
     libc.src.sys.stat.stat
     libc.src.sys.stat.umask
     libc.src.sys.stat.utimensat

diff  --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index ff7b7099d28c6..263437c11fabd 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -389,6 +389,7 @@ set(TARGET_LIBC_ENTRYPOINTS
     libc.src.sys.stat.lstat
     libc.src.sys.stat.mkdir
     libc.src.sys.stat.mkdirat
+    libc.src.sys.stat.mkfifo
     libc.src.sys.stat.stat
     libc.src.sys.stat.umask
     libc.src.sys.stat.utimensat

diff  --git a/libc/include/sys/stat.yaml b/libc/include/sys/stat.yaml
index b12e2ac620a4f..3c75ce3d796cb 100644
--- a/libc/include/sys/stat.yaml
+++ b/libc/include/sys/stat.yaml
@@ -58,6 +58,11 @@ functions:
       - type: int
       - type: const char *
       - type: mode_t
+  - name: mkfifo
+    return_type: int
+    arguments:
+      - type: const char *
+      - type: mode_t
   - name: stat
     return_type: int
     arguments:

diff  --git a/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt b/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt
index 3857c736086dc..17665f87dfcd8 100644
--- a/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt
+++ b/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt
@@ -603,6 +603,20 @@ add_header_library(
     libc.include.sys_syscall
 )
 
+add_header_library(
+  mknodat
+  HDRS
+    mknodat.h
+  DEPENDS
+    libc.src.__support.OSUtil.osutil
+    libc.src.__support.common
+    libc.src.__support.error_or
+    libc.src.__support.macros.config
+    libc.hdr.types.dev_t
+    libc.hdr.types.mode_t
+    libc.include.sys_syscall
+)
+
 add_header_library(
   chmod
   HDRS

diff  --git a/libc/src/__support/OSUtil/linux/syscall_wrappers/mknodat.h b/libc/src/__support/OSUtil/linux/syscall_wrappers/mknodat.h
new file mode 100644
index 0000000000000..50fd804ae61b2
--- /dev/null
+++ b/libc/src/__support/OSUtil/linux/syscall_wrappers/mknodat.h
@@ -0,0 +1,40 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Syscall wrapper for mknodat.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_MKNODAT_H
+#define LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_MKNODAT_H
+
+#include "hdr/types/dev_t.h"
+#include "hdr/types/mode_t.h"
+#include "src/__support/OSUtil/linux/syscall.h" // For syscall_checked
+#include "src/__support/common.h"
+#include "src/__support/error_or.h"
+#include "src/__support/macros/config.h"
+#include <sys/syscall.h> // For syscall numbers
+
+namespace LIBC_NAMESPACE_DECL {
+namespace linux_syscalls {
+
+// Note that the kernel expects |dev| in its own old-style encoding
+// ((major << 8) | minor, with the extended bits), which is not necessarily the
+// encoding of dev_t. Callers creating device nodes must encode it themselves;
+// callers creating FIFOs and sockets pass 0.
+LIBC_INLINE ErrorOr<int> mknodat(int dfd, const char *path, mode_t mode,
+                                 dev_t dev) {
+  return syscall_checked<int>(SYS_mknodat, dfd, path, mode, dev);
+}
+
+} // namespace linux_syscalls
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_MKNODAT_H

diff  --git a/libc/src/sys/stat/CMakeLists.txt b/libc/src/sys/stat/CMakeLists.txt
index 7338fac02bc29..ae1a3f76078f1 100644
--- a/libc/src/sys/stat/CMakeLists.txt
+++ b/libc/src/sys/stat/CMakeLists.txt
@@ -51,6 +51,13 @@ add_entrypoint_object(
     .${LIBC_TARGET_OS}.mkdirat
 )
 
+add_entrypoint_object(
+  mkfifo
+  ALIAS
+  DEPENDS
+    .${LIBC_TARGET_OS}.mkfifo
+)
+
 add_entrypoint_object(
   stat
   ALIAS

diff  --git a/libc/src/sys/stat/linux/CMakeLists.txt b/libc/src/sys/stat/linux/CMakeLists.txt
index 52ae4566a2b87..b087fc927459c 100644
--- a/libc/src/sys/stat/linux/CMakeLists.txt
+++ b/libc/src/sys/stat/linux/CMakeLists.txt
@@ -60,6 +60,20 @@ add_entrypoint_object(
     libc.src.errno.errno
 )
 
+add_entrypoint_object(
+  mkfifo
+  SRCS
+    mkfifo.cpp
+  HDRS
+    ../mkfifo.h
+  DEPENDS
+    libc.hdr.fcntl_macros
+    libc.hdr.sys_stat_macros
+    libc.hdr.types.mode_t
+    libc.src.__support.OSUtil.linux.syscall_wrappers.mknodat
+    libc.src.errno.errno
+)
+
 add_entrypoint_object(
   stat
   SRCS

diff  --git a/libc/src/sys/stat/linux/mkfifo.cpp b/libc/src/sys/stat/linux/mkfifo.cpp
new file mode 100644
index 0000000000000..7d1025ea0f59f
--- /dev/null
+++ b/libc/src/sys/stat/linux/mkfifo.cpp
@@ -0,0 +1,35 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Linux implementation of mkfifo.
+///
+//===----------------------------------------------------------------------===//
+
+#include "src/sys/stat/mkfifo.h"
+
+#include "hdr/fcntl_macros.h"
+#include "hdr/sys_stat_macros.h"
+#include "hdr/types/mode_t.h"
+#include "src/__support/OSUtil/linux/syscall_wrappers/mknodat.h"
+#include "src/__support/common.h"
+#include "src/__support/libc_errno.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, mkfifo, (const char *path, mode_t mode)) {
+  auto result = linux_syscalls::mknodat(AT_FDCWD, path, mode | S_IFIFO, 0);
+  if (!result) {
+    libc_errno = result.error();
+    return -1;
+  }
+  return 0;
+}
+
+} // namespace LIBC_NAMESPACE_DECL

diff  --git a/libc/src/sys/stat/mkfifo.h b/libc/src/sys/stat/mkfifo.h
new file mode 100644
index 0000000000000..c814159bb215a
--- /dev/null
+++ b/libc/src/sys/stat/mkfifo.h
@@ -0,0 +1,26 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Implementation header for mkfifo.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_SYS_STAT_MKFIFO_H
+#define LLVM_LIBC_SRC_SYS_STAT_MKFIFO_H
+
+#include "hdr/types/mode_t.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+int mkfifo(const char *path, mode_t mode);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_SYS_STAT_MKFIFO_H

diff  --git a/libc/test/src/sys/stat/CMakeLists.txt b/libc/test/src/sys/stat/CMakeLists.txt
index 3e87a11b05e6e..32ce8f50c0ef1 100644
--- a/libc/test/src/sys/stat/CMakeLists.txt
+++ b/libc/test/src/sys/stat/CMakeLists.txt
@@ -75,6 +75,26 @@ add_libc_test(
     libc.test.UnitTest.ErrnoSetterMatcher
 )
 
+add_libc_test(
+  mkfifo_test
+  SUITE
+    libc_sys_stat_unittests
+  SRCS
+    mkfifo_test.cpp
+  DEPENDS
+    libc.hdr.errno_macros
+    libc.hdr.sys_stat_macros
+    libc.hdr.types.mode_t
+    libc.hdr.types.struct_stat
+    libc.src.errno.errno
+    libc.src.sys.stat.mkfifo
+    libc.src.sys.stat.stat
+    libc.src.sys.stat.umask
+    libc.src.unistd.unlink
+    libc.test.UnitTest.ErrnoCheckingTest
+    libc.test.UnitTest.ErrnoSetterMatcher
+)
+
 add_libc_test(
   stat_test
   SUITE

diff  --git a/libc/test/src/sys/stat/mkfifo_test.cpp b/libc/test/src/sys/stat/mkfifo_test.cpp
new file mode 100644
index 0000000000000..df93a03f86653
--- /dev/null
+++ b/libc/test/src/sys/stat/mkfifo_test.cpp
@@ -0,0 +1,57 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Unittests for mkfifo.
+///
+//===----------------------------------------------------------------------===//
+
+#include "hdr/errno_macros.h"
+#include "hdr/sys_stat_macros.h"
+#include "hdr/types/mode_t.h"
+#include "hdr/types/struct_stat.h"
+#include "src/sys/stat/mkfifo.h"
+#include "src/sys/stat/stat.h"
+#include "src/sys/stat/umask.h"
+#include "src/unistd/unlink.h"
+#include "test/UnitTest/ErrnoCheckingTest.h"
+#include "test/UnitTest/ErrnoSetterMatcher.h"
+#include "test/UnitTest/Test.h"
+
+using namespace LIBC_NAMESPACE::testing::ErrnoSetterMatcher;
+using LlvmLibcMkfifoTest = LIBC_NAMESPACE::testing::ErrnoCheckingTest;
+
+TEST_F(LlvmLibcMkfifoTest, CreateAndRemove) {
+  constexpr const char *FILENAME = "testdata/mkfifo.testfifo";
+  auto TEST_FIFO = libc_make_test_file_path(FILENAME);
+  constexpr mode_t FIFO_MODE = S_IRUSR | S_IWUSR;
+
+  // Clear the file creation mask so that the resulting permission bits are
+  // exactly the requested ones.
+  mode_t old_mask = LIBC_NAMESPACE::umask(0);
+  ASSERT_THAT(LIBC_NAMESPACE::mkfifo(TEST_FIFO, FIFO_MODE), Succeeds(0));
+  LIBC_NAMESPACE::umask(old_mask);
+
+  // The created file must be a FIFO with the requested permissions, which
+  // verifies that S_IFIFO was requested and that mode was passed along.
+  struct stat statbuf;
+  ASSERT_THAT(LIBC_NAMESPACE::stat(TEST_FIFO, &statbuf), Succeeds(0));
+  ASSERT_TRUE(S_ISFIFO(statbuf.st_mode));
+  ASSERT_EQ(static_cast<int>(statbuf.st_mode & 07777),
+            static_cast<int>(FIFO_MODE));
+
+  ASSERT_THAT(LIBC_NAMESPACE::unlink(TEST_FIFO), Succeeds(0));
+}
+
+TEST_F(LlvmLibcMkfifoTest, BadPath) {
+  constexpr const char *FILENAME = "testdata/non-existent-dir/mkfifo.testfifo";
+  auto TEST_FIFO = libc_make_test_file_path(FILENAME);
+
+  ASSERT_THAT(LIBC_NAMESPACE::mkfifo(TEST_FIFO, S_IRUSR | S_IWUSR),
+              Fails(ENOENT));
+}


        


More information about the libc-commits mailing list