Skip to content

[libc] Add sys/stat syscall wrappers#195295

Merged
kaladron merged 2 commits into
llvm:mainfrom
kaladron:syscall-stat
May 4, 2026
Merged

[libc] Add sys/stat syscall wrappers#195295
kaladron merged 2 commits into
llvm:mainfrom
kaladron:syscall-stat

Conversation

@kaladron
Copy link
Copy Markdown
Member

@kaladron kaladron commented May 1, 2026

Added ErrorOr-returning syscall wrappers for chmod, fchmod, fchmodat, mkdir, mkdirat, and statx in src/__support/OSUtil/linux/syscall_wrappers/. Migrated the sys/stat Linux entrypoints to use them.

Added hdr/types/struct_stat.h proxy header. Updated stat, lstat, fstat to use it, and kernel_statx to use the new statx wrapper.

Fixed fchmodat CMakeLists.txt to reference fchmodat.h (was fchmod.h). Updated test dependencies to use hdr/sys_stat_macros.

Added ErrorOr-returning syscall wrappers for chmod, fchmod, fchmodat,
mkdir, mkdirat, and statx in src/__support/OSUtil/linux/syscall_wrappers/.
Migrated the sys/stat Linux entrypoints to use them.

Added hdr/types/struct_stat.h proxy header. Updated stat, lstat, fstat
to use it, and kernel_statx to use the new statx wrapper.

Fixed fchmodat CMakeLists.txt to reference fchmodat.h (was fchmod.h).
Updated test dependencies to use hdr/sys_stat_macros.
@kaladron kaladron requested a review from vonosmas May 1, 2026 17:07
@kaladron kaladron marked this pull request as ready for review May 1, 2026 19:59
@llvmorg-github-actions
Copy link
Copy Markdown

@llvm/pr-subscribers-libc

Author: Jeff Bailey (kaladron)

Changes

Added ErrorOr-returning syscall wrappers for chmod, fchmod, fchmodat, mkdir, mkdirat, and statx in src/__support/OSUtil/linux/syscall_wrappers/. Migrated the sys/stat Linux entrypoints to use them.

Added hdr/types/struct_stat.h proxy header. Updated stat, lstat, fstat to use it, and kernel_statx to use the new statx wrapper.

Fixed fchmodat CMakeLists.txt to reference fchmodat.h (was fchmod.h). Updated test dependencies to use hdr/sys_stat_macros.


Patch is 32.41 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/195295.diff

37 Files Affected:

  • (modified) libc/hdr/types/CMakeLists.txt (+8)
  • (added) libc/hdr/types/struct_stat.h (+27)
  • (modified) libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt (+80)
  • (added) libc/src/__support/OSUtil/linux/syscall_wrappers/chmod.h (+47)
  • (added) libc/src/__support/OSUtil/linux/syscall_wrappers/fchmod.h (+37)
  • (added) libc/src/__support/OSUtil/linux/syscall_wrappers/fchmodat.h (+38)
  • (added) libc/src/__support/OSUtil/linux/syscall_wrappers/mkdir.h (+42)
  • (added) libc/src/__support/OSUtil/linux/syscall_wrappers/mkdirat.h (+37)
  • (added) libc/src/__support/OSUtil/linux/syscall_wrappers/statx.h (+37)
  • (modified) libc/src/sys/stat/chmod.h (+1-1)
  • (modified) libc/src/sys/stat/fchmod.h (+1-1)
  • (modified) libc/src/sys/stat/fchmodat.h (+1-1)
  • (modified) libc/src/sys/stat/fstat.h (+1-1)
  • (modified) libc/src/sys/stat/linux/CMakeLists.txt (+13-22)
  • (modified) libc/src/sys/stat/linux/chmod.cpp (+4-20)
  • (modified) libc/src/sys/stat/linux/fchmod.cpp (+4-8)
  • (modified) libc/src/sys/stat/linux/fchmodat.cpp (+4-8)
  • (modified) libc/src/sys/stat/linux/fstat.cpp (+1-1)
  • (modified) libc/src/sys/stat/linux/kernel_statx.h (+6-7)
  • (modified) libc/src/sys/stat/linux/lstat.cpp (+1-1)
  • (modified) libc/src/sys/stat/linux/mkdir.cpp (+4-17)
  • (modified) libc/src/sys/stat/linux/mkdirat.cpp (+4-12)
  • (modified) libc/src/sys/stat/linux/stat.cpp (+1-1)
  • (modified) libc/src/sys/stat/lstat.h (+1-1)
  • (modified) libc/src/sys/stat/mkdir.h (+1-1)
  • (modified) libc/src/sys/stat/mkdirat.h (+1-1)
  • (modified) libc/src/sys/stat/stat.h (+1-1)
  • (modified) libc/test/src/stdio/CMakeLists.txt (+2)
  • (modified) libc/test/src/stdio/remove_test.cpp (+1)
  • (modified) libc/test/src/stdio/rename_test.cpp (+1-1)
  • (modified) libc/test/src/sys/stat/CMakeLists.txt (+1-1)
  • (modified) libc/test/src/sys/stat/mkdirat_test.cpp (+1)
  • (modified) libc/test/src/sys/statvfs/linux/CMakeLists.txt (+2)
  • (modified) libc/test/src/sys/statvfs/linux/fstatvfs_test.cpp (+1)
  • (modified) libc/test/src/sys/statvfs/linux/statvfs_test.cpp (+1)
  • (modified) libc/test/src/unistd/CMakeLists.txt (+1)
  • (modified) libc/test/src/unistd/rmdir_test.cpp (+1)
