1f857971dSopenharmony_ci/*
2f857971dSopenharmony_ci * Copyright (c) 2022-2023 Huawei Device Co., Ltd.
3f857971dSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4f857971dSopenharmony_ci * you may not use this file except in compliance with the License.
5f857971dSopenharmony_ci * You may obtain a copy of the License at
6f857971dSopenharmony_ci *
7f857971dSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8f857971dSopenharmony_ci *
9f857971dSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10f857971dSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11f857971dSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12f857971dSopenharmony_ci * See the License for the specific language governing permissions and
13f857971dSopenharmony_ci * limitations under the License.
14f857971dSopenharmony_ci */
15f857971dSopenharmony_ci
16f857971dSopenharmony_ci#include "devicestatus_data_parse.h"
17f857971dSopenharmony_ci
18f857971dSopenharmony_ci#include <fcntl.h>
19f857971dSopenharmony_ci#include <unistd.h>
20f857971dSopenharmony_ci
21f857971dSopenharmony_ci#include <sys/stat.h>
22f857971dSopenharmony_ci
23f857971dSopenharmony_ci#include "devicestatus_data_define.h"
24f857971dSopenharmony_ci#include "devicestatus_errors.h"
25f857971dSopenharmony_ci#include "fi_log.h"
26f857971dSopenharmony_ci#include "json_parser.h"
27f857971dSopenharmony_ci#include "utility.h"
28f857971dSopenharmony_ci
29f857971dSopenharmony_ci#undef LOG_TAG
30f857971dSopenharmony_ci#define LOG_TAG "DeviceStatusDataParse"
31f857971dSopenharmony_ci
32f857971dSopenharmony_cinamespace OHOS {
33f857971dSopenharmony_cinamespace Msdp {
34f857971dSopenharmony_cinamespace DeviceStatus {
35f857971dSopenharmony_cinamespace {
36f857971dSopenharmony_ciconstexpr int32_t FILE_SIZE_MAX { 0x5000 };
37f857971dSopenharmony_ciconstexpr int32_t READ_DATA_BUFF_SIZE { 256 };
38f857971dSopenharmony_ciconst std::string MSDP_DATA_PATH { "/data/msdp/device_status_data.json" };
39f857971dSopenharmony_ciconst std::string MSDP_DATA_DIR { "/data/msdp" };
40f857971dSopenharmony_ci} // namespace
41f857971dSopenharmony_ci
42f857971dSopenharmony_cistd::vector<int32_t> DeviceStatusDataParse::tempcount_ =
43f857971dSopenharmony_ci    std::vector<int32_t> (static_cast<int32_t>(Type::TYPE_MAX), static_cast<int32_t>(TypeValue::INVALID));
44f857971dSopenharmony_ci
45f857971dSopenharmony_ciint32_t DeviceStatusDataParse::CreateJsonFile()
46f857971dSopenharmony_ci{
47f857971dSopenharmony_ci    int32_t fd = open(MSDP_DATA_PATH.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP);
48f857971dSopenharmony_ci    if (fd < 0) {
49f857971dSopenharmony_ci        FI_HILOGE("open failed");
50f857971dSopenharmony_ci        return DEVICESTATUS_FAILED;
51f857971dSopenharmony_ci    }
52f857971dSopenharmony_ci    if (close(fd) < 0) {
53f857971dSopenharmony_ci        FI_HILOGE("close fd failed, error:%{public}s, fd:%{public}d", strerror(errno), fd);
54f857971dSopenharmony_ci    }
55f857971dSopenharmony_ci
56f857971dSopenharmony_ci    struct stat buf;
57f857971dSopenharmony_ci    if (stat(MSDP_DATA_DIR.c_str(), &buf) != 0) {
58f857971dSopenharmony_ci        FI_HILOGE("start folder path is invalid %{public}d", errno);
59f857971dSopenharmony_ci        return DEVICESTATUS_FAILED;
60f857971dSopenharmony_ci    }
61f857971dSopenharmony_ci    if (chown(MSDP_DATA_PATH.c_str(), buf.st_uid, buf.st_gid) != 0) {
62f857971dSopenharmony_ci        FI_HILOGE("chown failed, errno:%{public}d", errno);
63f857971dSopenharmony_ci        return DEVICESTATUS_FAILED;
64f857971dSopenharmony_ci    }
65f857971dSopenharmony_ci
66f857971dSopenharmony_ci    return DEVICESTATUS_OK;
67f857971dSopenharmony_ci}
68f857971dSopenharmony_ci
69f857971dSopenharmony_cibool DeviceStatusDataParse::ParseDeviceStatusData(Type type, Data& data)
70f857971dSopenharmony_ci{
71f857971dSopenharmony_ci    std::string jsonBuf = ReadJsonFile(MSDP_DATA_PATH.c_str());
72f857971dSopenharmony_ci    if (jsonBuf.empty()) {
73f857971dSopenharmony_ci        FI_HILOGE("Read json failed, errno:%{public}d", errno);
74f857971dSopenharmony_ci        data.type = type;
75f857971dSopenharmony_ci        data.value = OnChangedValue::VALUE_INVALID;
76f857971dSopenharmony_ci        return false;
77f857971dSopenharmony_ci    }
78f857971dSopenharmony_ci    return DeviceStatusDataInit(jsonBuf, true, type, data);
79f857971dSopenharmony_ci}
80f857971dSopenharmony_ci
81f857971dSopenharmony_cibool DeviceStatusDataParse::DeviceStatusDataInit(const std::string& fileData, bool logStatus, Type& type,
82f857971dSopenharmony_ci    Data& data)
83f857971dSopenharmony_ci{
84f857971dSopenharmony_ci    CALL_DEBUG_ENTER;
85f857971dSopenharmony_ci    JsonParser parser;
86f857971dSopenharmony_ci    parser.json = cJSON_Parse(fileData.c_str());
87f857971dSopenharmony_ci    data.type = type;
88f857971dSopenharmony_ci    data.value = OnChangedValue::VALUE_INVALID;
89f857971dSopenharmony_ci    if (cJSON_IsArray(parser.json)) {
90f857971dSopenharmony_ci        FI_HILOGE("parser is array");
91f857971dSopenharmony_ci        return false;
92f857971dSopenharmony_ci    }
93f857971dSopenharmony_ci
94f857971dSopenharmony_ci    if (type < Type::TYPE_ABSOLUTE_STILL || type >= Type::TYPE_MAX) {
95f857971dSopenharmony_ci        FI_HILOGE("type error");
96f857971dSopenharmony_ci        return false;
97f857971dSopenharmony_ci    }
98f857971dSopenharmony_ci
99f857971dSopenharmony_ci    cJSON* mockarray = cJSON_GetObjectItem(parser.json, DeviceStatusJson[type].json.c_str());
100f857971dSopenharmony_ci    if (!cJSON_IsArray(mockarray)) {
101f857971dSopenharmony_ci        FI_HILOGE("mockarray is not array");
102f857971dSopenharmony_ci        return false;
103f857971dSopenharmony_ci    }
104f857971dSopenharmony_ci    int32_t jsonsize = cJSON_GetArraySize(mockarray);
105f857971dSopenharmony_ci    if (jsonsize == 0) {
106f857971dSopenharmony_ci        FI_HILOGE("Json size is zero");
107f857971dSopenharmony_ci        return false;
108f857971dSopenharmony_ci    }
109f857971dSopenharmony_ci    tempcount_[type] = tempcount_[type] % jsonsize;
110f857971dSopenharmony_ci    cJSON* mockvalue = cJSON_GetArrayItem(mockarray, tempcount_[type]);
111f857971dSopenharmony_ci    tempcount_[type]++;
112f857971dSopenharmony_ci    data.type = type;
113f857971dSopenharmony_ci    if (mockvalue == nullptr || !cJSON_IsNumber(mockvalue)) {
114f857971dSopenharmony_ci        FI_HILOGE("Json parser number is failed");
115f857971dSopenharmony_ci        return false;
116f857971dSopenharmony_ci    }
117f857971dSopenharmony_ci    data.value = static_cast<OnChangedValue>(mockvalue->valueint);
118f857971dSopenharmony_ci    FI_HILOGD("type:%{public}d, status:%{public}d", data.type, data.value);
119f857971dSopenharmony_ci    return true;
120f857971dSopenharmony_ci}
121f857971dSopenharmony_ci
122f857971dSopenharmony_cibool DeviceStatusDataParse::DisableCount(const Type type)
123f857971dSopenharmony_ci{
124f857971dSopenharmony_ci    CALL_DEBUG_ENTER;
125f857971dSopenharmony_ci    if (tempcount_.size() <= static_cast<size_t>(type)) {
126f857971dSopenharmony_ci        FI_HILOGE("The index is out of bounds, size is %{public}zu", tempcount_.size());
127f857971dSopenharmony_ci        return false;
128f857971dSopenharmony_ci    }
129f857971dSopenharmony_ci    tempcount_[static_cast<int32_t>(type)] = static_cast<int32_t>(TypeValue::INVALID);
130f857971dSopenharmony_ci    return true;
131f857971dSopenharmony_ci}
132f857971dSopenharmony_ci
133f857971dSopenharmony_cistd::string DeviceStatusDataParse::ReadJsonFile(const std::string &filePath)
134f857971dSopenharmony_ci{
135f857971dSopenharmony_ci    if (filePath.empty()) {
136f857971dSopenharmony_ci        FI_HILOGE("Path is empty");
137f857971dSopenharmony_ci        return {};
138f857971dSopenharmony_ci    }
139f857971dSopenharmony_ci    char realPath[PATH_MAX] = { 0 };
140f857971dSopenharmony_ci    if (realpath(filePath.c_str(), realPath) == nullptr) {
141f857971dSopenharmony_ci        FI_HILOGE("Path is error, %{public}d", errno);
142f857971dSopenharmony_ci        return {};
143f857971dSopenharmony_ci    }
144f857971dSopenharmony_ci    if (!CheckFileDir(realPath, MSDP_DATA_DIR)) {
145f857971dSopenharmony_ci        FI_HILOGE("File dir is invalid");
146f857971dSopenharmony_ci        return {};
147f857971dSopenharmony_ci    }
148f857971dSopenharmony_ci    if (!CheckFileExtendName(realPath, "json")) {
149f857971dSopenharmony_ci        FI_HILOGE("Unable to parse files other than json format");
150f857971dSopenharmony_ci        return {};
151f857971dSopenharmony_ci    }
152f857971dSopenharmony_ci    if (!Utility::DoesFileExist(filePath.c_str())) {
153f857971dSopenharmony_ci        FI_HILOGE("File not exist");
154f857971dSopenharmony_ci        return {};
155f857971dSopenharmony_ci    }
156f857971dSopenharmony_ci    if (!CheckFileSize(filePath)) {
157f857971dSopenharmony_ci        FI_HILOGE("File size out of read range");
158f857971dSopenharmony_ci        return {};
159f857971dSopenharmony_ci    }
160f857971dSopenharmony_ci    return ReadFile(realPath);
161f857971dSopenharmony_ci}
162f857971dSopenharmony_ci
163f857971dSopenharmony_cibool DeviceStatusDataParse::CheckFileDir(const std::string& filePath, const std::string& dir)
164f857971dSopenharmony_ci{
165f857971dSopenharmony_ci    if (filePath.compare(0, MSDP_DATA_DIR.size(), MSDP_DATA_DIR) != 0) {
166f857971dSopenharmony_ci        FI_HILOGE("FilePath dir is invalid");
167f857971dSopenharmony_ci        return false;
168f857971dSopenharmony_ci    }
169f857971dSopenharmony_ci    return true;
170f857971dSopenharmony_ci}
171f857971dSopenharmony_ci
172f857971dSopenharmony_cibool DeviceStatusDataParse::CheckFileSize(const std::string& filePath)
173f857971dSopenharmony_ci{
174f857971dSopenharmony_ci    int32_t fileSize = Utility::GetFileSize(filePath);
175f857971dSopenharmony_ci    if ((fileSize <= 0) || (fileSize > FILE_SIZE_MAX)) {
176f857971dSopenharmony_ci        FI_HILOGE("File size out of read range");
177f857971dSopenharmony_ci        return false;
178f857971dSopenharmony_ci    }
179f857971dSopenharmony_ci    return true;
180f857971dSopenharmony_ci}
181f857971dSopenharmony_ci
182f857971dSopenharmony_cibool DeviceStatusDataParse::CheckFileExtendName(const std::string& filePath, const std::string& checkExtension)
183f857971dSopenharmony_ci{
184f857971dSopenharmony_ci    std::string::size_type pos = filePath.find_last_of('.');
185f857971dSopenharmony_ci    if (pos == std::string::npos) {
186f857971dSopenharmony_ci        FI_HILOGE("File is not find extension");
187f857971dSopenharmony_ci        return false;
188f857971dSopenharmony_ci    }
189f857971dSopenharmony_ci    return (filePath.substr(pos + 1, filePath.npos) == checkExtension);
190f857971dSopenharmony_ci}
191f857971dSopenharmony_ci
192f857971dSopenharmony_cistd::string DeviceStatusDataParse::ReadFile(const std::string &filePath)
193f857971dSopenharmony_ci{
194f857971dSopenharmony_ci    CALL_DEBUG_ENTER;
195f857971dSopenharmony_ci    FILE* fp = fopen(filePath.c_str(), "r");
196f857971dSopenharmony_ci    if (fp == nullptr) {
197f857971dSopenharmony_ci        FI_HILOGE("Open failed");
198f857971dSopenharmony_ci        return {};
199f857971dSopenharmony_ci    }
200f857971dSopenharmony_ci    std::string dataStr;
201f857971dSopenharmony_ci    char buf[READ_DATA_BUFF_SIZE] = { 0 };
202f857971dSopenharmony_ci    while (fgets(buf, sizeof(buf), fp) != nullptr) {
203f857971dSopenharmony_ci        dataStr += buf;
204f857971dSopenharmony_ci    }
205f857971dSopenharmony_ci    if (fclose(fp) != 0) {
206f857971dSopenharmony_ci        FI_HILOGW("Close file failed");
207f857971dSopenharmony_ci    }
208f857971dSopenharmony_ci    return dataStr;
209f857971dSopenharmony_ci}
210f857971dSopenharmony_ci} // namespace DeviceStatus
211f857971dSopenharmony_ci} // namespace Msdp
212f857971dSopenharmony_ci} // namespace OHOS
213