[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