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 <cstdio>
18#include <cstdlib>
19#include <string>
20#include <vector>
21#include <fcntl.h>
22#include <unistd.h>
23#include <gtest/gtest.h>
24#include <sys/file.h>
25#include <sys/stat.h>
26#include <sys/types.h>
27#include "securec.h"
28
29using namespace testing::ext;
30using namespace std;
31
32static const int PATH_MAX_LEN = 128;
33static const char *TEST_FILE = "/data/local/tmp/fchownat.txt";
34static const char *TEST_FILE_PATH = "/data/local/tmp";
35static const char *TEST_FILE_NAME = "fchownat.txt";
36static const char *SYMBOL_LINK_NAME = "TestFchmodatSymlink";
37mode_t MODE_0644 = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
38mode_t MODE_0755 = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
39
40class FchownatApiTest : public testing::Test {
41public:
42    static void SetUpTestCase();
43    static void TearDownTestCase();
44    void SetUp();
45    void TearDown();
46private:
47};
48void FchownatApiTest::SetUp()
49{
50}
51void FchownatApiTest::TearDown()
52{
53}
54void FchownatApiTest::SetUpTestCase()
55{
56}
57void FchownatApiTest::TearDownTestCase()
58{
59}
60
61/*
62 * @tc.number : SUB_KERNEL_SYSCALL_FCHOWNAT_0100
63 * @tc.name   : FchownatFileSuccess_0001
64 * @tc.desc   : fchownat change specify path file owner id and group id success.
65 * @tc.size   : MediumTest
66 * @tc.type   : Function
67 * @tc.level  : Level 1
68 */
69HWTEST_F(FchownatApiTest, FchownatFileSuccess_0001, Function | MediumTest | Level1)
70{
71    int ret = -1;
72    struct stat stat1;
73    struct stat stat2;
74
75    int dirfd = open(TEST_FILE_PATH, O_RDONLY | O_DIRECTORY);
76    EXPECT_TRUE(dirfd > 0);
77
78    int fd = open(TEST_FILE, O_RDWR | O_CREAT, MODE_0755);
79    EXPECT_TRUE(fd > 0);
80    ret = fstat(fd, &stat1);
81    EXPECT_EQ(ret, 0);
82    uid_t uid = stat1.st_uid + 1;
83    gid_t gid = stat1.st_gid + 1;
84
85    ret = fchownat(dirfd, TEST_FILE_NAME, uid, gid, 0);
86    EXPECT_EQ(ret, 0);
87    ret = fstat(fd, &stat2);
88    EXPECT_EQ(stat2.st_uid, uid);
89    EXPECT_EQ(stat2.st_gid, gid);
90
91    close(dirfd);
92    close(fd);
93    remove(TEST_FILE);
94}
95
96/*
97 * @tc.number : SUB_KERNEL_SYSCALL_FCHOWNAT_0200
98 * @tc.name   : FchownatAT_FDCWDTestSuccess_0002
99 * @tc.desc   : fchownat change current path file owner id and group id by AT_FDCWD success.
100 * @tc.size   : MediumTest
101 * @tc.type   : Function
102 * @tc.level  : Level 1
103 */
104HWTEST_F(FchownatApiTest, FchownatAT_FDCWDTestSuccess_0002, Function | MediumTest | Level1)
105{
106    int ret = -1;
107    char path[PATH_MAX_LEN];
108    struct stat stat1;
109    struct stat stat2;
110    int fd = 0;
111
112    char *dir = getcwd(path, sizeof(path));
113    EXPECT_NE(dir, nullptr);
114    ret = chdir(TEST_FILE_PATH);
115    EXPECT_EQ(ret, 0);
116    if (access(TEST_FILE_NAME, F_OK) == -1) {
117        fd = open(TEST_FILE_NAME, O_RDWR | O_CREAT, MODE_0644);
118    }
119
120    ret = fstat(fd, &stat1);
121    EXPECT_EQ(ret, 0);
122    uid_t uid = stat1.st_uid + 1;
123    gid_t gid = stat1.st_gid + 1;
124
125    ret = fchownat(AT_FDCWD, TEST_FILE_NAME, uid, gid, 0);
126    EXPECT_EQ(ret, 0);
127    ret = fstat(fd, &stat2);
128    EXPECT_EQ(stat2.st_uid, uid);
129    EXPECT_EQ(stat2.st_gid, gid);
130
131    chdir(path);
132    close(fd);
133    remove(TEST_FILE);
134}
135
136/*
137 * @tc.number : SUB_KERNEL_SYSCALL_FCHOWNAT_0300
138 * @tc.name   : FchownatInvalidFdFail_0003
139 * @tc.desc   : fchownat change invalid file owner id and group id fail, errno EBADF.
140 * @tc.size   : MediumTest
141 * @tc.type   : Function
142 * @tc.level  : Level 2
143 */
144HWTEST_F(FchownatApiTest, FchownatInvalidFdFail_0003, Function | MediumTest | Level2)
145{
146    int invalidFd = -1;
147    errno = 0;
148    int ret = fchownat(invalidFd, TEST_FILE_NAME, 1, 1, 0);
149    EXPECT_NE(ret, 0);
150    EXPECT_EQ(errno, EBADF);
151}
152
153/*
154 * @tc.number : SUB_KERNEL_SYSCALL_FCHOWNAT_0400
155 * @tc.name   : FchownatLinkFileTestSuccess_0004
156 * @tc.desc   : fchownat change file owner id and group id by file link success.
157 * @tc.size   : MediumTest
158 * @tc.type   : Function
159 * @tc.level  : Level 1
160 */
161HWTEST_F(FchownatApiTest, FchownatLinkFileTestSuccess_0004, Function | MediumTest | Level1)
162{
163    int ret = -1;
164    struct stat stat1;
165    struct stat stat2;
166    char path[PATH_MAX_LEN];
167    char *dir = getcwd(path, sizeof(path));
168    EXPECT_NE(dir, nullptr);
169    ret = chdir(TEST_FILE_PATH);
170    EXPECT_EQ(ret, 0);
171
172    int fd = open(TEST_FILE, O_RDWR | O_CREAT, MODE_0755);
173    EXPECT_TRUE(fd > 0);
174    ret = fstat(fd, &stat1);
175    EXPECT_EQ(ret, 0);
176    uid_t uid = stat1.st_uid + 1;
177    gid_t gid = stat1.st_gid + 1;
178
179    ret = symlink(TEST_FILE_NAME, SYMBOL_LINK_NAME);
180    EXPECT_EQ(ret, 0);
181
182    ret = fchownat(AT_FDCWD, SYMBOL_LINK_NAME, uid, gid, 0);
183    EXPECT_EQ(ret, 0);
184    ret = fstat(fd, &stat2);
185    EXPECT_EQ(ret, 0);
186    EXPECT_EQ(stat2.st_uid, uid);
187    EXPECT_EQ(stat2.st_gid, gid);
188
189    unlink(TEST_FILE_NAME);
190    close(fd);
191    remove(TEST_FILE);
192    remove(SYMBOL_LINK_NAME);
193    chdir(path);
194}
195
196/*
197 * @tc.number : SUB_KERNEL_SYSCALL_FCHOWNAT_0500
198 * @tc.name   : FchownatAT_SYMLINK_NOFOLLOWTestSuccess_0005
199 * @tc.desc   : fchownat change owner id and group id of file link itself success.
200 * @tc.size   : MediumTest
201 * @tc.type   : Function
202 * @tc.level  : Level 1
203 */
204HWTEST_F(FchownatApiTest, FchownatAT_SYMLINK_NOFOLLOWTestSuccess_0005, Function | MediumTest | Level1)
205{
206    int ret = -1;
207    struct stat stat1;
208    struct stat stat2;
209    char path[PATH_MAX_LEN];
210    char *dir = getcwd(path, sizeof(path));
211    EXPECT_NE(dir, nullptr);
212    ret = chdir(TEST_FILE_PATH);
213    EXPECT_EQ(ret, 0);
214
215    int fd = open(TEST_FILE_NAME, O_RDWR | O_CREAT, MODE_0644);
216    EXPECT_TRUE(fd > 0);
217    ret = symlink(TEST_FILE_NAME, SYMBOL_LINK_NAME);
218    EXPECT_EQ(ret, 0);
219
220    ret = fstat(fd, &stat1);
221    EXPECT_EQ(ret, 0);
222    uid_t uid = stat1.st_uid + 1;
223    gid_t gid = stat1.st_gid + 1;
224
225    ret = fchownat(AT_FDCWD, SYMBOL_LINK_NAME, uid, gid, AT_SYMLINK_NOFOLLOW);
226    EXPECT_EQ(ret, 0);
227    ret = fstat(fd, &stat2);
228    EXPECT_EQ(ret, 0);
229    EXPECT_NE(stat2.st_uid, uid);
230    EXPECT_NE(stat2.st_gid, gid);
231
232    unlink(TEST_FILE_NAME);
233    close(fd);
234    remove(TEST_FILE);
235    remove(SYMBOL_LINK_NAME);
236    chdir(path);
237}
238
239/*
240 * @tc.number : SUB_KERNEL_SYSCALL_FCHOWNAT_0600
241 * @tc.name   : FchownatAT_EMPTY_PATHTestSuccess_0006
242 * @tc.desc   : fchownat change current path file owner id and group id by AT_EMPTY_PATH success.
243 * @tc.size   : MediumTest
244 * @tc.type   : Function
245 * @tc.level  : Level 1
246 */
247HWTEST_F(FchownatApiTest, FchownatAT_EMPTY_PATHTestSuccess_0006, Function | MediumTest | Level1)
248{
249    int ret = -1;
250    struct stat stat1;
251
252    int fd = open(TEST_FILE, O_RDWR | O_CREAT, 0644);
253    EXPECT_TRUE(fd > 0);
254
255    ret = fstat(fd, &stat1);
256    EXPECT_EQ(ret, 0);
257    uid_t uid = stat1.st_uid + 1;
258    gid_t gid = stat1.st_gid + 1;
259
260    ret = fchownat(fd, "", uid, gid, AT_EMPTY_PATH);
261    EXPECT_EQ(ret, 0);
262
263    close(fd);
264    remove(TEST_FILE);
265}
266