1 /*
2 * Copyright (C) 2024 HiHope Open Source Organization.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <cerrno>
17 #include <cstdlib>
18 #include <cstdio>
19 #include <string>
20 #include <fcntl.h>
21 #include <unistd.h>
22 #include <gtest/gtest.h>
23 #include <sys/stat.h>
24 #include <sys/types.h>
25
26 using namespace testing::ext;
27 using namespace std;
28
29 class OpenatApiTest : public testing::Test {
30 public:
31 static void SetUpTestCase();
32 static void TearDownTestCase();
33 void SetUp();
34 void TearDown();
35
36 private:
37 };
38
39 static const char *TEST_DIR = "/data/local/tmp/tmp";
40 static const char *TEST_FILE = "/data/local/tmp/tmp/test";
41
SetUpTestCase()42 void OpenatApiTest::SetUpTestCase()
43 {
44 }
45
TearDownTestCase()46 void OpenatApiTest::TearDownTestCase()
47 {
48 }
49
SetUp()50 void OpenatApiTest::SetUp()
51 {
52 mkdir(TEST_DIR, S_IRWXU | S_IRWXG | S_IRWXO);
53 }
54
TearDown()55 void OpenatApiTest::TearDown()
56 {
57 rmdir(TEST_DIR);
58 }
59
60 /*
61 * @tc.number : SUB_KERNEL_SYSCALL_OPENAT_0100
62 * @tc.name : OpenatReadOnlySuccess_0001
63 * @tc.desc : openat with O_RDONLY should open a file for reading only.
64 * @tc.size : MediumTest
65 * @tc.type : Function
66 * @tc.level : Level 1
67 */
HWTEST_F(OpenatApiTest, OpenatReadOnlySuccess_0001, Function | MediumTest | Level1)68 HWTEST_F(OpenatApiTest, OpenatReadOnlySuccess_0001, Function | MediumTest | Level1)
69 {
70 int dirFd = open(TEST_DIR, O_RDONLY | O_DIRECTORY);
71
72 int fd = openat(dirFd, TEST_FILE, O_WRONLY | O_CREAT, 0644);
73 EXPECT_TRUE(fd >= 0);
74 close(fd);
75
76 fd = openat(dirFd, TEST_FILE, O_RDONLY);
77 EXPECT_TRUE(fd >= 0);
78
79 errno = 0;
80 ssize_t bytesWritten = write(fd, "A", 1);
81 EXPECT_EQ(bytesWritten, -1);
82 EXPECT_EQ(errno, EBADF);
83 close(fd);
84 unlinkat(dirFd, TEST_FILE, 0);
85 close(dirFd);
86 }
87
88 /*
89 * @tc.number : SUB_KERNEL_SYSCALL_OPENAT_0200
90 * @tc.name : OpenatReadWriteSuccess_0002
91 * @tc.desc : openat with O_RDWR should open a file for reading and writing.
92 * @tc.size : MediumTest
93 * @tc.type : Function
94 * @tc.level : Level 1
95 */
HWTEST_F(OpenatApiTest, OpenatReadWriteSuccess_0002, Function | MediumTest | Level1)96 HWTEST_F(OpenatApiTest, OpenatReadWriteSuccess_0002, Function | MediumTest | Level1)
97 {
98 const char *data = "Hello, World!";
99 char readBuf[128];
100 int dirFd = -1;
101 int fd = -1;
102 dirFd = open(TEST_DIR, O_RDONLY | O_DIRECTORY);
103 EXPECT_TRUE(dirFd >= 0);
104
105 fd = openat(dirFd, TEST_FILE, O_RDWR | O_CREAT, 0644);
106 EXPECT_TRUE(fd >= 0);
107 write(fd, data, strlen(data));
108 lseek(fd, 0, SEEK_SET);
109 read(fd, readBuf, sizeof(readBuf));
110 EXPECT_STREQ(readBuf, data);
111 close(fd);
112 unlinkat(dirFd, TEST_FILE, 0);
113 close(dirFd);
114 }
115
116 /*
117 * @tc.number : SUB_KERNEL_SYSCALL_OPENAT_0300
118 * @tc.name : OpenatAppendSuccess_0003
119 * @tc.desc : openat with O_APPEND should append to the end of the file.
120 * @tc.size : MediumTest
121 * @tc.type : Function
122 * @tc.level : Level 1
123 */
HWTEST_F(OpenatApiTest, OpenatAppendSuccess_0003, Function | MediumTest | Level1)124 HWTEST_F(OpenatApiTest, OpenatAppendSuccess_0003, Function | MediumTest | Level1)
125 {
126 char readBuf[256] = {0};
127 const char *data = "Hello, World!";
128 const char *appendData = " More data";
129 int dirFd = -1;
130 int fd = -1;
131
132 dirFd = open(TEST_DIR, O_RDONLY | O_DIRECTORY);
133
134 fd = openat(dirFd, TEST_FILE, O_WRONLY | O_CREAT, 0644);
135 EXPECT_TRUE(fd >= 0);
136 ssize_t bytesWritten = write(fd, data, strlen(data));
137 EXPECT_EQ(bytesWritten, strlen(data));
138
139 close(fd);
140
141 fd = openat(dirFd, TEST_FILE, O_WRONLY | O_APPEND);
142 EXPECT_TRUE(fd >= 0);
143 bytesWritten = write(fd, appendData, strlen(appendData));
144 EXPECT_EQ(bytesWritten, strlen(appendData));
145
146 close(fd);
147
148 fd = openat(dirFd, TEST_FILE, O_RDONLY);
149 EXPECT_TRUE(fd >= 0);
150 ssize_t bytesRead = read(fd, readBuf, sizeof(readBuf) - 1);
151 EXPECT_TRUE(bytesRead > 0);
152
153 readBuf[bytesRead] = '\0';
154 std::string expectedContent(data);
155 expectedContent += appendData;
156 EXPECT_STREQ(readBuf, expectedContent.c_str());
157
158 close(fd);
159 unlinkat(dirFd, TEST_FILE, 0);
160 close(dirFd);
161 }
162
163 /*
164 * @tc.number : SUB_KERNEL_SYSCALL_OPENAT_0400
165 * @tc.name : OpenatNoFollowFailed_0004
166 * @tc.desc : openat with O_NOFOLLOW should fail if the path is a symbolic link.
167 * @tc.size : MediumTest
168 * @tc.type : Function
169 * @tc.level : Level 2
170 */
HWTEST_F(OpenatApiTest, OpenatNoFollowFailed_0004, Function | MediumTest | Level2)171 HWTEST_F(OpenatApiTest, OpenatNoFollowFailed_0004, Function | MediumTest | Level2)
172 {
173 int dirFd = -1;
174 int fd = -1;
175 dirFd = open(TEST_DIR, O_RDONLY | O_DIRECTORY);
176
177 errno = 0;
178 symlink("target", TEST_FILE);
179 fd = openat(dirFd, TEST_FILE, O_WRONLY | O_CREAT | O_NOFOLLOW);
180 EXPECT_EQ(fd, -1);
181 EXPECT_EQ(errno, ELOOP);
182 close(dirFd);
183 }
184
185 /*
186 * @tc.number : SUB_KERNEL_SYSCALL_OPENAT_0500
187 * @tc.name : OpenatWriteOnlySuccess_0005
188 * @tc.desc : openat with O_WRONLY should open a file for writing only.
189 * @tc.size : MediumTest
190 * @tc.type : Function
191 * @tc.level : Level 1
192 */
HWTEST_F(OpenatApiTest, OpenatWriteOnlySuccess_0005, Function | MediumTest | Level1)193 HWTEST_F(OpenatApiTest, OpenatWriteOnlySuccess_0005, Function | MediumTest | Level1)
194 {
195 int dirFd;
196 int fd;
197 char buf;
198 ssize_t bytesRead;
199 ssize_t bytesWritten;
200 const char *data;
201
202
203 dirFd = open(TEST_DIR, O_RDONLY | O_DIRECTORY);
204 fd = openat(dirFd, TEST_FILE, O_WRONLY | O_CREAT, 0644);
205 EXPECT_TRUE(fd >= 0);
206
207 bytesRead = read(fd, &buf, 1);
208 EXPECT_EQ(bytesRead, -1);
209 EXPECT_EQ(errno, EBADF);
210
211 data = "Test data";
212 bytesWritten = write(fd, data, strlen(data));
213 EXPECT_TRUE(bytesWritten == strlen(data));
214
215 close(fd);
216 unlinkat(dirFd, TEST_FILE, 0);
217 close(dirFd);
218 }
219
220 /*
221 * @tc.number : SUB_KERNEL_SYSCALL_OPENAT_0600
222 * @tc.name : OpenatCreateTest_0006
223 * @tc.desc : openat with O_CREAT.
224 * @tc.size : MediumTest
225 * @tc.type : Function
226 * @tc.level : Level 2
227 */
HWTEST_F(OpenatApiTest, OpenatCreateTest_0006, Function | MediumTest | Level2)228 HWTEST_F(OpenatApiTest, OpenatCreateTest_0006, Function | MediumTest | Level2)
229 {
230 int dirFd = -1;
231 int fd = -1;
232 struct stat buf;
233 dirFd = open(TEST_DIR, O_RDONLY | O_DIRECTORY);
234
235 fd = openat(dirFd, TEST_FILE, O_WRONLY, 0644);
236 EXPECT_TRUE(fd == -1);
237 stat(TEST_FILE, &buf);
238 EXPECT_EQ(errno, ENOENT);
239 fd = openat(dirFd, TEST_FILE, O_WRONLY | O_CREAT, 0644);
240 EXPECT_TRUE(fd >= 0);
241 EXPECT_TRUE(stat(TEST_FILE, &buf) == 0);
242
243 close(fd);
244 unlinkat(dirFd, TEST_FILE, 0);
245 close(dirFd);
246 }
247
248 /*
249 * @tc.number : SUB_KERNEL_SYSCALL_OPENAT_0700
250 * @tc.name : OpenatDirectoryTest_0007
251 * @tc.desc : openat with O_DIRECTORY.
252 * @tc.size : MediumTest
253 * @tc.type : Function
254 * @tc.level : Level 2
255 */
HWTEST_F(OpenatApiTest, OpenatDirectoryTest_0007, Function | MediumTest | Level2)256 HWTEST_F(OpenatApiTest, OpenatDirectoryTest_0007, Function | MediumTest | Level2)
257 {
258 int dirFd = -1;
259 int fd = -1;
260 struct stat buf;
261 dirFd = open(TEST_DIR, O_RDONLY | O_DIRECTORY);
262
263 fd = open(TEST_FILE, O_WRONLY | O_CREAT, 0644);
264 close(fd);
265 fd = openat(dirFd, TEST_FILE, O_WRONLY | O_DIRECTORY, 0644);
266 EXPECT_TRUE(fd == -1);
267 stat(TEST_FILE, &buf);
268 EXPECT_TRUE(S_ISREG(buf.st_mode));
269 unlinkat(dirFd, TEST_FILE, 0);
270
271 mkdir(TEST_FILE, 0644);
272 fd = openat(dirFd, TEST_FILE, O_DIRECTORY, 0644);
273 EXPECT_TRUE(fd >= 0);
274 stat(TEST_FILE, &buf);
275 EXPECT_TRUE(S_ISDIR(buf.st_mode));
276
277 close(fd);
278 rmdir(TEST_FILE);
279 close(dirFd);
280 }
281
282 /*
283 * @tc.number : SUB_KERNEL_SYSCALL_OPENAT_0800
284 * @tc.name : OpenatExclTest_0008
285 * @tc.desc : openat with O_EXCL to prevent overwriting the content of existing files.
286 * @tc.size : MediumTest
287 * @tc.type : Function
288 * @tc.level : Level 2
289 */
HWTEST_F(OpenatApiTest, OpenatExclTest_0008, Function | MediumTest | Level2)290 HWTEST_F(OpenatApiTest, OpenatExclTest_0008, Function | MediumTest | Level2)
291 {
292 int dirFd = -1;
293 int fd = -1;
294 dirFd = open(TEST_DIR, O_RDONLY | O_DIRECTORY);
295
296 EXPECT_TRUE(access(TEST_FILE, F_OK) == -1);
297 fd = openat(dirFd, TEST_FILE, O_WRONLY | O_CREAT | O_EXCL, 0644);
298 EXPECT_TRUE(fd >= 0);
299 close(fd);
300 EXPECT_TRUE(access(TEST_FILE, F_OK) == 0);
301
302 fd = openat(dirFd, TEST_FILE, O_WRONLY | O_CREAT | O_EXCL, 0644);
303 EXPECT_TRUE(fd == -1);
304 EXPECT_TRUE(access(TEST_FILE, F_OK) == 0);
305
306 unlinkat(dirFd, TEST_FILE, 0);
307 close(dirFd);
308 }
309
310 /*
311 * @tc.number : SUB_KERNEL_SYSCALL_OPENAT_0900
312 * @tc.name : OpenatNoatimeSuccess_0009
313 * @tc.desc : openat with O_NOATIME to prevent changing atime but still changing mtime.
314 * @tc.size : MediumTest
315 * @tc.type : Function
316 * @tc.level : Level 1
317 */
HWTEST_F(OpenatApiTest, OpenatNoatimeSuccess_0009, Function | MediumTest | Level1)318 HWTEST_F(OpenatApiTest, OpenatNoatimeSuccess_0009, Function | MediumTest | Level1)
319 {
320 int dirFd = -1;
321 int fd = -1;
322 struct stat bufFirst;
323 struct stat bufSecond;
324 dirFd = open(TEST_DIR, O_RDONLY | O_DIRECTORY);
325
326 fd = openat(dirFd, TEST_FILE, O_WRONLY | O_CREAT, 0644);
327 EXPECT_TRUE(fd >= 0);
328 close(fd);
329 stat(TEST_FILE, &bufFirst);
330
331 usleep(100);
332 fd = openat(dirFd, TEST_FILE, O_WRONLY | O_NOATIME, 0644);
333 EXPECT_TRUE(fd >= 0);
334 close(fd);
335 stat(TEST_FILE, &bufSecond);
336 EXPECT_TRUE(bufFirst.st_atime == bufSecond.st_atime);
337
338 unlinkat(dirFd, TEST_FILE, 0);
339 close(dirFd);
340 }
341
342 /*
343 * @tc.number : SUB_KERNEL_SYSCALL_OPENAT_1000
344 * @tc.name : OpenatFlagsTestSuccess_0010
345 * @tc.desc : openat with some flags.
346 * @tc.size : MediumTest
347 * @tc.type : Function
348 * @tc.level : Level 1
349 */
HWTEST_F(OpenatApiTest, OpenatFlagsTestSuccess_0010, Function | MediumTest | Level1)350 HWTEST_F(OpenatApiTest, OpenatFlagsTestSuccess_0010, Function | MediumTest | Level1)
351 {
352 int dirFd = open(TEST_DIR, O_RDONLY | O_DIRECTORY);
353
354 // O_TRUNC test
355 int fd = openat(dirFd, TEST_FILE, O_RDWR | O_CREAT, 0644);
356 const char *data = "Test data";
357 write(fd, data, strlen(data));
358 close(fd);
359 fd = openat(dirFd, TEST_FILE, O_RDWR | O_TRUNC, 0644);
360 EXPECT_TRUE(fd >= 0);
361 close(fd);
362 unlinkat(dirFd, TEST_FILE, 0);
363
364 // O_ASYNC test
365 fd = openat(dirFd, TEST_FILE, O_RDWR | O_CREAT | O_ASYNC, 0644);
366 EXPECT_TRUE(fd >= 0);
367 close(fd);
368 unlinkat(dirFd, TEST_FILE, 0);
369
370 // O_DIRECT test
371 fd = openat(dirFd, TEST_FILE, O_RDWR | O_CREAT | O_DIRECT, 0644);
372 EXPECT_TRUE(fd >= 0);
373 close(fd);
374 unlinkat(dirFd, TEST_FILE, 0);
375
376 // O_DSYNC test
377 fd = openat(dirFd, TEST_FILE, O_RDWR | O_CREAT | O_DSYNC, 0644);
378 EXPECT_TRUE(fd >= 0);
379 close(fd);
380 unlinkat(dirFd, TEST_FILE, 0);
381
382 // O_SYNC test
383 fd = openat(dirFd, TEST_FILE, O_RDWR | O_CREAT | O_SYNC, 0644);
384 EXPECT_TRUE(fd >= 0);
385 close(fd);
386 unlinkat(dirFd, TEST_FILE, 0);
387
388 close(dirFd);
389 }
390
391 /*
392 * @tc.number : SUB_KERNEL_SYSCALL_OPENAT_1100
393 * @tc.name : OpenatFlagsTestSuccess_0011
394 * @tc.desc : openat O_CLOEXEC/O_LARGEFILE/O_NOCTTY/O_NONBLOCK flags test success.
395 * @tc.size : MediumTest
396 * @tc.type : Function
397 * @tc.level : Level 1
398 */
HWTEST_F(OpenatApiTest, OpenatO_CLOEXECFlagSuccess_0011, Function | MediumTest | Level1)399 HWTEST_F(OpenatApiTest, OpenatO_CLOEXECFlagSuccess_0011, Function | MediumTest | Level1)
400 {
401 int dirFd = open(TEST_DIR, O_RDONLY | O_DIRECTORY);
402
403 int fd = openat(dirFd, TEST_FILE, O_RDWR | O_CLOEXEC | O_CREAT, 0755);
404 EXPECT_TRUE(fd >= 0);
405 close(fd);
406 unlinkat(dirFd, TEST_FILE, 0);
407
408 fd = openat(dirFd, TEST_FILE, O_RDWR | O_LARGEFILE | O_CREAT, 0755);
409 EXPECT_TRUE(fd >= 0);
410 close(fd);
411 unlinkat(dirFd, TEST_FILE, 0);
412
413 fd = openat(dirFd, TEST_FILE, O_RDWR | O_NOCTTY | O_CREAT, 0755);
414 EXPECT_TRUE(fd >= 0);
415 close(fd);
416 unlinkat(dirFd, TEST_FILE, 0);
417
418 fd = openat(dirFd, TEST_FILE, O_RDWR | O_NONBLOCK | O_CREAT, 0755);
419 EXPECT_TRUE(fd >= 0);
420 close(fd);
421 unlinkat(dirFd, TEST_FILE, 0);
422
423 close(dirFd);
424 }