1/*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
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 <dirent.h>
17#include <fcntl.h>
18#include <stdio.h>
19#include <string.h>
20#include <unistd.h>
21
22#include "filepath_util.h"
23
24const char buf[] = "hello";
25const char *filename = "./file.txt";
26const char *linkfilename = "./linkfile.txt";
27
28int create_file(char *path)
29{
30    int fd = open(path, O_RDWR | O_CREAT, TEST_MODE);
31    if (fd < 0) {
32        return -1;
33    }
34
35    ssize_t bytes = write(fd, buf, sizeof(buf));
36    if (bytes <= 0) {
37        return -1;
38    }
39
40    int result = close(fd);
41    if (result != 0) {
42        return -1;
43    }
44
45    return 0;
46}
47
48/**
49 * @tc.name      : readlinkat_0100
50 * @tc.desc      : read value of a symbolic link
51 * @tc.level     : Level 0
52 */
53void readlinkat_0100(void)
54{
55    char path[PATH_MAX] = {0};
56    FILE_ABSOLUTE_PATH(STR_FILE_TXT, path);
57    int result = create_file(path);
58    if (result != 0) {
59        t_error("%s failed: result = %d\n", __func__, result);
60        return;
61    }
62
63    char linkpath[PATH_MAX] = {0};
64    FILE_ABSOLUTE_PATH(STR_FILE_LINK_TXT, linkpath);
65    remove(linkpath);
66
67    result = symlink(path, linkpath);
68    if (result != 0) {
69        t_error("%s failed: result = %d\n", __func__, result);
70        return;
71    }
72
73    int fd = open(linkpath, O_RDONLY);
74    if (fd < 0) {
75        t_error("%s failed: fd = %d\n", __func__, fd);
76        return;
77    }
78
79    char rbuf[BUFSIZ] = {0};
80    ssize_t bytes = readlinkat(fd, linkpath, rbuf, sizeof(rbuf));
81    if (bytes != strlen(rbuf)) {
82        t_error("%s failed: bytes = %ld\n", __func__, bytes);
83    }
84
85    if (strcmp(rbuf, path)) {
86        t_error("%s failed: rbuf = %s\n", __func__, rbuf);
87    }
88
89    remove(linkpath);
90    remove(path);
91}
92
93/**
94 * @tc.name      : readlinkat_0200
95 * @tc.desc      : read value of a symbolic link with a dir fd
96 * @tc.level     : Level 1
97 */
98void readlinkat_0200(void)
99{
100    char path[PATH_MAX] = {0};
101    FILE_ABSOLUTE_PATH(STR_FILE_TXT, path);
102    int result = create_file(path);
103    if (result != 0) {
104        t_error("%s failed: result = %d\n", __func__, result);
105        return;
106    }
107
108    char dirname[PATH_MAX] = {0};
109    FILE_ABSOLUTE_DIR(dirname);
110    DIR *dir = opendir(dirname);
111    if (dir == NULL) {
112        t_error("%s failed: dirname = %s\n", __func__, dirname);
113        return;
114    }
115
116    int fd = dirfd(dir);
117    if (fd < 0) {
118        t_error("%s failed: fd = %d\n", __func__, fd);
119    }
120
121    char linkpath[PATH_MAX] = {0};
122    FILE_ABSOLUTE_PATH(STR_FILE_LINK_TXT, linkpath);
123    remove(linkpath);
124
125    result = symlinkat(filename, fd, linkfilename);
126    if (result != 0) {
127        t_error("%s failed: result = %d\n", __func__, result);
128        return;
129    }
130
131    char rbuf[BUFSIZ] = {0};
132    ssize_t bytes = readlinkat(fd, linkfilename, rbuf, sizeof(rbuf));
133    if (bytes != strlen(rbuf)) {
134        t_error("%s failed: bytes = %ld\n", __func__, bytes);
135    }
136
137    if (strcmp(rbuf, filename)) {
138        t_error("%s failed: rbuf = %s\n", __func__, rbuf);
139    }
140
141    remove(linkpath);
142    remove(path);
143}
144
145/**
146 * @tc.name      : readlinkat_0300
147 * @tc.desc      : read value of a symbolic link with invalid parameters
148 * @tc.level     : Level 2
149 */
150void readlinkat_0300(void)
151{
152    ssize_t bytes = readlinkat(-1, NULL, NULL, 0);
153    if (bytes >= 0) {
154        t_error("%s failed: bytes = %ld\n", __func__, bytes);
155    }
156}
157
158int main(int argc, char *argv[])
159{
160    readlinkat_0100();
161    readlinkat_0200();
162    readlinkat_0300();
163
164    return t_status;
165}
166