1aca51173SVinayak Dev //===-- Unittest for fcntl ------------------------------------------------===// 2aca51173SVinayak Dev // 3aca51173SVinayak Dev // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4aca51173SVinayak Dev // See https://llvm.org/LICENSE.txt for license information. 5aca51173SVinayak Dev // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6aca51173SVinayak Dev // 7aca51173SVinayak Dev //===----------------------------------------------------------------------===// 8aca51173SVinayak Dev 9aca51173SVinayak Dev #include "hdr/fcntl_macros.h" 10*c63112a9Slntue #include "hdr/stdio_macros.h" 11aca51173SVinayak Dev #include "hdr/types/struct_flock.h" 12aca51173SVinayak Dev #include "src/errno/libc_errno.h" 13aca51173SVinayak Dev #include "src/fcntl/fcntl.h" 14aca51173SVinayak Dev #include "src/fcntl/open.h" 15aca51173SVinayak Dev #include "src/unistd/close.h" 167c4fc9ccSXu Zhang #include "src/unistd/getpid.h" 17aca51173SVinayak Dev #include "test/UnitTest/ErrnoSetterMatcher.h" 18aca51173SVinayak Dev #include "test/UnitTest/Test.h" 19aca51173SVinayak Dev 20aca51173SVinayak Dev #include <sys/stat.h> // For S_IRWXU 21aca51173SVinayak Dev 22aca51173SVinayak Dev TEST(LlvmLibcFcntlTest, FcntlDupfd) { 23aca51173SVinayak Dev using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds; 24aca51173SVinayak Dev constexpr const char *TEST_FILE_NAME = "testdata/fcntl_dup.test"; 25aca51173SVinayak Dev auto TEST_FILE = libc_make_test_file_path(TEST_FILE_NAME); 26aca51173SVinayak Dev int fd2, fd3; 27aca51173SVinayak Dev int fd = LIBC_NAMESPACE::open(TEST_FILE, O_CREAT | O_TRUNC, S_IRWXU); 28aca51173SVinayak Dev ASSERT_ERRNO_SUCCESS(); 29aca51173SVinayak Dev ASSERT_GT(fd, 0); 30aca51173SVinayak Dev 31aca51173SVinayak Dev fd2 = LIBC_NAMESPACE::fcntl(fd, F_DUPFD, 0); 32aca51173SVinayak Dev ASSERT_ERRNO_SUCCESS(); 33aca51173SVinayak Dev ASSERT_GT(fd2, 0); 34aca51173SVinayak Dev 35aca51173SVinayak Dev fd3 = LIBC_NAMESPACE::fcntl(fd, F_DUPFD, 10); 36aca51173SVinayak Dev ASSERT_ERRNO_SUCCESS(); 37aca51173SVinayak Dev ASSERT_GT(fd3, 0); 38aca51173SVinayak Dev 39aca51173SVinayak Dev ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds(0)); 40aca51173SVinayak Dev ASSERT_THAT(LIBC_NAMESPACE::close(fd2), Succeeds(0)); 41aca51173SVinayak Dev ASSERT_THAT(LIBC_NAMESPACE::close(fd3), Succeeds(0)); 42aca51173SVinayak Dev } 43aca51173SVinayak Dev 44aca51173SVinayak Dev TEST(LlvmLibcFcntlTest, FcntlGetFl) { 45aca51173SVinayak Dev using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds; 46aca51173SVinayak Dev constexpr const char *TEST_FILE_NAME = "testdata/fcntl_getfl.test"; 47aca51173SVinayak Dev auto TEST_FILE = libc_make_test_file_path(TEST_FILE_NAME); 48aca51173SVinayak Dev int retVal; 49aca51173SVinayak Dev int fd = LIBC_NAMESPACE::open(TEST_FILE, O_CREAT | O_TRUNC, S_IRWXU); 50aca51173SVinayak Dev ASSERT_ERRNO_SUCCESS(); 51aca51173SVinayak Dev ASSERT_GT(fd, 0); 52aca51173SVinayak Dev 53aca51173SVinayak Dev retVal = LIBC_NAMESPACE::fcntl(fd, F_GETFL); 54aca51173SVinayak Dev ASSERT_ERRNO_SUCCESS(); 55aca51173SVinayak Dev ASSERT_GT(retVal, -1); 56aca51173SVinayak Dev 57aca51173SVinayak Dev ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds(0)); 58aca51173SVinayak Dev } 59aca51173SVinayak Dev 60aca51173SVinayak Dev TEST(LlvmLibcFcntlTest, FcntlSetFl) { 61aca51173SVinayak Dev using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds; 62aca51173SVinayak Dev constexpr const char *TEST_FILE_NAME = "testdata/fcntl_setfl.test"; 63aca51173SVinayak Dev auto TEST_FILE = libc_make_test_file_path(TEST_FILE_NAME); 64aca51173SVinayak Dev 65aca51173SVinayak Dev int retVal; 66aca51173SVinayak Dev int fd = LIBC_NAMESPACE::open(TEST_FILE, O_CREAT | O_TRUNC | O_RDWR, S_IRWXU); 67aca51173SVinayak Dev ASSERT_ERRNO_SUCCESS(); 68aca51173SVinayak Dev ASSERT_GT(fd, 0); 69aca51173SVinayak Dev 70aca51173SVinayak Dev retVal = LIBC_NAMESPACE::fcntl(fd, F_GETFL); 71aca51173SVinayak Dev ASSERT_ERRNO_SUCCESS(); 72aca51173SVinayak Dev ASSERT_GT(retVal, -1); 73aca51173SVinayak Dev 74aca51173SVinayak Dev int oldFlags = LIBC_NAMESPACE::fcntl(fd, F_GETFL, 0); 75aca51173SVinayak Dev ASSERT_ERRNO_SUCCESS(); 76aca51173SVinayak Dev ASSERT_GT(oldFlags, 0); 77aca51173SVinayak Dev 78aca51173SVinayak Dev // Add the APPEND flag; 79aca51173SVinayak Dev oldFlags |= O_APPEND; 80aca51173SVinayak Dev 81aca51173SVinayak Dev retVal = LIBC_NAMESPACE::fcntl(fd, F_SETFL, oldFlags); 82aca51173SVinayak Dev ASSERT_ERRNO_SUCCESS(); 83aca51173SVinayak Dev ASSERT_GT(retVal, -1); 84aca51173SVinayak Dev 85aca51173SVinayak Dev // Remove the APPEND flag; 86aca51173SVinayak Dev oldFlags = -oldFlags & O_APPEND; 87aca51173SVinayak Dev 88aca51173SVinayak Dev retVal = LIBC_NAMESPACE::fcntl(fd, F_SETFL, oldFlags); 89aca51173SVinayak Dev ASSERT_ERRNO_SUCCESS(); 90aca51173SVinayak Dev ASSERT_GT(retVal, -1); 91aca51173SVinayak Dev 92aca51173SVinayak Dev ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds(0)); 93aca51173SVinayak Dev } 94aca51173SVinayak Dev 95aca51173SVinayak Dev TEST(LlvmLibcFcntlTest, FcntlGetLkRead) { 96aca51173SVinayak Dev using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds; 97aca51173SVinayak Dev constexpr const char *TEST_FILE_NAME = "testdata/fcntl_getlkread.test"; 98aca51173SVinayak Dev auto TEST_FILE = libc_make_test_file_path(TEST_FILE_NAME); 99aca51173SVinayak Dev 100aca51173SVinayak Dev struct flock flk, svflk; 101aca51173SVinayak Dev int retVal; 102aca51173SVinayak Dev int fd = 103aca51173SVinayak Dev LIBC_NAMESPACE::open(TEST_FILE, O_CREAT | O_TRUNC | O_RDONLY, S_IRWXU); 104aca51173SVinayak Dev ASSERT_ERRNO_SUCCESS(); 105aca51173SVinayak Dev ASSERT_GT(fd, 0); 106aca51173SVinayak Dev 107aca51173SVinayak Dev flk.l_type = F_RDLCK; 108aca51173SVinayak Dev flk.l_start = 0; 109aca51173SVinayak Dev flk.l_whence = SEEK_SET; 110aca51173SVinayak Dev flk.l_len = 50; 111aca51173SVinayak Dev 112aca51173SVinayak Dev // copy flk into svflk 113aca51173SVinayak Dev svflk = flk; 114aca51173SVinayak Dev 115aca51173SVinayak Dev retVal = LIBC_NAMESPACE::fcntl(fd, F_GETLK, &svflk); 116aca51173SVinayak Dev ASSERT_ERRNO_SUCCESS(); 117aca51173SVinayak Dev ASSERT_GT(retVal, -1); 118aca51173SVinayak Dev ASSERT_NE((int)flk.l_type, F_WRLCK); // File should not be write locked. 119aca51173SVinayak Dev 120aca51173SVinayak Dev retVal = LIBC_NAMESPACE::fcntl(fd, F_SETLK, &svflk); 121aca51173SVinayak Dev ASSERT_ERRNO_SUCCESS(); 122aca51173SVinayak Dev ASSERT_GT(retVal, -1); 123aca51173SVinayak Dev 124aca51173SVinayak Dev ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds(0)); 125aca51173SVinayak Dev } 126aca51173SVinayak Dev 127aca51173SVinayak Dev TEST(LlvmLibcFcntlTest, FcntlGetLkWrite) { 128aca51173SVinayak Dev using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds; 129aca51173SVinayak Dev constexpr const char *TEST_FILE_NAME = "testdata/fcntl_getlkwrite.test"; 130aca51173SVinayak Dev auto TEST_FILE = libc_make_test_file_path(TEST_FILE_NAME); 131aca51173SVinayak Dev 132aca51173SVinayak Dev struct flock flk, svflk; 133aca51173SVinayak Dev int retVal; 134aca51173SVinayak Dev int fd = LIBC_NAMESPACE::open(TEST_FILE, O_CREAT | O_TRUNC | O_RDWR, S_IRWXU); 135aca51173SVinayak Dev ASSERT_ERRNO_SUCCESS(); 136aca51173SVinayak Dev ASSERT_GT(fd, 0); 137aca51173SVinayak Dev 138aca51173SVinayak Dev flk.l_type = F_WRLCK; 139aca51173SVinayak Dev flk.l_start = 0; 140aca51173SVinayak Dev flk.l_whence = SEEK_SET; 141aca51173SVinayak Dev flk.l_len = 0; 142aca51173SVinayak Dev 143aca51173SVinayak Dev // copy flk into svflk 144aca51173SVinayak Dev svflk = flk; 145aca51173SVinayak Dev 146aca51173SVinayak Dev retVal = LIBC_NAMESPACE::fcntl(fd, F_GETLK, &svflk); 147aca51173SVinayak Dev ASSERT_ERRNO_SUCCESS(); 148aca51173SVinayak Dev ASSERT_GT(retVal, -1); 149aca51173SVinayak Dev ASSERT_NE((int)flk.l_type, F_RDLCK); // File should not be read locked. 150aca51173SVinayak Dev 151aca51173SVinayak Dev retVal = LIBC_NAMESPACE::fcntl(fd, F_SETLK, &svflk); 152aca51173SVinayak Dev ASSERT_ERRNO_SUCCESS(); 153aca51173SVinayak Dev ASSERT_GT(retVal, -1); 154aca51173SVinayak Dev 155aca51173SVinayak Dev ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds(0)); 156aca51173SVinayak Dev } 1570b24b470SXu Zhang 1580b24b470SXu Zhang TEST(LlvmLibcFcntlTest, UseAfterClose) { 1590b24b470SXu Zhang using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds; 1600b24b470SXu Zhang constexpr const char *TEST_FILE_NAME = "testdata/fcntl_use_after_close.test"; 1610b24b470SXu Zhang auto TEST_FILE = libc_make_test_file_path(TEST_FILE_NAME); 1620b24b470SXu Zhang int fd = LIBC_NAMESPACE::open(TEST_FILE, O_CREAT | O_TRUNC | O_RDWR, S_IRWXU); 1630b24b470SXu Zhang ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds(0)); 1640b24b470SXu Zhang ASSERT_EQ(-1, LIBC_NAMESPACE::fcntl(fd, F_GETFL)); 1650b24b470SXu Zhang ASSERT_ERRNO_EQ(EBADF); 1660b24b470SXu Zhang } 1677c4fc9ccSXu Zhang 1687c4fc9ccSXu Zhang TEST(LlvmLibcFcntlTest, SetGetOwnerTest) { 1697c4fc9ccSXu Zhang LIBC_NAMESPACE::libc_errno = 0; 1707c4fc9ccSXu Zhang using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds; 1717c4fc9ccSXu Zhang pid_t pid = LIBC_NAMESPACE::getpid(); 1727c4fc9ccSXu Zhang ASSERT_GT(pid, -1); 1737c4fc9ccSXu Zhang constexpr const char *TEST_FILE_NAME = "testdata/fcntl_set_get_owner.test"; 1747c4fc9ccSXu Zhang auto TEST_FILE = libc_make_test_file_path(TEST_FILE_NAME); 1757c4fc9ccSXu Zhang int fd = LIBC_NAMESPACE::open(TEST_FILE, O_CREAT | O_TRUNC | O_RDWR, S_IRWXU); 1767c4fc9ccSXu Zhang ASSERT_ERRNO_SUCCESS(); 1777c4fc9ccSXu Zhang ASSERT_GT(fd, 0); 1787c4fc9ccSXu Zhang int ret = LIBC_NAMESPACE::fcntl(fd, F_SETOWN, pid); 1797c4fc9ccSXu Zhang ASSERT_ERRNO_SUCCESS(); 1807c4fc9ccSXu Zhang ASSERT_GT(ret, -1); 1817c4fc9ccSXu Zhang int ret2 = LIBC_NAMESPACE::fcntl(fd, F_GETOWN); 1827c4fc9ccSXu Zhang ASSERT_ERRNO_SUCCESS(); 1837c4fc9ccSXu Zhang ASSERT_EQ(ret2, pid); 1847c4fc9ccSXu Zhang ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds(0)); 1857c4fc9ccSXu Zhang } 186