xref: /aosp_15_r20/external/llvm-libc/test/src/fcntl/fcntl_test.cpp (revision 71db0c75aadcf003ffe3238005f61d7618a3fead)
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