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