• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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