diff --git a/libc/hdr/types/CMakeLists.txt b/libc/hdr/types/CMakeLists.txt
index a3057397725bd..a511944547d8a 100644
--- a/libc/hdr/types/CMakeLists.txt
+++ b/libc/hdr/types/CMakeLists.txt
@@ -159,6 +159,14 @@ add_proxy_header_library(
     libc.include.llvm-libc-types.size_t
 )
 
+add_proxy_header_library(
+  struct_stat
+  HDRS
+    struct_stat.h
+  FULL_BUILD_DEPENDS
+    libc.include.llvm-libc-types.struct_stat
+)
+
 add_proxy_header_library(
   ssize_t
   HDRS
diff --git a/libc/hdr/types/struct_stat.h b/libc/hdr/types/struct_stat.h
new file mode 100644
index 0000000000000..74cf381b27f05
--- /dev/null
+++ b/libc/hdr/types/struct_stat.h
@@ -0,0 +1,27 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+/// Proxy header for struct stat.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_HDR_TYPES_STRUCT_STAT_H
+#define LLVM_LIBC_HDR_TYPES_STRUCT_STAT_H
+
+#ifdef LIBC_FULL_BUILD
+
+#include "include/llvm-libc-types/struct_stat.h"
+
+#else // Overlay mode
+
+#include <sys/stat.h>
+
+#endif // LLVM_LIBC_FULL_BUILD
+
+#endif // LLVM_LIBC_HDR_TYPES_STRUCT_STAT_H
diff --git a/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt b/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt
index 2215d2cab2851..edfda18146bce 100644
--- a/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt
+++ b/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt
@@ -235,3 +235,83 @@ add_header_library(
     libc.hdr.errno_macros
     libc.include.sys_syscall
 )
+
+add_header_library(
+  statx
+  HDRS
+    statx.h
+  DEPENDS
+    libc.src.__support.OSUtil.osutil
+    libc.src.__support.common
+    libc.src.__support.error_or
+    libc.src.__support.macros.config
+    libc.include.sys_syscall
+)
+
+add_header_library(
+  mkdir
+  HDRS
+    mkdir.h
+  DEPENDS
+    libc.src.__support.OSUtil.osutil
+    libc.src.__support.common
+    libc.src.__support.error_or
+    libc.src.__support.macros.config
+    libc.hdr.fcntl_macros
+    libc.hdr.types.mode_t
+    libc.include.sys_syscall
+)
+
+add_header_library(
+  mkdirat
+  HDRS
+    mkdirat.h
+  DEPENDS
+    libc.src.__support.OSUtil.osutil
+    libc.src.__support.common
+    libc.src.__support.error_or
+    libc.src.__support.macros.config
+    libc.hdr.types.mode_t
+    libc.include.sys_syscall
+)
+
+add_header_library(
+  chmod
+  HDRS
+    chmod.h
+  DEPENDS
+    libc.src.__support.OSUtil.osutil
+    libc.src.__support.common
+    libc.src.__support.error_or
+    libc.src.__support.macros.config
+    libc.hdr.fcntl_macros
+    libc.hdr.types.mode_t
+    libc.include.sys_syscall
+)
+
+add_header_library(
+  fchmod
+  HDRS
+    fchmod.h
+  DEPENDS
+    libc.src.__support.OSUtil.osutil
+    libc.src.__support.common
+    libc.src.__support.error_or
+    libc.src.__support.macros.config
+    libc.hdr.types.mode_t
+    libc.include.sys_syscall
+)
+
+add_header_library(
+  fchmodat
+  HDRS
+    fchmodat.h
+  DEPENDS
+    libc.src.__support.OSUtil.osutil
+    libc.src.__support.common
+    libc.src.__support.error_or
+    libc.src.__support.macros.config
+    libc.hdr.types.mode_t
+    libc.include.sys_syscall
+)
+
diff --git a/libc/src/__support/OSUtil/linux/syscall_wrappers/chmod.h b/libc/src/__support/OSUtil/linux/syscall_wrappers/chmod.h
new file mode 100644
index 0000000000000..69acf4c5cf1b3
--- /dev/null
+++ b/libc/src/__support/OSUtil/linux/syscall_wrappers/chmod.h
@@ -0,0 +1,47 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+/// ErrorOr-returning syscall wrapper for chmod.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_CHMOD_H
+#define LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_CHMOD_H
+
+#include "hdr/fcntl_macros.h"
+#include "hdr/types/mode_t.h"
+#include "src/__support/OSUtil/linux/syscall.h" // syscall_impl
+#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 {
+
+LIBC_INLINE ErrorOr<int> chmod(const char *path, mode_t mode) {
+#ifdef SYS_chmod
+  int ret = syscall_impl<int>(SYS_chmod, path, mode);
+#elif defined(SYS_fchmodat)
+  int ret = syscall_impl<int>(SYS_fchmodat, AT_FDCWD, path, mode, 0);
+#elif defined(SYS_fchmodat2)
+  int ret = syscall_impl<int>(SYS_fchmodat2, AT_FDCWD, path, mode, 0,
+                              AT_SYMLINK_NOFOLLOW);
+#else
+#error "chmod, fchmodat and fchmodat2 syscalls not available."
+#endif
+  if (ret < 0)
+    return Error(-ret);
+  return ret;
+}
+
+} // namespace linux_syscalls
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_CHMOD_H
diff --git a/libc/src/__support/OSUtil/linux/syscall_wrappers/fchmod.h b/libc/src/__support/OSUtil/linux/syscall_wrappers/fchmod.h
new file mode 100644
index 0000000000000..4760a821726e1
--- /dev/null
+++ b/libc/src/__support/OSUtil/linux/syscall_wrappers/fchmod.h
@@ -0,0 +1,37 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+/// ErrorOr-returning syscall wrapper for fchmod.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_FCHMOD_H
+#define LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_FCHMOD_H
+
+#include "hdr/types/mode_t.h"
+#include "src/__support/OSUtil/linux/syscall.h" // syscall_impl
+#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 {
+
+LIBC_INLINE ErrorOr<int> fchmod(int fd, mode_t mode) {
+  int ret = syscall_impl<int>(SYS_fchmod, fd, mode);
+  if (ret < 0)
+    return Error(-ret);
+  return ret;
+}
+
+} // namespace linux_syscalls
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_FCHMOD_H
diff --git a/libc/src/__support/OSUtil/linux/syscall_wrappers/fchmodat.h b/libc/src/__support/OSUtil/linux/syscall_wrappers/fchmodat.h
new file mode 100644
index 0000000000000..7b8ee1a079b99
--- /dev/null
+++ b/libc/src/__support/OSUtil/linux/syscall_wrappers/fchmodat.h
@@ -0,0 +1,38 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+/// ErrorOr-returning syscall wrapper for fchmodat.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_FCHMODAT_H
+#define LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_FCHMODAT_H
+
+#include "hdr/types/mode_t.h"
+#include "src/__support/OSUtil/linux/syscall.h" // syscall_impl
+#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 {
+
+LIBC_INLINE ErrorOr<int> fchmodat(int fd, const char *path, mode_t mode,
+                                  int flags) {
+  int ret = syscall_impl<int>(SYS_fchmodat, fd, path, mode, flags);
+  if (ret < 0)
+    return Error(-ret);
+  return ret;
+}
+
+} // namespace linux_syscalls
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_FCHMODAT_H
diff --git a/libc/src/__support/OSUtil/linux/syscall_wrappers/mkdir.h b/libc/src/__support/OSUtil/linux/syscall_wrappers/mkdir.h
new file mode 100644
index 0000000000000..6d77894c36b6b
--- /dev/null
+++ b/libc/src/__support/OSUtil/linux/syscall_wrappers/mkdir.h
@@ -0,0 +1,42 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+/// ErrorOr-returning syscall wrapper for mkdir.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_MKDIR_H
+#define LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_MKDIR_H
+
+#include "hdr/fcntl_macros.h"
+#include "hdr/types/mode_t.h"
+#include "src/__support/OSUtil/linux/syscall.h" // syscall_impl
+#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 {
+
+LIBC_INLINE ErrorOr<int> mkdir(const char *path, mode_t mode) {
+#ifdef SYS_mkdir
+  int ret = syscall_impl<int>(SYS_mkdir, path, mode);
+#else
+  int ret = syscall_impl<int>(SYS_mkdirat, AT_FDCWD, path, mode);
+#endif
+  if (ret < 0)
+    return Error(-ret);
+  return ret;
+}
+
+} // namespace linux_syscalls
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_MKDIR_H
diff --git a/libc/src/__support/OSUtil/linux/syscall_wrappers/mkdirat.h b/libc/src/__support/OSUtil/linux/syscall_wrappers/mkdirat.h
new file mode 100644
index 0000000000000..70e67e3fb7809
--- /dev/null
+++ b/libc/src/__support/OSUtil/linux/syscall_wrappers/mkdirat.h
@@ -0,0 +1,37 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+/// ErrorOr-returning syscall wrapper for mkdirat.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_MKDIRAT_H
+#define LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_MKDIRAT_H
+
+#include "hdr/types/mode_t.h"
+#include "src/__support/OSUtil/linux/syscall.h" // syscall_impl
+#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 {
+
+LIBC_INLINE ErrorOr<int> mkdirat(int dfd, const char *path, mode_t mode) {
+  int ret = syscall_impl<int>(SYS_mkdirat, dfd, path, mode);
+  if (ret < 0)
+    return Error(-ret);
+  return ret;
+}
+
+} // namespace linux_syscalls
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_MKDIRAT_H
diff --git a/libc/src/__support/OSUtil/linux/syscall_wrappers/statx.h b/libc/src/__support/OSUtil/linux/syscall_wrappers/statx.h
new file mode 100644
index 0000000000000..c65a74fc3ec08
--- /dev/null
+++ b/libc/src/__support/OSUtil/linux/syscall_wrappers/statx.h
@@ -0,0 +1,37 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+/// ErrorOr-returning syscall wrapper for statx.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_STATX_H
+#define LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_STATX_H
+
+#include "src/__support/OSUtil/linux/syscall.h" // syscall_impl
+#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 {
+
+LIBC_INLINE ErrorOr<int> statx(int dirfd, const char *path, int flags,
+                               unsigned int mask, void *statxbuf) {
+  int ret = syscall_impl<int>(SYS_statx, dirfd, path, flags, mask, statxbuf);
+  if (ret < 0)
+    return Error(-ret);
+  return ret;
+}
+
+} // namespace linux_syscalls
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_STATX_H
diff --git a/libc/src/sys/stat/chmod.h b/libc/src/sys/stat/chmod.h
index a05407a40978f..0db42000794f2 100644
--- a/libc/src/sys/stat/chmod.h
+++ b/libc/src/sys/stat/chmod.h
@@ -9,8 +9,8 @@
 #ifndef LLVM_LIBC_SRC_SYS_STAT_CHMOD_H
 #define LLVM_LIBC_SRC_SYS_STAT_CHMOD_H
 
