1 /*
2 * Copyright (c) 2021-2024 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 "binary_file_packer.h"
17
18 #include "compression_parser.h"
19 #include "restool_errors.h"
20
21 namespace OHOS {
22 namespace Global {
23 namespace Restool {
24 using namespace std;
25
BinaryFilePacker(const PackageParser & packageParser,const std::string & moduleName)26 BinaryFilePacker::BinaryFilePacker(const PackageParser &packageParser, const std::string &moduleName)
27 : packageParser_(packageParser), moduleName_(moduleName)
28 {
29 }
30
~BinaryFilePacker()31 BinaryFilePacker::~BinaryFilePacker()
32 {
33 }
34
StopCopy()35 void BinaryFilePacker::StopCopy()
36 {
37 stopCopy_.store(true);
38 }
39
CopyBinaryFileAsync(const std::vector<std::string> & inputs)40 std::future<uint32_t> BinaryFilePacker::CopyBinaryFileAsync(const std::vector<std::string> &inputs)
41 {
42 auto func = [this](const vector<string> &inputs) { return this->CopyBinaryFile(inputs); };
43 std::future<uint32_t> res = ThreadPool::GetInstance().Enqueue(func, inputs);
44 return res;
45 }
46
CopyBinaryFile(const vector<string> & inputs)47 uint32_t BinaryFilePacker::CopyBinaryFile(const vector<string> &inputs)
48 {
49 for (const auto &input : inputs) {
50 CopyBinaryFile(input);
51 }
52 if (CheckCopyResults() != RESTOOL_SUCCESS) {
53 return RESTOOL_ERROR;
54 }
55 return RESTOOL_SUCCESS;
56 }
57
CopyBinaryFile(const string & input)58 uint32_t BinaryFilePacker::CopyBinaryFile(const string &input)
59 {
60 string rawfilePath = FileEntry::FilePath(input).Append(RAW_FILE_DIR).GetPath();
61 if (CopyBinaryFile(rawfilePath, RAW_FILE_DIR) == RESTOOL_ERROR) {
62 return RESTOOL_ERROR;
63 }
64 string resfilePath = FileEntry::FilePath(input).Append(RES_FILE_DIR).GetPath();
65 if (CopyBinaryFile(resfilePath, RES_FILE_DIR) == RESTOOL_ERROR) {
66 return RESTOOL_ERROR;
67 }
68 return RESTOOL_SUCCESS;
69 }
70
CopyBinaryFile(const string & filePath,const string & fileType)71 uint32_t BinaryFilePacker::CopyBinaryFile(const string &filePath, const string &fileType)
72 {
73 if (!ResourceUtil::FileExist(filePath)) {
74 return RESTOOL_SUCCESS;
75 }
76
77 if (!FileEntry::IsDirectory(filePath)) {
78 PrintError(GetError(ERR_CODE_INVALID_RESOURCE_PATH).FormatCause(filePath.c_str(), "not a directory"));
79 return RESTOOL_ERROR;
80 }
81
82 string dst = FileEntry::FilePath(packageParser_.GetOutput()).Append(RESOURCES_DIR).Append(fileType).GetPath();
83 if (CopyBinaryFileImpl(filePath, dst) != RESTOOL_SUCCESS) {
84 return RESTOOL_ERROR;
85 }
86 return RESTOOL_SUCCESS;
87 }
88
CopyBinaryFileImpl(const string & src,const string & dst)89 uint32_t BinaryFilePacker::CopyBinaryFileImpl(const string &src, const string &dst)
90 {
91 if (!ResourceUtil::CreateDirs(dst)) {
92 return RESTOOL_ERROR;
93 }
94
95 FileEntry f(src);
96 if (!f.Init()) {
97 return RESTOOL_ERROR;
98 }
99 for (const auto &entry : f.GetChilds()) {
100 string filename = entry->GetFilePath().GetFilename();
101 if (ResourceUtil::IsIgnoreFile(filename, entry->IsFile())) {
102 continue;
103 }
104
105 string subPath = FileEntry::FilePath(dst).Append(filename).GetPath();
106 if (!entry->IsFile()) {
107 if (CopyBinaryFileImpl(entry->GetFilePath().GetPath(), subPath) != RESTOOL_SUCCESS) {
108 return RESTOOL_ERROR;
109 }
110 continue;
111 }
112
113 if (IsDuplicated(entry, subPath)) {
114 continue;
115 }
116
117 if (stopCopy_.load()) {
118 cout << "Info: CopyBinaryFileImpl: stop copy binary file." << endl;
119 return RESTOOL_ERROR;
120 }
121
122 string path = entry->GetFilePath().GetPath();
123 auto copyFunc = [this](const string path, string subPath) { return this->CopySingleFile(path, subPath); };
124 std::future<uint32_t> res = ThreadPool::GetInstance().Enqueue(copyFunc, path, subPath);
125 copyResults_.push_back(std::move(res));
126 }
127 return RESTOOL_SUCCESS;
128 }
129
IsDuplicated(const unique_ptr<FileEntry> & entry,string subPath)130 bool BinaryFilePacker::IsDuplicated(const unique_ptr<FileEntry> &entry, string subPath)
131 {
132 lock_guard<mutex> lock(mutex_);
133 if (g_hapResourceSet.count(subPath)) {
134 g_hapResourceSet.erase(subPath);
135 } else if (!g_resourceSet.emplace(subPath).second) {
136 cout << "Warning: '" << entry->GetFilePath().GetPath() << "' is defined repeatedly." << endl;
137 return true;
138 }
139 return false;
140 }
141
CopySingleFile(const std::string & path,std::string & subPath)142 uint32_t BinaryFilePacker::CopySingleFile(const std::string &path, std::string &subPath)
143 {
144 if (moduleName_ == "har" || CompressionParser::GetCompressionParser()->GetDefaultCompress()) {
145 if (!ResourceUtil::CopyFileInner(path, subPath)) {
146 return RESTOOL_ERROR;
147 }
148 return RESTOOL_SUCCESS;
149 }
150 if (!CompressionParser::GetCompressionParser()->CopyAndTranscode(path, subPath, true)) {
151 return RESTOOL_ERROR;
152 }
153 return RESTOOL_SUCCESS;
154 }
155
CheckCopyResults()156 uint32_t BinaryFilePacker::CheckCopyResults()
157 {
158 for (auto &res : copyResults_) {
159 if (stopCopy_.load()) {
160 cout << "Info: CopyBinaryFile: stop copy binary file." << endl;
161 return RESTOOL_ERROR;
162 }
163 uint32_t ret = res.get();
164 if (ret != RESTOOL_SUCCESS) {
165 return RESTOOL_ERROR;
166 }
167 }
168 return RESTOOL_SUCCESS;
169 }
170 } // namespace Restool
171 } // namespace Global
172 } // namespace OHOS
173