[libc-commits] [libc] 7e2d179 - [libc] Implement lockf in unistd (#230856) (#231145)

via libc-commits libc-commits at lists.llvm.org
Wed Oct 14 02:31:33 PDT 2026


Author: Aman Maurya
Date: 2026-10-14T09:31:25Z
New Revision: 7e2d1797af58e26e9e4c92a49c6ba9b7d2f11151

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

LOG: [libc] Implement lockf in unistd (#230856) (#231145)

Implement the POSIX function `lockf(int fd, int cmd, off_t len)` in
`<unistd.h>`.

Fixes #230856.

Assisted by Antigravity and reviewed by Aman Maurya.

Added: 
    libc/src/unistd/linux/lockf.cpp
    libc/src/unistd/lockf.h
    libc/test/integration/src/unistd/lockf_test.cpp
    libc/test/src/unistd/lockf_test.cpp

Modified: 
    libc/config/linux/aarch64/entrypoints.txt
    libc/config/linux/arm/entrypoints.txt
    libc/config/linux/riscv/entrypoints.txt
    libc/config/linux/x86_64/entrypoints.txt
    libc/hdr/CMakeLists.txt
    libc/hdr/unistd_macros.h
    libc/include/llvm-libc-macros/linux/unistd-macros.h
    libc/include/unistd.yaml
    libc/src/unistd/CMakeLists.txt
    libc/src/unistd/linux/CMakeLists.txt
    libc/test/integration/src/unistd/CMakeLists.txt
    libc/test/src/unistd/CMakeLists.txt

Removed: 
    


################################################################################
diff  --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index 8866925d22611..13130efdf79bb 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -487,6 +487,7 @@ set(TARGET_LIBC_ENTRYPOINTS
     libc.src.unistd.lchown
     libc.src.unistd.link
     libc.src.unistd.linkat
+    libc.src.unistd.lockf
     libc.src.unistd.lseek
     libc.src.unistd.nice
     libc.src.unistd.pathconf

diff  --git a/libc/config/linux/arm/entrypoints.txt b/libc/config/linux/arm/entrypoints.txt
index 9ae4108133eeb..d52e3428a4aef 100644
--- a/libc/config/linux/arm/entrypoints.txt
+++ b/libc/config/linux/arm/entrypoints.txt
@@ -283,6 +283,7 @@ set(TARGET_LIBC_ENTRYPOINTS
     libc.src.unistd.lchown
     libc.src.unistd.link
     libc.src.unistd.linkat
+    libc.src.unistd.lockf
     libc.src.unistd.lseek
     libc.src.unistd.nice
     libc.src.unistd.pause

diff  --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index 1ab1e4007b900..e53f61dd43e90 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -507,6 +507,7 @@ set(TARGET_LIBC_ENTRYPOINTS
     libc.src.unistd.lchown
     libc.src.unistd.link
     libc.src.unistd.linkat
+    libc.src.unistd.lockf
     libc.src.unistd.lseek
     libc.src.unistd.nice
     libc.src.unistd.pathconf

diff  --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 3cada69a99116..dcfa2ef81338e 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -527,6 +527,7 @@ set(TARGET_LIBC_ENTRYPOINTS
     libc.src.unistd.lchown
     libc.src.unistd.link
     libc.src.unistd.linkat
+    libc.src.unistd.lockf
     libc.src.unistd.lseek
     libc.src.unistd.nice
     libc.src.unistd.pathconf

diff  --git a/libc/hdr/CMakeLists.txt b/libc/hdr/CMakeLists.txt
index cf8b1f36d349e..10ac84340523d 100644
--- a/libc/hdr/CMakeLists.txt
+++ b/libc/hdr/CMakeLists.txt
@@ -320,6 +320,7 @@ add_proxy_header_library(
   DEPENDS
     .unistd_overlay
   FULL_BUILD_DEPENDS
+    libc.include.llvm-libc-macros.file_seek_macros
     libc.include.llvm-libc-macros.unistd_macros
 )
 

diff  --git a/libc/hdr/unistd_macros.h b/libc/hdr/unistd_macros.h
index bda16224608bf..b1a63b2dd1e7d 100644
--- a/libc/hdr/unistd_macros.h
+++ b/libc/hdr/unistd_macros.h
@@ -11,6 +11,7 @@
 
 #ifdef LIBC_FULL_BUILD
 
+#include "include/llvm-libc-macros/file-seek-macros.h"
 #include "include/llvm-libc-macros/unistd-macros.h"
 
 #else // Overlay mode

diff  --git a/libc/include/llvm-libc-macros/linux/unistd-macros.h b/libc/include/llvm-libc-macros/linux/unistd-macros.h
index 0a9facd82fcb2..e14d44960de0e 100644
--- a/libc/include/llvm-libc-macros/linux/unistd-macros.h
+++ b/libc/include/llvm-libc-macros/linux/unistd-macros.h
@@ -20,6 +20,12 @@
 #define W_OK 2
 #define R_OK 4
 
+// Values for command argument to the lockf(...) function.
+#define F_ULOCK 0
+#define F_LOCK 1
+#define F_TLOCK 2
+#define F_TEST 3
+
 #define _SC_ARG_MAX 0
 #define _SC_CLK_TCK 2
 #define _SC_OPEN_MAX 4

diff  --git a/libc/include/unistd.yaml b/libc/include/unistd.yaml
index 2136adecccd99..87883dbf9bc24 100644
--- a/libc/include/unistd.yaml
+++ b/libc/include/unistd.yaml
@@ -88,6 +88,14 @@ macros:
     macro_header: unistd-macros.h
   - macro_name: _POSIX_THREAD_SPORADIC_SERVER
     macro_header: unistd-macros.h
+  - macro_name: F_ULOCK
+    macro_header: unistd-macros.h
+  - macro_name: F_LOCK
+    macro_header: unistd-macros.h
+  - macro_name: F_TLOCK
+    macro_header: unistd-macros.h
+  - macro_name: F_TEST
+    macro_header: unistd-macros.h
 types:
   - type_name: uid_t
   - type_name: gid_t
@@ -422,6 +430,14 @@ functions:
       - type: int
       - type: const char *
       - type: int
+  - name: lockf
+    standards:
+      - posix
+    return_type: int
+    arguments:
+      - type: int
+      - type: int
+      - type: off_t
   - name: lseek
     standards:
       - posix

diff  --git a/libc/src/unistd/CMakeLists.txt b/libc/src/unistd/CMakeLists.txt
index 1cea7d10d9f95..19a2bdd6f9b85 100644
--- a/libc/src/unistd/CMakeLists.txt
+++ b/libc/src/unistd/CMakeLists.txt
@@ -301,6 +301,13 @@ add_entrypoint_object(
     .${LIBC_TARGET_OS}.linkat
 )
 
+add_entrypoint_object(
+  lockf
+  ALIAS
+  DEPENDS
+    .${LIBC_TARGET_OS}.lockf
+)
+
 add_entrypoint_object(
   lseek
   ALIAS

diff  --git a/libc/src/unistd/linux/CMakeLists.txt b/libc/src/unistd/linux/CMakeLists.txt
index 4cfcc8012eaae..fb77b8b738e61 100644
--- a/libc/src/unistd/linux/CMakeLists.txt
+++ b/libc/src/unistd/linux/CMakeLists.txt
@@ -497,6 +497,26 @@ add_entrypoint_object(
     libc.src.errno.errno
 )
 
+add_entrypoint_object(
+  lockf
+  SRCS
+    lockf.cpp
+  HDRS
+    ../lockf.h
+  DEPENDS
+    libc.hdr.errno_macros
+    libc.hdr.fcntl_macros
+    libc.hdr.types.off_t
+    libc.hdr.types.struct_flock
+    libc.hdr.unistd_macros
+    libc.src.__support.OSUtil.linux.syscall_wrappers.fcntl
+    libc.src.__support.OSUtil.linux.syscall_wrappers.getpid
+    libc.src.__support.common
+    libc.src.__support.error_or
+    libc.src.__support.libc_errno
+    libc.src.__support.macros.config
+)
+
 add_entrypoint_object(
   lseek
   SRCS

diff  --git a/libc/src/unistd/linux/lockf.cpp b/libc/src/unistd/linux/lockf.cpp
new file mode 100644
index 0000000000000..e2fc005df9f01
--- /dev/null
+++ b/libc/src/unistd/linux/lockf.cpp
@@ -0,0 +1,69 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 lockf.
+///
+//===----------------------------------------------------------------------===//
+
+#include "src/unistd/lockf.h"
+
+#include "hdr/errno_macros.h"
+#include "hdr/fcntl_macros.h"
+#include "hdr/types/off_t.h"
+#include "hdr/types/struct_flock.h"
+#include "hdr/unistd_macros.h"
+#include "src/__support/OSUtil/linux/syscall_wrappers/fcntl.h"
+#include "src/__support/OSUtil/linux/syscall_wrappers/getpid.h"
+#include "src/__support/common.h"
+#include "src/__support/error_or.h"
+#include "src/__support/libc_errno.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+static ErrorOr<int> lockf_impl(int fd, int cmd, off_t len) {
+  struct flock fl = {};
+  fl.l_whence = SEEK_CUR;
+  fl.l_start = 0;
+  fl.l_len = len;
+
+  switch (cmd) {
+  case F_TEST: {
+    fl.l_type = F_RDLCK;
+    auto result = linux_syscalls::fcntl(fd, F_GETLK, &fl);
+    if (!result.has_value())
+      return Error(result.error());
+    if (fl.l_type == F_UNLCK || fl.l_pid == linux_syscalls::getpid())
+      return 0;
+    return Error(EACCES);
+  }
+  case F_ULOCK:
+    fl.l_type = F_UNLCK;
+    return linux_syscalls::fcntl(fd, F_SETLK, &fl);
+  case F_LOCK:
+    fl.l_type = F_WRLCK;
+    return linux_syscalls::fcntl(fd, F_SETLKW, &fl);
+  case F_TLOCK:
+    fl.l_type = F_WRLCK;
+    return linux_syscalls::fcntl(fd, F_SETLK, &fl);
+  default:
+    return Error(EINVAL);
+  }
+}
+
+LLVM_LIBC_FUNCTION(int, lockf, (int fd, int cmd, off_t len)) {
+  auto result = lockf_impl(fd, cmd, len);
+  if (!result.has_value()) {
+    libc_errno = result.error();
+    return -1;
+  }
+  return 0;
+}
+
+} // namespace LIBC_NAMESPACE_DECL

diff  --git a/libc/src/unistd/lockf.h b/libc/src/unistd/lockf.h
new file mode 100644
index 0000000000000..27a9949753fe5
--- /dev/null
+++ b/libc/src/unistd/lockf.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 lockf.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_UNISTD_LOCKF_H
+#define LLVM_LIBC_SRC_UNISTD_LOCKF_H
+
+#include "hdr/types/off_t.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+int lockf(int fd, int cmd, off_t len);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_UNISTD_LOCKF_H

diff  --git a/libc/test/integration/src/unistd/CMakeLists.txt b/libc/test/integration/src/unistd/CMakeLists.txt
index 069385a532543..1cb2e7b6d335f 100644
--- a/libc/test/integration/src/unistd/CMakeLists.txt
+++ b/libc/test/integration/src/unistd/CMakeLists.txt
@@ -38,6 +38,29 @@ add_integration_test(
     libc.include.sys_syscall
 )
 
+add_integration_test(
+  lockf_test
+  SUITE
+    unistd-integration-tests
+  SRCS
+    lockf_test.cpp
+  DEPENDS
+    libc.hdr.errno_macros
+    libc.hdr.fcntl_macros
+    libc.hdr.sys_stat_macros
+    libc.hdr.sys_wait_macros
+    libc.hdr.unistd_macros
+    libc.src.__support.CPP.scope
+    libc.src.errno.errno
+    libc.src.fcntl.open
+    libc.src.stdlib.exit
+    libc.src.sys.wait.waitpid
+    libc.src.unistd.close
+    libc.src.unistd.fork
+    libc.src.unistd.lockf
+    libc.src.unistd.unlink
+)
+
 if((${LIBC_TARGET_OS} STREQUAL "linux") AND (${LIBC_TARGET_ARCHITECTURE_IS_X86}))
   add_integration_test(
     stack_smashing_test

diff  --git a/libc/test/integration/src/unistd/lockf_test.cpp b/libc/test/integration/src/unistd/lockf_test.cpp
new file mode 100644
index 0000000000000..019c6df98aff0
--- /dev/null
+++ b/libc/test/integration/src/unistd/lockf_test.cpp
@@ -0,0 +1,81 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+/// Integration test for lockf.
+///
+//===----------------------------------------------------------------------===//
+
+#include "hdr/errno_macros.h"
+#include "hdr/fcntl_macros.h"
+#include "hdr/sys_stat_macros.h"
+#include "hdr/sys_wait_macros.h"
+#include "hdr/unistd_macros.h"
+#include "src/__support/CPP/scope.h"
+#include "src/fcntl/open.h"
+#include "src/stdlib/exit.h"
+#include "src/sys/wait/waitpid.h"
+#include "src/unistd/close.h"
+#include "src/unistd/fork.h"
+#include "src/unistd/lockf.h"
+#include "src/unistd/unlink.h"
+
+#include "test/IntegrationTest/test.h"
+
+#include <errno.h>
+
+TEST_MAIN([[maybe_unused]] int argc, [[maybe_unused]] char **argv,
+          [[maybe_unused]] char **envp) {
+  constexpr const char TEST_FILE[] = "lockf_integration.test";
+
+  int fd = LIBC_NAMESPACE::open(TEST_FILE, O_CREAT | O_TRUNC | O_RDWR, S_IRWXU);
+  ASSERT_TRUE(fd > 0);
+
+  LIBC_NAMESPACE::cpp::scope_exit cleanup([&] {
+    ASSERT_EQ(LIBC_NAMESPACE::close(fd), 0);
+    ASSERT_EQ(LIBC_NAMESPACE::unlink(TEST_FILE), 0);
+  });
+
+  // Acquire an exclusive lock on the file in the parent process.
+  ASSERT_EQ(LIBC_NAMESPACE::lockf(fd, F_LOCK, 0), 0);
+
+  pid_t pid = LIBC_NAMESPACE::fork();
+  ASSERT_TRUE(pid >= 0);
+
+  if (pid == 0) {
+    // Child process:
+    int child_fd = LIBC_NAMESPACE::open(TEST_FILE, O_RDWR, 0);
+    if (child_fd < 0)
+      LIBC_NAMESPACE::exit(1);
+
+    // F_TEST should fail because the section is locked by another process
+    // (parent).
+    if (LIBC_NAMESPACE::lockf(child_fd, F_TEST, 0) == 0)
+      LIBC_NAMESPACE::exit(2);
+    if (errno != EACCES && errno != EAGAIN)
+      LIBC_NAMESPACE::exit(3);
+
+    // F_TLOCK should fail because non-blocking lock cannot be acquired.
+    if (LIBC_NAMESPACE::lockf(child_fd, F_TLOCK, 0) == 0)
+      LIBC_NAMESPACE::exit(4);
+    if (errno != EACCES && errno != EAGAIN)
+      LIBC_NAMESPACE::exit(5);
+
+    LIBC_NAMESPACE::close(child_fd);
+    LIBC_NAMESPACE::exit(0);
+  }
+
+  // Parent process waits for child.
+  int status = 0;
+  pid_t cpid = LIBC_NAMESPACE::waitpid(pid, &status, 0);
+  ASSERT_EQ(cpid, pid);
+  ASSERT_TRUE(WIFEXITED(status));
+  ASSERT_EQ(WEXITSTATUS(status), 0);
+
+  return 0;
+}

diff  --git a/libc/test/src/unistd/CMakeLists.txt b/libc/test/src/unistd/CMakeLists.txt
index 785f04172d314..d99eaf5028682 100644
--- a/libc/test/src/unistd/CMakeLists.txt
+++ b/libc/test/src/unistd/CMakeLists.txt
@@ -1015,6 +1015,26 @@ add_libc_test(
     libc.test.UnitTest.ErrnoSetterMatcher
 )
 
+add_libc_test(
+  lockf_test
+  SUITE
+    libc_unistd_unittests
+  SRCS
+    lockf_test.cpp
+  DEPENDS
+    libc.hdr.fcntl_macros
+    libc.hdr.sys_stat_macros
+    libc.hdr.unistd_macros
+    libc.src.__support.CPP.scope
+    libc.src.errno.errno
+    libc.src.fcntl.open
+    libc.src.unistd.close
+    libc.src.unistd.lockf
+    libc.src.unistd.unlink
+    libc.test.UnitTest.ErrnoCheckingTest
+    libc.test.UnitTest.ErrnoSetterMatcher
+)
+
 if(LLVM_LIBC_FULL_BUILD)
   add_libc_test(
     _exit_test

diff  --git a/libc/test/src/unistd/lockf_test.cpp b/libc/test/src/unistd/lockf_test.cpp
new file mode 100644
index 0000000000000..d2b264c71c5b6
--- /dev/null
+++ b/libc/test/src/unistd/lockf_test.cpp
@@ -0,0 +1,103 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+/// Unittest for lockf.
+///
+//===----------------------------------------------------------------------===//
+
+#include "hdr/fcntl_macros.h"
+#include "hdr/sys_stat_macros.h"
+#include "hdr/unistd_macros.h"
+#include "src/__support/CPP/scope.h"
+#include "src/fcntl/open.h"
+#include "src/unistd/close.h"
+#include "src/unistd/lockf.h"
+#include "src/unistd/unlink.h"
+#include "test/UnitTest/ErrnoCheckingTest.h"
+#include "test/UnitTest/ErrnoSetterMatcher.h"
+#include "test/UnitTest/Test.h"
+
+using LlvmLibcLockfTest = LIBC_NAMESPACE::testing::ErrnoCheckingTest;
+
+TEST_F(LlvmLibcLockfTest, BadFd) {
+  using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Fails;
+  EXPECT_THAT(LIBC_NAMESPACE::lockf(-1, F_LOCK, 0), Fails(EBADF));
+  EXPECT_THAT(LIBC_NAMESPACE::lockf(-1, F_TLOCK, 0), Fails(EBADF));
+  EXPECT_THAT(LIBC_NAMESPACE::lockf(-1, F_ULOCK, 0), Fails(EBADF));
+  EXPECT_THAT(LIBC_NAMESPACE::lockf(-1, F_TEST, 0), Fails(EBADF));
+}
+
+TEST_F(LlvmLibcLockfTest, InvalidCmd) {
+  using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Fails;
+  using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds;
+  constexpr const char *TEST_FILE_NAME = "testdata/lockf_invalid_cmd.test";
+  auto TEST_FILE = libc_make_test_file_path(TEST_FILE_NAME);
+  int fd = LIBC_NAMESPACE::open(TEST_FILE, O_CREAT | O_TRUNC | O_RDWR, S_IRWXU);
+  ASSERT_ERRNO_SUCCESS();
+  ASSERT_GT(fd, 0);
+
+  LIBC_NAMESPACE::cpp::scope_exit cleanup([&] {
+    EXPECT_THAT(LIBC_NAMESPACE::close(fd), Succeeds(0));
+    EXPECT_THAT(LIBC_NAMESPACE::unlink(TEST_FILE), Succeeds(0));
+  });
+
+  EXPECT_THAT(LIBC_NAMESPACE::lockf(fd, 999, 0), Fails(EINVAL));
+}
+
+TEST_F(LlvmLibcLockfTest, LockUnlockAndTest) {
+  using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds;
+  constexpr const char *TEST_FILE_NAME = "testdata/lockf_basic.test";
+  auto TEST_FILE = libc_make_test_file_path(TEST_FILE_NAME);
+  int fd = LIBC_NAMESPACE::open(TEST_FILE, O_CREAT | O_TRUNC | O_RDWR, S_IRWXU);
+  ASSERT_ERRNO_SUCCESS();
+  ASSERT_GT(fd, 0);
+
+  LIBC_NAMESPACE::cpp::scope_exit cleanup([&] {
+    EXPECT_THAT(LIBC_NAMESPACE::close(fd), Succeeds(0));
+    EXPECT_THAT(LIBC_NAMESPACE::unlink(TEST_FILE), Succeeds(0));
+  });
+
+  // Section is not locked: F_TEST should succeed (return 0).
+  EXPECT_THAT(LIBC_NAMESPACE::lockf(fd, F_TEST, 0), Succeeds(0));
+
+  // Lock the entire file: F_LOCK should succeed.
+  EXPECT_THAT(LIBC_NAMESPACE::lockf(fd, F_LOCK, 0), Succeeds(0));
+
+  // When locked by calling process, F_TEST still succeeds (POSIX requirement).
+  EXPECT_THAT(LIBC_NAMESPACE::lockf(fd, F_TEST, 0), Succeeds(0));
+
+  // Unlock the entire file: F_ULOCK should succeed.
+  EXPECT_THAT(LIBC_NAMESPACE::lockf(fd, F_ULOCK, 0), Succeeds(0));
+
+  // Non-blocking lock: F_TLOCK should succeed.
+  EXPECT_THAT(LIBC_NAMESPACE::lockf(fd, F_TLOCK, 100), Succeeds(0));
+
+  // Unlock the section: F_ULOCK should succeed.
+  EXPECT_THAT(LIBC_NAMESPACE::lockf(fd, F_ULOCK, 100), Succeeds(0));
+}
+
+TEST_F(LlvmLibcLockfTest, ReadOnlyFd) {
+  using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Fails;
+  using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds;
+  constexpr const char *TEST_FILE_NAME = "testdata/lockf_rdonly.test";
+  auto TEST_FILE = libc_make_test_file_path(TEST_FILE_NAME);
+
+  int fd = LIBC_NAMESPACE::open(TEST_FILE, O_CREAT | O_RDONLY, S_IRWXU);
+  ASSERT_ERRNO_SUCCESS();
+  ASSERT_GT(fd, 0);
+
+  LIBC_NAMESPACE::cpp::scope_exit cleanup([&] {
+    EXPECT_THAT(LIBC_NAMESPACE::close(fd), Succeeds(0));
+    EXPECT_THAT(LIBC_NAMESPACE::unlink(TEST_FILE), Succeeds(0));
+  });
+
+  // F_LOCK on a read-only fd should fail with EBADF.
+  EXPECT_THAT(LIBC_NAMESPACE::lockf(fd, F_LOCK, 0), Fails(EBADF));
+  EXPECT_THAT(LIBC_NAMESPACE::lockf(fd, F_TLOCK, 0), Fails(EBADF));
+}


        


More information about the libc-commits mailing list