• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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 "unified_data_helper.h"
17 
18 #include <cstdio>
19 #include <string>
20 #include <sys/stat.h>
21 #include <cinttypes>
22 #include "common_func.h"
23 #include "directory_ex.h"
24 #include "file_ex.h"
25 #include "file_uri.h"
26 #include "file.h"
27 #include "logger.h"
28 #include "tlv_object.h"
29 #include "tlv_util.h"
30 #include "unified_meta.h"
31 
32 namespace OHOS {
33 namespace UDMF {
34 const mode_t MODE = 0700;
35 static constexpr int64_t MAX_KV_RECORD_SIZE = 2 * 1024 * 1024;
36 static constexpr int64_t MAX_KV_DATA_SIZE = 4 * 1024 * 1024;
37 
38 const std::string TEMP_UNIFIED_DATA_ROOT_PATH = "data/storage/el2/base/temp/udata";
39 const std::string TEMP_UNIFIED_DATA_SUFFIX = ".ud";
40 const std::string TEMP_UNIFIED_DATA_FLAG = "temp_udmf_file_flag";
41 
42 std::string UnifiedDataHelper::rootPath_ = "";
43 
SetRootPath(const std::string & rootPath)44 void UnifiedDataHelper::SetRootPath(const std::string &rootPath)
45 {
46     rootPath_ = rootPath;
47 }
48 
ExceedKVSizeLimit(UnifiedData & data)49 bool UnifiedDataHelper::ExceedKVSizeLimit(UnifiedData &data)
50 {
51     int64_t totalSize = data.GetSize();
52     if (data.GetSize() > MAX_KV_DATA_SIZE) {
53         LOG_DEBUG(UDMF_FRAMEWORK, "Exceeded KV data limit, totalSize:%{public}" PRId64 " !", totalSize);
54         return true;
55     }
56     for (const auto &record : data.GetRecords()) {
57         if (record->GetSize() > MAX_KV_RECORD_SIZE) {
58             LOG_DEBUG(UDMF_FRAMEWORK, "Exceeded KV record limit, recordSize:%{public}" PRId64 "!", record->GetSize());
59             return true;
60         }
61     }
62     return false;
63 }
64 
IsTempUData(UnifiedData & data)65 bool UnifiedDataHelper::IsTempUData(UnifiedData &data)
66 {
67     auto records = data.GetRecords();
68     if (records.size() != 1) {
69         return false;
70     }
71     if (records[0] == nullptr || records[0]->GetType() != UDType::FILE) {
72         return false;
73     }
74     auto file = static_cast<File*>(records[0].get());
75     if (file == nullptr) {
76         LOG_ERROR(UDMF_FRAMEWORK, "Invalid file record!");
77         return false;
78     }
79     auto details = file->GetDetails();
80     if (details.find(TEMP_UNIFIED_DATA_FLAG) == details.end()) {
81         return false;
82     }
83     LOG_DEBUG(UDMF_FRAMEWORK, "exist temp unified data flag!");
84     return true;
85 }
86 
CreateDirIfNotExist(const std::string & dirPath,const mode_t & mode)87 void UnifiedDataHelper::CreateDirIfNotExist(const std::string& dirPath, const mode_t& mode)
88 {
89     if (OHOS::FileExists(dirPath)) {
90         if (!OHOS::ForceRemoveDirectory(dirPath)) {
91             LOG_ERROR(UDMF_FRAMEWORK, "remove dir %{public}s failed, errno: %{public}d.", dirPath.c_str(), errno);
92         }
93     }
94     LOG_DEBUG(UDMF_FRAMEWORK, "ForceCreateDirectory, dir: %{public}s", dirPath.c_str());
95     bool success = OHOS::ForceCreateDirectory(dirPath);
96     if (!success) {
97         LOG_ERROR(UDMF_FRAMEWORK, "create dir %{public}s failed, errno: %{public}d.", dirPath.c_str(), errno);
98         return;
99     }
100     if (mode != 0) {
101         chmod(dirPath.c_str(), mode);
102     }
103 }
104 
GetSummary(const UnifiedData & data,Summary & summary)105 void UnifiedDataHelper::GetSummary(const UnifiedData &data, Summary &summary)
106 {
107     for (const auto &record : data.GetRecords()) {
108         int64_t recordSize = record->GetSize();
109         auto udType = UD_TYPE_MAP.at(record->GetType());
110         auto it = summary.summary.find(udType);
111         if (it == summary.summary.end()) {
112             summary.summary[udType] = recordSize;
113         } else {
114             summary.summary[udType] += recordSize;
115         }
116         summary.totalSize += recordSize;
117     }
118 }
119 
Pack(UnifiedData & data)120 bool UnifiedDataHelper::Pack(UnifiedData &data)
121 {
122     Summary summary;
123     GetSummary(data, summary);
124 
125     int64_t now = std::chrono::duration_cast<std::chrono::milliseconds>
126                     (std::chrono::system_clock::now().time_since_epoch()).count();
127     CreateDirIfNotExist(GetRootPath(), MODE);
128     std::string filePath = GetRootPath() + std::to_string(now) + TEMP_UNIFIED_DATA_SUFFIX;
129     if (!SaveUDataToFile(filePath, data)) {
130         LOG_ERROR(UDMF_FRAMEWORK, "fail to save unified data to file");
131         return false;
132     }
133     std::string uri = AppFileService::CommonFunc::GetUriFromPath(filePath);
134     auto fileRecord = std::make_shared<File>(uri);
135     UDDetails details;
136     details.insert(std::make_pair(TEMP_UNIFIED_DATA_FLAG, true));
137     for (auto &item : summary.summary) {
138         details.insert(std::make_pair(item.first, item.second));
139     }
140     fileRecord->SetDetails(details);
141     std::vector<std::shared_ptr<UnifiedRecord>> records {};
142     records.emplace_back(fileRecord);
143     data.SetRecords(records);
144     return true;
145 }
146 
Unpack(UnifiedData & data)147 bool UnifiedDataHelper::Unpack(UnifiedData &data)
148 {
149     auto records = data.GetRecords();
150     if (records.size() != 1) {
151         return false;
152     }
153 
154     auto file = static_cast<File*>(records[0].get());
155     if (file == nullptr) {
156         LOG_ERROR(UDMF_FRAMEWORK, "Invalid file record!");
157         return false;
158     }
159     UnifiedData tempData;
160     if (!LoadUDataFromFile(file->GetUri(), tempData)) {
161         LOG_ERROR(UDMF_FRAMEWORK, "Fail to load udata from file!");
162         return false;
163     }
164     data.SetRecords(tempData.GetRecords());
165     return true;
166 }
167 
SaveUDataToFile(const std::string & dataFile,UnifiedData & data)168 bool UnifiedDataHelper::SaveUDataToFile(const std::string &dataFile, UnifiedData &data)
169 {
170     std::vector<uint8_t> dataBytes;
171     auto recordTlv = TLVObject(dataBytes);
172 
173     std::FILE *file = fopen(dataFile.c_str(), "w+");
174     if (file == nullptr) {
175         LOG_ERROR(UDMF_FRAMEWORK, "failed to open file");
176         return false;
177     }
178     recordTlv.SetFile(file);
179 
180     if (!TLVUtil::Writing(data, recordTlv)) {
181         LOG_ERROR(UDMF_FRAMEWORK, "TLV Writing failed!");
182         (void)fclose(file);
183         return false;
184     }
185     (void)fclose(file);
186     return true;
187 }
188 
LoadUDataFromFile(const std::string & dataFile,UnifiedData & data)189 bool UnifiedDataHelper::LoadUDataFromFile(const std::string &dataFile, UnifiedData &data)
190 {
191     std::vector<uint8_t> dataBytes;
192     auto recordTlv = TLVObject(dataBytes);
193     AppFileService::ModuleFileUri::FileUri fileUri(dataFile);
194     std::string path = fileUri.GetRealPath();
195     std::FILE *file = fopen(path.c_str(), "r");
196     if (file == nullptr) {
197         LOG_ERROR(UDMF_FRAMEWORK, "failed to open file");
198         return false;
199     }
200     recordTlv.SetFile(file);
201 
202     if (!TLVUtil::Reading(data, recordTlv)) {
203         LOG_ERROR(UDMF_FRAMEWORK, "TLV Reading failed!");
204         (void)fclose(file);
205         return false;
206     }
207     (void)fclose(file);
208     return true;
209 }
210 
GetRootPath()211 std::string UnifiedDataHelper::GetRootPath()
212 {
213     if (rootPath_ == "") {
214         return TEMP_UNIFIED_DATA_ROOT_PATH;
215     }
216     return rootPath_;
217 }
218 } // namespace UDMF
219 } // namespace OHOS