1 /*
2 * Copyright (c) 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 "fast_app_packager.h"
17
18 #include <fstream>
19 #include <string>
20 #include <sstream>
21
22 #include "constants.h"
23 #include "json/module_json.h"
24 #include "json/pack_info.h"
25 #include "json/module_json_utils.h"
26 #include "log.h"
27 #include "utils.h"
28 #include "zip_utils.h"
29
30 namespace OHOS {
31 namespace AppPackingTool {
FastAppPackager(const std::map<std::string,std::string> & parameterMap,std::string & resultReceiver)32 FastAppPackager::FastAppPackager(const std::map<std::string, std::string> ¶meterMap, std::string &resultReceiver)
33 : Packager(parameterMap, resultReceiver)
34 {}
35
InitAllowedParam()36 int32_t FastAppPackager::InitAllowedParam()
37 {
38 allowedParameters_ = {
39 {}
40 };
41 return ERR_OK;
42 }
43
PreProcess()44 int32_t FastAppPackager::PreProcess()
45 {
46 if (!CheckForceFlag()) {
47 return ERR_INVALID_VALUE;
48 }
49
50 bool ret = IsVerifyValidInFastAppMode();
51 if (!ret) {
52 return ERR_INVALID_VALUE;
53 }
54 return ERR_OK;
55 }
56
Process()57 int32_t FastAppPackager::Process()
58 {
59 bool ret = CompressFastAppMode();
60 if (!ret) {
61 std::string outPath;
62 if (parameterMap_.find(Constants::PARAM_OUT_PATH) != parameterMap_.end()) {
63 outPath = parameterMap_.at(Constants::PARAM_OUT_PATH);
64 }
65 if (fs::exists(outPath)) {
66 fs::remove_all(outPath);
67 }
68 LOGE("FastApp Process failed.");
69 return ERR_INVALID_VALUE;
70 }
71 return ERR_OK;
72 }
73
PostProcess()74 int32_t FastAppPackager::PostProcess()
75 {
76 return ERR_OK;
77 }
78
IsVerifyValidInFastAppMode()79 bool FastAppPackager::IsVerifyValidInFastAppMode()
80 {
81 if (!IsVerifyValid()) {
82 return false;
83 }
84
85 if (!FormatPath()) {
86 return false;
87 }
88
89 if (!ModuleJsonAndPackInfoExists(formattedHapPathList_, formattedHspPathList_)) {
90 LOGE("hap-path or hsp-path is invalid.");
91 return false;
92 }
93
94 if (!CheckBundleTypeConsistency(formattedHapPathList_, formattedHspPathList_)) {
95 LOGE("bundleType is inconsistent.");
96 return false;
97 }
98
99 std::string packInfoPath;
100 std::map<std::string, std::string>::const_iterator it = parameterMap_.find(Constants::PARAM_PACK_INFO_PATH);
101 if (it != parameterMap_.end() && !it->second.empty()) {
102 packInfoPath = it->second;
103 }
104 if (!IsPackInfoValid(fs::path(packInfoPath), formattedHapPathList_, formattedHspPathList_)) {
105 LOGE("pack.info is invalid.");
106 return false;
107 }
108
109 std::string outPath = "";
110 std::string forceRewrite = "";
111 it = parameterMap_.find(Constants::PARAM_OUT_PATH);
112 if (it != parameterMap_.end()) {
113 outPath = it->second;
114 }
115
116 it = parameterMap_.find(Constants::PARAM_FORCE);
117 if (it != parameterMap_.end()) {
118 forceRewrite = it->second;
119 }
120
121 return IsOutPathValid(outPath, forceRewrite, Constants::APP_SUFFIX);
122 }
123
FormatPath()124 bool FastAppPackager::FormatPath()
125 {
126 std::map<std::string, std::string>::const_iterator itHap = parameterMap_.find(Constants::PARAM_HAP_PATH);
127 if (itHap != parameterMap_.end() && !itHap->second.empty() &&
128 (!IsFormatPathValid(itHap->second, formattedHapPathList_) || !IsHapPathValid(formattedHapPathList_))) {
129 LOGE("FastAppPackager::isVerifyValidInFastAppMode hap-path is invalid.");
130 return false;
131 }
132
133 std::map<std::string, std::string>::const_iterator itHsp = parameterMap_.find(Constants::PARAM_HSP_PATH);
134 if (itHsp != parameterMap_.end() && !itHsp->second.empty() && (!IsFormatPathValid(itHsp->second,
135 formattedHspPathList_) || !IsHspPathValid(formattedHspPathList_, Constants::HSP_SUFFIX))) {
136 LOGE("FastAppPackager::isVerifyValidInFastAppMode hsp-path is invalid.");
137 return false;
138 }
139
140 if ((itHap == parameterMap_.end() || itHap->second.empty()) &&
141 (itHsp == parameterMap_.end() || itHsp->second.empty())) {
142 LOGE("FastAppPackager::isVerifyValidInFastAppMode hap-path and hsp-path is empty.");
143 return false;
144 }
145 return true;
146 }
147
IsVerifyValid()148 bool FastAppPackager::IsVerifyValid()
149 {
150 std::map<std::string, std::string>::const_iterator it = parameterMap_.find(Constants::PARAM_PACK_INFO_PATH);
151 if (it == parameterMap_.end() || it->second.empty()) {
152 LOGE("FastAppPackager::isArgsValidInAppMode pack-info-path is empty.");
153 return false;
154 }
155
156 packInfoPath_ = it->second;
157 if (!IsPathValid(packInfoPath_, true, Constants::PACK_INFO)) {
158 LOGE("FastAppPackager::isArgsValidInAppMode pack-info-path is invalid.");
159 return false;
160 }
161
162 it = parameterMap_.find(Constants::PARAM_SIGNATURE_PATH);
163 if (it != parameterMap_.end() && !it->second.empty() && !IsPathValid(it->second, true)) {
164 LOGE("FastAppPackager::isVerifyValidInFastAppMode signature-path is invalid.");
165 return false;
166 }
167
168 it = parameterMap_.find(Constants::PARAM_CERTIFICATE_PATH);
169 if (it != parameterMap_.end() && !it->second.empty() && !IsPathValid(it->second, true)) {
170 LOGE("FastAppPackager::isVerifyValidInFastAppMode certificate-path is invalid.");
171 return false;
172 }
173
174 it = parameterMap_.find(Constants::PARAM_PACK_RES_PATH);
175 if (it != parameterMap_.end() && !it->second.empty() &&
176 !IsPathValid(it->second, true, Constants::FILE_PACK_RES)) {
177 LOGE("FastAppPackager::isVerifyValidInFastAppMode pack-res-path is invalid.");
178 return false;
179 }
180
181 it = parameterMap_.find(Constants::PARAM_ENTRYCARD_PATH);
182 if (it != parameterMap_.end() && !it->second.empty() &&
183 !CompatibleProcess(it->second, formattedEntryCardPathList_, Constants::PNG_SUFFIX)) {
184 LOGE("FastAppPackager::isVerifyValidInFastAppMode entrycard-path is invalid.");
185 return false;
186 }
187
188 it = parameterMap_.find(Constants::PARAM_OUT_PATH);
189 if (it == parameterMap_.end() || it->second.empty()) {
190 LOGE("FastAppPackager::isVerifyValidInFastAppMode out-path is empty.");
191 return false;
192 }
193 return true;
194 }
195
IsFormatPathValid(const std::string & inputPath,std::list<std::string> & formattedPathList)196 bool FastAppPackager::IsFormatPathValid(const std::string &inputPath, std::list<std::string> &formattedPathList)
197 {
198 std::set<std::string> formatPathSet;
199 std::istringstream iss(inputPath);
200 std::string path;
201
202 while (std::getline(iss, path, Constants::COMMA_SPLIT)) {
203 try {
204 fs::path realpath = fs::canonical(path);
205 if (fs::exists(realpath)) {
206 formatPathSet.insert(realpath.string());
207 } else {
208 LOGE("FastAppPackager::formatPath not exists: %s", realpath.string().c_str());
209 return false;
210 }
211 } catch (const std::exception& ex) {
212 LOGE("FastAppPackager::formatPath err: %s", ex.what());
213 return false;
214 }
215 }
216
217 formattedPathList.assign(formatPathSet.begin(), formatPathSet.end());
218 return true;
219 }
220
IsHapPathValid(const std::list<std::string> & formatPathList)221 bool FastAppPackager::IsHapPathValid(const std::list<std::string> &formatPathList)
222 {
223 for (const auto& path : formatPathList) {
224 if (!fs::is_directory(path)) {
225 return false;
226 }
227 }
228 return true;
229 }
230
IsHspPathValid(const std::list<std::string> & formatPathList,const std::string & hspSuffix)231 bool FastAppPackager::IsHspPathValid(const std::list<std::string> &formatPathList, const std::string &hspSuffix)
232 {
233 for (const auto& path : formatPathList) {
234 if (!fs::is_directory(path) && !IsPathValid(path, true, hspSuffix)) {
235 return false;
236 }
237 }
238 return true;
239 }
240
ModuleJsonAndPackInfoExists(const std::list<std::string> & hapPathList,const std::list<std::string> & hspPathList)241 bool FastAppPackager::ModuleJsonAndPackInfoExists(const std::list<std::string> &hapPathList,
242 const std::list<std::string> &hspPathList)
243 {
244 for (const auto& hapPath : hapPathList) {
245 fs::path path = fs::path(hapPath);
246 if (!fs::exists(path / fs::path(Constants::MODULE_JSON))) {
247 LOGE("not found module.json in path: %s", path.string().c_str());
248 return false;
249 }
250 if (!fs::exists(path / fs::path(Constants::PACK_INFO))) {
251 LOGE("not found pack.info in path: %s", path.string().c_str());
252 return false;
253 }
254 }
255 for (const auto& hspPath : hspPathList) {
256 fs::path path = fs::path(hspPath);
257 if (fs::is_directory(path)) {
258 if (!fs::exists(path / fs::path(Constants::MODULE_JSON))) {
259 LOGE("not found module.json in path: %s", path.string().c_str());
260 return false;
261 }
262 if (!fs::exists(path / fs::path(Constants::PACK_INFO))) {
263 LOGE("not found pack.info in path: %s", path.string().c_str());
264 return false;
265 }
266 }
267 }
268 return true;
269 }
270
CheckBundleTypeConsistency(const std::list<std::string> & hapPathList,const std::list<std::string> & hspPathList)271 bool FastAppPackager::CheckBundleTypeConsistency(const std::list<std::string> &hapPathList,
272 const std::list<std::string> &hspPathList)
273 {
274 std::string bundleType;
275 if (!hapPathList.empty()) {
276 bundleType = GetBundleTypeFromPath(hapPathList.front());
277 } else if (!hspPathList.empty()) {
278 bundleType = GetBundleTypeFromPath(hspPathList.front());
279 }
280 if (bundleType.empty()) {
281 return false;
282 }
283 for (const auto& hapPath : hapPathList) {
284 if (GetBundleTypeFromPath(hapPath) != bundleType) {
285 LOGE("bundleType is not same");
286 return false;
287 }
288 }
289 for (const auto& hspPath : hspPathList) {
290 if (GetBundleTypeFromPath(hspPath) != bundleType) {
291 LOGE("bundleType is not same");
292 return false;
293 }
294 }
295 if (bundleType == Constants::TYPE_SHARED) {
296 isSharedApp_ = true;
297 }
298 return true;
299 }
300
GetBundleTypeFromPath(const std::string & filePath)301 std::string FastAppPackager::GetBundleTypeFromPath(const std::string &filePath)
302 {
303 fs::path path(filePath);
304 if (!fs::exists(path)) {
305 LOGE("getBundleTypeFromPath path not exists: %s", path.string().c_str());
306 return "";
307 }
308 std::string content = GetModuleJsonContentFromPath(path);
309 if (content.empty()) {
310 return "";
311 }
312 return GetBundleTypeFromModuleJson(content);
313 }
314
GetModuleJsonContentFromPath(const fs::path & path)315 std::string FastAppPackager::GetModuleJsonContentFromPath(const fs::path &path)
316 {
317 if (fs::is_regular_file(path)) {
318 std::string filename = path.filename().string();
319 if (filename == Constants::MODULE_JSON) {
320 return ReadFileToString(path);
321 } else if (Utils::EndsWith(filename, Constants::HSP_SUFFIX)) {
322 std::string fileContent;
323 if (!ZipUtils::GetFileContentFromZip(path, Constants::MODULE_JSON, fileContent)) {
324 LOGE("GetModuleJsonContentFromPath err: %s", path.string().c_str());
325 return "";
326 }
327 return fileContent;
328 }
329 } else {
330 return ReadFileToString(path / fs::path(Constants::MODULE_JSON));
331 }
332 return "";
333 }
334
ReadFileToString(const fs::path & path)335 std::string FastAppPackager::ReadFileToString(const fs::path &path)
336 {
337 std::string realPath;
338 if (!Utils::GetRealPath(path.string(), realPath)) {
339 LOGE("get real path failed! path=%s", path.string().c_str());
340 return "";
341 }
342 std::ifstream file(realPath, std::ios::in | std::ios::binary);
343 if (!file.is_open()) {
344 return "";
345 }
346
347 std::stringstream buffer;
348 buffer << file.rdbuf();
349
350 return buffer.str();
351 }
352
GetBundleTypeFromModuleJson(const std::string & moduleJsonContent)353 std::string FastAppPackager::GetBundleTypeFromModuleJson(const std::string &moduleJsonContent)
354 {
355 ModuleJson moduleJson;
356 if (!moduleJson.ParseFromString(moduleJsonContent)) {
357 LOGE("GetBundleTypeFromModuleJson ParseFromString err.");
358 return "";
359 }
360
361 std::string bundleType;
362 if (!moduleJson.GetStageBundleType(bundleType)) {
363 LOGE("GetBundleTypeFromModuleJson GetStageBundleType err.");
364 return "";
365 }
366 return bundleType != "" ? bundleType : Constants::MODE_APP;
367 }
368
IsPackInfoValid(const fs::path & packInfo,const std::list<std::string> & hapPathList,const std::list<std::string> & hspPathList)369 bool FastAppPackager::IsPackInfoValid(const fs::path &packInfo, const std::list<std::string> &hapPathList,
370 const std::list<std::string> &hspPathList)
371 {
372 std::list<std::string> allPackages;
373 if (!GetPackageNameFromPath(packInfo, allPackages)) {
374 LOGE("GetPackageNameFromPath for packInfo err: %s", packInfo.string().c_str());
375 return false;
376 }
377 std::set<std::string> allPackageSet(allPackages.begin(), allPackages.end());
378 if (allPackages.size() > allPackageSet.size()) {
379 LOGE("package name is redundant in app pack.info: %s", packInfo.string().c_str());
380 return false;
381 }
382 if (allPackages.empty()) {
383 LOGE("app pack.info format err: %s", packInfo.string().c_str());
384 return false;
385 }
386 std::set<std::string> packages;
387 if (!IsPackInfoPathListValid(hapPathList, packages, allPackageSet) ||
388 !IsPackInfoPathListValid(hspPathList, packages, allPackageSet)) {
389 return false;
390 }
391
392 if (allPackageSet != packages) {
393 LOGE("package name not same between module and app pack.info.");
394 return false;
395 }
396 return true;
397 }
398
IsPackInfoPathListValid(const std::list<std::string> & pathList,std::set<std::string> & packages,const std::set<std::string> & allPackageSet)399 bool FastAppPackager::IsPackInfoPathListValid(const std::list<std::string> &pathList, std::set<std::string> &packages,
400 const std::set<std::string> &allPackageSet)
401 {
402 for (const auto& path : pathList) {
403 std::list<std::string> list;
404 if (!GetPackageNameFromPath(fs::path(path), list)) {
405 LOGE("GetPackageNameFromPath for packInfo err");
406 return false;
407 }
408 if (list.size() != 1) {
409 LOGE("module pack.info format err: %s", path.c_str());
410 return false;
411 }
412 std::string packageName = list.front();
413 if (allPackageSet.find(packageName) == allPackageSet.end()) {
414 LOGE("module pack.info name not exist in app pack.info name list: %s", path.c_str());
415 return false;
416 }
417 if (packages.find(packageName) != packages.end()) {
418 LOGE("package name is redundant in %s", path.c_str());
419 return false;
420 }
421 packages.insert(packageName);
422 }
423 return true;
424 }
425
GetPackageNameFromPath(const fs::path & path,std::list<std::string> & packageNameList)426 bool FastAppPackager::GetPackageNameFromPath(const fs::path &path, std::list<std::string> &packageNameList)
427 {
428 if (!fs::exists(path)) {
429 LOGE("GetPackageNameFromPath path not exists: %s", path.string().c_str());
430 return false;
431 }
432 if (fs::is_regular_file(path)) {
433 std::string filename = path.filename().string();
434 if (Utils::EndsWith(filename, Constants::HSP_SUFFIX)) {
435 // .hsp: return filename
436 packageNameList.push_back(filename.substr(0, filename.find(Constants::HSP_SUFFIX)));
437 return true;
438 }
439 }
440 std::string content = GetPackInfoContentFromPath(path);
441 if (content.empty()) {
442 return false;
443 }
444
445 PackInfo packInfo;
446 if (!packInfo.ParseFromString(content)) {
447 LOGE("GetPackageNameFromPath ParseFromString err.");
448 return false;
449 }
450 return packInfo.GetPackageNames(packageNameList);
451 }
452
GetPackInfoContentFromPath(const fs::path & path)453 std::string FastAppPackager::GetPackInfoContentFromPath(const fs::path &path)
454 {
455 if (fs::is_regular_file(path)) {
456 std::string filename = path.filename().string();
457 if (filename == Constants::PACK_INFO) {
458 return ReadFileToString(path);
459 } else if (Utils::EndsWith(filename, Constants::HSP_SUFFIX)) {
460 std::string fileContent;
461 if (!ZipUtils::GetFileContentFromZip(path, Constants::PACK_INFO, fileContent)) {
462 LOGE("GetPackInfoContentFromPath err: %s", path.string().c_str());
463 return "";
464 }
465 return fileContent;
466 }
467 } else {
468 return ReadFileToString(path / fs::path(Constants::PACK_INFO));
469 }
470 return "";
471 }
472
CompressFastAppMode()473 bool FastAppPackager::CompressFastAppMode()
474 {
475 fs::path tmpDir;
476 fs::path appOutPath;
477 std::map<std::string, std::string>::const_iterator it = parameterMap_.find(Constants::PARAM_OUT_PATH);
478 if (it != parameterMap_.end() && !it->second.empty()) {
479 appOutPath = fs::path(it->second);
480 }
481
482 try {
483 tmpDir = appOutPath.parent_path() / fs::path(Constants::COMPRESSOR_FAST_APP_TEMP_DIR + Utils::GenerateUUID());
484 if (!fs::create_directories(tmpDir)) {
485 LOGE("FastAppPackager::compressAppMode create tmpDir failed: %s", tmpDir.string().c_str());
486 return false;
487 }
488
489 std::list<std::string> fileList;
490 if (!Pack(tmpDir, fileList)) {
491 if (fs::exists(tmpDir)) {
492 fs::remove_all(tmpDir);
493 }
494 return false;
495 }
496
497 if (!CheckHapAndPackFastApp(fileList, tmpDir)) {
498 if (fs::exists(tmpDir)) {
499 fs::remove_all(tmpDir);
500 }
501 return false;
502 }
503 } catch (const std::exception& ex) {
504 LOGE("FastAppPackager::CompressFastAppMode compress failed: %s", ex.what());
505 if (fs::exists(tmpDir)) {
506 fs::remove_all(tmpDir);
507 }
508 return false;
509 }
510 if (fs::exists(tmpDir)) {
511 fs::remove_all(tmpDir);
512 }
513 return true;
514 }
515
CheckHapAndPackFastApp(std::list<std::string> & fileList,const fs::path & tmpDir)516 bool FastAppPackager::CheckHapAndPackFastApp(std::list<std::string> &fileList, const fs::path &tmpDir)
517 {
518 if (!ModuleJsonUtils::CheckHapsIsValid(fileList, isSharedApp_)) {
519 LOGE("FastAppPackager::CheckHapsIsValid verify failed, "
520 "check version, apiVersion, moduleName, packageName.");
521 return false;
522 }
523
524 if (!PackFastApp(fileList)) {
525 LOGE("FastAppPackager::CompressFastAppMode PackFastApp failed.");
526 return false;
527 }
528 return true;
529 }
530
Pack(const std::string & tmpDir,std::list<std::string> & fileList)531 bool FastAppPackager::Pack(const std::string &tmpDir, std::list<std::string> &fileList)
532 {
533 fs::path appPackInfo = fs::path(packInfoPath_);
534 for (const auto& hapPath : formattedHapPathList_) {
535 fs::path path = fs::path(hapPath);
536 fs::path hap;
537 if (!Pack(path, appPackInfo, tmpDir, hap)) {
538 if (fs::exists(tmpDir)) {
539 fs::remove_all(tmpDir);
540 }
541 return false;
542 }
543 if (!hap.empty()) {
544 fileList.push_back(hap.string());
545 }
546 }
547 for (const auto& hspPath : formattedHspPathList_) {
548 fs::path path = fs::path(hspPath);
549 fs::path hsp;
550 if (!Pack(path, appPackInfo, tmpDir, hsp)) {
551 if (fs::exists(tmpDir)) {
552 fs::remove_all(tmpDir);
553 }
554 return false;
555 }
556 if (!hsp.empty()) {
557 fileList.push_back(hsp.string());
558 }
559 }
560 return true;
561 }
562
Pack(const fs::path & inputPath,const fs::path & appPackInfo,const fs::path & outPath,fs::path & path)563 bool FastAppPackager::Pack(const fs::path &inputPath, const fs::path &appPackInfo, const fs::path &outPath,
564 fs::path &path)
565 {
566 if (!fs::exists(inputPath)) {
567 LOGE("pack err, input path not exists.");
568 return false;
569 }
570 if (!fs::exists(appPackInfo)) {
571 LOGE("pack err, app pack.info not exists.");
572 return false;
573 }
574 if (fs::is_directory(inputPath)) {
575 return PackDir(inputPath, appPackInfo, outPath, path);
576 } else if (fs::is_regular_file(inputPath) && Utils::EndsWith(inputPath.filename().string(),
577 Constants::HSP_SUFFIX)) {
578 return RepackHsp(inputPath, appPackInfo, outPath, path);
579 }
580
581 LOGE("pack err, not support: %s", inputPath.string().c_str());
582 return false;
583 }
584
PackDir(const fs::path & inputPath,const fs::path & appPackInfo,const fs::path & outPath,fs::path & path)585 bool FastAppPackager::PackDir(const fs::path &inputPath, const fs::path &appPackInfo,
586 const fs::path &outPath, fs::path &path)
587 {
588 std::list<std::string> packageNames;
589 if (!GetPackageNameFromPath(inputPath / fs::path(Constants::PACK_INFO), packageNames)) {
590 LOGE("pack err, pack.info format err");
591 return false;
592 }
593 if (packageNames.size() != 1) {
594 LOGE("pack err, pack.info format err");
595 return false;
596 }
597 ModuleJson moduleJson;
598 if (!moduleJson.ParseFromFile(inputPath / fs::path(Constants::MODULE_JSON))) {
599 LOGE("pack err, module.json format err");
600 return false;
601 }
602 std::string pkgName = packageNames.front();
603 std::string moudleType;
604 moduleJson.GetStageModuleType(moudleType);
605 moduleJson.GetStageCompressNativeLibs(compressNativeLibs_);
606 moduleJson.GetGenerateBuildHash(isGenerateBuildHash_);
607 std::string suffix = moudleType == Constants::TYPE_SHARED ? Constants::HSP_SUFFIX : Constants::HAP_SUFFIX;
608
609 fs::path outHap = outPath / fs::path(pkgName);
610 outHap += fs::path(suffix);
611 return packSingleThread(inputPath, appPackInfo, outHap, path);
612 }
613
RepackHsp(const fs::path & inputPath,const fs::path & appPackInfo,const fs::path & outPath,fs::path & path)614 bool FastAppPackager::RepackHsp(const fs::path &inputPath, const fs::path &appPackInfo,
615 const fs::path &outPath, fs::path &path)
616 {
617 fs::path outHsp = outPath / inputPath.filename();
618 std::string outHspStr = outHsp.string();
619 zipWrapper_.Open(outHspStr);
620 if (!zipWrapper_.IsOpen()) {
621 LOGE("FastAppPackager::RepackHsp: zipWrapper Open failed!");
622 return false;
623 }
624
625 std::string zipPath = Constants::NULL_DIR_NAME;
626 if (!fs::is_directory(appPackInfo)) {
627 zipPath = (appPackInfo).filename().string();
628 }
629 if (zipWrapper_.AddFileOrDirectoryToZip(appPackInfo.string(), zipPath) != ZipErrCode::ZIP_ERR_SUCCESS) {
630 LOGE("FastAppPackager::RepackHsp: zipWrapper AddFileOrDirectoryToZip failed!");
631 return false;
632 }
633
634 std::string uZipTempPath = "uzip_fastAppTemp_";
635 fs::path unzipPathString = inputPath.parent_path() / fs::path(uZipTempPath + Utils::GenerateUUID());
636 if (!fs::create_directories(unzipPathString)) {
637 LOGE("Can't create directory to path %s", unzipPathString.string().c_str());
638 return false;
639 }
640 std::string uzipHsp = UzipHspAndRemovePackInfo(inputPath.string(), unzipPathString.string());
641 if (zipWrapper_.AddFileOrDirectoryToZip(uzipHsp, Constants::NULL_DIR_NAME) != ZipErrCode::ZIP_ERR_SUCCESS) {
642 LOGE("FastAppPackager::RepackHsp: zipWrapper AddFileOrDirectoryToZip failed!");
643 if (fs::exists(uzipHsp)) {
644 fs::remove_all(uzipHsp);
645 }
646 return false;
647 }
648 fs::remove_all(uzipHsp);
649 zipWrapper_.Close();
650 path = outHspStr;
651 return true;
652 }
653
PackFastApp(const std::list<std::string> & fileList)654 bool FastAppPackager::PackFastApp(const std::list<std::string> &fileList)
655 {
656 std::map<std::string, std::string>::const_iterator it = parameterMap_.find(Constants::PARAM_OUT_PATH);
657 std::string outPath;
658 if (it != parameterMap_.end()) {
659 outPath = it->second;
660 }
661 zipWrapper_.Open(outPath);
662 if (!zipWrapper_.IsOpen()) {
663 LOGE("FastAppPackager::PackFastApp: zipWrapper Open failed!");
664 return false;
665 }
666
667 if (zipWrapper_.AddFileOrDirectoryToZip(packInfoPath_, Constants::PACK_INFO) != ZipErrCode::ZIP_ERR_SUCCESS) {
668 LOGE("FastAppPackager::PackFastApp: zipWrapper WriteStringToZip failed!");
669 return false;
670 }
671
672 if (!AddHapListToApp(fileList)) {
673 zipWrapper_.SetZipLevel(ZipLevel::ZIP_LEVEL_DEFAULT);
674 LOGE("FastAppPackager::AddHapListToApp failed");
675 return false;
676 }
677
678 std::string moduleName;
679 it = parameterMap_.find(Constants::PARAM_ENTRYCARD_PATH);
680 if (it != parameterMap_.end() && !it->second.empty()) {
681 std::string entryCardPath = Constants::ENTRYCARD_NAME + Constants::LINUX_FILE_SEPARATOR +
682 moduleName + Constants::LINUX_FILE_SEPARATOR +
683 Constants::ENTRYCARD_BASE_NAME + Constants::LINUX_FILE_SEPARATOR +
684 Constants::ENTRYCARD_SNAPSHOT_NAME + Constants::LINUX_FILE_SEPARATOR;
685 for (auto itemFormattedEntryCardPath : formattedEntryCardPathList_) {
686 if (zipWrapper_.AddFileOrDirectoryToZip(itemFormattedEntryCardPath, entryCardPath +
687 fs::path(itemFormattedEntryCardPath).filename().string()) !=
688 ZipErrCode::ZIP_ERR_SUCCESS) {
689 LOGE("FastAppPackager::Process: zipWrapper AddFileOrDirectoryToZip failed!");
690 return false;
691 }
692 }
693 }
694 it = parameterMap_.find(Constants::PARAM_PACK_RES_PATH);
695 if (it != parameterMap_.end() && !it->second.empty()) {
696 if (zipWrapper_.AddFileOrDirectoryToZip(it->second, Constants::FILE_PACK_RES) != ZipErrCode::ZIP_ERR_SUCCESS) {
697 LOGE("FastAppPackager::Process: zipWrapper AddFileOrDirectoryToZip failed!");
698 return false;
699 }
700 }
701 return AddSignatureAndCertificateToApp();
702 }
703
AddHapListToApp(const std::list<std::string> & fileList)704 bool FastAppPackager::AddHapListToApp(const std::list<std::string> &fileList)
705 {
706 for (const auto& hapPath : fileList) {
707 HapVerifyInfo hapVerifyInfo;
708 if (ModuleJsonUtils::IsModuleHap(hapPath)) {
709 if (!ModuleJsonUtils::GetStageHapVerifyInfo(hapPath, hapVerifyInfo)) {
710 LOGW("GetStageHapVerifyInfo failed! hapPath:%s", hapPath.c_str());
711 }
712 } else {
713 if (!ModuleJsonUtils::GetFaHapVerifyInfo(hapPath, hapVerifyInfo)) {
714 LOGW("GetFaHapVerifyInfo failed! hapPath:%s", hapPath.c_str());
715 }
716 }
717 if (hapVerifyInfo.IsDebug()) {
718 zipWrapper_.SetZipLevel(ZipLevel::ZIP_LEVEL_0);
719 }
720 if (zipWrapper_.AddFileOrDirectoryToZip(hapPath, fs::path(hapPath).filename().string()) !=
721 ZipErrCode::ZIP_ERR_SUCCESS) {
722 LOGE("FastAppPackager::Process: zipWrapper AddFileOrDirectoryToZip failed!");
723 return false;
724 }
725 zipWrapper_.SetZipLevel(ZipLevel::ZIP_LEVEL_DEFAULT);
726 }
727 return true;
728 }
729
AddSignatureAndCertificateToApp()730 bool FastAppPackager::AddSignatureAndCertificateToApp()
731 {
732 std::map<std::string, std::string>::const_iterator it = parameterMap_.find(Constants::PARAM_CERTIFICATE_PATH);
733 if (it != parameterMap_.end() && !it->second.empty()) {
734 fs::path filePath = fs::path(it->second);
735 std::string zipPath = Constants::NULL_DIR_NAME;
736 if (!fs::is_directory(filePath)) {
737 zipPath = (filePath).filename().string();
738 }
739 if (zipWrapper_.AddFileOrDirectoryToZip(it->second, zipPath) != ZipErrCode::ZIP_ERR_SUCCESS) {
740 LOGE("FastAppPackager::Process: zipWrapper AddFileOrDirectoryToZip failed!");
741 return false;
742 }
743 }
744
745 it = parameterMap_.find(Constants::PARAM_SIGNATURE_PATH);
746 if (it != parameterMap_.end() && !it->second.empty()) {
747 fs::path filePath = fs::path(it->second);
748 std::string zipPath = Constants::NULL_DIR_NAME;
749 if (!fs::is_directory(filePath)) {
750 zipPath = (filePath).filename().string();
751 }
752 if (zipWrapper_.AddFileOrDirectoryToZip(it->second, zipPath) != ZipErrCode::ZIP_ERR_SUCCESS) {
753 LOGE("FastAppPackager::Process: zipWrapper AddFileOrDirectoryToZip failed!");
754 return false;
755 }
756 }
757
758 zipWrapper_.Close();
759 return true;
760 }
761
packMultiThread(const fs::path & inputPath,const fs::path & appPackInfo,const fs::path & outHap,fs::path & path)762 bool FastAppPackager::packMultiThread(const fs::path &inputPath, const fs::path &appPackInfo,
763 const fs::path &outHap, fs::path &path)
764 {
765 return true;
766 }
767
packSingleThread(const fs::path & inputPath,const fs::path & appPackInfo,const fs::path & outHap,fs::path & path)768 bool FastAppPackager::packSingleThread(const fs::path &inputPath, const fs::path &appPackInfo,
769 const fs::path &outHap, fs::path &path)
770 {
771 if (!fs::exists(inputPath) || !fs::is_directory(inputPath)) {
772 LOGE("Directory does not exist or is not a directory");
773 return false;
774 }
775
776 std::string pathStr = outHap.string();
777 zipWrapper_.Open(pathStr);
778 if (!zipWrapper_.IsOpen()) {
779 LOGE("FastAppPackager::packSingleThread: zipWrapper Open failed! path: %s", pathStr.c_str());
780 return false;
781 }
782
783 std::string zipPath = Constants::NULL_DIR_NAME;
784 if (!fs::is_directory(appPackInfo)) {
785 zipPath = (appPackInfo).filename().string();
786 }
787 if (zipWrapper_.AddFileOrDirectoryToZip(appPackInfo.string(), zipPath) != ZipErrCode::ZIP_ERR_SUCCESS) {
788 LOGE("FastAppPackager::Process: zipWrapper AddFileOrDirectoryToZip failed!");
789 return false;
790 }
791
792 if (isGenerateBuildHash_) {
793 std::string jsonString;
794 GenBuildHash(inputPath, jsonString);
795 if (zipWrapper_.WriteStringToZip(jsonString, Constants::MODULE_JSON) != ZipErrCode::ZIP_ERR_SUCCESS) {
796 LOGE("FastAppPackager::packSingleThread: zipWrapper WriteStringToZip failed!");
797 return false;
798 }
799 }
800 for (const auto& entry : fs::directory_iterator(inputPath)) {
801 if (!AddOtherFileToZip(entry.path())) {
802 return false;
803 }
804 }
805 zipWrapper_.Close();
806 path = pathStr;
807 isGenerateBuildHash_ = false;
808 return true;
809 }
810
AddOtherFileToZip(const fs::path & entry)811 bool FastAppPackager::AddOtherFileToZip(const fs::path &entry)
812 {
813 if (fs::is_regular_file(entry) && entry.filename().string() != Constants::PACK_INFO) {
814 if (isGenerateBuildHash_ && entry.filename().string() == Constants::MODULE_JSON) {
815 return true;
816 }
817 std::string zipPath = entry.filename().string();
818 if (zipWrapper_.AddFileOrDirectoryToZip(entry.string(), zipPath) != ZipErrCode::ZIP_ERR_SUCCESS) {
819 LOGE("FastAppPackager::Process: zipWrapper AddFileOrDirectoryToZip failed!");
820 return false;
821 }
822 } else if (fs::is_directory(entry)) {
823 if (entry.filename() == Constants::LIB_PATH) {
824 if (zipWrapper_.AddFileOrDirectoryToZip(entry.string(), Constants::LIB_PATH) !=
825 ZipErrCode::ZIP_ERR_SUCCESS) {
826 LOGE("FastAppPackager::Process: zipWrapper AddFileOrDirectoryToZip failed!");
827 return false;
828 }
829 } else {
830 if (zipWrapper_.AddFileOrDirectoryToZip(entry.string(), entry.filename().string() +
831 Constants::NULL_DIR_NAME) != ZipErrCode::ZIP_ERR_SUCCESS) {
832 LOGE("FastAppPackager::Process: zipWrapper AddFileOrDirectoryToZip failed!");
833 return false;
834 }
835 }
836 }
837 return true;
838 }
839
GenBuildHash(const fs::path & inputPath,std::string & jsonString)840 void FastAppPackager::GenBuildHash(const fs::path &inputPath, std::string &jsonString)
841 {
842 std::string hash = Utils::GetSha256Folder(inputPath);
843 if (hash.empty()) {
844 return;
845 }
846 ModuleJson moduleJson;
847 if (!moduleJson.ParseFromFile(inputPath / fs::path(Constants::MODULE_JSON))) {
848 LOGE("pack err, module.json format err");
849 return;
850 }
851 moduleJson.SetBuildHash(hash);
852 jsonString = moduleJson.ToString();
853 }
854
UzipHspAndRemovePackInfo(const std::string & hspPath,const std::string & unzipPathString)855 std::string FastAppPackager::UzipHspAndRemovePackInfo(const std::string& hspPath, const std::string& unzipPathString)
856 {
857 ZipUtils::Unzip(hspPath, unzipPathString);
858 for (const auto& entry : fs::directory_iterator(unzipPathString)) {
859 if (entry.path().filename() == Constants::PACK_INFO) {
860 fs::remove(entry.path());
861 continue;
862 }
863 }
864 return unzipPathString;
865 }
866 } // namespace AppPackingTool
867 } // namespace OHOS