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 }