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
TEST(LlvmLibcFcntlTest,FcntlDupfd)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
TEST(LlvmLibcFcntlTest,FcntlGetFl)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
TEST(LlvmLibcFcntlTest,FcntlSetFl)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
TEST(LlvmLibcFcntlTest,FcntlGetLkRead)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
TEST(LlvmLibcFcntlTest,FcntlGetLkWrite)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
TEST(LlvmLibcFcntlTest,UseAfterClose)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
TEST(LlvmLibcFcntlTest,SetGetOwnerTest)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