+#include "hdr/types/mode_t.h"
 #include "src/__support/macros/config.h"
-#include <sys/stat.h>
 
 namespace LIBC_NAMESPACE_DECL {
 
diff --git a/libc/src/sys/stat/fchmod.h b/libc/src/sys/stat/fchmod.h
index 470ce3e3a03a2..ba99d4d5e0469 100644
--- a/libc/src/sys/stat/fchmod.h
+++ b/libc/src/sys/stat/fchmod.h
@@ -9,8 +9,8 @@
 #ifndef LLVM_LIBC_SRC_SYS_STAT_FCHMOD_H
 #define LLVM_LIBC_SRC_SYS_STAT_FCHMOD_H
 
+#include "hdr/types/mode_t.h"
 #include "src/__support/macros/config.h"
-#include <sys/stat.h>
 
 namespace LIBC_NAMESPACE_DECL {
 
diff --git a/libc/src/sys/stat/fchmodat.h b/libc/src/sys/stat/fchmodat.h
index e4500f505bfda..848a2f04f9d7f 100644
--- a/libc/src/sys/stat/fchmodat.h
+++ b/libc/src/sys/stat/fchmodat.h
@@ -9,8 +9,8 @@
 #ifndef LLVM_LIBC_SRC_SYS_STAT_FCHMODAT_H
 #define LLVM_LIBC_SRC_SYS_STAT_FCHMODAT_H
 
+#include "hdr/types/mode_t.h"
 #include "src/__support/macros/config.h"
-#include <sys/stat.h>
 
 namespace LIBC_NAMESPACE_DECL {
 
diff --git a/libc/src/sys/stat/fstat.h b/libc/src/sys/stat/fstat.h
index a3ec9e45384c9..1e2eef5dbf47f 100644
--- a/libc/src/sys/stat/fstat.h
+++ b/libc/src/sys/stat/fstat.h
@@ -9,8 +9,8 @@
 #ifndef LLVM_LIBC_SRC_SYS_STAT_FSTAT_H
 #define LLVM_LIBC_SRC_SYS_STAT_FSTAT_H
 
+#include "hdr/types/struct_stat.h"
 #include "src/__support/macros/config.h"
-#include <sys/stat.h>
 
 namespace LIBC_NAMESPACE_DECL {
 
diff --git a/libc/src/sys/stat/linux/CMakeLists.txt b/libc/src/sys/stat/linux/CMakeLists.txt
index 4fd8fe98890de..20ebd7716f75b 100644
--- a/libc/src/sys/stat/linux/CMakeLists.txt
+++ b/libc/src/sys/stat/linux/CMakeLists.txt
@@ -7,9 +7,7 @@ add_entrypoint_object(
   DEPENDS
     libc.hdr.types.mode_t
     libc.hdr.fcntl_macros
-    libc.include.sys_stat
-    libc.include.sys_syscall
-    libc.src.__support.OSUtil.osutil
+    libc.src.__support.OSUtil.linux.syscall_wrappers.chmod
     libc.src.errno.errno
 )
 
@@ -21,9 +19,7 @@ add_entrypoint_object(
     ../fchmod.h
   DEPENDS
     libc.hdr.types.mode_t
-    libc.include.sys_stat
-    libc.include.sys_syscall
-    libc.src.__support.OSUtil.osutil
+    libc.src.__support.OSUtil.linux.syscall_wrappers.fchmod
     libc.src.errno.errno
 )
 
@@ -32,11 +28,10 @@ add_entrypoint_object(
   SRCS
     fchmodat.cpp
   HDRS
-    ../fchmod.h
+    ../fchmodat.h
   DEPENDS
-    libc.include.sys_stat
-    libc.include.sys_syscall
-    libc.src.__support.OSUtil.osutil
+    libc.hdr.types.mode_t
+    libc.src.__support.OSUtil.linux.syscall_wrappers.fchmodat
     libc.src.errno.errno
 )
 
@@ -49,9 +44,7 @@ add_entrypoint_object(
   DEPENDS
     libc.hdr.types.mode_t
     libc.hdr.fcntl_macros
-    libc.include.sys_stat
-    libc.include.sys_syscall
-    libc.src.__support.OSUtil.osutil
+    libc.src.__support.OSUtil.linux.syscall_wrappers.mkdir
     libc.src.errno.errno
 )
 
@@ -62,9 +55,8 @@ add_entrypoint_object(
   HDRS
     ../mkdirat.h
   DEPENDS
-    libc.include.sys_stat
-    libc.include.sys_syscall
-    libc.src.__support.OSUtil.osutil
+    libc.hdr.types.mode_t
+    libc.src.__support.OSUtil.linux.syscall_wrappers.mkdirat
     libc.src.errno.errno
 )
 
@@ -74,9 +66,8 @@ add_header_library(
     kernel_statx.h
   DEPENDS
     libc.hdr.stdint_proxy
-    libc.include.sys_stat
-    libc.include.sys_syscall
-    libc.src.__support.OSUtil.osutil
+    libc.hdr.types.struct_stat
+    libc.src.__support.OSUtil.linux.syscall_wrappers.statx
     libc.src.__support.common
 )
 
@@ -89,7 +80,7 @@ add_entrypoint_object(
   DEPENDS
     .kernel_statx
     libc.hdr.fcntl_macros
-    libc.include.sys_stat
+    libc.hdr.types.struct_stat
     libc.src.errno.errno
 )
 
@@ -102,7 +93,7 @@ add_entrypoint_object(
   DEPENDS
     .kernel_statx
     libc.hdr.fcntl_macros
-    libc.include.sys_stat
+    libc.hdr.types.struct_stat
     libc.src.errno.errno
 )
 
@@ -115,7 +106,7 @@ add_entrypoint_object(
   DEPENDS
     .kernel_statx
     libc.hdr.fcntl_macros
-    libc.include.sys_stat
+    libc.hdr.types.struct_stat
     libc.src.errno.errno
 )
 
diff --git a/libc/src/sys/stat/linux/chmod.cpp b/libc/src/sys/stat/linux/chmod.cpp
index 2bd0788ec1dfd..bd9b12fea50d3 100644
--- a/libc/src/sys/stat/linux/chmod.cpp
+++ b/libc/src/sys/stat/linux/chmod.cpp
@@ -8,33 +8,17 @@
 
 #include "src/sys/stat/chmod.h"
 
-#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
+#include "src/__support/OSUtil/linux/syscall_wrappers/chmod.h"
 #include "src/__support/common.h"
-
-#include "hdr/fcntl_macros.h"
-#include "hdr/types/mode_t.h"
 #include "src/__support/libc_errno.h"
 #include "src/__support/macros/config.h"
-#include <sys/stat.h>
-#include <sys/syscall.h> // For syscall numbers.
 
 namespace LIBC_NAMESPACE_DECL {
 
 LLVM_LIBC_FUNCTION(int, chmod, (const char *path, mode_t mode)) {
-#ifdef SYS_chmod
-  int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_chmod, path, mode);
-#elif defined(SYS_fchmodat)
-  int ret =
-      LIBC_NAMESPACE::syscall_impl<int>(SYS_fchmodat, AT_FDCWD, path, mode, 0);
-#elif defined(SYS_fchmodat2)
-  int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_fchmodat2, AT_FDCWD, path,
-                                              mode, 0, AT_SYMLINK_NOFOLLOW);
-#else
-#error "chmod, fchmodat and fchmodat2 syscalls not available."
-#endif
-
-  if (ret < 0) {
-    libc_errno = -ret;
+  auto result = linux_syscalls::chmod(path, mode);
+  if (!result) {
+    libc_errno = result.error();
     return -1;
   }
   return 0;
diff --git a/libc/src/sys/stat/linux/fchmod.cpp b/libc/src/sys/stat/linux/fchmod.cpp
index 3dadfdd1d943c..aa59b59a50cd7 100644
--- a/libc/src/sys/stat/linux/fchmod.cpp
+++ b/libc/src/sys/stat/linux/fchmod.cpp
@@ -8,21 +8,17 @@
 
 #include "src/sys/stat/fchmod.h"
 
-#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
+#include "src/__support/OSUtil/linux/syscall_wrappers/fchmod.h"
 #include "src/__support/common.h"
-
-#include "hdr/types/mode_t.h"
 #include "src/__support/libc_errno.h"
 #include "src/__support/macros/config.h"
-#include <sys/stat.h>
-#include <sys/syscall.h> // For syscall numbers.
 
 namespace LIBC_NAMESPACE_DECL {
 
 LLVM_LIBC_FUNCTION(int, fchmod, (int fd, mode_t mode)) {
-  int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_fchmod, fd, mode);
-  if (ret < 0) {
-    libc_errno = -ret;
+  auto result = linux_syscalls::fchmod(fd, mode);
+  if (!result) {
+    libc_errno = result.error();
     return -1;
   }
   return 0;
diff --git a/libc/src/sys/stat/linux/fchmodat.cpp b/libc/src/sys/stat/linux/fchmodat.cpp
index add2192a558a4...
[truncated]

Copy link
Copy Markdown
Member

@michaelrj-google michaelrj-google left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Copy link
Copy Markdown
Contributor

@vonosmas vonosmas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with a couple of nits

Comment thread libc/hdr/types/struct_stat.h

namespace LIBC_NAMESPACE_DECL {

LIBC_INLINE int statx(int dirfd, const char *__restrict path, int flags,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't we just propagate ErrorOr from this function as well? Otherwise its contract is unclear.

Copy link
Copy Markdown
Member Author

@kaladron kaladron May 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://man7.org/linux/man-pages/man2/statx.2.html fixes the contract of this function.

However, it looks like this function never set errno before, which was a bug. I've fixed that (and adjusted its internal callers)

Copy link
Copy Markdown
Contributor

@vonosmas vonosmas May 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it was a bug per se, as this statx is an internal (LIBC_INLINE) function, not an implementation of statx entrypoint (which we don't have yet). Generally, we don't want one entrypoint to call into another. And I think it's more idiomatic to set errno in the entrypoint implementation itself, instead of inside the helper function (in this case - statx) that entrypoint implementation calls into. But... given that lstat/fstat/stat are such a thin wrappers, I'm OK with it here.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, github ate my comment:

My preference here is that I'd like the kernel handling of the error message not to propagate into the rest of the library, since that makes more of the library OS-specific. Handling the conversion and setting of errno right beside the syscall means that everything after that only has to handle the errno setting.

Comment thread libc/src/__support/OSUtil/linux/syscall_wrappers/mkdir.h
kernel_statx now sets libc_errno and returns -1 on failure,
matching the convention used by the other stat entrypoints.
Simplified stat, lstat, and fstat to forward the return value
directly.
@kaladron kaladron requested a review from vonosmas May 4, 2026 09:12
@kaladron kaladron merged commit 90e17d2 into llvm:main May 4, 2026
32 checks passed
@kaladron kaladron deleted the syscall-stat branch May 4, 2026 22:40
moar55 pushed a commit to moar55/llvm-project that referenced this pull request May 12, 2026
Added ErrorOr-returning syscall wrappers for chmod, fchmod, fchmodat,
mkdir, mkdirat, and statx in
src/__support/OSUtil/linux/syscall_wrappers/. Migrated the sys/stat
Linux entrypoints to use them.

Added hdr/types/struct_stat.h proxy header. Updated stat, lstat, fstat
to use it, and kernel_statx to use the new statx wrapper.

Fixed fchmodat CMakeLists.txt to reference fchmodat.h (was fchmod.h).
Updated test dependencies to use hdr/sys_stat_macros.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants