13920e296Sopenharmony_ci/* 23920e296Sopenharmony_ci * Copyright (c) 2022 Huawei Device Co., Ltd. 33920e296Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 43920e296Sopenharmony_ci * you may not use this file except in compliance with the License. 53920e296Sopenharmony_ci * You may obtain a copy of the License at 63920e296Sopenharmony_ci * 73920e296Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 83920e296Sopenharmony_ci * 93920e296Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 103920e296Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 113920e296Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 123920e296Sopenharmony_ci * See the License for the specific language governing permissions and 133920e296Sopenharmony_ci * limitations under the License. 143920e296Sopenharmony_ci */ 153920e296Sopenharmony_ci 163920e296Sopenharmony_ci#include "resource_append.h" 173920e296Sopenharmony_ci#include <algorithm> 183920e296Sopenharmony_ci#include <iomanip> 193920e296Sopenharmony_ci#include <iostream> 203920e296Sopenharmony_ci#include <regex> 213920e296Sopenharmony_ci#include "config_parser.h" 223920e296Sopenharmony_ci#include "header.h" 233920e296Sopenharmony_ci#include "id_worker.h" 243920e296Sopenharmony_ci#include "key_parser.h" 253920e296Sopenharmony_ci#include "reference_parser.h" 263920e296Sopenharmony_ci#include "resource_table.h" 273920e296Sopenharmony_ci#include "resource_util.h" 283920e296Sopenharmony_ci#include "select_compile_parse.h" 293920e296Sopenharmony_ci#ifdef __WIN32 303920e296Sopenharmony_ci#include "windows.h" 313920e296Sopenharmony_ci#endif 323920e296Sopenharmony_ci#include "securec.h" 333920e296Sopenharmony_ci 343920e296Sopenharmony_cinamespace OHOS { 353920e296Sopenharmony_cinamespace Global { 363920e296Sopenharmony_cinamespace Restool { 373920e296Sopenharmony_ciusing namespace std; 383920e296Sopenharmony_ci 393920e296Sopenharmony_ciResourceAppend::ResourceAppend(const PackageParser &packageParser) : packageParser_(packageParser) 403920e296Sopenharmony_ci{ 413920e296Sopenharmony_ci} 423920e296Sopenharmony_ci 433920e296Sopenharmony_ciuint32_t ResourceAppend::Append() 443920e296Sopenharmony_ci{ 453920e296Sopenharmony_ci string outputPath = packageParser_.GetOutput(); 463920e296Sopenharmony_ci for (const auto &iter : packageParser_.GetAppend()) { 473920e296Sopenharmony_ci if (!ScanResources(iter, outputPath)) { 483920e296Sopenharmony_ci return RESTOOL_ERROR; 493920e296Sopenharmony_ci } 503920e296Sopenharmony_ci } 513920e296Sopenharmony_ci return RESTOOL_SUCCESS; 523920e296Sopenharmony_ci} 533920e296Sopenharmony_ci 543920e296Sopenharmony_ciuint32_t ResourceAppend::Combine() 553920e296Sopenharmony_ci{ 563920e296Sopenharmony_ci vector<pair<ResType, string>> noBaseResource; 573920e296Sopenharmony_ci for (const auto &iter : packageParser_.GetInputs()) { 583920e296Sopenharmony_ci if (!Combine(iter)) { 593920e296Sopenharmony_ci return RESTOOL_ERROR; 603920e296Sopenharmony_ci } 613920e296Sopenharmony_ci CheckAllItems(noBaseResource); 623920e296Sopenharmony_ci } 633920e296Sopenharmony_ci if (!noBaseResource.empty()) { 643920e296Sopenharmony_ci ResourceUtil::PrintWarningMsg(noBaseResource); 653920e296Sopenharmony_ci } 663920e296Sopenharmony_ci 673920e296Sopenharmony_ci if (!ParseRef()) { 683920e296Sopenharmony_ci return false; 693920e296Sopenharmony_ci } 703920e296Sopenharmony_ci 713920e296Sopenharmony_ci ResourceTable resourceTable; 723920e296Sopenharmony_ci if (resourceTable.CreateResourceTable(items_) != RESTOOL_SUCCESS) { 733920e296Sopenharmony_ci return RESTOOL_ERROR; 743920e296Sopenharmony_ci } 753920e296Sopenharmony_ci return RESTOOL_SUCCESS; 763920e296Sopenharmony_ci} 773920e296Sopenharmony_ci 783920e296Sopenharmony_ci// private 793920e296Sopenharmony_cibool ResourceAppend::Combine(const string &folderPath) 803920e296Sopenharmony_ci{ 813920e296Sopenharmony_ci FileEntry entry(folderPath); 823920e296Sopenharmony_ci if (!entry.Init()) { 833920e296Sopenharmony_ci return false; 843920e296Sopenharmony_ci } 853920e296Sopenharmony_ci 863920e296Sopenharmony_ci itemsForModule_.clear(); 873920e296Sopenharmony_ci for (const auto &child : entry.GetChilds()) { 883920e296Sopenharmony_ci if (!child->IsFile()) { 893920e296Sopenharmony_ci cerr << "Error:" << child->GetFilePath().GetPath() << " not file" << endl; 903920e296Sopenharmony_ci return false; 913920e296Sopenharmony_ci } 923920e296Sopenharmony_ci if (child->GetFilePath().GetFilename() == ID_DEFINED_FILE) { 933920e296Sopenharmony_ci continue; 943920e296Sopenharmony_ci } 953920e296Sopenharmony_ci if (!LoadResourceItem(child->GetFilePath().GetPath())) { 963920e296Sopenharmony_ci return false; 973920e296Sopenharmony_ci } 983920e296Sopenharmony_ci } 993920e296Sopenharmony_ci return true; 1003920e296Sopenharmony_ci} 1013920e296Sopenharmony_ci 1023920e296Sopenharmony_cibool ResourceAppend::ParseRef() 1033920e296Sopenharmony_ci{ 1043920e296Sopenharmony_ci for (auto &iter : refs_) { 1053920e296Sopenharmony_ci ReferenceParser ref; 1063920e296Sopenharmony_ci if (iter->GetResType() == ResType::PROF || iter->GetResType() == ResType::MEDIA) { 1073920e296Sopenharmony_ci if (ref.ParseRefInJsonFile(*iter, packageParser_.GetOutput(), true) != RESTOOL_SUCCESS) { 1083920e296Sopenharmony_ci return false; 1093920e296Sopenharmony_ci } 1103920e296Sopenharmony_ci } else if (ref.ParseRefInResourceItem(*iter) != RESTOOL_SUCCESS) { 1113920e296Sopenharmony_ci return false; 1123920e296Sopenharmony_ci } 1133920e296Sopenharmony_ci } 1143920e296Sopenharmony_ci return true; 1153920e296Sopenharmony_ci} 1163920e296Sopenharmony_ci 1173920e296Sopenharmony_cibool ResourceAppend::ScanResources(const string &resourcePath, const string &outputPath) 1183920e296Sopenharmony_ci{ 1193920e296Sopenharmony_ci if (!ResourceUtil::FileExist(resourcePath)) { 1203920e296Sopenharmony_ci string filePath = FileEntry::FilePath(outputPath).Append(ResourceUtil::GenerateHash(resourcePath)).GetPath(); 1213920e296Sopenharmony_ci if (remove(filePath.c_str()) != 0) { 1223920e296Sopenharmony_ci cerr << "Error: remove failed '" << filePath << "', reason: " << strerror(errno) << endl; 1233920e296Sopenharmony_ci return false; 1243920e296Sopenharmony_ci } 1253920e296Sopenharmony_ci return true; 1263920e296Sopenharmony_ci } 1273920e296Sopenharmony_ci 1283920e296Sopenharmony_ci FileEntry entry(resourcePath); 1293920e296Sopenharmony_ci if (!entry.Init()) { 1303920e296Sopenharmony_ci return false; 1313920e296Sopenharmony_ci } 1323920e296Sopenharmony_ci 1333920e296Sopenharmony_ci if (entry.IsFile()) { 1343920e296Sopenharmony_ci return ScanSingleFile(resourcePath, outputPath); 1353920e296Sopenharmony_ci } 1363920e296Sopenharmony_ci 1373920e296Sopenharmony_ci return ScanSubResources(entry, resourcePath, outputPath); 1383920e296Sopenharmony_ci} 1393920e296Sopenharmony_ci 1403920e296Sopenharmony_cibool ResourceAppend::ScanSubResources(const FileEntry entry, const string &resourcePath, const string &outputPath) 1413920e296Sopenharmony_ci{ 1423920e296Sopenharmony_ci vector<KeyParam> keyParams; 1433920e296Sopenharmony_ci if (KeyParser::Parse(entry.GetFilePath().GetFilename(), keyParams)) { 1443920e296Sopenharmony_ci for (const auto &child : entry.GetChilds()) { 1453920e296Sopenharmony_ci if (!ResourceUtil::IslegalPath(child->GetFilePath().GetFilename())) { 1463920e296Sopenharmony_ci continue; 1473920e296Sopenharmony_ci } 1483920e296Sopenharmony_ci if (!ScanIegalResources(child->GetFilePath().GetPath(), outputPath)) { 1493920e296Sopenharmony_ci return false; 1503920e296Sopenharmony_ci } 1513920e296Sopenharmony_ci } 1523920e296Sopenharmony_ci return true; 1533920e296Sopenharmony_ci } 1543920e296Sopenharmony_ci 1553920e296Sopenharmony_ci if (ResourceUtil::IslegalPath(entry.GetFilePath().GetFilename())) { 1563920e296Sopenharmony_ci return ScanIegalResources(resourcePath, outputPath); 1573920e296Sopenharmony_ci } 1583920e296Sopenharmony_ci 1593920e296Sopenharmony_ci return ScanSubLimitkeyResources(entry, resourcePath, outputPath); 1603920e296Sopenharmony_ci} 1613920e296Sopenharmony_ci 1623920e296Sopenharmony_cibool ResourceAppend::ScanSubLimitkeyResources(const FileEntry entry, const string &resourcePath, 1633920e296Sopenharmony_ci const string &outputPath) 1643920e296Sopenharmony_ci{ 1653920e296Sopenharmony_ci for (const auto &child : entry.GetChilds()) { 1663920e296Sopenharmony_ci string limitKey = child->GetFilePath().GetFilename(); 1673920e296Sopenharmony_ci if (ResourceUtil::IsIgnoreFile(limitKey, child->IsFile())) { 1683920e296Sopenharmony_ci continue; 1693920e296Sopenharmony_ci } 1703920e296Sopenharmony_ci 1713920e296Sopenharmony_ci if (limitKey == RAW_FILE_DIR || limitKey == RES_FILE_DIR) { 1723920e296Sopenharmony_ci if (!ScanRawFilesOrResFiles(child->GetFilePath().GetPath(), outputPath, limitKey)) { 1733920e296Sopenharmony_ci return false; 1743920e296Sopenharmony_ci } 1753920e296Sopenharmony_ci continue; 1763920e296Sopenharmony_ci } 1773920e296Sopenharmony_ci 1783920e296Sopenharmony_ci if (child->IsFile()) { 1793920e296Sopenharmony_ci cerr << "Error: " << child->GetFilePath().GetPath() << " not directory" << endl; 1803920e296Sopenharmony_ci return false; 1813920e296Sopenharmony_ci } 1823920e296Sopenharmony_ci 1833920e296Sopenharmony_ci if (!ScanLimitKey(child, limitKey, outputPath)) { 1843920e296Sopenharmony_ci return false; 1853920e296Sopenharmony_ci } 1863920e296Sopenharmony_ci } 1873920e296Sopenharmony_ci return true; 1883920e296Sopenharmony_ci} 1893920e296Sopenharmony_ci 1903920e296Sopenharmony_cibool ResourceAppend::ScanIegalResources(const string &resourcePath, const string &outputPath) 1913920e296Sopenharmony_ci{ 1923920e296Sopenharmony_ci FileEntry entry(resourcePath); 1933920e296Sopenharmony_ci if (!entry.Init()) { 1943920e296Sopenharmony_ci return false; 1953920e296Sopenharmony_ci } 1963920e296Sopenharmony_ci for (const auto &child : entry.GetChilds()) { 1973920e296Sopenharmony_ci if (!ScanSingleFile(child->GetFilePath().GetPath(), outputPath)) { 1983920e296Sopenharmony_ci return false; 1993920e296Sopenharmony_ci } 2003920e296Sopenharmony_ci } 2013920e296Sopenharmony_ci return true; 2023920e296Sopenharmony_ci} 2033920e296Sopenharmony_cibool ResourceAppend::ScanLimitKey(const unique_ptr<FileEntry> &entry, 2043920e296Sopenharmony_ci const string &limitKey, const string outputPath) 2053920e296Sopenharmony_ci{ 2063920e296Sopenharmony_ci vector<KeyParam> keyParams; 2073920e296Sopenharmony_ci if (!KeyParser::Parse(limitKey, keyParams)) { 2083920e296Sopenharmony_ci cerr << "Error: invalid limit key '" << limitKey << "'."; 2093920e296Sopenharmony_ci cerr << NEW_LINE_PATH << entry->GetFilePath().GetPath() << endl; 2103920e296Sopenharmony_ci return false; 2113920e296Sopenharmony_ci } 2123920e296Sopenharmony_ci 2133920e296Sopenharmony_ci for (const auto &child : entry->GetChilds()) { 2143920e296Sopenharmony_ci string fileCuster = child->GetFilePath().GetFilename(); 2153920e296Sopenharmony_ci if (ResourceUtil::IsIgnoreFile(fileCuster, child->IsFile())) { 2163920e296Sopenharmony_ci continue; 2173920e296Sopenharmony_ci } 2183920e296Sopenharmony_ci 2193920e296Sopenharmony_ci if (child->IsFile()) { 2203920e296Sopenharmony_ci cerr << "Error: " << child->GetFilePath().GetPath() << " not directory" << endl; 2213920e296Sopenharmony_ci return false; 2223920e296Sopenharmony_ci } 2233920e296Sopenharmony_ci 2243920e296Sopenharmony_ci ResType resType = ResourceUtil::GetResTypeByDir(fileCuster); 2253920e296Sopenharmony_ci if (resType == ResType::INVALID_RES_TYPE) { 2263920e296Sopenharmony_ci cerr << "Error: invalid resType." << NEW_LINE_PATH << child->GetFilePath().GetPath() << endl; 2273920e296Sopenharmony_ci return false; 2283920e296Sopenharmony_ci } 2293920e296Sopenharmony_ci 2303920e296Sopenharmony_ci DirectoryInfo directoryInfo = { limitKey, fileCuster, child->GetFilePath().GetPath(), keyParams, resType}; 2313920e296Sopenharmony_ci if (!ScanFiles(child, directoryInfo, outputPath)) { 2323920e296Sopenharmony_ci return false; 2333920e296Sopenharmony_ci } 2343920e296Sopenharmony_ci } 2353920e296Sopenharmony_ci return true; 2363920e296Sopenharmony_ci} 2373920e296Sopenharmony_ci 2383920e296Sopenharmony_ci 2393920e296Sopenharmony_cibool ResourceAppend::ScanFiles(const unique_ptr<FileEntry> &entry, 2403920e296Sopenharmony_ci const DirectoryInfo &directoryInfo, const string &outputPath) 2413920e296Sopenharmony_ci{ 2423920e296Sopenharmony_ci for (const auto &child : entry->GetChilds()) { 2433920e296Sopenharmony_ci string filename = child->GetFilePath().GetFilename(); 2443920e296Sopenharmony_ci if (ResourceUtil::IsIgnoreFile(filename, child->IsFile())) { 2453920e296Sopenharmony_ci continue; 2463920e296Sopenharmony_ci } 2473920e296Sopenharmony_ci 2483920e296Sopenharmony_ci if (!child->IsFile()) { 2493920e296Sopenharmony_ci cerr << "Error: '" << child->GetFilePath().GetPath() << "' not file." << endl; 2503920e296Sopenharmony_ci return false; 2513920e296Sopenharmony_ci } 2523920e296Sopenharmony_ci 2533920e296Sopenharmony_ci FileInfo fileInfo = {directoryInfo, child->GetFilePath().GetPath(), filename}; 2543920e296Sopenharmony_ci if (!ScanFile(fileInfo, outputPath)) { 2553920e296Sopenharmony_ci return false; 2563920e296Sopenharmony_ci } 2573920e296Sopenharmony_ci } 2583920e296Sopenharmony_ci return true; 2593920e296Sopenharmony_ci} 2603920e296Sopenharmony_ci 2613920e296Sopenharmony_cibool ResourceAppend::ScanFile(const FileInfo &fileInfo, const string &outputPath) 2623920e296Sopenharmony_ci{ 2633920e296Sopenharmony_ci if (ResourceAppend::IsBaseIdDefined(fileInfo)) { 2643920e296Sopenharmony_ci cout << "Warning: id_defined.json does not compile to generate intermediate files" << endl; 2653920e296Sopenharmony_ci FileEntry::FilePath outPath(outputPath); 2663920e296Sopenharmony_ci return ResourceUtil::CopyFileInner(fileInfo.filePath, outPath.Append(ID_DEFINED_FILE).GetPath()); 2673920e296Sopenharmony_ci } 2683920e296Sopenharmony_ci 2693920e296Sopenharmony_ci unique_ptr<IResourceCompiler> resourceCompiler = 2703920e296Sopenharmony_ci FactoryResourceCompiler::CreateCompilerForAppend(fileInfo.dirType, outputPath); 2713920e296Sopenharmony_ci if (resourceCompiler == nullptr) { 2723920e296Sopenharmony_ci return true; 2733920e296Sopenharmony_ci } 2743920e296Sopenharmony_ci 2753920e296Sopenharmony_ci if (resourceCompiler->CompileForAppend(fileInfo) != RESTOOL_SUCCESS) { 2763920e296Sopenharmony_ci return false; 2773920e296Sopenharmony_ci } 2783920e296Sopenharmony_ci 2793920e296Sopenharmony_ci ostringstream outStream; 2803920e296Sopenharmony_ci const auto &items = resourceCompiler->GetResourceItems(); 2813920e296Sopenharmony_ci for (const auto &item : items) { 2823920e296Sopenharmony_ci for (const auto &resourceItem : item.second) { 2833920e296Sopenharmony_ci if (!WriteResourceItem(resourceItem, outStream)) { 2843920e296Sopenharmony_ci return false; 2853920e296Sopenharmony_ci } 2863920e296Sopenharmony_ci } 2873920e296Sopenharmony_ci } 2883920e296Sopenharmony_ci 2893920e296Sopenharmony_ci string hash = ResourceUtil::GenerateHash(fileInfo.filePath); 2903920e296Sopenharmony_ci FileEntry::FilePath output(outputPath); 2913920e296Sopenharmony_ci if (!WriteFileInner(outStream, output.Append(hash).GetPath())) { 2923920e296Sopenharmony_ci return false; 2933920e296Sopenharmony_ci } 2943920e296Sopenharmony_ci return true; 2953920e296Sopenharmony_ci} 2963920e296Sopenharmony_ci 2973920e296Sopenharmony_cibool ResourceAppend::ScanSingleFile(const string &filePath, const string &outputPath) 2983920e296Sopenharmony_ci{ 2993920e296Sopenharmony_ci if (filePath.find(RAW_FILE_DIR) != string::npos) { 3003920e296Sopenharmony_ci return WriteRawFilesOrResFiles(filePath, outputPath, RAW_FILE_DIR); 3013920e296Sopenharmony_ci } 3023920e296Sopenharmony_ci 3033920e296Sopenharmony_ci if (filePath.find(RES_FILE_DIR) != string::npos) { 3043920e296Sopenharmony_ci return WriteRawFilesOrResFiles(filePath, outputPath, RES_FILE_DIR); 3053920e296Sopenharmony_ci } 3063920e296Sopenharmony_ci 3073920e296Sopenharmony_ci FileEntry::FilePath path(filePath); 3083920e296Sopenharmony_ci string fileCuster = path.GetParent().GetFilename(); 3093920e296Sopenharmony_ci ResType resType = ResourceUtil::GetResTypeByDir(fileCuster); 3103920e296Sopenharmony_ci if (resType == ResType::INVALID_RES_TYPE) { 3113920e296Sopenharmony_ci cerr << "Error: invalid resType." << NEW_LINE_PATH << filePath << endl; 3123920e296Sopenharmony_ci return false; 3133920e296Sopenharmony_ci } 3143920e296Sopenharmony_ci 3153920e296Sopenharmony_ci string limitKey = path.GetParent().GetParent().GetFilename(); 3163920e296Sopenharmony_ci vector<KeyParam> keyParams; 3173920e296Sopenharmony_ci if (!KeyParser::Parse(limitKey, keyParams)) { 3183920e296Sopenharmony_ci cerr << "Error: invalid limit key." << NEW_LINE_PATH << filePath << endl; 3193920e296Sopenharmony_ci return false; 3203920e296Sopenharmony_ci } 3213920e296Sopenharmony_ci 3223920e296Sopenharmony_ci DirectoryInfo directoryInfo = {limitKey, fileCuster, path.GetParent().GetPath(), keyParams, resType}; 3233920e296Sopenharmony_ci FileInfo fileInfo = {directoryInfo, filePath, path.GetFilename() }; 3243920e296Sopenharmony_ci if (!ScanFile(fileInfo, outputPath)) { 3253920e296Sopenharmony_ci return false; 3263920e296Sopenharmony_ci } 3273920e296Sopenharmony_ci return true; 3283920e296Sopenharmony_ci} 3293920e296Sopenharmony_ci 3303920e296Sopenharmony_cibool ResourceAppend::WriteFileInner(ostringstream &outStream, const string &outputPath) const 3313920e296Sopenharmony_ci{ 3323920e296Sopenharmony_ci#ifdef __WIN32 3333920e296Sopenharmony_ci HANDLE hWriteFile = CreateFile(outputPath.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, 3343920e296Sopenharmony_ci nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); 3353920e296Sopenharmony_ci if (hWriteFile == INVALID_HANDLE_VALUE) { 3363920e296Sopenharmony_ci cerr << "Error: '" << outputPath << "' " << GetLastError() << endl; 3373920e296Sopenharmony_ci return false; 3383920e296Sopenharmony_ci } 3393920e296Sopenharmony_ci 3403920e296Sopenharmony_ci DWORD writeBytes; 3413920e296Sopenharmony_ci if (!WriteFile(hWriteFile, outStream.str().c_str(), outStream.tellp(), &writeBytes, nullptr)) { 3423920e296Sopenharmony_ci cerr << "Error: write '" << outputPath << "' " << GetLastError() << endl; 3433920e296Sopenharmony_ci CloseHandle(hWriteFile); 3443920e296Sopenharmony_ci return false; 3453920e296Sopenharmony_ci } 3463920e296Sopenharmony_ci CloseHandle(hWriteFile); 3473920e296Sopenharmony_ci#else 3483920e296Sopenharmony_ci ofstream out(outputPath, ofstream::out | ofstream::binary); 3493920e296Sopenharmony_ci if (!out.is_open()) { 3503920e296Sopenharmony_ci cerr << "Error: open failed '" << outputPath << "', reason: " << strerror(errno) << endl; 3513920e296Sopenharmony_ci return false; 3523920e296Sopenharmony_ci } 3533920e296Sopenharmony_ci out << outStream.str(); 3543920e296Sopenharmony_ci#endif 3553920e296Sopenharmony_ci return true; 3563920e296Sopenharmony_ci} 3573920e296Sopenharmony_ci 3583920e296Sopenharmony_cibool ResourceAppend::WriteResourceItem(const ResourceItem &resourceItem, ostringstream &out) 3593920e296Sopenharmony_ci{ 3603920e296Sopenharmony_ci uint32_t size = resourceItem.GetName().length(); 3613920e296Sopenharmony_ci out.write(reinterpret_cast<const char *>(&size), sizeof(int32_t)); 3623920e296Sopenharmony_ci out.write(reinterpret_cast<const char *>(resourceItem.GetName().c_str()), size); 3633920e296Sopenharmony_ci 3643920e296Sopenharmony_ci size = resourceItem.GetLimitKey().length(); 3653920e296Sopenharmony_ci out.write(reinterpret_cast<const char *>(&size), sizeof(int32_t)); 3663920e296Sopenharmony_ci out.write(reinterpret_cast<const char *>(resourceItem.GetLimitKey().c_str()), size); 3673920e296Sopenharmony_ci 3683920e296Sopenharmony_ci size = resourceItem.GetFilePath().length(); 3693920e296Sopenharmony_ci out.write(reinterpret_cast<const char *>(&size), sizeof(int32_t)); 3703920e296Sopenharmony_ci out.write(reinterpret_cast<const char *>(resourceItem.GetFilePath().c_str()), size); 3713920e296Sopenharmony_ci 3723920e296Sopenharmony_ci int32_t type = static_cast<int32_t>(resourceItem.GetResType()); 3733920e296Sopenharmony_ci out.write(reinterpret_cast<const char *>(&type), sizeof(int32_t)); 3743920e296Sopenharmony_ci 3753920e296Sopenharmony_ci size = resourceItem.GetKeyParam().size(); 3763920e296Sopenharmony_ci out.write(reinterpret_cast<const char *>(&size), sizeof(int32_t)); 3773920e296Sopenharmony_ci for (const auto &keyParam : resourceItem.GetKeyParam()) { 3783920e296Sopenharmony_ci out.write(reinterpret_cast<const char *>(&keyParam.keyType), sizeof(int32_t)); 3793920e296Sopenharmony_ci out.write(reinterpret_cast<const char *>(&keyParam.value), sizeof(int32_t)); 3803920e296Sopenharmony_ci } 3813920e296Sopenharmony_ci 3823920e296Sopenharmony_ci size = resourceItem.GetDataLength(); 3833920e296Sopenharmony_ci out.write(reinterpret_cast<const char *>(&size), sizeof(int32_t)); 3843920e296Sopenharmony_ci out.write(reinterpret_cast<const char *>(resourceItem.GetData()), size); 3853920e296Sopenharmony_ci return true; 3863920e296Sopenharmony_ci} 3873920e296Sopenharmony_ci 3883920e296Sopenharmony_cibool ResourceAppend::LoadResourceItem(const string &filePath) 3893920e296Sopenharmony_ci{ 3903920e296Sopenharmony_ci#ifdef __WIN32 3913920e296Sopenharmony_ci return LoadResourceItemWin(filePath); 3923920e296Sopenharmony_ci#else 3933920e296Sopenharmony_ci ifstream in(filePath, ifstream::in | ifstream::binary); 3943920e296Sopenharmony_ci if (!in.is_open()) { 3953920e296Sopenharmony_ci cerr << "Error: open failed '" << filePath << "', reason: " << strerror(errno) << endl; 3963920e296Sopenharmony_ci return false; 3973920e296Sopenharmony_ci } 3983920e296Sopenharmony_ci 3993920e296Sopenharmony_ci in.seekg(0, in.end); 4003920e296Sopenharmony_ci int32_t length = in.tellg(); 4013920e296Sopenharmony_ci in.seekg(0, in.beg); 4023920e296Sopenharmony_ci if (length <= 0) { 4033920e296Sopenharmony_ci cerr << "Error: invalid file size = " << length << NEW_LINE_PATH << filePath << endl; 4043920e296Sopenharmony_ci return false; 4053920e296Sopenharmony_ci } 4063920e296Sopenharmony_ci char buffer[length]; 4073920e296Sopenharmony_ci in.read(buffer, length); 4083920e296Sopenharmony_ci return LoadResourceItemFromMem(buffer, length); 4093920e296Sopenharmony_ci#endif 4103920e296Sopenharmony_ci} 4113920e296Sopenharmony_ci 4123920e296Sopenharmony_cibool ResourceAppend::ScanRawFilesOrResFiles(const string &path, const string &outputPath, const string &limit) 4133920e296Sopenharmony_ci{ 4143920e296Sopenharmony_ci FileEntry entry(path); 4153920e296Sopenharmony_ci if (!entry.Init()) { 4163920e296Sopenharmony_ci return false; 4173920e296Sopenharmony_ci } 4183920e296Sopenharmony_ci 4193920e296Sopenharmony_ci for (const auto &child : entry.GetChilds()) { 4203920e296Sopenharmony_ci string filename = child->GetFilePath().GetFilename(); 4213920e296Sopenharmony_ci if (ResourceUtil::IsIgnoreFile(filename, child->IsFile())) { 4223920e296Sopenharmony_ci continue; 4233920e296Sopenharmony_ci } 4243920e296Sopenharmony_ci 4253920e296Sopenharmony_ci bool ret = false; 4263920e296Sopenharmony_ci if (child->IsFile()) { 4273920e296Sopenharmony_ci ret = WriteRawFilesOrResFiles(child->GetFilePath().GetPath(), outputPath, limit); 4283920e296Sopenharmony_ci } else { 4293920e296Sopenharmony_ci ret = ScanRawFilesOrResFiles(child->GetFilePath().GetPath(), outputPath, limit); 4303920e296Sopenharmony_ci } 4313920e296Sopenharmony_ci 4323920e296Sopenharmony_ci if (!ret) { 4333920e296Sopenharmony_ci return false; 4343920e296Sopenharmony_ci } 4353920e296Sopenharmony_ci } 4363920e296Sopenharmony_ci return true; 4373920e296Sopenharmony_ci} 4383920e296Sopenharmony_ci 4393920e296Sopenharmony_cibool ResourceAppend::WriteRawFilesOrResFiles(const string &filePath, const string &outputPath, const string &limit) 4403920e296Sopenharmony_ci{ 4413920e296Sopenharmony_ci string::size_type pos = filePath.find(limit); 4423920e296Sopenharmony_ci if (pos == string::npos) { 4433920e296Sopenharmony_ci cerr << "Error: invalid file path." << NEW_LINE_PATH << filePath << endl; 4443920e296Sopenharmony_ci return false; 4453920e296Sopenharmony_ci } 4463920e296Sopenharmony_ci 4473920e296Sopenharmony_ci string sub = filePath.substr(pos); 4483920e296Sopenharmony_ci sub = FileEntry::FilePath(RESOURCES_DIR).Append(sub).GetPath(); 4493920e296Sopenharmony_ci vector<KeyParam> keyParams; 4503920e296Sopenharmony_ci auto iter = g_copyFileMap.find(limit); 4513920e296Sopenharmony_ci ResourceItem resourceItem("", keyParams, iter->second); 4523920e296Sopenharmony_ci resourceItem.SetData(sub); 4533920e296Sopenharmony_ci resourceItem.SetFilePath(filePath); 4543920e296Sopenharmony_ci resourceItem.SetLimitKey(""); 4553920e296Sopenharmony_ci 4563920e296Sopenharmony_ci ostringstream outStream; 4573920e296Sopenharmony_ci if (!WriteResourceItem(resourceItem, outStream)) { 4583920e296Sopenharmony_ci return false; 4593920e296Sopenharmony_ci } 4603920e296Sopenharmony_ci 4613920e296Sopenharmony_ci string hash = ResourceUtil::GenerateHash(filePath); 4623920e296Sopenharmony_ci FileEntry::FilePath output(outputPath); 4633920e296Sopenharmony_ci if (!WriteFileInner(outStream, output.Append(hash).GetPath())) { 4643920e296Sopenharmony_ci return false; 4653920e296Sopenharmony_ci } 4663920e296Sopenharmony_ci return true; 4673920e296Sopenharmony_ci} 4683920e296Sopenharmony_ci 4693920e296Sopenharmony_cibool ResourceAppend::Push(const shared_ptr<ResourceItem> &resourceItem) 4703920e296Sopenharmony_ci{ 4713920e296Sopenharmony_ci string idName = ResourceUtil::GetIdName(resourceItem->GetName(), resourceItem->GetResType()); 4723920e296Sopenharmony_ci int64_t id = IdWorker::GetInstance().GenerateId(resourceItem->GetResType(), idName); 4733920e296Sopenharmony_ci if (id < 0) { 4743920e296Sopenharmony_ci return false; 4753920e296Sopenharmony_ci } 4763920e296Sopenharmony_ci 4773920e296Sopenharmony_ci if (!CheckModuleResourceItem(resourceItem, id)) { 4783920e296Sopenharmony_ci return false; 4793920e296Sopenharmony_ci } 4803920e296Sopenharmony_ci 4813920e296Sopenharmony_ci const auto &result = items_.find(id); 4823920e296Sopenharmony_ci if (result == items_.end()) { 4833920e296Sopenharmony_ci items_[id].push_back(resourceItem); 4843920e296Sopenharmony_ci AddRef(resourceItem); 4853920e296Sopenharmony_ci return true; 4863920e296Sopenharmony_ci } 4873920e296Sopenharmony_ci 4883920e296Sopenharmony_ci if (find_if(result->second.begin(), result->second.end(), [resourceItem](auto &iter) { 4893920e296Sopenharmony_ci return resourceItem->GetLimitKey() == iter->GetLimitKey(); 4903920e296Sopenharmony_ci }) != result->second.end()) { 4913920e296Sopenharmony_ci return true; 4923920e296Sopenharmony_ci } 4933920e296Sopenharmony_ci 4943920e296Sopenharmony_ci items_[id].push_back(resourceItem); 4953920e296Sopenharmony_ci AddRef(resourceItem); 4963920e296Sopenharmony_ci return true; 4973920e296Sopenharmony_ci} 4983920e296Sopenharmony_ci 4993920e296Sopenharmony_civoid ResourceAppend::AddRef(const shared_ptr<ResourceItem> &resourceItem) 5003920e296Sopenharmony_ci{ 5013920e296Sopenharmony_ci string data(reinterpret_cast<const char *>(resourceItem->GetData()), resourceItem->GetDataLength()); 5023920e296Sopenharmony_ci ResType resType = resourceItem->GetResType(); 5033920e296Sopenharmony_ci if (resType == ResType::MEDIA) { 5043920e296Sopenharmony_ci if (FileEntry::FilePath(resourceItem->GetFilePath()).GetExtension() == JSON_EXTENSION) { 5053920e296Sopenharmony_ci refs_.push_back(resourceItem); 5063920e296Sopenharmony_ci } 5073920e296Sopenharmony_ci return; 5083920e296Sopenharmony_ci } 5093920e296Sopenharmony_ci 5103920e296Sopenharmony_ci if (resType == ResType::PROF) { 5113920e296Sopenharmony_ci if (resourceItem->GetLimitKey() != "base" || 5123920e296Sopenharmony_ci FileEntry::FilePath(resourceItem->GetFilePath()).GetExtension() != JSON_EXTENSION) { 5133920e296Sopenharmony_ci return; 5143920e296Sopenharmony_ci } 5153920e296Sopenharmony_ci refs_.push_back(resourceItem); 5163920e296Sopenharmony_ci return; 5173920e296Sopenharmony_ci } 5183920e296Sopenharmony_ci 5193920e296Sopenharmony_ci if (regex_match(data, regex(".*\\$.+:.*"))) { 5203920e296Sopenharmony_ci refs_.push_back(resourceItem); 5213920e296Sopenharmony_ci } 5223920e296Sopenharmony_ci} 5233920e296Sopenharmony_ci 5243920e296Sopenharmony_cibool ResourceAppend::LoadResourceItemFromMem(const char buffer[], int32_t length) 5253920e296Sopenharmony_ci{ 5263920e296Sopenharmony_ci int32_t offset = 0; 5273920e296Sopenharmony_ci do { 5283920e296Sopenharmony_ci // name 5293920e296Sopenharmony_ci string nameStr = ParseString(buffer, length, offset); 5303920e296Sopenharmony_ci // limit key 5313920e296Sopenharmony_ci string limitKeyStr = ParseString(buffer, length, offset); 5323920e296Sopenharmony_ci // file path 5333920e296Sopenharmony_ci string filePathStr = ParseString(buffer, length, offset); 5343920e296Sopenharmony_ci // ResType 5353920e296Sopenharmony_ci int32_t type = ParseInt32(buffer, length, offset); 5363920e296Sopenharmony_ci ResType resType = static_cast<ResType>(type); 5373920e296Sopenharmony_ci // keyParam 5383920e296Sopenharmony_ci int32_t keyParamSize = ParseInt32(buffer, length, offset); 5393920e296Sopenharmony_ci vector<KeyParam> keyParams; 5403920e296Sopenharmony_ci for (int i = 0; i < keyParamSize; i++) { 5413920e296Sopenharmony_ci KeyParam keyParam; 5423920e296Sopenharmony_ci keyParam.keyType = static_cast<KeyType>(ParseInt32(buffer, length, offset)); 5433920e296Sopenharmony_ci int32_t value = ParseInt32(buffer, length, offset); 5443920e296Sopenharmony_ci if (value == -1) { 5453920e296Sopenharmony_ci return false; 5463920e296Sopenharmony_ci } 5473920e296Sopenharmony_ci keyParam.value = static_cast<uint32_t>(value); 5483920e296Sopenharmony_ci keyParams.push_back(keyParam); 5493920e296Sopenharmony_ci } 5503920e296Sopenharmony_ci if (limitKeyStr != "base" && !limitKeyStr.empty() && !SelectCompileParse::IsSelectCompile(keyParams)) { 5513920e296Sopenharmony_ci return true; 5523920e296Sopenharmony_ci } 5533920e296Sopenharmony_ci // data 5543920e296Sopenharmony_ci string data = ParseString(buffer, length, offset); 5553920e296Sopenharmony_ci if (resType == ResType::RAW || resType == ResType::RES) { 5563920e296Sopenharmony_ci FileEntry::FilePath outPath(packageParser_.GetOutput()); 5573920e296Sopenharmony_ci if (ResourceUtil::FileExist(outPath.Append(data).GetPath())) { 5583920e296Sopenharmony_ci continue; 5593920e296Sopenharmony_ci } 5603920e296Sopenharmony_ci if (!ResourceUtil::CreateDirs(outPath.Append(data).GetParent().GetPath())) { 5613920e296Sopenharmony_ci return false; 5623920e296Sopenharmony_ci } 5633920e296Sopenharmony_ci 5643920e296Sopenharmony_ci if (!ResourceUtil::FileExist(filePathStr)) { 5653920e296Sopenharmony_ci continue; 5663920e296Sopenharmony_ci } 5673920e296Sopenharmony_ci 5683920e296Sopenharmony_ci if (!ResourceUtil::CopyFileInner(filePathStr, outPath.Append(data).GetPath())) { 5693920e296Sopenharmony_ci return false; 5703920e296Sopenharmony_ci } 5713920e296Sopenharmony_ci continue; 5723920e296Sopenharmony_ci } 5733920e296Sopenharmony_ci 5743920e296Sopenharmony_ci shared_ptr<ResourceItem> resourceItem = make_shared<ResourceItem>(nameStr, keyParams, resType); 5753920e296Sopenharmony_ci resourceItem->SetData(reinterpret_cast<const int8_t *>(data.c_str()), data.length()); 5763920e296Sopenharmony_ci resourceItem->SetLimitKey(limitKeyStr); 5773920e296Sopenharmony_ci resourceItem->SetFilePath(filePathStr); 5783920e296Sopenharmony_ci if (!Push(resourceItem)) { 5793920e296Sopenharmony_ci return false; 5803920e296Sopenharmony_ci } 5813920e296Sopenharmony_ci } while (offset < length); 5823920e296Sopenharmony_ci return true; 5833920e296Sopenharmony_ci} 5843920e296Sopenharmony_ci 5853920e296Sopenharmony_cistring ResourceAppend::ParseString(const char buffer[], int32_t length, int32_t &offset) const 5863920e296Sopenharmony_ci{ 5873920e296Sopenharmony_ci int32_t size = ParseInt32(buffer, length, offset); 5883920e296Sopenharmony_ci if (size < 0 || offset + size > length) { 5893920e296Sopenharmony_ci offset = length; 5903920e296Sopenharmony_ci return ""; 5913920e296Sopenharmony_ci } 5923920e296Sopenharmony_ci 5933920e296Sopenharmony_ci if (size == 0) { 5943920e296Sopenharmony_ci return ""; 5953920e296Sopenharmony_ci } 5963920e296Sopenharmony_ci 5973920e296Sopenharmony_ci string value(buffer + offset, size); 5983920e296Sopenharmony_ci offset += size; 5993920e296Sopenharmony_ci return value; 6003920e296Sopenharmony_ci} 6013920e296Sopenharmony_ci 6023920e296Sopenharmony_ciint32_t ResourceAppend::ParseInt32(const char buffer[], int32_t length, int32_t &offset) const 6033920e296Sopenharmony_ci{ 6043920e296Sopenharmony_ci if (offset + static_cast<int32_t>(sizeof(int32_t)) > length) { 6053920e296Sopenharmony_ci offset = length; 6063920e296Sopenharmony_ci return -1; 6073920e296Sopenharmony_ci } 6083920e296Sopenharmony_ci 6093920e296Sopenharmony_ci int32_t size = 0; 6103920e296Sopenharmony_ci if (memcpy_s(&size, sizeof(int32_t), buffer + offset, sizeof(int32_t)) != EOK) { 6113920e296Sopenharmony_ci offset = length; 6123920e296Sopenharmony_ci return -1; 6133920e296Sopenharmony_ci } 6143920e296Sopenharmony_ci offset += sizeof(int32_t); 6153920e296Sopenharmony_ci return size; 6163920e296Sopenharmony_ci} 6173920e296Sopenharmony_ci 6183920e296Sopenharmony_cibool ResourceAppend::CheckModuleResourceItem(const shared_ptr<ResourceItem> &resourceItem, int64_t id) 6193920e296Sopenharmony_ci{ 6203920e296Sopenharmony_ci const auto &result = itemsForModule_.find(id); 6213920e296Sopenharmony_ci if (result == itemsForModule_.end()) { 6223920e296Sopenharmony_ci itemsForModule_[id].push_back(resourceItem); 6233920e296Sopenharmony_ci return true; 6243920e296Sopenharmony_ci } 6253920e296Sopenharmony_ci 6263920e296Sopenharmony_ci const auto &ret = find_if(result->second.begin(), result->second.end(), [resourceItem](auto iter) { 6273920e296Sopenharmony_ci return resourceItem->GetLimitKey() == iter->GetLimitKey(); 6283920e296Sopenharmony_ci }); 6293920e296Sopenharmony_ci 6303920e296Sopenharmony_ci if (ret != result->second.end()) { 6313920e296Sopenharmony_ci cerr << "Error: '" << resourceItem->GetName() << "' conflict, first declared."; 6323920e296Sopenharmony_ci cerr << NEW_LINE_PATH << (*ret)->GetFilePath() << endl; 6333920e296Sopenharmony_ci cerr << "but declared again." << NEW_LINE_PATH << resourceItem->GetFilePath() << endl; 6343920e296Sopenharmony_ci return false; 6353920e296Sopenharmony_ci } 6363920e296Sopenharmony_ci 6373920e296Sopenharmony_ci itemsForModule_[id].push_back(resourceItem); 6383920e296Sopenharmony_ci return true; 6393920e296Sopenharmony_ci} 6403920e296Sopenharmony_ci 6413920e296Sopenharmony_ci#ifdef __WIN32 6423920e296Sopenharmony_cibool ResourceAppend::LoadResourceItemWin(const string &filePath) 6433920e296Sopenharmony_ci{ 6443920e296Sopenharmony_ci bool result = false; 6453920e296Sopenharmony_ci HANDLE hReadFile = CreateFile(filePath.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 6463920e296Sopenharmony_ci FILE_ATTRIBUTE_READONLY | FILE_FLAG_RANDOM_ACCESS, nullptr); 6473920e296Sopenharmony_ci if (hReadFile == INVALID_HANDLE_VALUE) { 6483920e296Sopenharmony_ci cerr << "Error: "<< GetLastError() << NEW_LINE_PATH << filePath << endl; 6493920e296Sopenharmony_ci return result; 6503920e296Sopenharmony_ci } 6513920e296Sopenharmony_ci 6523920e296Sopenharmony_ci DWORD fileSize = GetFileSize(hReadFile, nullptr); 6533920e296Sopenharmony_ci HANDLE hFileMap = CreateFileMapping(hReadFile, nullptr, PAGE_READONLY, 0, fileSize, nullptr); 6543920e296Sopenharmony_ci if (hFileMap == INVALID_HANDLE_VALUE) { 6553920e296Sopenharmony_ci cerr << "Error: create file mapping " << GetLastError() << endl; 6563920e296Sopenharmony_ci CloseHandle(hReadFile); 6573920e296Sopenharmony_ci return result; 6583920e296Sopenharmony_ci } 6593920e296Sopenharmony_ci 6603920e296Sopenharmony_ci void* pBuffer = MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, 0); 6613920e296Sopenharmony_ci if (pBuffer == nullptr) { 6623920e296Sopenharmony_ci cerr << "Error: map view of file " << GetLastError() << endl; 6633920e296Sopenharmony_ci CloseHandle(hReadFile); 6643920e296Sopenharmony_ci return result; 6653920e296Sopenharmony_ci } 6663920e296Sopenharmony_ci 6673920e296Sopenharmony_ci char* buffer = reinterpret_cast<char *>(pBuffer); 6683920e296Sopenharmony_ci result = LoadResourceItemFromMem(buffer, fileSize); 6693920e296Sopenharmony_ci UnmapViewOfFile(hFileMap); 6703920e296Sopenharmony_ci CloseHandle(hReadFile); 6713920e296Sopenharmony_ci return result; 6723920e296Sopenharmony_ci} 6733920e296Sopenharmony_ci#endif 6743920e296Sopenharmony_ci 6753920e296Sopenharmony_cibool ResourceAppend::IsBaseIdDefined(const FileInfo &fileInfo) 6763920e296Sopenharmony_ci{ 6773920e296Sopenharmony_ci FileEntry::FilePath filePath(fileInfo.filePath); 6783920e296Sopenharmony_ci return filePath.GetParent().GetParent().GetFilename() == "base" && 6793920e296Sopenharmony_ci filePath.GetParent().GetFilename() == "element" && 6803920e296Sopenharmony_ci fileInfo.filename == ID_DEFINED_FILE; 6813920e296Sopenharmony_ci} 6823920e296Sopenharmony_ci 6833920e296Sopenharmony_civoid ResourceAppend::CheckAllItems(vector<pair<ResType, string>> &noBaseResource) 6843920e296Sopenharmony_ci{ 6853920e296Sopenharmony_ci for (const auto &item : items_) { 6863920e296Sopenharmony_ci bool found = any_of(item.second.begin(), item.second.end(), [](const auto &iter) { 6873920e296Sopenharmony_ci return iter->GetLimitKey() == "base"; 6883920e296Sopenharmony_ci }); 6893920e296Sopenharmony_ci if (!found) { 6903920e296Sopenharmony_ci auto firstItem = item.second.front(); 6913920e296Sopenharmony_ci bool ret = any_of(noBaseResource.begin(), noBaseResource.end(), [firstItem](const auto &iterItem) { 6923920e296Sopenharmony_ci return (firstItem->GetResType() == iterItem.first) && 6933920e296Sopenharmony_ci (firstItem->GetName() == iterItem.second); 6943920e296Sopenharmony_ci }); 6953920e296Sopenharmony_ci if (!ret) { 6963920e296Sopenharmony_ci noBaseResource.push_back(make_pair(firstItem->GetResType(), firstItem->GetName())); 6973920e296Sopenharmony_ci } 6983920e296Sopenharmony_ci } 6993920e296Sopenharmony_ci } 7003920e296Sopenharmony_ci} 7013920e296Sopenharmony_ci} 7023920e296Sopenharmony_ci} 7033920e296Sopenharmony_ci}