114cf0368Sopenharmony_ci/* 214cf0368Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd. 314cf0368Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 414cf0368Sopenharmony_ci * you may not use this file except in compliance with the License. 514cf0368Sopenharmony_ci * You may obtain a copy of the License at 614cf0368Sopenharmony_ci * 714cf0368Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 814cf0368Sopenharmony_ci * 914cf0368Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 1014cf0368Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 1114cf0368Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1214cf0368Sopenharmony_ci * See the License for the specific language governing permissions and 1314cf0368Sopenharmony_ci * limitations under the License. 1414cf0368Sopenharmony_ci */ 1514cf0368Sopenharmony_ci#define LOG_TAG "UnifiedDataHelper" 1614cf0368Sopenharmony_ci#include "unified_data_helper.h" 1714cf0368Sopenharmony_ci 1814cf0368Sopenharmony_ci#include "common_func.h" 1914cf0368Sopenharmony_ci#include "directory_ex.h" 2014cf0368Sopenharmony_ci#include "file_ex.h" 2114cf0368Sopenharmony_ci#include "file_uri.h" 2214cf0368Sopenharmony_ci#include "logger.h" 2314cf0368Sopenharmony_ci#include "tlv_util.h" 2414cf0368Sopenharmony_ci#include "udmf_conversion.h" 2514cf0368Sopenharmony_ci#include "file.h" 2614cf0368Sopenharmony_ci 2714cf0368Sopenharmony_cinamespace OHOS { 2814cf0368Sopenharmony_cinamespace UDMF { 2914cf0368Sopenharmony_ciconstexpr mode_t MODE = 0700; 3014cf0368Sopenharmony_cistatic constexpr int64_t MAX_KV_RECORD_SIZE = 2 * 1024 * 1024; 3114cf0368Sopenharmony_cistatic constexpr int64_t MAX_KV_DATA_SIZE = 4 * 1024 * 1024; 3214cf0368Sopenharmony_ci 3314cf0368Sopenharmony_ciconstexpr const char *TEMP_UNIFIED_DATA_ROOT_PATH = "data/storage/el2/base/temp/udata"; 3414cf0368Sopenharmony_ciconstexpr const char *TEMP_UNIFIED_DATA_SUFFIX = ".ud"; 3514cf0368Sopenharmony_ciconstexpr const char *TEMP_UNIFIED_DATA_FLAG = "temp_udmf_file_flag"; 3614cf0368Sopenharmony_ci 3714cf0368Sopenharmony_cistd::string UnifiedDataHelper::rootPath_ = ""; 3814cf0368Sopenharmony_ci 3914cf0368Sopenharmony_civoid UnifiedDataHelper::SetRootPath(const std::string &rootPath) 4014cf0368Sopenharmony_ci{ 4114cf0368Sopenharmony_ci rootPath_ = rootPath; 4214cf0368Sopenharmony_ci} 4314cf0368Sopenharmony_ci 4414cf0368Sopenharmony_cibool UnifiedDataHelper::ExceedKVSizeLimit(UnifiedData &data) 4514cf0368Sopenharmony_ci{ 4614cf0368Sopenharmony_ci int64_t totalSize = data.GetSize(); 4714cf0368Sopenharmony_ci if (data.GetSize() > MAX_KV_DATA_SIZE) { 4814cf0368Sopenharmony_ci LOG_DEBUG(UDMF_FRAMEWORK, "Exceeded KV data limit, totalSize:%{public}" PRId64 " !", totalSize); 4914cf0368Sopenharmony_ci return true; 5014cf0368Sopenharmony_ci } 5114cf0368Sopenharmony_ci for (const auto &record : data.GetRecords()) { 5214cf0368Sopenharmony_ci if (record->GetSize() > MAX_KV_RECORD_SIZE) { 5314cf0368Sopenharmony_ci LOG_DEBUG(UDMF_FRAMEWORK, "Exceeded KV record limit, recordSize:%{public}" PRId64 "!", record->GetSize()); 5414cf0368Sopenharmony_ci return true; 5514cf0368Sopenharmony_ci } 5614cf0368Sopenharmony_ci } 5714cf0368Sopenharmony_ci return false; 5814cf0368Sopenharmony_ci} 5914cf0368Sopenharmony_ci 6014cf0368Sopenharmony_cibool UnifiedDataHelper::IsTempUData(UnifiedData &data) 6114cf0368Sopenharmony_ci{ 6214cf0368Sopenharmony_ci auto records = data.GetRecords(); 6314cf0368Sopenharmony_ci if (records.size() != 1) { 6414cf0368Sopenharmony_ci return false; 6514cf0368Sopenharmony_ci } 6614cf0368Sopenharmony_ci if (records[0] == nullptr || records[0]->GetType() != UDType::FILE) { 6714cf0368Sopenharmony_ci return false; 6814cf0368Sopenharmony_ci } 6914cf0368Sopenharmony_ci auto file = static_cast<File*>(records[0].get()); 7014cf0368Sopenharmony_ci if (file == nullptr) { 7114cf0368Sopenharmony_ci LOG_ERROR(UDMF_FRAMEWORK, "Invalid file record!"); 7214cf0368Sopenharmony_ci return false; 7314cf0368Sopenharmony_ci } 7414cf0368Sopenharmony_ci auto details = file->GetDetails(); 7514cf0368Sopenharmony_ci if (details.find(TEMP_UNIFIED_DATA_FLAG) == details.end()) { 7614cf0368Sopenharmony_ci return false; 7714cf0368Sopenharmony_ci } 7814cf0368Sopenharmony_ci LOG_DEBUG(UDMF_FRAMEWORK, "exist temp unified data flag!"); 7914cf0368Sopenharmony_ci return true; 8014cf0368Sopenharmony_ci} 8114cf0368Sopenharmony_ci 8214cf0368Sopenharmony_civoid UnifiedDataHelper::CreateDirIfNotExist(const std::string& dirPath, const mode_t& mode) 8314cf0368Sopenharmony_ci{ 8414cf0368Sopenharmony_ci if (OHOS::FileExists(dirPath)) { 8514cf0368Sopenharmony_ci if (!OHOS::ForceRemoveDirectory(dirPath)) { 8614cf0368Sopenharmony_ci LOG_ERROR(UDMF_FRAMEWORK, "remove dir %{public}s failed, errno: %{public}d.", dirPath.c_str(), errno); 8714cf0368Sopenharmony_ci } 8814cf0368Sopenharmony_ci } 8914cf0368Sopenharmony_ci LOG_DEBUG(UDMF_FRAMEWORK, "ForceCreateDirectory, dir: %{public}s", dirPath.c_str()); 9014cf0368Sopenharmony_ci bool success = OHOS::ForceCreateDirectory(dirPath); 9114cf0368Sopenharmony_ci if (!success) { 9214cf0368Sopenharmony_ci LOG_ERROR(UDMF_FRAMEWORK, "create dir %{public}s failed, errno: %{public}d.", dirPath.c_str(), errno); 9314cf0368Sopenharmony_ci return; 9414cf0368Sopenharmony_ci } 9514cf0368Sopenharmony_ci if (mode != 0) { 9614cf0368Sopenharmony_ci chmod(dirPath.c_str(), mode); 9714cf0368Sopenharmony_ci } 9814cf0368Sopenharmony_ci} 9914cf0368Sopenharmony_ci 10014cf0368Sopenharmony_civoid UnifiedDataHelper::GetSummary(const UnifiedData &data, Summary &summary) 10114cf0368Sopenharmony_ci{ 10214cf0368Sopenharmony_ci for (const auto &record : data.GetRecords()) { 10314cf0368Sopenharmony_ci int64_t recordSize = record->GetSize(); 10414cf0368Sopenharmony_ci auto udType = UtdUtils::GetUtdIdFromUtdEnum(record->GetType()); 10514cf0368Sopenharmony_ci auto it = summary.summary.find(udType); 10614cf0368Sopenharmony_ci if (it == summary.summary.end()) { 10714cf0368Sopenharmony_ci summary.summary[udType] = recordSize; 10814cf0368Sopenharmony_ci } else { 10914cf0368Sopenharmony_ci summary.summary[udType] += recordSize; 11014cf0368Sopenharmony_ci } 11114cf0368Sopenharmony_ci summary.totalSize += recordSize; 11214cf0368Sopenharmony_ci } 11314cf0368Sopenharmony_ci} 11414cf0368Sopenharmony_ci 11514cf0368Sopenharmony_cibool UnifiedDataHelper::Pack(UnifiedData &data) 11614cf0368Sopenharmony_ci{ 11714cf0368Sopenharmony_ci Summary summary; 11814cf0368Sopenharmony_ci GetSummary(data, summary); 11914cf0368Sopenharmony_ci 12014cf0368Sopenharmony_ci int64_t now = std::chrono::duration_cast<std::chrono::milliseconds> 12114cf0368Sopenharmony_ci (std::chrono::system_clock::now().time_since_epoch()).count(); 12214cf0368Sopenharmony_ci CreateDirIfNotExist(GetRootPath(), MODE); 12314cf0368Sopenharmony_ci std::string filePath = GetRootPath() + std::to_string(now) + TEMP_UNIFIED_DATA_SUFFIX; 12414cf0368Sopenharmony_ci if (!SaveUDataToFile(filePath, data)) { 12514cf0368Sopenharmony_ci LOG_ERROR(UDMF_FRAMEWORK, "fail to save unified data to file"); 12614cf0368Sopenharmony_ci return false; 12714cf0368Sopenharmony_ci } 12814cf0368Sopenharmony_ci std::string uri = AppFileService::CommonFunc::GetUriFromPath(filePath); 12914cf0368Sopenharmony_ci auto fileRecord = std::make_shared<File>(uri); 13014cf0368Sopenharmony_ci UDDetails details; 13114cf0368Sopenharmony_ci details.insert(std::make_pair(TEMP_UNIFIED_DATA_FLAG, true)); 13214cf0368Sopenharmony_ci for (auto &item : summary.summary) { 13314cf0368Sopenharmony_ci details.insert(std::make_pair(item.first, item.second)); 13414cf0368Sopenharmony_ci } 13514cf0368Sopenharmony_ci fileRecord->SetDetails(details); 13614cf0368Sopenharmony_ci std::vector<std::shared_ptr<UnifiedRecord>> records {}; 13714cf0368Sopenharmony_ci records.emplace_back(fileRecord); 13814cf0368Sopenharmony_ci data.SetRecords(records); 13914cf0368Sopenharmony_ci return true; 14014cf0368Sopenharmony_ci} 14114cf0368Sopenharmony_ci 14214cf0368Sopenharmony_cibool UnifiedDataHelper::Unpack(UnifiedData &data) 14314cf0368Sopenharmony_ci{ 14414cf0368Sopenharmony_ci auto records = data.GetRecords(); 14514cf0368Sopenharmony_ci if (records.size() != 1) { 14614cf0368Sopenharmony_ci return false; 14714cf0368Sopenharmony_ci } 14814cf0368Sopenharmony_ci 14914cf0368Sopenharmony_ci auto file = static_cast<File*>(records[0].get()); 15014cf0368Sopenharmony_ci if (file == nullptr) { 15114cf0368Sopenharmony_ci LOG_ERROR(UDMF_FRAMEWORK, "Invalid file record!"); 15214cf0368Sopenharmony_ci return false; 15314cf0368Sopenharmony_ci } 15414cf0368Sopenharmony_ci UnifiedData tempData; 15514cf0368Sopenharmony_ci if (!LoadUDataFromFile(file->GetUri(), tempData)) { 15614cf0368Sopenharmony_ci LOG_ERROR(UDMF_FRAMEWORK, "Fail to load udata from file!"); 15714cf0368Sopenharmony_ci return false; 15814cf0368Sopenharmony_ci } 15914cf0368Sopenharmony_ci data.SetRecords(tempData.GetRecords()); 16014cf0368Sopenharmony_ci return true; 16114cf0368Sopenharmony_ci} 16214cf0368Sopenharmony_ci 16314cf0368Sopenharmony_cibool UnifiedDataHelper::SaveUDataToFile(const std::string &dataFile, UnifiedData &data) 16414cf0368Sopenharmony_ci{ 16514cf0368Sopenharmony_ci std::vector<uint8_t> dataBytes; 16614cf0368Sopenharmony_ci auto recordTlv = TLVObject(dataBytes); 16714cf0368Sopenharmony_ci 16814cf0368Sopenharmony_ci std::FILE *file = fopen(dataFile.c_str(), "w+"); 16914cf0368Sopenharmony_ci if (file == nullptr) { 17014cf0368Sopenharmony_ci LOG_ERROR(UDMF_FRAMEWORK, "failed to open file: %{public}s, errno is %{public}d", dataFile.c_str(), errno); 17114cf0368Sopenharmony_ci return false; 17214cf0368Sopenharmony_ci } 17314cf0368Sopenharmony_ci recordTlv.SetFile(file); 17414cf0368Sopenharmony_ci UdmfConversion::InitValueObject(data); 17514cf0368Sopenharmony_ci if (!TLVUtil::Writing(data, recordTlv, TAG::TAG_UNIFIED_DATA)) { 17614cf0368Sopenharmony_ci LOG_ERROR(UDMF_FRAMEWORK, "TLV Writing failed!"); 17714cf0368Sopenharmony_ci (void)fclose(file); 17814cf0368Sopenharmony_ci return false; 17914cf0368Sopenharmony_ci } 18014cf0368Sopenharmony_ci (void)fclose(file); 18114cf0368Sopenharmony_ci return true; 18214cf0368Sopenharmony_ci} 18314cf0368Sopenharmony_ci 18414cf0368Sopenharmony_cibool UnifiedDataHelper::LoadUDataFromFile(const std::string &dataFile, UnifiedData &data) 18514cf0368Sopenharmony_ci{ 18614cf0368Sopenharmony_ci std::vector<uint8_t> dataBytes; 18714cf0368Sopenharmony_ci auto recordTlv = TLVObject(dataBytes); 18814cf0368Sopenharmony_ci AppFileService::ModuleFileUri::FileUri fileUri(dataFile); 18914cf0368Sopenharmony_ci std::string path = fileUri.GetRealPath(); 19014cf0368Sopenharmony_ci std::FILE *file = fopen(path.c_str(), "r"); 19114cf0368Sopenharmony_ci if (file == nullptr) { 19214cf0368Sopenharmony_ci LOG_ERROR(UDMF_FRAMEWORK, "failed to open file, error:%{public}s, srcdir:%{public}s, relPath:%{public}s", 19314cf0368Sopenharmony_ci std::strerror(errno), 19414cf0368Sopenharmony_ci dataFile.c_str(), 19514cf0368Sopenharmony_ci path.c_str()); 19614cf0368Sopenharmony_ci return false; 19714cf0368Sopenharmony_ci } 19814cf0368Sopenharmony_ci recordTlv.SetFile(file); 19914cf0368Sopenharmony_ci 20014cf0368Sopenharmony_ci if (!TLVUtil::ReadTlv(data, recordTlv, TAG::TAG_UNIFIED_DATA)) { 20114cf0368Sopenharmony_ci LOG_ERROR(UDMF_FRAMEWORK, "TLV Reading failed!"); 20214cf0368Sopenharmony_ci (void)fclose(file); 20314cf0368Sopenharmony_ci return false; 20414cf0368Sopenharmony_ci } 20514cf0368Sopenharmony_ci UdmfConversion::ConvertRecordToSubclass(data); 20614cf0368Sopenharmony_ci (void)fclose(file); 20714cf0368Sopenharmony_ci return true; 20814cf0368Sopenharmony_ci} 20914cf0368Sopenharmony_ci 21014cf0368Sopenharmony_cistd::string UnifiedDataHelper::GetRootPath() 21114cf0368Sopenharmony_ci{ 21214cf0368Sopenharmony_ci if (rootPath_ == "") { 21314cf0368Sopenharmony_ci return TEMP_UNIFIED_DATA_ROOT_PATH; 21414cf0368Sopenharmony_ci } 21514cf0368Sopenharmony_ci return rootPath_; 21614cf0368Sopenharmony_ci} 21714cf0368Sopenharmony_ci} // namespace UDMF 21814cf0368Sopenharmony_ci} // namespace OHOS