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