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