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/__support/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_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 | |