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
16 #include "devicestatus_data_parse.h"
17
18 #include <fcntl.h>
19 #include <unistd.h>
20
21 #include <sys/stat.h>
22
23 #include "devicestatus_data_define.h"
24 #include "devicestatus_errors.h"
25 #include "fi_log.h"
26 #include "utility.h"
27
28 namespace OHOS {
29 namespace Msdp {
30 namespace DeviceStatus {
31 namespace {
32 constexpr ::OHOS::HiviewDFX::HiLogLabel LABEL { LOG_CORE, MSDP_DOMAIN_ID, "DeviceStatusDataParse" };
33 constexpr int32_t FILE_SIZE_MAX { 0x5000 };
34 constexpr int32_t READ_DATA_BUFF_SIZE { 256 };
35 constexpr int32_t INVALID_FILE_SIZE { -1 };
36 const std::string MSDP_DATA_PATH { "/data/msdp/device_status_data.json" };
37 const std::string MSDP_DATA_DIR { "/data/msdp" };
38 } // namespace
39
40 std::vector<int32_t> DeviceStatusDataParse::tempcount_ =
41 std::vector<int32_t> (static_cast<int32_t>(Type::TYPE_MAX), static_cast<int32_t>(TypeValue::INVALID));
42
CreateJsonFile()43 int32_t DeviceStatusDataParse::CreateJsonFile()
44 {
45 int32_t fd = open(MSDP_DATA_PATH.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP);
46 if (fd < 0) {
47 FI_HILOGE("open failed");
48 return DEVICESTATUS_FAILED;
49 }
50 if (close(fd) < 0) {
51 FI_HILOGE("Close fd failed, error:%{public}s, fd:%{public}d", strerror(errno), fd);
52 }
53
54 struct stat buf;
55 if (stat(MSDP_DATA_DIR.c_str(), &buf) != 0) {
56 FI_HILOGE("stat folder path is invalid %{public}d", errno);
57 return DEVICESTATUS_FAILED;
58 }
59 if (chown(MSDP_DATA_PATH.c_str(), buf.st_uid, buf.st_gid) != 0) {
60 FI_HILOGE("chown failed, errno is %{public}d", errno);
61 return DEVICESTATUS_FAILED;
62 }
63
64 return DEVICESTATUS_OK;
65 }
66
ParseDeviceStatusData(Type type,Data & data)67 bool DeviceStatusDataParse::ParseDeviceStatusData(Type type, Data& data)
68 {
69 std::string jsonBuf = ReadJsonFile(MSDP_DATA_PATH.c_str());
70 if (jsonBuf.empty()) {
71 FI_HILOGE("Read json failed, errno is %{public}d", errno);
72 data.type = type;
73 data.value = OnChangedValue::VALUE_INVALID;
74 return false;
75 }
76 return DeviceStatusDataInit(jsonBuf, true, type, data);
77 }
78
DeviceStatusDataInit(const std::string & fileData,bool logStatus,Type & type,Data & data)79 bool DeviceStatusDataParse::DeviceStatusDataInit(const std::string& fileData, bool logStatus, Type& type,
80 Data& data)
81 {
82 CALL_DEBUG_ENTER;
83 JsonParser parser;
84 parser.json = cJSON_Parse(fileData.c_str());
85 data.type = type;
86 data.value = OnChangedValue::VALUE_INVALID;
87 if (cJSON_IsArray(parser.json)) {
88 FI_HILOGE("parser is array");
89 return false;
90 }
91
92 if (type < Type::TYPE_ABSOLUTE_STILL || type >= Type::TYPE_MAX) {
93 FI_HILOGE("Type error");
94 return false;
95 }
96
97 cJSON* mockarray = cJSON_GetObjectItem(parser.json, DeviceStatusJson[type].json.c_str());
98 int32_t jsonsize = cJSON_GetArraySize(mockarray);
99 if (jsonsize == 0) {
100 FI_HILOGE("Json size is zero");
101 return false;
102 }
103 tempcount_[type] = tempcount_[type] % jsonsize;
104 cJSON* mockvalue = cJSON_GetArrayItem(mockarray, tempcount_[type]);
105 tempcount_[type]++;
106 data.type = type;
107 if (mockvalue == nullptr || !cJSON_IsNumber(mockvalue)) {
108 FI_HILOGE("Json parser number is failed");
109 return false;
110 }
111 data.value = static_cast<OnChangedValue>(mockvalue->valueint);
112 FI_HILOGD("type:%{public}d, status:%{public}d", data.type, data.value);
113 return true;
114 }
115
DisableCount(const Type type)116 bool DeviceStatusDataParse::DisableCount(const Type type)
117 {
118 CALL_DEBUG_ENTER;
119 tempcount_[static_cast<int32_t>(type)] = static_cast<int32_t>(TypeValue::INVALID);
120 return true;
121 }
122
ReadJsonFile(const std::string & filePath)123 std::string DeviceStatusDataParse::ReadJsonFile(const std::string &filePath)
124 {
125 if (filePath.empty()) {
126 FI_HILOGE("Path is empty");
127 return {};
128 }
129 char realPath[PATH_MAX] = {};
130 if (realpath(filePath.c_str(), realPath) == nullptr) {
131 FI_HILOGE("Path is error, %{public}d", errno);
132 return {};
133 }
134 if (!CheckFileDir(realPath, MSDP_DATA_DIR)) {
135 FI_HILOGE("File dir is invalid");
136 return {};
137 }
138 if (!CheckFileExtendName(realPath, "json")) {
139 FI_HILOGE("Unable to parse files other than json format");
140 return {};
141 }
142 if (!Utility::DoesFileExist(filePath.c_str())) {
143 FI_HILOGE("File not exist");
144 return {};
145 }
146 if (!CheckFileSize(filePath)) {
147 FI_HILOGE("File size out of read range");
148 return {};
149 }
150 return ReadFile(realPath);
151 }
152
GetFileSize(const std::string & filePath)153 int32_t DeviceStatusDataParse::GetFileSize(const std::string& filePath)
154 {
155 struct stat statbuf = { 0 };
156 if (stat(filePath.c_str(), &statbuf) != 0) {
157 FI_HILOGE("Get file size error");
158 return INVALID_FILE_SIZE;
159 }
160 return statbuf.st_size;
161 }
162
CheckFileDir(const std::string & filePath,const std::string & dir)163 bool DeviceStatusDataParse::CheckFileDir(const std::string& filePath, const std::string& dir)
164 {
165 if (filePath.compare(0, MSDP_DATA_DIR.size(), MSDP_DATA_DIR) != 0) {
166 FI_HILOGE("FilePath dir is invalid");
167 return false;
168 }
169 return true;
170 }
171
CheckFileSize(const std::string & filePath)172 bool DeviceStatusDataParse::CheckFileSize(const std::string& filePath)
173 {
174 int32_t fileSize = GetFileSize(filePath);
175 if ((fileSize <= 0) || (fileSize > FILE_SIZE_MAX)) {
176 FI_HILOGE("File size out of read range");
177 return false;
178 }
179 return true;
180 }
181
CheckFileExtendName(const std::string & filePath,const std::string & checkExtension)182 bool DeviceStatusDataParse::CheckFileExtendName(const std::string& filePath, const std::string& checkExtension)
183 {
184 std::string::size_type pos = filePath.find_last_of('.');
185 if (pos == std::string::npos) {
186 FI_HILOGE("File is not find extension");
187 return false;
188 }
189 return (filePath.substr(pos + 1, filePath.npos) == checkExtension);
190 }
191
ReadFile(const std::string & filePath)192 std::string DeviceStatusDataParse::ReadFile(const std::string &filePath)
193 {
194 CALL_DEBUG_ENTER;
195 FILE* fp = fopen(filePath.c_str(), "r");
196 if (fp == nullptr) {
197 FI_HILOGE("Open failed");
198 return {};
199 }
200 std::string dataStr;
201 char buf[READ_DATA_BUFF_SIZE] = {};
202 while (fgets(buf, sizeof(buf), fp) != nullptr) {
203 dataStr += buf;
204 }
205 if (fclose(fp) != 0) {
206 FI_HILOGW("Close file failed");
207 }
208 return dataStr;
209 }
210 } // namespace DeviceStatus
211 } // namespace Msdp
212 } // namespace OHOS
213