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