1 /*
2 * Copyright (c) 2022-2023 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 #include "file_utils.h"
16
17 #include <cinttypes>
18 #include <sys/stat.h>
19 #include <unistd.h>
20
21 #include "securec.h"
22 #include "sensors_errors.h"
23
24 #undef LOG_TAG
25 #define LOG_TAG "MiscdeviceFileUtils"
26
27 namespace OHOS {
28 namespace Sensors {
29 namespace {
30 const std::string CONFIG_DIR = "/vendor/etc/vibrator/";
31 constexpr int32_t FILE_SIZE_MAX = 0x5000;
32 constexpr int64_t READ_DATA_BUFF_SIZE = 256;
33 constexpr int32_t INVALID_FILE_SIZE = -1;
34 constexpr int32_t FILE_PATH_MAX = 1024;
35 } // namespace
36
ReadJsonFile(const std::string & filePath)37 std::string ReadJsonFile(const std::string &filePath)
38 {
39 if (filePath.empty()) {
40 MISC_HILOGE("Path is empty");
41 return {};
42 }
43 char realPath[PATH_MAX] = {};
44 if (realpath(filePath.c_str(), realPath) == nullptr) {
45 MISC_HILOGE("Path is error, %{public}d", errno);
46 return {};
47 }
48 if (!CheckFileDir(realPath, CONFIG_DIR)) {
49 MISC_HILOGE("File dir is invalid");
50 return {};
51 }
52 if (!CheckFileExtendName(realPath, "json")) {
53 MISC_HILOGE("Unable to parse files other than json format");
54 return {};
55 }
56 if (!IsFileExists(realPath)) {
57 MISC_HILOGE("File not exist");
58 return {};
59 }
60 if (!CheckFileSize(realPath)) {
61 MISC_HILOGE("File size out of read range");
62 return {};
63 }
64 FILE *fp = fopen(realPath, "r");
65 CHKPS(fp);
66 std::string dataStr;
67 char buf[READ_DATA_BUFF_SIZE] = { '\0' };
68 while (fgets(buf, sizeof(buf), fp) != nullptr) {
69 dataStr += buf;
70 }
71 if (fclose(fp) != 0) {
72 MISC_HILOGW("Close file failed, errno:%{public}d", errno);
73 }
74 return dataStr;
75 }
76
GetFileSize(const std::string & filePath)77 int32_t GetFileSize(const std::string &filePath)
78 {
79 struct stat statbuf = { 0 };
80 if (stat(filePath.c_str(), &statbuf) != 0) {
81 MISC_HILOGE("Get file size error");
82 return INVALID_FILE_SIZE;
83 }
84 return statbuf.st_size;
85 }
86
GetFileSize(int32_t fd)87 int64_t GetFileSize(int32_t fd)
88 {
89 if (fd < 0) {
90 MISC_HILOGE("fd is invalid, fd:%{public}d", fd);
91 return INVALID_FILE_SIZE;
92 }
93 struct stat64 statbuf = { 0 };
94 if (fstat64(fd, &statbuf) != 0) {
95 MISC_HILOGE("fstat error, errno:%{public}d", errno);
96 return INVALID_FILE_SIZE;
97 }
98 return statbuf.st_size;
99 }
100
GetFileName(const int32_t & fd,std::string & fileName)101 int32_t GetFileName(const int32_t &fd, std::string &fileName)
102 {
103 if (fd < 0) {
104 MISC_HILOGE("fd is invalid, fd:%{public}d", fd);
105 return ERROR;
106 }
107 char buf[FILE_PATH_MAX] = {'\0'};
108 char filePath[FILE_PATH_MAX] = {'\0'};
109
110 int ret = snprintf_s(buf, sizeof(buf), (sizeof(buf) - 1), "/proc/self/fd/%d", fd);
111 if (ret < 0) {
112 MISC_HILOGE("snprintf failed with %{public}d", errno);
113 return ERROR;
114 }
115
116 ret = readlink(buf, filePath, FILE_PATH_MAX - 1);
117 if (ret < 0 || ret >= FILE_PATH_MAX) {
118 MISC_HILOGE("readlink failed with %{public}d", errno);
119 return ERROR;
120 }
121
122 fileName = filePath;
123 std::size_t firstSlash = fileName.rfind("/");
124 if (firstSlash == fileName.npos) {
125 MISC_HILOGE("Get error path");
126 return ERROR;
127 }
128 fileName = fileName.substr(firstSlash + 1, fileName.size() - firstSlash);
129 return SUCCESS;
130 }
131
GetFileExtName(const int32_t & fd,std::string & extName)132 int32_t GetFileExtName(const int32_t &fd, std::string &extName)
133 {
134 if (fd < 0) {
135 MISC_HILOGE("fd is invalid, fd:%{public}d", fd);
136 return ERROR;
137 }
138 std::string fileName = "";
139 if (GetFileName(fd, fileName) == ERROR) {
140 MISC_HILOGE("GetFileName failed");
141 return ERROR;
142 }
143 extName = fileName.substr(fileName.find_last_of(".") + 1);
144 return SUCCESS;
145 }
146
CheckFileDir(const std::string & filePath,const std::string & dir)147 bool CheckFileDir(const std::string &filePath, const std::string &dir)
148 {
149 if (filePath.compare(0, CONFIG_DIR.size(), CONFIG_DIR) != 0) {
150 MISC_HILOGE("filePath dir is invalid");
151 return false;
152 }
153 return true;
154 }
155
CheckFileSize(const std::string & filePath)156 bool CheckFileSize(const std::string &filePath)
157 {
158 int32_t fileSize = GetFileSize(filePath);
159 if ((fileSize <= 0) || (fileSize > FILE_SIZE_MAX)) {
160 MISC_HILOGE("File size out of read range");
161 return false;
162 }
163 return true;
164 }
165
CheckFileExtendName(const std::string & filePath,const std::string & checkExtension)166 bool CheckFileExtendName(const std::string &filePath, const std::string &checkExtension)
167 {
168 std::string::size_type pos = filePath.find_last_of('.');
169 if (pos == std::string::npos) {
170 MISC_HILOGE("File is not find extension");
171 return false;
172 }
173 return (filePath.substr(pos + 1, filePath.npos) == checkExtension);
174 }
175
IsFileExists(const std::string & fileName)176 bool IsFileExists(const std::string &fileName)
177 {
178 return (access(fileName.c_str(), F_OK) == 0);
179 }
180
ReadFd(const RawFileDescriptor & rawFd)181 std::string ReadFd(const RawFileDescriptor &rawFd)
182 {
183 if (rawFd.fd < 0) {
184 MISC_HILOGE("fd is invalid, fd:%{public}d", rawFd.fd);
185 return {};
186 }
187 int64_t fdSize = GetFileSize(rawFd.fd);
188 if ((rawFd.offset < 0) || (rawFd.offset > fdSize)) {
189 MISC_HILOGE("offset is invalid, offset:%{public}" PRId64, rawFd.offset);
190 return {};
191 }
192 if ((rawFd.length <= 0) || (rawFd.length > fdSize - rawFd.offset)) {
193 MISC_HILOGE("length is invalid, length:%{public}" PRId64, rawFd.length);
194 return {};
195 }
196 int dupFd = dup(rawFd.fd);
197 if (dupFd < 0) {
198 MISC_HILOGE("dup fd failed, fd:%{public}d, errno:%{public}d", rawFd.fd, errno);
199 return {};
200 }
201 FILE *fp = fdopen(dupFd, "r");
202 if (fp == nullptr) {
203 MISC_HILOGE("fdopen failed, fd:%{public}d, errno:%{public}d", dupFd, errno);
204 close(dupFd);
205 return {};
206 }
207 if (fseek(fp, rawFd.offset, SEEK_SET) != 0) {
208 MISC_HILOGE("fseek failed, errno:%{public}d", errno);
209 if (fclose(fp) != 0) {
210 MISC_HILOGW("Close file failed, errno:%{public}d", errno);
211 }
212 return {};
213 }
214 std::string dataStr;
215 char buf[READ_DATA_BUFF_SIZE] = { '\0' };
216 int64_t alreadyRead = 0;
217 while (alreadyRead < rawFd.length) {
218 int64_t onceRead = std::min(rawFd.length - alreadyRead, READ_DATA_BUFF_SIZE - 1);
219 fgets(buf, onceRead + 1, fp);
220 dataStr += buf;
221 alreadyRead = ftell(fp) - rawFd.offset;
222 }
223 if (fclose(fp) != 0) {
224 MISC_HILOGW("Close file failed, errno:%{public}d", errno);
225 }
226 return dataStr;
227 }
228
GetFileSuffix(int32_t fd)229 std::string GetFileSuffix(int32_t fd)
230 {
231 std::string fdPath = "/proc/self/fd/" + std::to_string(fd);
232 char filePath[FILE_PATH_MAX + 1] = { '\0' };
233 ssize_t ret = readlink(fdPath.c_str(), filePath, FILE_PATH_MAX);
234 if (ret < 0 || ret > FILE_PATH_MAX) {
235 MISC_HILOGE("Readlink failed, errno:%{public}d", errno);
236 return {};
237 }
238 std::string fileAbsolutePath(filePath);
239 size_t pos = fileAbsolutePath.find_last_of('.');
240 if (pos == std::string::npos) {
241 MISC_HILOGE("File suffix is invalid, fileAbsolutePath:%{public}s", fileAbsolutePath.c_str());
242 return {};
243 }
244 return fileAbsolutePath.substr(pos + 1);
245 }
246 } // namespace Sensors
247 } // namespace OHOS
248