• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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> &parameterMap, 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