diff --git a/ohos_packing_tool/frameworks/include/constants.h b/ohos_packing_tool/frameworks/include/constants.h index b6daeb26455718c9a3390759960714bf59329d01..54bfc8817faea38c812453e823522d74971a1b53 100644 --- a/ohos_packing_tool/frameworks/include/constants.h +++ b/ohos_packing_tool/frameworks/include/constants.h @@ -36,11 +36,26 @@ const std::string MODE_APPQF = "appqf"; const std::string MODE_MULTIAPP = "multiApp"; const std::string MODE_VERSION_NORMALIZE = "versionNormalize"; const std::string MODE_PACKAGE_NORMALIZE = "packageNormalize"; +const std::string MODE_FAST_APP = "fastApp"; const std::string PARAM_PREFIX = "--"; const std::string PARAM_MODE = "mode"; const std::string PARAM_JSON_PATH = "json-path"; const std::string PARAM_LIB_PATH = "lib-path"; +const std::string PARAM_RES_PATH = "res-path"; +const std::string PARAM_HNP_PATH = "hnp-path"; +const std::string PARAM_FILE_PATH = "file-path"; +const std::string PARAM_BIN_PATH = "bin-path"; +const std::string PARAM_APK_PATH = "shell-apk-path"; +const std::string PARAM_ASSETS_PATH = "assets-path"; +const std::string PARAM_SHAREDLIBS_PATH = "shared-libs-path"; +const std::string PARAM_DEX_PATH = "dex-path"; +const std::string PARAM_ABC_PATH = "abc-path"; +const std::string PARAM_ABILITY_SO_PATH = "ability-so-path"; +const std::string PARAM_JAR_PATH = "jar-path"; +const std::string PARAM_TXT_PATH = "txt-path"; +const std::string PARAM_PACK_RES_PATH = "pack-res-path"; +const std::string PARAM_ENTRYCARD_PATH = "entrycard-path"; const std::string PARAM_RESOURCES_PATH = "resources-path"; const std::string PARAM_INDEX_PATH = "index-path"; const std::string PARAM_PACK_INFO_PATH = "pack-info-path"; @@ -77,17 +92,52 @@ const std::string PARAM_NORMAL_MODULE_LIMIT = "normal-module-limit"; const std::string MODULE_JSON = "module.json"; const std::string CONFIG_JSON = "config.json"; const std::string LIB_PATH = "libs"; +const std::string AN_PATH = "an"; +const std::string AP_PATH = "ap"; +const std::string JS_PATH = "js"; +const std::string HNP_PATH = "hnp"; +const std::string ASSETS_PATH = "assets"; +const std::string RES_PATH = "res"; +const std::string SO_DIR = "maple"; +const std::string SO_ARM64_DIR = "maple/arm64/"; +const std::string SHARED_LIBS_DIR = "shared_libs"; +const std::string LINUX_FILE_SEPARATOR = "/"; +const std::string ENTRYCARD_NAME = "EntryCard/"; +const std::string ENTRYCARD_BASE_NAME = "base"; +const std::string ENTRYCARD_SNAPSHOT_NAME = "snapshot"; const std::string RESOURCES_PATH = "resources"; const std::string RESOURCES_INDEX = "resources.index"; const std::string PACK_INFO = "pack.info"; const std::string ETS_PATH = "ets"; const std::string RPCID_SC = "rpcid.sc"; const std::string PKG_CONTEXT_JSON = "pkgContextInfo.json"; +const std::string PROFILE_NAME = "CAPABILITY.profile"; +const std::string FILE_PACK_RES = "pack.res"; const std::string JSON_SUFFIX = ".json"; const std::string HAP_SUFFIX = ".hap"; +const std::string HAR_SUFFIX = ".har"; const std::string HSP_SUFFIX = ".hsp"; const std::string APP_SUFFIX = ".app"; +const std::string SO_SUFFIX = ".so"; +const std::string RES_SUFFIX = ".res"; +const std::string APK_SUFFIX = ".apk"; +const std::string DEX_SUFFIX = ".dex"; +const std::string ABC_SUFFIX = ".abc"; +const std::string JAR_SUFFIX = ".jar"; +const std::string TXT_SUFFIX = ".txt"; +const std::string PNG_SUFFIX = ".png"; + +const char COMMA_SPLIT = ','; +const std::string INVALID_PATH = "invalid"; + +//Compressor constants +const std::string COMPRESSOR_TEMP_DIR = "temp"; +const std::string TYPE_SHARED = "shared"; +const std::string NULL_DIR_NAME = ""; +const std::string TYPE_APP = "app"; +const std::string DEVICE_TYPE_FITNESSWATCH = "fitnessWatch"; +const std::string DEVICE_TYPE_FITNESSWATCH_NEW = "liteWearable"; constexpr const char* SHORT_OPTIONS = ""; const struct option LONG_OPTIONS[] = { @@ -126,6 +176,14 @@ const struct option LONG_OPTIONS[] = { {PARAM_APPQF_PATH.c_str(), required_argument, nullptr, 34}, {PARAM_MAIN_MODULE_LIMIT.c_str(), required_argument, nullptr, 35}, {PARAM_NORMAL_MODULE_LIMIT.c_str(), required_argument, nullptr, 36}, + {PARAM_FILE_PATH.c_str(), required_argument, nullptr, 37}, + {PARAM_DEX_PATH.c_str(), required_argument, nullptr, 38}, + {PARAM_HNP_PATH.c_str(), required_argument, nullptr, 39}, + {PARAM_JAR_PATH.c_str(), required_argument, nullptr, 40}, + {PARAM_ASSETS_PATH.c_str(), required_argument, nullptr, 41}, + {PARAM_RES_PATH.c_str(), required_argument, nullptr, 42}, + {PARAM_PACK_RES_PATH.c_str(), required_argument, nullptr, 43}, + {PARAM_ENTRYCARD_PATH.c_str(), required_argument, nullptr, 44}, {nullptr, 0, nullptr, 0}, }; constexpr const int OPTIONS_SIZE = sizeof(LONG_OPTIONS) / sizeof(LONG_OPTIONS[0]); diff --git a/ohos_packing_tool/frameworks/include/fast_app_packager.h b/ohos_packing_tool/frameworks/include/fast_app_packager.h new file mode 100755 index 0000000000000000000000000000000000000000..d0a1e90832b14b59a05ca9e08f7e6eedd64bdef4 --- /dev/null +++ b/ohos_packing_tool/frameworks/include/fast_app_packager.h @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DEVELOPTOOLS_PACKING_TOOL_APT_FRAMEWORKS_INCLUDE_FAST_APP_PACKAGER_H +#define DEVELOPTOOLS_PACKING_TOOL_APT_FRAMEWORKS_INCLUDE_FAST_APP_PACKAGER_H + +#include +#include +#include +#include +#include + +#include "packager.h" +#include "zip_wrapper.h" + +namespace OHOS { +namespace AppPackingTool { + +class FastAppackager : public Packager { +public: + FastAppackager(const std::map ¶meterMap, std::string &resultReceiver); + ~FastAppackager() override {} + bool IsVerifyValidInFastAppMode(); + bool IsVerifyValid(); + bool IsFormatPathValid(const std::string &inputPath, std::list &formattedPathList); + bool IsHapPathValid(const std::list &formatPathList); + bool IsHspPathValid(const std::list &formatPathList, const std::string &hspSuffix); + bool ModuleJsonAndPackInfoExists(const std::list &hapPathList, + const std::list &hspPathList); + bool CheckBundleTypeConsistency(const std::list &hapPathList, + const std::list &hspPathList); + bool IsPackInfoValid(const fs::path &packInfo, const std::list &hapPathList, + const std::list &hspPathList); + bool IsPackInfoPathListValid(const std::list &pathList, std::set &packages, + const std::set &allPackageSet); + bool GetPackageNameFromPath(const fs::path &path, std::list &packageNameList); + bool CompressFastAppMode(); + bool CheckHapAndPackFastApp(std::list &fileList, const fs::path &tmpDir); + bool Pack(const std::string &tmpDir, std::list &fileList); + bool Pack(const fs::path &inputPath, const fs::path &appPackInfo, const fs::path &outPath, fs::path &path); + bool PackDir(const fs::path &inputPath, const fs::path &appPackInfo, const fs::path &outPath, fs::path &path); + bool RepackHsp(const fs::path &inputPath, const fs::path &appPackInfo, const fs::path &outPath, fs::path &path); + bool PackFastApp(const std::list &fileList); + bool AddSignatureAndCertificateToApp(); + bool packSingleThread(const fs::path &inputPath, const fs::path &appPackInfo, + const fs::path &outHap, fs::path &path); + bool AddOtherFileToZip(const fs::path &inputPath); + bool packMultiThread(const fs::path &inputPath, const fs::path &appPackInfo, + const fs::path &outHap, fs::path &path); + void GenBuildHash(const fs::path &inputPath, std::string &jsonString); + std::string GetBundleTypeFromPath(const std::string &filePath); + std::string GetModuleJsonContentFromPath(const fs::path &path); + std::string ReadFileToString(const fs::path &path); + std::string GetBundleTypeFromModuleJson(const std::string &moduleJsonContent); + std::string GetPackInfoContentFromPath(const fs::path &path); + std::string UzipHspAndRemovePackInfo(const std::string& hspPath, const std::string& unzipPathString); + +protected: + int InitAllowedParam() override; + int PreProcess() override; + int Process() override; + int PostProcess() override; + +private: + bool isSharedApp_ = false; + bool compressNativeLibs_ = false; + bool isGenerateBuildHash_ = false; + std::string packInfoPath_; + std::list formattedEntryCardPathList_; + std::list formattedHapPathList_; + std::list formattedHspPathList_; + ZipWrapper zipWrapper_; +}; + +} // namespace AppExecFwk +} // namespace OHOS + +#endif // DEVELOPTOOLS_PACKING_TOOL_APT_FRAMEWORKS_INCLUDE_FAST_APP_PACKAGER_H \ No newline at end of file diff --git a/ohos_packing_tool/frameworks/include/hap_packager.h b/ohos_packing_tool/frameworks/include/hap_packager.h index a6e142875bef82d8238204d24a8dc0144c18bc4a..b296ba85b32535a0e5448bd78cc4aed0edaf83c0 100644 --- a/ohos_packing_tool/frameworks/include/hap_packager.h +++ b/ohos_packing_tool/frameworks/include/hap_packager.h @@ -19,8 +19,11 @@ #include #include #include +#include #include "packager.h" +#include "zip_wrapper.h" +#include "json/module_json.h" namespace OHOS { namespace AppPackingTool { @@ -29,12 +32,47 @@ class HapPackager : public Packager { public: HapPackager(const std::map ¶meterMap, std::string &resultReceiver); ~HapPackager() override {} + bool IsVerifyValidInHapCommonMode(); + bool Compatible(const std::string ¶mPath, std::list &fileList, const std::string &suffix); + bool IsVerifyValidInHapMode(); + bool IsValidRpcid(); + bool IsValidPackInfo(); + bool IsHapPathValid(); + bool IsHapPathValid(const std::string ¶meterMapKey); + bool CompressHap(); + bool CheckStageHap(const std::string &jsonPath); + bool AddFileListToZip(const std::list &pathList_); + bool OpenZipWrapper(); + bool AddCommonFileOrDirectoryToZip(const std::string ¶mPath, const std::string &targetPath); + bool AddParamFileToZip(); + bool AddResFileAndDirLsitToZip(); + bool AddIndexToZipForFaMaode(); + bool AddPkgAndBinFileToZipForStageMaode(); + bool CompressHapModeForModule(const std::string &jsonPath); + bool CompressHapMode(); + bool CompressHapModeMultiple(); protected: int InitAllowedParam() override; int PreProcess() override; int Process() override; int PostProcess() override; + +private: + std::list formattedSoPathList_; + std::list formatedDirList_; + std::list formattedApkPathList_; + std::list formattedDexPathList_; + std::list formattedAbcPathList_; + std::list formattedAbilitySoPathList_; + std::list formattedJarPathList_; + std::list formattedTxtPathList_; + + std::string moduleName_; + std::string jsonPath_; + std::list deviceTypes_; + ZipWrapper zipWrapper_; + ModuleJson moduleJson_; }; } // namespace AppExecFwk diff --git a/ohos_packing_tool/frameworks/include/hsp_packager.h b/ohos_packing_tool/frameworks/include/hsp_packager.h index bfc88de1f8bd194cb269216a71d3530557ee451d..176987d4a428be1ea51e6cf1e397043e587476b0 100644 --- a/ohos_packing_tool/frameworks/include/hsp_packager.h +++ b/ohos_packing_tool/frameworks/include/hsp_packager.h @@ -19,8 +19,11 @@ #include #include #include +#include #include "packager.h" +#include "zip_wrapper.h" +#include "json/module_json.h" namespace OHOS { namespace AppPackingTool { @@ -29,12 +32,37 @@ class HspPackager : public Packager { public: HspPackager(const std::map ¶meterMap, std::string &resultReceiver); ~HspPackager() override {} + bool IsVerifyValidInHspCommonMode(); + bool Compatible(const std::string ¶mPath, std::list &fileList, const std::string &suffix); + bool IsVerifyValidInHspMode(); + bool IsHspPathValid(); + bool IsHspPathValid(const std::string ¶meterMapKey); + bool CompressHsp(); + bool CompressHspMode(const std::string &jsonPath); + bool CompressHspModePartSecond(const std::string &jsonPath); + bool CompressHspModePartThird(const std::string &jsonPath); + bool CompressHspModePartFourth(); + bool CompressHspModeMultiple(); + bool AddCommonFileOrDirectoryToZip(const std::string ¶mPath, const std::string &targetPath); protected: int InitAllowedParam() override; int PreProcess() override; int Process() override; int PostProcess() override; + +private: + std::list formatedDirList_; + std::list formattedJarPathList_; + std::list formattedTxtPathList_; + std::list formattedSoPathList_; + std::list formattedDexPathList_; + + std::string moduleName_; + std::string jsonPath_; + std::list deviceTypes_; + ZipWrapper zipWrapper_; + ModuleJson moduleJson_; }; } // namespace AppExecFwk diff --git a/ohos_packing_tool/frameworks/include/packager.h b/ohos_packing_tool/frameworks/include/packager.h index eb643dabafff1f6338d1b25b87ae77173c0121c5..ca956b22f5bab2eb1515a681b21e75f604aa51d3 100644 --- a/ohos_packing_tool/frameworks/include/packager.h +++ b/ohos_packing_tool/frameworks/include/packager.h @@ -23,11 +23,10 @@ #include #include #include +#include #include "constants.h" -#include "contrib/minizip/zip.h" -#include "contrib/minizip/unzip.h" -#include "nlohmann/json.hpp" +#include "json/module_json.h" namespace fs = std::filesystem; @@ -63,14 +62,23 @@ protected: const std::map ¶meterMap_; std::string &resultReceiver_; std::vector allowedParameters_; - nlohmann::json moduleJson; - nlohmann::json packInfo; + bool buildHashFinish_ = false; + bool generateBuildHash_ = false; - void AddFileToZip(zipFile zf, const fs::path &filePath, const fs::path &zipPath, zip_fileinfo &zipfi); - void WriteStringToZip(zipFile zf, const std::string &content, const fs::path &zipPath, zip_fileinfo &zipfi); - bool ParseJsonFile(nlohmann::json &jsonObject, std::string filePath); - bool CheckFileValid(const std::string &filePath, const std::string &filename); - bool endWith(const std::string &str, const std::string &suffix); + bool CheckForceFlag(); + bool IsPathValid(const std::string &path, const bool &isFile, const std::string suffix = ""); + bool SplitDirList(const std::string &dirList, std::list &fileList); + void RemoveDuplicatePath(const std::string &path, std::list &pathList); + bool CompatibleProcess(const std::string &inputPath, std::list &fileList, const std::string &suffix); + bool IsOutPathValid(const std::string &outPath, const std::string &forceRewrite, const std::string &suffix); + bool SetGenerateBuildHash(std::string &jsonPath, bool &generateBuildHash, bool &buildHashFinish); + bool CopyFileToTempDir(std::string &jsonPath); + bool BuildHash(bool &buildHashFinish, const bool &generateBuildHash, + const std::map ¶meterMap, const std::string &jsonPath); + bool PutBuildHash(const std::string &jsonPath, const std::string &hash, bool &buildHashFinish); + bool IsModuleHap(const std::string& hapPath); + void CompressPackinfoIntoHap(const std::string& hapPathItem, const std::string& unzipPathString, + const std::string& outPathString, const std::string& packInfoPath); }; } // namespace AppExecFwk diff --git a/ohos_packing_tool/frameworks/src/fast_app_packager.cpp b/ohos_packing_tool/frameworks/src/fast_app_packager.cpp new file mode 100755 index 0000000000000000000000000000000000000000..09a32e5422099c54140d64afed1ea601dd7e7695 --- /dev/null +++ b/ohos_packing_tool/frameworks/src/fast_app_packager.cpp @@ -0,0 +1,819 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include + +#include "fast_app_packager.h" +#include "constants.h" +#include "utils.h" +#include "zip_utils.h" +#include "json/module_json.h" +#include "json/pack_info.h" +#include "json/module_json_utils.h" + +namespace OHOS { +namespace AppPackingTool { +namespace {} + +FastAppackager::FastAppackager(const std::map ¶meterMap, std::string &resultReceiver) + : Packager(parameterMap, resultReceiver) +{} + +int FastAppackager::InitAllowedParam() +{ + allowedParameters_ = { + {} + }; + return ERR_OK; +} + +int FastAppackager::PreProcess() +{ + if (!CheckForceFlag()) { + return ERR_INVALID_VALUE; + } + + bool ret = IsVerifyValidInFastAppMode(); + if (!ret) { + return ERR_INVALID_VALUE; + } + return ERR_OK; +} + +int FastAppackager::Process() +{ + bool ret = CompressFastAppMode(); + if (!ret) { + return ERR_INVALID_VALUE; + } + return ERR_OK; +} + +int FastAppackager::PostProcess() +{ + return ERR_OK; +} + +bool FastAppackager::IsVerifyValidInFastAppMode() +{ + if (!IsVerifyValid()) { + return false; + } + + std::map::const_iterator itHap = parameterMap_.find(Constants::PARAM_HAP_PATH); + if (itHap != parameterMap_.end() && !itHap->second.empty() && + (!IsFormatPathValid(itHap->second, formattedHapPathList_) || !IsHapPathValid(formattedHapPathList_))) { + std::cout << "CompressVerify::isVerifyValidInFastAppMode hap-path is invalid." << std::endl; + return false; + } + + std::map::const_iterator itHsp = parameterMap_.find(Constants::PARAM_HSP_PATH); + if (itHsp != parameterMap_.end() && !itHsp->second.empty() && (!IsFormatPathValid(itHsp->second, + formattedHspPathList_) || !IsHspPathValid(formattedHspPathList_, Constants::HSP_SUFFIX))) { + std::cout << "CompressVerify::isVerifyValidInFastAppMode hsp-path is invalid." << std::endl; + return false; + } + + if ((itHap == parameterMap_.end() || itHap->second.empty()) && + (itHsp == parameterMap_.end() || itHsp->second.empty())) { + std::cout << "CompressVerify::isVerifyValidInFastAppMode hap-path and hsp-path is empty." << std::endl; + return false; + } + + if (!ModuleJsonAndPackInfoExists(formattedHapPathList_, formattedHspPathList_)) { + std::cout << "CompressVerify::isVerifyValidInFastAppMode hap-path or hsp-path is invalid." << std::endl; + return false; + } + + if (!CheckBundleTypeConsistency(formattedHapPathList_, formattedHspPathList_)) { + std::cout << "CompressVerify::isVerifyValidInFastAppMode bundleType is inconsistent." << std::endl; + return false; + } + + std::string packInfoPath; + std::map::const_iterator it = parameterMap_.find(Constants::PARAM_PACK_INFO_PATH); + if (it != parameterMap_.end() && !it->second.empty()) { + packInfoPath = it->second; + } + if (!IsPackInfoValid(fs::path(packInfoPath), formattedHapPathList_, formattedHspPathList_)) { + std::cout << "CompressVerify::isVerifyValidInFastAppMode pack.info is invalid." << std::endl; + return false; + } + + std::string outPath = ""; + std::string forceRewrite = ""; + it = parameterMap_.find(Constants::PARAM_OUT_PATH); + if (it != parameterMap_.end()) { + outPath = it->second; + } + + it = parameterMap_.find(Constants::PARAM_FORCE); + if (it != parameterMap_.end()) { + forceRewrite = it->second; + } + + return IsOutPathValid(outPath, forceRewrite, Constants::APP_SUFFIX); +} + +bool FastAppackager::IsVerifyValid() +{ + std::map::const_iterator it = parameterMap_.find(Constants::PARAM_PACK_INFO_PATH); + if (it == parameterMap_.end() || it->second.empty()) { + std::cout << "CompressVerify::isArgsValidInAppMode pack-info-path is empty." << std::endl; + return false; + } + + packInfoPath_ = it->second; + if (!IsPathValid(packInfoPath_, true, Constants::PACK_INFO)) { + std::cout << "CompressVerify::isArgsValidInAppMode pack-info-path is invalid." << std::endl; + return false; + } + + it = parameterMap_.find(Constants::PARAM_SIGNATURE_PATH); + if (it != parameterMap_.end() && !it->second.empty() && !IsPathValid(it->second, true)) { + std::cout << "CompressVerify::isVerifyValidInFastAppMode signature-path is invalid." << std::endl; + return false; + } + + it = parameterMap_.find(Constants::PARAM_CERTIFICATE_PATH); + if (it != parameterMap_.end() && !it->second.empty() && !IsPathValid(it->second, true)) { + std::cout << "CompressVerify::isVerifyValidInFastAppMode certificate-path is invalid." << std::endl; + return false; + } + + it = parameterMap_.find(Constants::PARAM_PACK_RES_PATH); + if (it != parameterMap_.end() && !it->second.empty() && + !IsPathValid(it->second, true, Constants::FILE_PACK_RES)) { + std::cout << "CompressVerify::isVerifyValidInFastAppMode pack-res-path is invalid." << std::endl; + return false; + } + + it = parameterMap_.find(Constants::PARAM_ENTRYCARD_PATH); + if (it != parameterMap_.end() && !it->second.empty() && + !CompatibleProcess(it->second, formattedEntryCardPathList_, Constants::PNG_SUFFIX)) { + std::cout << "CompressVerify::isVerifyValidInFastAppMode entrycard-path is invalid." << std::endl; + return false; + } + + it = parameterMap_.find(Constants::PARAM_OUT_PATH); + if (it == parameterMap_.end() || it->second.empty()) { + std::cout << "CompressVerify::isVerifyValidInFastAppMode out-path is empty." << std::endl; + return false; + } + return true; +} + +bool FastAppackager::IsFormatPathValid(const std::string &inputPath, std::list &formattedPathList) +{ + std::set formatPathSet; + std::istringstream iss(inputPath); + std::string path; + + while (std::getline(iss, path, Constants::COMMA_SPLIT)) { + try { + fs::path realpath = fs::canonical(path); + if (fs::exists(realpath)) { + formatPathSet.insert(realpath.string()); + } else { + std::cout << "PackageUtil::formatPath not exists: " << realpath << std::endl; + return false; + } + } catch (const std::exception& ex) { + std::cout << "PackageUtil::formatPath err: " << ex.what() << std::endl; + return false; + } + } + + formattedPathList.assign(formatPathSet.begin(), formatPathSet.end()); + return true; +} + +bool FastAppackager::IsHapPathValid(const std::list &formatPathList) +{ + for (const auto& path : formatPathList) { + if (!fs::is_directory(path)) { + return false; + } + } + return true; +} + +bool FastAppackager::IsHspPathValid(const std::list &formatPathList, const std::string &hspSuffix) +{ + for (const auto& path : formatPathList) { + if (!fs::is_directory(path) && !IsPathValid(path, true, hspSuffix)) { + return false; + } + } + return true; +} + +bool FastAppackager::ModuleJsonAndPackInfoExists(const std::list &hapPathList, + const std::list &hspPathList) +{ + for (const auto& hapPath : hapPathList) { + fs::path path = fs::path(hapPath); + if (!fs::exists(path / fs::path(Constants::MODULE_JSON))) { + std::cout << "not found module.json in path: " << path << std::endl; + return false; + } + if (!fs::exists(path / fs::path(Constants::PACK_INFO))) { + std::cout << "not found pack.info in path: " << path << std::endl; + return false; + } + } + for (const auto& hspPath : hspPathList) { + fs::path path = fs::path(hspPath); + if (fs::is_directory(path)) { + if (!fs::exists(path / fs::path(Constants::MODULE_JSON))) { + std::cout << "not found module.json in path: " << path << std::endl; + return false; + } + if (!fs::exists(path / fs::path(Constants::PACK_INFO))) { + std::cout << "not found pack.info in path: " << path << std::endl; + return false; + } + } + } + return true; +} + +bool FastAppackager::CheckBundleTypeConsistency(const std::list &hapPathList, + const std::list &hspPathList) +{ + std::string bundleType; + if (!hapPathList.empty()) { + bundleType = GetBundleTypeFromPath(hapPathList.front()); + } else if (!hspPathList.empty()) { + bundleType = GetBundleTypeFromPath(hspPathList.front()); + } + if (bundleType.empty()) { + return false; + } + for (const auto& hapPath : hapPathList) { + if (GetBundleTypeFromPath(hapPath) != bundleType) { + std::cout << "bundleType is not same" << std::endl; + return false; + } + } + for (const auto& hspPath : hspPathList) { + if (GetBundleTypeFromPath(hspPath) != bundleType) { + std::cout << "bundleType is not same" << std::endl; + return false; + } + } + if (bundleType == Constants::TYPE_SHARED) { + isSharedApp_ = true; + } + return true; +} + +std::string FastAppackager::GetBundleTypeFromPath(const std::string &filePath) +{ + fs::path path(filePath); + if (!fs::exists(path)) { + std::cout << "getBundleTypeFromPath path not exists: " << path << std::endl; + return ""; + } + std::string content = GetModuleJsonContentFromPath(path); + if (content.empty()) { + return ""; + } + return GetBundleTypeFromModuleJson(content); +} + +std::string FastAppackager::GetModuleJsonContentFromPath(const fs::path &path) +{ + if (fs::is_regular_file(path)) { + std::string filename = path.filename().string(); + if (filename == Constants::MODULE_JSON) { + return ReadFileToString(path); + } else if (Utils::EndsWith(filename, Constants::HSP_SUFFIX)) { + std::string fileContent; + if (!ZipUtils::GetFileContentFromZip(path, Constants::MODULE_JSON, fileContent)) { + std::cout << "GetModuleJsonContentFromPath err: " << path << std::endl; + return ""; + } + return fileContent; + } + } else { + return ReadFileToString(path / fs::path(Constants::MODULE_JSON)); + } + return ""; +} + +std::string FastAppackager::ReadFileToString(const fs::path &path) +{ + std::ifstream file(path.string(), std::ios::in | std::ios::binary); + if (!file.is_open()) { + throw std::runtime_error("Failed to open file: " + path.string()); + } + + std::stringstream buffer; + buffer << file.rdbuf(); + + return buffer.str(); +} + +std::string FastAppackager::GetBundleTypeFromModuleJson(const std::string &moduleJsonContent) +{ + ModuleJson moduleJson; + if (!moduleJson.ParseFromString(moduleJsonContent)) { + std::cout << "GetBundleTypeFromModuleJson ParseFromString err." << std::endl; + return ""; + } + + std::string bundleType; + if (!moduleJson.GetStageBundleType(bundleType)) { + std::cout << "GetBundleTypeFromModuleJson GetStageBundleType err." << std::endl; + return ""; + } + return bundleType != "" ? bundleType : Constants::TYPE_APP; +} + +bool FastAppackager::IsPackInfoValid(const fs::path &packInfo, const std::list &hapPathList, + const std::list &hspPathList) +{ + std::list allPackages; + if (!GetPackageNameFromPath(packInfo, allPackages)) { + std::cout << "GetPackageNameFromPath for packInfo err: " << packInfo << std::endl; + return false; + } + std::set allPackageSet(allPackages.begin(), allPackages.end()); + if (allPackages.size() > allPackageSet.size()) { + std::cout << "package name is redundant in app pack.info: " << packInfo << std::endl; + return false; + } + if (allPackages.empty()) { + std::cout << "app pack.info format err: " << packInfo << std::endl; + return false; + } + std::set packages; + if (!IsPackInfoPathListValid(hapPathList, packages, allPackageSet) || + !IsPackInfoPathListValid(hspPathList, packages, allPackageSet)) { + return false; + } + + if (allPackageSet != packages) { + std::cout << "package name not same between module and app pack.info." << std::endl; + return false; + } + return true; +} + +bool FastAppackager::IsPackInfoPathListValid(const std::list &pathList, std::set &packages, + const std::set &allPackageSet) +{ + for (const auto& path : pathList) { + std::list list; + if (!GetPackageNameFromPath(fs::path(path), list)) { + std::cout << "GetPackageNameFromPath for packInfo err" << std::endl; + return false; + } + if (list.size() != 1) { + std::cout << "module pack.info format err: " << path << std::endl; + return false; + } + std::string packageName = list.front(); + if (allPackageSet.find(packageName) == allPackageSet.end()) { + std::cout << "module pack.info name not exist in app pack.info name list: " << path << std::endl; + return false; + } + if (packages.find(packageName) != packages.end()) { + std::cout << "package name is redundant in " << path << std::endl; + return false; + } + packages.insert(packageName); + } + return true; +} + +bool FastAppackager::GetPackageNameFromPath(const fs::path &path, std::list &packageNameList) +{ + if (!fs::exists(path)) { + std::cout << "GetPackageNameFromPath path not exists: " << path << std::endl; + return false; + } + if (fs::is_regular_file(path)) { + std::string filename = path.filename().string(); + if (Utils::EndsWith(filename, Constants::HSP_SUFFIX)) { + // .hsp: return filename + packageNameList.push_back(filename.substr(0, filename.find(Constants::HSP_SUFFIX))); + return true; + } + } + std::string content = GetPackInfoContentFromPath(path); + if (content.empty()) { + return false; + } + + PackInfo packInfo; + if (!packInfo.ParseFromString(content)) { + std::cout << "GetPackageNameFromPath ParseFromString err." << std::endl; + return false; + } + return packInfo.GetPackageNames(packageNameList); +} + +std::string FastAppackager::GetPackInfoContentFromPath(const fs::path &path) +{ + + if (fs::is_regular_file(path)) { + std::string filename = path.filename().string(); + if (filename == Constants::PACK_INFO) { + return ReadFileToString(path); + } else if (Utils::EndsWith(filename, Constants::HSP_SUFFIX)) { + std::string fileContent; + if (!ZipUtils::GetFileContentFromZip(path, Constants::PACK_INFO, fileContent)) { + std::cout << "GetPackInfoContentFromPath err: " << path << std::endl; + return ""; + } + return fileContent; + } + } else { + return ReadFileToString(path / fs::path(Constants::PACK_INFO)); + } + return ""; +} + +bool FastAppackager::CompressFastAppMode() +{ + fs::path tmpDir; + fs::path appOutPath; + std::map::const_iterator it = parameterMap_.find(Constants::PARAM_OUT_PATH); + if (it != parameterMap_.end() && !it->second.empty()) { + appOutPath = fs::path(it->second); + } + + try { + tmpDir = appOutPath.parent_path() / fs::path(Constants::COMPRESSOR_TEMP_DIR); + if (!fs::create_directory(tmpDir)) { + std::cout << "Compressor::compressAppMode create tmpDir failed: " << tmpDir.string() << std::endl; + return false; + } + + std::list fileList; + if (!Pack(tmpDir, fileList)) { + if (fs::exists(tmpDir)) { + fs::remove_all(tmpDir); + } + return false; + } + + if (!CheckHapAndPackFastApp(fileList, tmpDir)) { + if (fs::exists(tmpDir)) { + fs::remove_all(tmpDir); + } + return false; + } + } catch (const std::exception& ex) { + std::cout << "Compressor::CompressFastAppMode compress failed: " << ex.what() << std::endl; + if (fs::exists(tmpDir)) { + fs::remove_all(tmpDir); + } + return false; + } + if (fs::exists(tmpDir)) { + fs::remove_all(tmpDir); + } + return true; +} + +bool FastAppackager::CheckHapAndPackFastApp(std::list &fileList, const fs::path &tmpDir) +{ + if (!ModuleJsonUtils::CheckHapsIsValid(fileList, isSharedApp_)) { + std::cout << "Compressor::CheckHapsIsValid verify failed, " + "check version, apiVersion, moduleName, packageName." << std::endl; + return false; + } + + if (!PackFastApp(fileList)) { + std::cout << "Compressor::CompressFastAppMode PackFastApp failed." << std::endl; + return false; + } + return true; +} + +bool FastAppackager::Pack(const std::string &tmpDir, std::list &fileList) +{ + fs::path appPackInfo = fs::path(packInfoPath_); + for (const auto& hapPath : formattedHapPathList_) { + fs::path path = fs::path(hapPath); + fs::path hap; + if (!Pack(path, appPackInfo, tmpDir, hap)) { + if (fs::exists(tmpDir)) { + fs::remove_all(tmpDir); + } + return false; + } + if (!hap.empty()) { + fileList.push_back(hap.string()); + } + } + for (const auto& hspPath : formattedHspPathList_) { + fs::path path = fs::path(hspPath); + fs::path hsp; + if (!Pack(path, appPackInfo, tmpDir, hsp)) { + if (fs::exists(tmpDir)) { + fs::remove_all(tmpDir); + } + return false; + } + if (!hsp.empty()) { + fileList.push_back(hsp.string()); + } + } + return true; +} + +bool FastAppackager::Pack(const fs::path &inputPath, const fs::path &appPackInfo, const fs::path &outPath, + fs::path &path) +{ + if (!fs::exists(inputPath)) { + std::cout << "pack err, input path not exists." << std::endl; + return false; + } + if (!fs::exists(appPackInfo)) { + std::cout << "pack err, app pack.info not exists." << std::endl; + return false; + } + if (fs::is_directory(inputPath)) { + return PackDir(inputPath, appPackInfo, outPath, path); + } else if (fs::is_regular_file(inputPath) && Utils::EndsWith(inputPath.filename().string(), + Constants::HSP_SUFFIX)) { + return RepackHsp(inputPath, appPackInfo, outPath, path); + } + + std::cout << "pack err, not support: " << inputPath.string() << std::endl; + return false; +} + +bool FastAppackager::PackDir(const fs::path &inputPath, const fs::path &appPackInfo, + const fs::path &outPath, fs::path &path) +{ + std::list packageNames; + if (!GetPackageNameFromPath(inputPath / fs::path(Constants::PACK_INFO), packageNames)) { + std::cout << "pack err, pack.info format err" << std::endl; + return false; + } + if (packageNames.size() != 1) { + std::cout << "pack err, pack.info format err" << std::endl; + return false; + } + ModuleJson moduleJson; + if (!moduleJson.ParseFromFile(inputPath / fs::path(Constants::MODULE_JSON))) { + std::cout << "pack err, module.json format err" << std::endl; + return false; + } + std::string pkgName = packageNames.front(); + std::string moudleType; + moduleJson.GetStageModuleType(moudleType); + moduleJson.GetStageCompressNativeLibs(compressNativeLibs_); + moduleJson.GetGenerateBuildHash(isGenerateBuildHash_); + std::string suffix = moudleType == Constants::TYPE_SHARED ? Constants::HSP_SUFFIX : Constants::HAP_SUFFIX; + + fs::path outHap = outPath / fs::path(pkgName); + outHap += fs::path(suffix); + return packSingleThread(inputPath, appPackInfo, outHap, path); +} + +bool FastAppackager::RepackHsp(const fs::path &inputPath, const fs::path &appPackInfo, + const fs::path &outPath, fs::path &path) +{ + fs::path outHsp = outPath / inputPath.filename(); + std::string outHspStr = outHsp.string(); + zipWrapper_.Open(outHspStr); + if (!zipWrapper_.IsOpen()) { + std::cout << "FastAppackager::RepackHsp: zipWrapper Open failed!" << std::endl; + return false; + } + + std::string zipPath = Constants::NULL_DIR_NAME; + if (!fs::is_directory(appPackInfo)) { + zipPath = (appPackInfo).filename().string(); + } + if (zipWrapper_.AddFileOrDirectoryToZip(appPackInfo.string(), zipPath) != ZipErrCode::ZIP_ERR_SUCCESS) { + std::cout << "FastAppackager::RepackHsp: zipWrapper AddFileOrDirectoryToZip failed!" << std::endl; + return false; + } + + std::string uZipTempPath = "uzip_temp_path"; + fs::path unzipPathString = inputPath.parent_path() / fs::path(uZipTempPath); + if (!fs::create_directories(unzipPathString)) { + std::cout << "Can't create directory to path " << unzipPathString.string() << std::endl; + return false; + } + std::string uzipHsp = UzipHspAndRemovePackInfo(inputPath.string(), unzipPathString.string()); + if (zipWrapper_.AddFileOrDirectoryToZip(uzipHsp, Constants::NULL_DIR_NAME) != ZipErrCode::ZIP_ERR_SUCCESS) { + std::cout << "FastAppackager::RepackHsp: zipWrapper AddFileOrDirectoryToZip failed!" << std::endl; + return false; + } + fs::remove_all(uzipHsp); + zipWrapper_.Close(); + path = outHspStr; + return true; +} + +bool FastAppackager::PackFastApp(const std::list &fileList) +{ + std::map::const_iterator it = parameterMap_.find(Constants::PARAM_OUT_PATH); + std::string outPath; + if (it != parameterMap_.end()) { + outPath = it->second; + } + zipWrapper_.Open(outPath); + if (!zipWrapper_.IsOpen()) { + std::cout << "FastAppackager::PackFastApp: zipWrapper Open failed!" << std::endl; + return false; + } + + if (zipWrapper_.AddFileOrDirectoryToZip(packInfoPath_, Constants::PACK_INFO) != ZipErrCode::ZIP_ERR_SUCCESS) { + std::cout << "FastAppackager::PackFastApp: zipWrapper WriteStringToZip failed!" << std::endl; + return false; + } + + for (const auto& hapPath : fileList) { + if (zipWrapper_.AddFileOrDirectoryToZip(hapPath, fs::path(hapPath).filename().string()) != + ZipErrCode::ZIP_ERR_SUCCESS) { + std::cout << "HapPackager::Process: zipWrapper AddFileOrDirectoryToZip failed!" << std::endl; + return false; + } + } + + std::string moduleName; + it = parameterMap_.find(Constants::PARAM_ENTRYCARD_PATH); + if (it != parameterMap_.end() && !it->second.empty()) { + std::string entryCardPath = Constants::ENTRYCARD_NAME + moduleName + Constants::LINUX_FILE_SEPARATOR + + Constants::ENTRYCARD_BASE_NAME + Constants::ENTRYCARD_SNAPSHOT_NAME; + for (auto itemFormattedEntryCardPath : formattedEntryCardPathList_) { + if (zipWrapper_.AddFileOrDirectoryToZip(itemFormattedEntryCardPath, entryCardPath + + fs::path(itemFormattedEntryCardPath).filename().string()) != + ZipErrCode::ZIP_ERR_SUCCESS) { + std::cout << "HapPackager::Process: zipWrapper AddFileOrDirectoryToZip failed!" << std::endl; + return false; + } + } + } + it = parameterMap_.find(Constants::PARAM_PACK_RES_PATH); + if (it != parameterMap_.end() && !it->second.empty()) { + if (zipWrapper_.AddFileOrDirectoryToZip(it->second, Constants::FILE_PACK_RES) != ZipErrCode::ZIP_ERR_SUCCESS) { + std::cout << "HapPackager::Process: zipWrapper AddFileOrDirectoryToZip failed!" << std::endl; + return false; + } + } + return AddSignatureAndCertificateToApp(); +} + +bool FastAppackager::AddSignatureAndCertificateToApp() +{ + std::map::const_iterator it = parameterMap_.find(Constants::PARAM_CERTIFICATE_PATH); + if (it != parameterMap_.end() && !it->second.empty()) { + fs::path filePath = fs::path(it->second); + std::string zipPath = Constants::NULL_DIR_NAME; + if (!fs::is_directory(filePath)) { + zipPath = (filePath).filename().string(); + } + if (zipWrapper_.AddFileOrDirectoryToZip(it->second, zipPath) != ZipErrCode::ZIP_ERR_SUCCESS) { + std::cout << "HapPackager::Process: zipWrapper AddFileOrDirectoryToZip failed!" << std::endl; + return false; + } + } + + it = parameterMap_.find(Constants::PARAM_SIGNATURE_PATH); + if (it != parameterMap_.end() && !it->second.empty()) { + fs::path filePath = fs::path(it->second); + std::string zipPath = Constants::NULL_DIR_NAME; + if (!fs::is_directory(filePath)) { + zipPath = (filePath).filename().string(); + } + if (zipWrapper_.AddFileOrDirectoryToZip(it->second, zipPath) != ZipErrCode::ZIP_ERR_SUCCESS) { + std::cout << "HapPackager::Process: zipWrapper AddFileOrDirectoryToZip failed!" << std::endl; + return false; + } + } + + zipWrapper_.Close(); + return true; +} + +bool FastAppackager::packMultiThread(const fs::path &inputPath, const fs::path &appPackInfo, + const fs::path &outHap, fs::path &path) +{ + return true; +} + +bool FastAppackager::packSingleThread(const fs::path &inputPath, const fs::path &appPackInfo, + const fs::path &outHap, fs::path &path) +{ + if (!fs::exists(inputPath) || !fs::is_directory(inputPath)) { + std::cout << "Directory does not exist or is not a directory" << std::endl; + return false; + } + + std::string pathStr = outHap.string(); + zipWrapper_.Open(pathStr); + if (!zipWrapper_.IsOpen()) { + std::cout << "FastAppackager::packSingleThread: zipWrapper Open failed! path: " << pathStr << std::endl; + return false; + } + + std::string zipPath = Constants::NULL_DIR_NAME; + if (!fs::is_directory(appPackInfo)) { + zipPath = (appPackInfo).filename().string(); + } + if (zipWrapper_.AddFileOrDirectoryToZip(appPackInfo.string(), zipPath) != ZipErrCode::ZIP_ERR_SUCCESS) { + std::cout << "FastAppackager::Process: zipWrapper AddFileOrDirectoryToZip failed!" << std::endl; + return false; + } + + if (isGenerateBuildHash_) { + std::string jsonString; + GenBuildHash(inputPath, jsonString); + if (zipWrapper_.WriteStringToZip(jsonString, Constants::MODULE_JSON) != ZipErrCode::ZIP_ERR_SUCCESS) { + std::cout << "FastAppackager::packSingleThread: zipWrapper WriteStringToZip failed!" << std::endl; + return false; + } + } + if (!AddOtherFileToZip(inputPath)) { + return false; + } + path = pathStr; + return true; +} + +bool FastAppackager::AddOtherFileToZip(const fs::path &inputPath) +{ + for (const auto& entry : fs::directory_iterator(inputPath)) { + if (fs::is_regular_file(entry) && entry.path().filename().string() != Constants::PACK_INFO) { + if (isGenerateBuildHash_ && entry.path().filename().string() == Constants::MODULE_JSON) { + continue; + } + std::string zipPath = entry.path().filename().string(); + if (zipWrapper_.AddFileOrDirectoryToZip(entry.path().string(), zipPath) != ZipErrCode::ZIP_ERR_SUCCESS) { + std::cout << "FastAppackager::Process: zipWrapper AddFileOrDirectoryToZip failed!" << std::endl; + return false; + } + } else if (fs::is_directory(entry)) { + if (entry.path().filename() == Constants::LIB_PATH) { + if (zipWrapper_.AddFileOrDirectoryToZip(entry.path().string(), Constants::LIB_PATH) != + ZipErrCode::ZIP_ERR_SUCCESS) { + std::cout << "FastAppackager::Process: zipWrapper AddFileOrDirectoryToZip failed!" << std::endl; + return false; + } + } else { + if (zipWrapper_.AddFileOrDirectoryToZip(entry.path().string(), entry.path().filename().string() + + Constants::NULL_DIR_NAME) != ZipErrCode::ZIP_ERR_SUCCESS) { + std::cout << "FastAppackager::Process: zipWrapper AddFileOrDirectoryToZip failed!" << std::endl; + return false; + } + } + } + } + zipWrapper_.Close(); + return true; +} + +void FastAppackager::GenBuildHash(const fs::path &inputPath, std::string &jsonString) +{ + std::string hash = Utils::GetSha256File(inputPath); + if (hash.empty()) { + return; + } + ModuleJson moduleJson; + if (!moduleJson.ParseFromFile(inputPath / fs::path(Constants::MODULE_JSON))) { + std::cout << "pack err, module.json format err" << std::endl; + return; + } + moduleJson.SetBuildHash(hash); + jsonString = moduleJson.ToString(); +} + +std::string FastAppackager::UzipHspAndRemovePackInfo(const std::string& hspPath, const std::string& unzipPathString) +{ + ZipUtils::Unzip(hspPath, unzipPathString); + for (const auto& entry : fs::directory_iterator(unzipPathString)) { + if (entry.path().filename() == Constants::PACK_INFO) { + fs::remove(entry.path()); + continue; + } + } + return unzipPathString; +} +} // namespace AppPackingTool +} // namespace OHOS \ No newline at end of file diff --git a/ohos_packing_tool/frameworks/src/hap_packager.cpp b/ohos_packing_tool/frameworks/src/hap_packager.cpp index fda8730b78a34631cbb4b22bcfdfb85f3f48cd5a..233f18361ebb9af5410284721cfe36ef1a1030e3 100644 --- a/ohos_packing_tool/frameworks/src/hap_packager.cpp +++ b/ohos_packing_tool/frameworks/src/hap_packager.cpp @@ -13,18 +13,13 @@ * limitations under the License. */ -#include -#include #include #include -#include #include #include "hap_packager.h" #include "constants.h" -#include "contrib/minizip/zip.h" -#include "nlohmann/json.hpp" -#include "packager.h" +#include "json/json_utils.h" namespace OHOS { namespace AppPackingTool { @@ -44,61 +39,584 @@ int HapPackager::InitAllowedParam() int HapPackager::PreProcess() { + if (!CheckForceFlag()) { + return ERR_INVALID_VALUE; + } + + std::map::const_iterator it = parameterMap_.find(Constants::PARAM_JSON_PATH); + std::string jsonPath; + if (it != parameterMap_.end()) { + jsonPath = it->second; + } + it = parameterMap_.find(Constants::PARAM_BIN_PATH); + if (it != parameterMap_.end() && !it->second.empty() && jsonPath.empty()) { + std::string outPath = ""; + std::string forceRewrite = ""; + it = parameterMap_.find(Constants::PARAM_OUT_PATH); + if (it != parameterMap_.end()) { + outPath = it->second; + } + + it = parameterMap_.find(Constants::PARAM_FORCE); + if (it != parameterMap_.end()) { + forceRewrite = it->second; + } + + return IsOutPathValid(outPath, forceRewrite, Constants::HAP_SUFFIX); + } else { + bool ret = IsVerifyValidInHapCommonMode() && IsVerifyValidInHapMode(); + if (!ret) { + return ERR_INVALID_VALUE; + } + } return ERR_OK; } int HapPackager::Process() { std::cout << "Hap DoPackage" << std::endl; - std::string outPath = parameterMap_.at(Constants::PARAM_OUT_PATH); - zipFile zf = zipOpen64(outPath.c_str(), APPEND_STATUS_CREATE); - if (zf == nullptr) { - std::cout << "err zipOpen64 null" << std::endl; + if (!CompressHap()) { + std::cout << "Hap DoPackage failed." << std::endl; return ERR_INVALID_VALUE; } - zip_fileinfo fi = {}; + return ERR_OK; +} + +int HapPackager::PostProcess() +{ + if (generateBuildHash_) { + std::cout << "start sencond CompressHap" << std::endl; + if (!CompressHap()) { + std::cout << "sencond CompressHap failed." << std::endl; + return ERR_INVALID_VALUE; + } + } + return ERR_OK; +} + +bool HapPackager::IsVerifyValidInHapCommonMode() +{ std::map::const_iterator it = parameterMap_.find(Constants::PARAM_JSON_PATH); + if (it == parameterMap_.end() || it->second.empty()) { + std::cout << "CompressVerify::commandPathVerify json-path is empty." << std::endl; + return false; + } + jsonPath_ = it->second; + if (!IsPathValid(it->second, true, Constants::CONFIG_JSON) + && !IsPathValid(it->second, true, Constants::MODULE_JSON)) { + std::cout << "CompressVerify::isArgsValidInHarMode json-path must be" + " config.json or module.json file." << std::endl; + return false; + } + if (!IsValidRpcid() || !IsValidPackInfo()) { + return false; + } + it = parameterMap_.find(Constants::PARAM_PROFILE_PATH); if (it != parameterMap_.end()) { - if (ParseJsonFile(moduleJson, it->second)) { - WriteStringToZip(zf, moduleJson.dump(), fs::path(Constants::MODULE_JSON), fi); + const std::string filePath = it->second; + if (!fs::is_regular_file(filePath) || + fs::path(filePath).filename().string() != Constants::PROFILE_NAME) { + std::cout << "CompressVerify::isArgsValidInHapMode profile-path" + " must be CAPABILITY.profile file." << std::endl; + return false; } } - it = parameterMap_.find(Constants::PARAM_LIB_PATH); + if (!Compatible(Constants::PARAM_APK_PATH, formattedApkPathList_, Constants::APK_SUFFIX) || + !Compatible(Constants::PARAM_DEX_PATH, formattedDexPathList_, Constants::DEX_SUFFIX) || + !Compatible(Constants::PARAM_ABC_PATH, formattedAbcPathList_, Constants::ABC_SUFFIX)) { + return false; + } + it = parameterMap_.find(Constants::PARAM_DIR_LIST); + if (it != parameterMap_.end() && !SplitDirList(it->second, formatedDirList_)) { + std::cout << "CompressVerify::isArgsValidInHapMode --dir-list is invalid." << std::endl; + return false; + } + it = parameterMap_.find(Constants::PARAM_PKG_CONTEXT_PATH); if (it != parameterMap_.end()) { - AddFileToZip(zf, fs::path(it->second), fs::path(Constants::LIB_PATH), fi); + const std::string filePath = it->second; + if (!fs::is_regular_file(filePath) || + fs::path(filePath).filename().string() != Constants::PKG_CONTEXT_JSON) { + std::cout << "CompressVerify::isArgsValidInHapMode --pkg-context-path" + " file must be pkgContextInfo.json file." << std::endl; + return false; + } } - it = parameterMap_.find(Constants::PARAM_RESOURCES_PATH); + return true; +} + +bool HapPackager::Compatible(const std::string ¶mPath, std::list &fileList, + const std::string &suffix) +{ + std::map::const_iterator it = parameterMap_.find(paramPath); + if (it != parameterMap_.end() && !it->second.empty() && !CompatibleProcess(it->second, + fileList, suffix)) { + std::cout << "CompressVerify::isArgsValidInHapMode "<< paramPath << " is invalid." << std::endl; + return false; + } + return true; +} + +bool HapPackager::IsVerifyValidInHapMode() +{ + std::cout << "start IsVerifyValidInHapMode" << std::endl; + std::map::const_iterator it = parameterMap_.find(Constants::PARAM_INDEX_PATH); if (it != parameterMap_.end()) { - AddFileToZip(zf, fs::path(it->second), fs::path(Constants::RESOURCES_PATH), fi); + const std::string filePath = it->second; + if (!fs::is_regular_file(filePath) || + fs::path(filePath).filename().string() != Constants::RESOURCES_INDEX) { + std::cout << "CompressVerify::isArgsValidInHapMode index-path must be resources.index file." << std::endl; + return false; + } + } + + if (!Compatible(Constants::PARAM_MAPLE_SO_PATH, formattedSoPathList_, Constants::SO_SUFFIX) || + !Compatible(Constants::PARAM_ABILITY_SO_PATH, formattedAbilitySoPathList_, Constants::SO_SUFFIX) || + !Compatible(Constants::PARAM_JAR_PATH, formattedJarPathList_, Constants::JAR_SUFFIX) || + !Compatible(Constants::PARAM_TXT_PATH, formattedTxtPathList_, Constants::TXT_SUFFIX)) { + return false; } - it = parameterMap_.find(Constants::PARAM_INDEX_PATH); + + if (!IsHapPathValid()) { + return false; + } + + it = parameterMap_.find(Constants::PARAM_ETS_PATH); if (it != parameterMap_.end()) { - AddFileToZip(zf, fs::path(it->second), fs::path(Constants::RESOURCES_INDEX), fi); + const std::string filePath = it->second; + if (!filePath.empty() && !fs::exists(filePath)) { + return false; + } } - it = parameterMap_.find(Constants::PARAM_PACK_INFO_PATH); + + std::string outPath = ""; + std::string forceRewrite = ""; + it = parameterMap_.find(Constants::PARAM_OUT_PATH); if (it != parameterMap_.end()) { - AddFileToZip(zf, fs::path(it->second), fs::path(Constants::PACK_INFO), fi); + outPath = it->second; } - it = parameterMap_.find(Constants::PARAM_ETS_PATH); + + it = parameterMap_.find(Constants::PARAM_FORCE); if (it != parameterMap_.end()) { - AddFileToZip(zf, fs::path(it->second), fs::path(Constants::ETS_PATH), fi); + forceRewrite = it->second; } - it = parameterMap_.find(Constants::PARAM_RPCID_PATH); + + return IsOutPathValid(outPath, forceRewrite, Constants::HAP_SUFFIX); +} + + +bool HapPackager::IsValidRpcid() +{ + std::map::const_iterator it = parameterMap_.find(Constants::PARAM_RPCID_PATH); if (it != parameterMap_.end()) { - AddFileToZip(zf, fs::path(it->second), fs::path(Constants::RPCID_SC), fi); + const std::string filePath = it->second; + if (!fs::is_regular_file(filePath)) { + std::cout << "CompressVerify::isValidRpcid rpcid-path is not a file." << std::endl; + return false; + } + if (fs::path(filePath).filename().string() != Constants::RPCID_SC) { + std::cout << "CompressVerify::isValidRpcid rpcid-path must be rpcid.sc file." << std::endl; + return false; + } } - it = parameterMap_.find(Constants::PARAM_PKG_CONTEXT_PATH); + return true; +} + +bool HapPackager::IsValidPackInfo() +{ + std::map::const_iterator it = parameterMap_.find(Constants::PARAM_PACK_INFO_PATH); if (it != parameterMap_.end()) { - AddFileToZip(zf, fs::path(it->second), fs::path(Constants::PKG_CONTEXT_JSON), fi); + const std::string filePath = it->second; + if (!fs::is_regular_file(filePath)) { + std::cout << "CompressVerify::isValidPackInfo --pack-info-path is not a file." << std::endl; + return false; + } + if (fs::path(filePath).filename().string() != Constants::PACK_INFO) { + std::cout << "CompressVerify::isValidPackInfo --pack-info-path must be pack.info file." << std::endl; + return false; + } } - zipClose(zf, nullptr); - return ERR_OK; + return true; } -int HapPackager::PostProcess() +bool HapPackager::IsHapPathValid() { - return ERR_OK; + if (IsHapPathValid(Constants::PARAM_MAPLE_SO_DIR)) { + std::cout << "CompressVerify::isArgsValidInHapMode maple-so-dir is invalid." << std::endl; + return false; + } + + if (IsHapPathValid(Constants::PARAM_LIB_PATH)) { + std::cout << "CompressVerify::isArgsValidInHapMode lib-path is invalid." << std::endl; + return false; + } + + if (IsHapPathValid(Constants::PARAM_HNP_PATH)) { + std::cout << "CompressVerify::isArgsValidInHapMode hnp-path is invalid." << std::endl; + return false; + } + + if (IsHapPathValid(Constants::PARAM_RES_PATH)) { + std::cout << "CompressVerify::isArgsValidInHapMode res-path is invalid." << std::endl; + return false; + } + + if (IsHapPathValid(Constants::PARAM_RESOURCES_PATH)) { + std::cout << "CompressVerify::isArgsValidInHapMode resources-path is invalid." << std::endl; + return false; + } + + if (IsHapPathValid(Constants::PARAM_ASSETS_PATH)) { + std::cout << "CompressVerify::isArgsValidInHapMode assets-path is invalid." << std::endl; + return false; + } + + if (IsHapPathValid(Constants::PARAM_SHAREDLIBS_PATH)) { + std::cout << "CompressVerify::isArgsValidInHapMode shared-libs-path is invalid." << std::endl; + return false; + } + + if (IsHapPathValid(Constants::PARAM_AN_PATH)) { + std::cout << "CompressVerify::isArgsValidInHapMode an-path is invalid." << std::endl; + return false; + } + return true; +} + +bool HapPackager::IsHapPathValid(const std::string ¶meterMapKey) +{ + std::map::const_iterator it = parameterMap_.find(parameterMapKey); + if (it == parameterMap_.end()) { + return false; + } + const std::string path = it->second; + return (!path.empty() && !IsPathValid(path, false)); +} + +bool HapPackager::CompressHap() +{ + std::map::const_iterator it = parameterMap_.find(Constants::PARAM_BIN_PATH); + if (jsonPath_.empty() && it != parameterMap_.end() && !it->second.empty()) { + CompressHapMode(); + return true; + } + if (!SetGenerateBuildHash(jsonPath_, generateBuildHash_, buildHashFinish_)) { + return false; + } + if (!moduleJson_.ParseFromFile(jsonPath_)) { + std::cout << "ParseFromFile failed" << std::endl; + return false; + } + if (JsonUtils::IsModuleJson(jsonPath_)) { + if (!CheckStageHap(jsonPath_)) { + std::cout << "CheckStageHap failed." << std::endl; + return false; + } + std::string moduleType; + if (!moduleJson_.GetStageModuleType(moduleType)) { + std::cout << "GetStageModuleType failed" << std::endl; + } + if (Constants::TYPE_SHARED == moduleType) { + std::cout << "Compress mode is hap, but module type is shared." << std::endl; + } + + std::string bundleType; + if (!moduleJson_.GetStageBundleType(bundleType)) { + std::cout << "GetStageBundleType failed" << std::endl; + } + if (Constants::TYPE_SHARED == bundleType) { + std::cout << "Compress mode is hap, but app type is shared." << std::endl; + } + if (!CompressHapModeForModule(jsonPath_) || !BuildHash(buildHashFinish_, generateBuildHash_, + parameterMap_, jsonPath_)) { + return false; + } + } else { + if (!CompressHapMode() || !BuildHash(buildHashFinish_, generateBuildHash_, parameterMap_, jsonPath_)) { + return false; + } + } + return true; +} + +bool HapPackager::CheckStageHap(const std::string &jsonPath) +{ + if (!moduleJson_.CheckStageAsanTsanEnabledValid()) { + std::cout << "CheckStageAsanTsanEnabledValid failed." << std::endl; + return false; + } + + if (!moduleJson_.CheckStageAtomicService()) { + std::cout << "CheckStageAtomicService failed." << std::endl; + return false; + } + + return true; +} + +bool HapPackager::CompressHapModeForModule(const std::string &jsonPath) +{ + if (!moduleJson_.GetStageModuleName(moduleName_)) { + std::cout << "HapPackager::Process: GetStageModuleName failed!" << std::endl; + } + if (!moduleJson_.GetStageDeviceTypes(deviceTypes_)) { + std::cout << "HapPackager::Process: GetStageDeviceTypes failed!" << std::endl; + } + if (!OpenZipWrapper()) { + return false; + } + + std::string jsonString = moduleJson_.ToString(); + if (!jsonString.empty()) { + if (zipWrapper_.WriteStringToZip(jsonString, Constants::MODULE_JSON) != ZipErrCode::ZIP_ERR_SUCCESS) { + std::cout << "HapPackager::Process: zipWrapper WriteStringToZip failed!" << std::endl; + return false; + } + } + + std::map paramFileMap = { + {Constants::PARAM_PROFILE_PATH, Constants::PROFILE_NAME}, + {Constants::PARAM_INDEX_PATH, Constants::RESOURCES_INDEX}, + {Constants::PARAM_LIB_PATH, Constants::LIB_PATH}, + {Constants::PARAM_AN_PATH, Constants::AN_PATH}, + {Constants::PARAM_AP_PATH, Constants::AP_PATH}, + {Constants::PARAM_RESOURCES_PATH, Constants::RESOURCES_PATH}, + {Constants::PARAM_JS_PATH, Constants::JS_PATH}, + {Constants::PARAM_ETS_PATH, Constants::ETS_PATH}, + {Constants::PARAM_HNP_PATH, Constants::HNP_PATH}, + {Constants::PARAM_RPCID_PATH, Constants::RPCID_SC}, + {Constants::PARAM_ASSETS_PATH, Constants::ASSETS_PATH}, + {Constants::PARAM_PACK_INFO_PATH, Constants::PACK_INFO} + }; + for (auto& item : paramFileMap) { + if (!AddCommonFileOrDirectoryToZip(item.first, item.second)) { + return false; + } + } + + if (!AddParamFileToZip() || !AddResFileAndDirLsitToZip() || !AddPkgAndBinFileToZipForStageMaode()) { + return false; + } + return CompressHapModeMultiple(); +} + +bool HapPackager::CompressHapMode() +{ + if (!moduleJson_.GetFaModuleName(moduleName_)) { + std::cout << "HapPackager::Process: GetFaModuleName failed!" << std::endl; + } + if (!moduleJson_.GetFaDeviceTypes(deviceTypes_)) { + std::cout << "HapPackager::Process: GetFaDeviceTypes failed!" << std::endl; + } + + if (!OpenZipWrapper()) { + return false; + } + + std::string jsonString = moduleJson_.ToString(); + if (!jsonString.empty()) { + if (zipWrapper_.WriteStringToZip(jsonString, Constants::CONFIG_JSON) != ZipErrCode::ZIP_ERR_SUCCESS) { + std::cout << "HapPackager::Process: zipWrapper WriteStringToZip failed!" << std::endl; + return false; + } + } + + std::map paramFileMap = { + {Constants::PARAM_PROFILE_PATH, Constants::PROFILE_NAME}, + {Constants::PARAM_LIB_PATH, Constants::LIB_PATH}, + {Constants::PARAM_RPCID_PATH, Constants::RPCID_SC}, + {Constants::PARAM_PACK_INFO_PATH, Constants::PACK_INFO}, + {Constants::PARAM_ASSETS_PATH, Constants::ASSETS_PATH} + }; + for (auto& item : paramFileMap) { + if (!AddCommonFileOrDirectoryToZip(item.first, item.second)) { + return false; + } + } + + if (!AddIndexToZipForFaMaode() || !AddParamFileToZip() || !AddResFileAndDirLsitToZip()) { + return false; + } + + std::map::const_iterator it = parameterMap_.find(Constants::PARAM_RESOURCES_PATH); + if (it != parameterMap_.end() && !it->second.empty() && !moduleName_.empty()) { + std::string resourcesPath = Constants::ASSETS_PATH + Constants::LINUX_FILE_SEPARATOR + moduleName_ + + Constants::LINUX_FILE_SEPARATOR + Constants::RESOURCES_PATH; + if (zipWrapper_.AddFileOrDirectoryToZip(it->second, resourcesPath) != ZipErrCode::ZIP_ERR_SUCCESS) { + std::cout << "HapPackager::Process: zipWrapper AddFileOrDirectoryToZip failed!" << std::endl; + return false; + } + } + return CompressHapModeMultiple(); +} + +bool HapPackager::CompressHapModeMultiple() +{ + for (std::string soPathItem : formattedSoPathList_) { + std::string zipPath = Constants::SO_ARM64_DIR + fs::path(soPathItem).filename().string(); + if (zipWrapper_.AddFileOrDirectoryToZip(soPathItem, zipPath) != ZipErrCode::ZIP_ERR_SUCCESS) { + std::cout << "HapPackager::Process: zipWrapper AddFileOrDirectoryToZip failed!" << std::endl; + return false; + } + } + + std::map::const_iterator it = parameterMap_.find(Constants::PARAM_MAPLE_SO_DIR); + if (it != parameterMap_.end() && formattedSoPathList_.size() == 0 && !it->second.empty()) { + if (zipWrapper_.AddFileOrDirectoryToZip(it->second, Constants::SO_DIR) != ZipErrCode::ZIP_ERR_SUCCESS) { + std::cout << "HapPackager::Process: zipWrapper AddFileOrDirectoryToZip failed!" << std::endl; + return false; + } + } + + for (auto& pathList : {formattedAbilitySoPathList_, formattedDexPathList_, formattedAbcPathList_, + formattedApkPathList_, formattedJarPathList_, formattedTxtPathList_}) { + if (!AddFileListToZip(pathList)) { + return false; + } + } + + if (!AddCommonFileOrDirectoryToZip(Constants::PARAM_SHAREDLIBS_PATH, Constants::SHARED_LIBS_DIR)) { + return false; + } + zipWrapper_.Close(); + return true; +} + +bool HapPackager::AddFileListToZip(const std::list &pathList_) +{ + for (auto Item : pathList_) { + std::string zipPath = fs::path(Item).filename().string(); + if (zipWrapper_.AddFileOrDirectoryToZip(Item, zipPath) != ZipErrCode::ZIP_ERR_SUCCESS) { + std::cout << "HapPackager::Process: zipWrapper AddFileOrDirectoryToZip failed!" << std::endl; + return false; + } + } + return true; +} + +bool HapPackager::OpenZipWrapper() +{ + std::map::const_iterator it = parameterMap_.find(Constants::PARAM_OUT_PATH); + std::string outPath; + if (it != parameterMap_.end()) { + outPath = it->second; + } + + zipWrapper_.Open(outPath); + if (!zipWrapper_.IsOpen()) { + std::cout << "HapPackager::Process: zipWrapper Open failed!" << std::endl; + return false; + } + return true; +} + +bool HapPackager::AddCommonFileOrDirectoryToZip(const std::string ¶mPath, const std::string &targetPath) +{ + std::map::const_iterator it = parameterMap_.find(paramPath); + if (it != parameterMap_.end() && !it->second.empty()) { + if (zipWrapper_.AddFileOrDirectoryToZip(it->second, targetPath) != ZipErrCode::ZIP_ERR_SUCCESS) { + std::cout << "HapPackager::Process: zipWrapper AddFileOrDirectoryToZip failed!" << std::endl; + return false; + } + } + return true; +} + +bool HapPackager::AddParamFileToZip() +{ + std::map::const_iterator it = parameterMap_.find(Constants::PARAM_FILE_PATH); + if (it != parameterMap_.end() && !it->second.empty()) { + fs::path filePath = fs::path(it->second); + std::string zipPath = Constants::NULL_DIR_NAME; + if (!fs::is_directory(filePath)) { + zipPath = (filePath).filename().string(); + } + if (zipWrapper_.AddFileOrDirectoryToZip(it->second, zipPath) != ZipErrCode::ZIP_ERR_SUCCESS) { + std::cout << "HapPackager::Process: zipWrapper AddFileOrDirectoryToZip failed!" << std::endl; + return false; + } + } + return true; } +bool HapPackager::AddResFileAndDirLsitToZip() +{ + std::map::const_iterator it = parameterMap_.find(Constants::PARAM_RES_PATH); + if (it != parameterMap_.end() && !it->second.empty() && !moduleName_.empty()) { + std::string resPath = Constants::ASSETS_PATH + Constants::LINUX_FILE_SEPARATOR + moduleName_ + + Constants::LINUX_FILE_SEPARATOR + Constants::RESOURCES_PATH; + std::string deviceType; + if (!deviceTypes_.empty()) { + deviceType = deviceTypes_.front(); + } + if (Constants::DEVICE_TYPE_FITNESSWATCH == deviceType || + Constants::DEVICE_TYPE_FITNESSWATCH_NEW == deviceType) { + resPath = Constants::RES_PATH; + } + if (zipWrapper_.AddFileOrDirectoryToZip(it->second, resPath) != ZipErrCode::ZIP_ERR_SUCCESS) { + std::cout << "HapPackager::Process: zipWrapper AddFileOrDirectoryToZip failed!" << std::endl; + return false; + } + } + + if (!formatedDirList_.empty()) { + for (const auto& dirPath : formatedDirList_) { + std::string baseDir = fs::path(dirPath).filename().string() + fs::path::preferred_separator; + if (zipWrapper_.AddFileOrDirectoryToZip(dirPath, baseDir) != ZipErrCode::ZIP_ERR_SUCCESS) { + std::cout << "HapPackager::Process: zipWrapper AddFileOrDirectoryToZip failed!" << std::endl; + return false; + } + } + } + return true; +} + +bool HapPackager::AddIndexToZipForFaMaode() +{ + std::map::const_iterator it = parameterMap_.find(Constants::PARAM_INDEX_PATH); + if (it != parameterMap_.end() && !it->second.empty() && !moduleName_.empty()) { + std::string assetsPath = Constants::ASSETS_PATH + Constants::LINUX_FILE_SEPARATOR + moduleName_ + + Constants::LINUX_FILE_SEPARATOR + fs::path(it->second).filename().string(); + if (zipWrapper_.AddFileOrDirectoryToZip(it->second, assetsPath) != ZipErrCode::ZIP_ERR_SUCCESS) { + std::cout << "HapPackager::Process: zipWrapper AddFileOrDirectoryToZip failed!" << std::endl; + return false; + } + } + return true; +} + +bool HapPackager::AddPkgAndBinFileToZipForStageMaode() +{ + std::map::const_iterator it = parameterMap_.find(Constants::PARAM_BIN_PATH); + if (it != parameterMap_.end() && !it->second.empty()) { + fs::path filePath = fs::path(it->second); + std::string zipPath = Constants::NULL_DIR_NAME; + if (!fs::is_directory(filePath)) { + zipPath = (filePath).filename().string(); + } + if (zipWrapper_.AddFileOrDirectoryToZip(it->second, zipPath) != ZipErrCode::ZIP_ERR_SUCCESS) { + std::cout << "HapPackager::Process: zipWrapper AddFileOrDirectoryToZip failed!" << std::endl; + return false; + } + } + it = parameterMap_.find(Constants::PARAM_PKG_CONTEXT_PATH); + if (it != parameterMap_.end() && !it->second.empty()) { + ModuleJson moduleJson; + if (!moduleJson.ParseFromFile(it->second)) { + std::cout << "HapPackager::Process: moduleJson Read failed!" << std::endl; + return false; + } + std::string jsonString = moduleJson.ToString(); + if (!jsonString.empty()) { + if (zipWrapper_.WriteStringToZip(jsonString, Constants::PKG_CONTEXT_JSON) != ZipErrCode::ZIP_ERR_SUCCESS) { + std::cout << "HapPackager::Process: zipWrapper WriteStringToZip failed!" << std::endl; + return false; + } + } else { + std::cout << "HapPackager::Process: jsonFile error!" << std::endl; + return false; + } + } + return true; +} } // namespace AppPackingTool } // namespace OHOS \ No newline at end of file diff --git a/ohos_packing_tool/frameworks/src/hsp_packager.cpp b/ohos_packing_tool/frameworks/src/hsp_packager.cpp index e625197de4b0dcaaa351f0ef7e7514374c72621c..16ee29d0d4610b2c8a9d2db2075bdf4fe42573d5 100644 --- a/ohos_packing_tool/frameworks/src/hsp_packager.cpp +++ b/ohos_packing_tool/frameworks/src/hsp_packager.cpp @@ -19,7 +19,7 @@ #include "hsp_packager.h" #include "constants.h" -#include "packager.h" +#include "json/json_utils.h" namespace OHOS { namespace AppPackingTool { @@ -35,59 +35,432 @@ int HspPackager::InitAllowedParam() } int HspPackager::PreProcess() { + if (!CheckForceFlag()) { + return ERR_INVALID_VALUE; + } + + bool ret = IsVerifyValidInHspCommonMode() && IsVerifyValidInHspMode(); + if (!ret) { + return ERR_INVALID_VALUE; + } return ERR_OK; } int HspPackager::Process() { std::cout << "Hsp DoPackage" << std::endl; - std::string outPath = parameterMap_.at(Constants::PARAM_OUT_PATH); - zipFile zf = zipOpen64(outPath.c_str(), APPEND_STATUS_CREATE); - if (zf == nullptr) { - std::cout << "err zipOpen64 null" << std::endl; + if (!CompressHsp()) { + std::cout << "Hsp DoPackage failed!" << std::endl; return ERR_INVALID_VALUE; } - zip_fileinfo fi = {}; + return ERR_OK; +} +int HspPackager::PostProcess() +{ + if (generateBuildHash_) { + std::cout << "start sencond CompressHsp" << std::endl; + if (!CompressHsp()) { + std::cout << "sencond CompressHsp failed!" << std::endl; + return ERR_INVALID_VALUE; + } + } + return ERR_OK; +} + +bool HspPackager::IsVerifyValidInHspCommonMode() +{ std::map::const_iterator it = parameterMap_.find(Constants::PARAM_JSON_PATH); + if (it == parameterMap_.end() || it->second.empty()) { + std::cout << "CompressVerify::isArgsValidInHspMode json-path is empty." << std::endl; + return false; + } + jsonPath_ = it->second; + if (!IsPathValid(it->second, true, Constants::MODULE_JSON)) { + std::cout << "CompressVerify::isArgsValidInHspMode json-path must be module.json file." << std::endl; + return false; + } + if (!Compatible(Constants::PARAM_DEX_PATH, formattedDexPathList_, Constants::DEX_SUFFIX) || + !Compatible(Constants::PARAM_JAR_PATH, formattedJarPathList_, Constants::JAR_SUFFIX) || + !Compatible(Constants::PARAM_TXT_PATH, formattedTxtPathList_, Constants::TXT_SUFFIX)) { + return false; + } + if (!IsHspPathValid()) { + return false; + } + it = parameterMap_.find(Constants::PARAM_DIR_LIST); + if (it != parameterMap_.end() && !it->second.empty() && + !SplitDirList(it->second, formatedDirList_)) { + std::cout << "CompressVerify::isArgsValidInHspMode --dir-list is invalid." << std::endl; + return false; + } + it = parameterMap_.find(Constants::PARAM_PROFILE_PATH); if (it != parameterMap_.end()) { - if (ParseJsonFile(moduleJson, it->second)) { - WriteStringToZip(zf, moduleJson.dump(), fs::path(Constants::MODULE_JSON), fi); + const std::string filePath = it->second; + if (!fs::is_regular_file(filePath) || + fs::path(filePath).filename().string() != Constants::PROFILE_NAME) { + std::cout << "CompressVerify::isArgsValidInHspMode profile-path" + " must be CAPABILITY.profile file." << std::endl; + return false; + } + } + it = parameterMap_.find(Constants::PARAM_PKG_CONTEXT_PATH); + if (it != parameterMap_.end() && !it ->second.empty()) { + const std::string filePath = it->second; + if (!fs::is_regular_file(filePath) || + fs::path(filePath).filename().string() != Constants::PKG_CONTEXT_JSON) { + std::cout << "CompressVerify::isArgsValidInHspMode --pkg-context-path file" + " must be pkgContextInfo.json file." << std::endl; + return false; } } - it = parameterMap_.find(Constants::PARAM_LIB_PATH); + return true; +} + +bool HspPackager::IsVerifyValidInHspMode() +{ + std::map::const_iterator it = parameterMap_.find(Constants::PARAM_ETS_PATH); if (it != parameterMap_.end()) { - AddFileToZip(zf, fs::path(it->second), fs::path(Constants::LIB_PATH), fi); + const std::string filePath = it->second; + if (!filePath.empty() && !fs::exists(filePath)) { + return false; + } } - it = parameterMap_.find(Constants::PARAM_RESOURCES_PATH); + + std::string outPath = ""; + std::string forceRewrite = ""; + it = parameterMap_.find(Constants::PARAM_OUT_PATH); if (it != parameterMap_.end()) { - AddFileToZip(zf, fs::path(it->second), fs::path(Constants::RESOURCES_PATH), fi); + outPath = it->second; } - it = parameterMap_.find(Constants::PARAM_INDEX_PATH); + + it = parameterMap_.find(Constants::PARAM_FORCE); if (it != parameterMap_.end()) { - AddFileToZip(zf, fs::path(it->second), fs::path(Constants::RESOURCES_INDEX), fi); + forceRewrite = it->second; + } + + return IsOutPathValid(outPath, forceRewrite, Constants::HSP_SUFFIX); +} + +bool HspPackager::Compatible(const std::string ¶mPath, std::list &fileList, + const std::string &suffix) +{ + std::map::const_iterator it = parameterMap_.find(paramPath); + if (it != parameterMap_.end() && !it->second.empty() && !CompatibleProcess(it->second, + fileList, suffix)) { + std::cout << "CompressVerify::isArgsValidInHspMode "<< paramPath << " is invalid." << std::endl; + return false; } - it = parameterMap_.find(Constants::PARAM_PACK_INFO_PATH); + return true; +} + +bool HspPackager::IsHspPathValid() +{ + if (IsHspPathValid(Constants::PARAM_LIB_PATH)) { + std::cout << "CompressVerify::isArgsValidInHspMode lib-path is invalid." << std::endl; + return false; + } + + if (IsHspPathValid(Constants::PARAM_RES_PATH)) { + std::cout << "CompressVerify::isArgsValidInHspMode res-path is invalid." << std::endl; + return false; + } + + if (IsHspPathValid(Constants::PARAM_RESOURCES_PATH)) { + std::cout << "CompressVerify::isArgsValidInHspMode resources-path is invalid." << std::endl; + return false; + } + + if (IsHspPathValid(Constants::PARAM_ASSETS_PATH)) { + std::cout << "CompressVerify::isArgsValidInHspMode assets-path is invalid." << std::endl; + return false; + } + + if (IsHspPathValid(Constants::PARAM_AP_PATH)) { + std::cout << "CompressVerify::isArgsValidInHspMode ap-path is invalid." << std::endl; + return false; + } + + if (IsHspPathValid(Constants::PARAM_AN_PATH)) { + std::cout << "CompressVerify::isArgsValidInHspMode an-path is invalid." << std::endl; + return false; + } + return true; +} + +bool HspPackager::IsHspPathValid(const std::string ¶meterMapKey) +{ + std::map::const_iterator it = parameterMap_.find(parameterMapKey); + if (it == parameterMap_.end()) { + return false; + } + const std::string path = it->second; + return (!path.empty() && !IsPathValid(path, false)); +} + +bool HspPackager::CompressHsp() +{ + if (!SetGenerateBuildHash(jsonPath_, generateBuildHash_, buildHashFinish_)) { + return false; + } + + if (!moduleJson_.ParseFromFile(jsonPath_)) { + std::cout << "ParseFromFile failed" << std::endl; + return false; + } + + if (JsonUtils::IsModuleJson(jsonPath_)) { + if (!moduleJson_.CheckStageAsanTsanEnabledValid()) { + std::cout << "CheckStageAsanTsanEnabledValid failed." << std::endl; + return false; + } + + if (!moduleJson_.CheckStageAtomicService()) { + std::cout << "CheckStageAtomicService failed." << std::endl; + return false; + } + + if (!moduleJson_.CheckStageOverlayCfg()) { + std::cout << "checkStageOverlayCfg failed." << std::endl; + return false; + } + + std::string moduleType; + if (!moduleJson_.GetStageModuleType(moduleType)) { + std::cout << "GetStageModuleType failed." << std::endl; + } + if (moduleType != Constants::TYPE_SHARED) { + std::cout << "module type must be shared." << std::endl; + return false; + } + } + if (!CompressHspMode(jsonPath_) || !BuildHash(buildHashFinish_, generateBuildHash_, parameterMap_, jsonPath_)) { + return false; + } + return true; +} + +bool HspPackager::CompressHspMode(const std::string &jsonPath) +{ + std::map::const_iterator it = parameterMap_.find(Constants::PARAM_OUT_PATH); + std::string outPath; if (it != parameterMap_.end()) { - AddFileToZip(zf, fs::path(it->second), fs::path(Constants::PACK_INFO), fi); + outPath = it->second; + } + zipWrapper_.Open(outPath); + if (!zipWrapper_.IsOpen()) { + std::cout << "HspPackager::Process: zipWrapper Open failed!" << std::endl; + return false; + } + std::string jsonString = moduleJson_.ToString(); + if (!jsonString.empty()) { + std::string jsonType; + if (JsonUtils::IsModuleJson(jsonPath)) { + jsonType = Constants::MODULE_JSON; + if (!moduleJson_.GetStageModuleName(moduleName_) || moduleJson_.GetStageDeviceTypes(deviceTypes_)) { + std::cout << "GetStageModuleName or GetStageDeviceTypes failed!" << std::endl; + } + } else { + jsonType = Constants::CONFIG_JSON; + if (!moduleJson_.GetFaModuleName(moduleName_) || moduleJson_.GetFaDeviceTypes(deviceTypes_)) { + std::cout << "GetStageModuleName or GetStageDeviceTypes failed!" << std::endl; + } + } + if (zipWrapper_.WriteStringToZip(jsonString, jsonType) != ZipErrCode::ZIP_ERR_SUCCESS) { + std::cout << "HspPackager::Process: zipWrapper WriteStringToZip failed!" << std::endl; + return false; + } + } + + if (!AddCommonFileOrDirectoryToZip(Constants::PARAM_PROFILE_PATH, Constants::PROFILE_NAME)) { + return false; + } + it = parameterMap_.find(Constants::PARAM_INDEX_PATH); + if (it != parameterMap_.end() && !it->second.empty() && JsonUtils::IsModuleJson(jsonPath)) { + if (zipWrapper_.AddFileOrDirectoryToZip(it->second, Constants::RESOURCES_INDEX) != + ZipErrCode::ZIP_ERR_SUCCESS) { + std::cout << "HspPackager::Process: zipWrapper AddFileOrDirectoryToZip failed!" << std::endl; + return false; + } + } + return CompressHspModePartSecond(jsonPath); +} + +bool HspPackager::CompressHspModePartSecond(const std::string &jsonPath) +{ + std::map paramFileMap = { + {Constants::PARAM_LIB_PATH, Constants::LIB_PATH}, + {Constants::PARAM_AN_PATH, Constants::AN_PATH}, + {Constants::PARAM_AP_PATH, Constants::AP_PATH}, + {Constants::PARAM_RPCID_PATH, Constants::RPCID_SC}, + {Constants::PARAM_ASSETS_PATH, Constants::ASSETS_PATH} + }; + for (auto& item : paramFileMap) { + if (!AddCommonFileOrDirectoryToZip(item.first, item.second)) { + return false; + } + } + + std::map::const_iterator it = parameterMap_.find(Constants::PARAM_FILE_PATH); + if (it != parameterMap_.end() && !it->second.empty()) { + fs::path filePath = fs::path(it->second); + std::string zipPath = Constants::NULL_DIR_NAME; + if (!fs::is_directory(filePath)) { + zipPath = (filePath).filename().string(); + } + if (zipWrapper_.AddFileOrDirectoryToZip(it->second, zipPath) != ZipErrCode::ZIP_ERR_SUCCESS) { + std::cout << "HspPackager::Process: zipWrapper AddFileOrDirectoryToZip failed!" << std::endl; + return false; + } + } + + it = parameterMap_.find(Constants::PARAM_RESOURCES_PATH); + if (it != parameterMap_.end() && !it->second.empty() && JsonUtils::IsModuleJson(jsonPath)) { + if (zipWrapper_.AddFileOrDirectoryToZip(it->second, Constants::RESOURCES_PATH) != ZipErrCode::ZIP_ERR_SUCCESS) { + std::cout << "HspPackager::Process: zipWrapper AddFileOrDirectoryToZip failed!" << std::endl; + return false; + } + } + return CompressHspModePartThird(jsonPath); +} + +bool HspPackager::CompressHspModePartThird(const std::string &jsonPath) +{ + std::map::const_iterator it = parameterMap_.find(Constants::PARAM_RES_PATH); + if (it != parameterMap_.end() && !it->second.empty() && !moduleName_.empty()) { + std::string resPath = Constants::ASSETS_PATH + Constants::LINUX_FILE_SEPARATOR + moduleName_ + + Constants::LINUX_FILE_SEPARATOR + Constants::RESOURCES_PATH; + std::string deviceType; + if (!deviceTypes_.empty()) { + deviceType = deviceTypes_.front(); + } + if (Constants::DEVICE_TYPE_FITNESSWATCH == deviceType || + Constants::DEVICE_TYPE_FITNESSWATCH_NEW == deviceType) { + resPath = Constants::RES_PATH; + } + if (zipWrapper_.AddFileOrDirectoryToZip(it->second, resPath) != ZipErrCode::ZIP_ERR_SUCCESS) { + std::cout << "HspPackager::Process: zipWrapper AddFileOrDirectoryToZip failed!" << std::endl; + return false; + } + } + it = parameterMap_.find(Constants::PARAM_JS_PATH); + if (it != parameterMap_.end() && !it->second.empty() && JsonUtils::IsModuleJson(jsonPath)) { + if (zipWrapper_.AddFileOrDirectoryToZip(it->second, Constants::JS_PATH) != ZipErrCode::ZIP_ERR_SUCCESS) { + std::cout << "HspPackager::Process: zipWrapper AddFileOrDirectoryToZip failed!" << std::endl; + return false; + } } it = parameterMap_.find(Constants::PARAM_ETS_PATH); - if (it != parameterMap_.end()) { - AddFileToZip(zf, fs::path(it->second), fs::path(Constants::ETS_PATH), fi); + if (it != parameterMap_.end() && !it->second.empty() && JsonUtils::IsModuleJson(jsonPath)) { + if (zipWrapper_.AddFileOrDirectoryToZip(it->second, Constants::ETS_PATH) != ZipErrCode::ZIP_ERR_SUCCESS) { + std::cout << "HspPackager::Process: zipWrapper AddFileOrDirectoryToZip failed!" << std::endl; + return false; + } } - it = parameterMap_.find(Constants::PARAM_RPCID_PATH); - if (it != parameterMap_.end()) { - AddFileToZip(zf, fs::path(it->second), fs::path(Constants::RPCID_SC), fi); + return CompressHspModePartFourth(); +} + +bool HspPackager::CompressHspModePartFourth() +{ + std::map::const_iterator it = parameterMap_.find(Constants::PARAM_BIN_PATH); + if (it != parameterMap_.end() && !it->second.empty()) { + fs::path filePath = fs::path(it->second); + std::string zipPath = Constants::NULL_DIR_NAME; + if (!fs::is_directory(filePath)) { + zipPath = (filePath).filename().string(); + } + if (zipWrapper_.AddFileOrDirectoryToZip(it->second, zipPath) != ZipErrCode::ZIP_ERR_SUCCESS) { + std::cout << "HspPackager::Process: zipWrapper AddFileOrDirectoryToZip failed!" << std::endl; + return false; + } + } + if (!AddCommonFileOrDirectoryToZip(Constants::PARAM_PACK_INFO_PATH, Constants::PACK_INFO)) { + return false; + } + if (!formatedDirList_.empty()) { + for (const auto& dirPath : formatedDirList_) { + std::string baseDir = fs::path(dirPath).filename().string() + fs::path::preferred_separator; + if (zipWrapper_.AddFileOrDirectoryToZip(dirPath, baseDir) != ZipErrCode::ZIP_ERR_SUCCESS) { + std::cout << "HspPackager::Process: zipWrapper AddFileOrDirectoryToZip failed!" << std::endl; + return false; + } + } } it = parameterMap_.find(Constants::PARAM_PKG_CONTEXT_PATH); - if (it != parameterMap_.end()) { - AddFileToZip(zf, fs::path(it->second), fs::path(Constants::PKG_CONTEXT_JSON), fi); + if (it != parameterMap_.end() && !it->second.empty()) { + ModuleJson moduleJson; + if (!moduleJson.ParseFromFile(it->second)) { + std::cout << "HspPackager::Process: moduleJson Read failed!" << std::endl; + return false; + } + std::string jsonString = moduleJson.ToString(); + if (!jsonString.empty()) { + if (zipWrapper_.WriteStringToZip(jsonString, Constants::PKG_CONTEXT_JSON) != ZipErrCode::ZIP_ERR_SUCCESS) { + std::cout << "HspPackager::Process: zipWrapper WriteStringToZip failed!" << std::endl; + return false; + } + } else { + std::cout << "HspPackager::Process: jsonFile error!" << std::endl; + return false; + } } - zipClose(zf, nullptr); - return ERR_OK; + return CompressHspModeMultiple(); } -int HspPackager::PostProcess() + +bool HspPackager::CompressHspModeMultiple() { - return ERR_OK; + std::map::const_iterator it = parameterMap_.find(Constants::PARAM_MAPLE_SO_DIR); + if (it != parameterMap_.end() && formattedSoPathList_.size() == 0 && !it->second.empty()) { + if (zipWrapper_.AddFileOrDirectoryToZip(it->second, Constants::SO_DIR) != ZipErrCode::ZIP_ERR_SUCCESS) { + std::cout << "HapPackager::Process: zipWrapper AddFileOrDirectoryToZip failed!" << std::endl; + return false; + } + } + + for (auto jarPathItem : formattedJarPathList_) { + std::string zipPath = fs::path(jarPathItem).filename().string(); + if (zipWrapper_.AddFileOrDirectoryToZip(jarPathItem, zipPath) != ZipErrCode::ZIP_ERR_SUCCESS) { + std::cout << "HspPackager::Process: zipWrapper AddFileOrDirectoryToZip failed!" << std::endl; + return false; + } + } + + for (auto txtPathItem : formattedTxtPathList_) { + std::string zipPath = fs::path(txtPathItem).filename().string(); + if (zipWrapper_.AddFileOrDirectoryToZip(txtPathItem, zipPath) != ZipErrCode::ZIP_ERR_SUCCESS) { + std::cout << "HspPackager::Process: zipWrapper AddFileOrDirectoryToZip failed!" << std::endl; + return false; + } + } + + for (auto dexPathItem : formattedDexPathList_) { + std::string zipPath = fs::path(dexPathItem).filename().string(); + if (zipWrapper_.AddFileOrDirectoryToZip(dexPathItem, zipPath) != ZipErrCode::ZIP_ERR_SUCCESS) { + std::cout << "HspPackager::Process: zipWrapper AddFileOrDirectoryToZip failed!" << std::endl; + return false; + } + } + + it = parameterMap_.find(Constants::PARAM_SHAREDLIBS_PATH); + if (it != parameterMap_.end() && !it->second.empty()) { + if (zipWrapper_.AddFileOrDirectoryToZip(it->second, Constants::SHARED_LIBS_DIR) != + ZipErrCode::ZIP_ERR_SUCCESS) { + std::cout << "HspPackager::Process: zipWrapper AddFileOrDirectoryToZip failed!" << std::endl; + return false; + } + } + zipWrapper_.Close(); + return true; } +bool HspPackager::AddCommonFileOrDirectoryToZip(const std::string ¶mPath, const std::string &targetPath) +{ + std::map::const_iterator it = parameterMap_.find(paramPath); + if (it != parameterMap_.end() && !it->second.empty()) { + if (zipWrapper_.AddFileOrDirectoryToZip(it->second, targetPath) != ZipErrCode::ZIP_ERR_SUCCESS) { + std::cout << "HspPackager::Process: zipWrapper AddFileOrDirectoryToZip failed!" << std::endl; + return false; + } + } + return true; +} } // namespace AppPackingTool } // namespace OHOS \ No newline at end of file diff --git a/ohos_packing_tool/frameworks/src/packager.cpp b/ohos_packing_tool/frameworks/src/packager.cpp index 77c2a7ed8d8fb9080f87e40ab23e962cce70a7e5..d22224124067b4b4b0dd31a869be82487d59dccd 100644 --- a/ohos_packing_tool/frameworks/src/packager.cpp +++ b/ohos_packing_tool/frameworks/src/packager.cpp @@ -18,8 +18,13 @@ #include #include #include +#include +#include #include "packager.h" +#include "utils.h" +#include "json/json_utils.h" +#include "zip_utils.h" namespace OHOS { namespace AppPackingTool { @@ -39,14 +44,17 @@ std::string Packager::MakePackage() if (PreProcess() != ERR_OK) { std::cout << "PreCheck err" << std::endl; + return ""; } if (Process() != ERR_OK) { std::cout << "DoPackage err" << std::endl; + return ""; } if (PostProcess() != ERR_OK) { std::cout << "PostCheck err" << std::endl; + return ""; } return "OHOS::ERR_OK"; @@ -73,98 +81,288 @@ int Packager::PostProcess() return ERR_OK; } -void Packager::AddFileToZip(zipFile zf, const fs::path &filePath, const fs::path &zipPath, zip_fileinfo &zipfi) +bool Packager::CheckForceFlag() { - if (fs::is_directory(filePath)) { - for (const auto &entry : fs::directory_iterator(filePath)) { - fs::path tmpPath = zipPath / entry.path().filename(); - AddFileToZip(zf, entry.path(), tmpPath, zipfi); - } - } else if (fs::is_regular_file(filePath)) { - std::ifstream file(filePath, std::ios::binary); - if (!file.is_open()) { - std::cout << "err opening file for read: " << filePath << std::endl; + auto it = parameterMap_.find(Constants::PARAM_FORCE); + if (it != parameterMap_.end() && it->second != "false" && it->second != "true") { + std::cout << "CompressVerify::commandVerify forceRewrite is invalid." << std::endl; + return false; + } + return true; +} + +bool Packager::IsPathValid(const std::string &path, const bool &isFile, const std::string suffix) +{ + if (isFile && fs::is_regular_file(path)) { + std::string name = fs::path(path).filename(); + std::locale englishLocale("en_US.UTF-8"); + std::transform(name.begin(), name.end(), name.begin(), + [&englishLocale](unsigned char c) { return std::tolower(c); }); + if (Utils::EndsWith(name, suffix)) { + return true; } - int ret = zipOpenNewFileInZip(zf, zipPath.string().c_str(), &zipfi, nullptr, 0, - nullptr, 0, nullptr, 0, Z_DEFAULT_COMPRESSION); - if (ret != ZIP_OK) { - std::cout << "zipOpenNewFileInZip err: " << ret << ", " << filePath << std::endl; - file.close(); - return ; + } + return (!isFile) && fs::is_directory(path); +} + +bool Packager::SplitDirList(const std::string &dirList, std::list &fileList) +{ + std::list pathList; + RemoveDuplicatePath(dirList, pathList); + for (const std::string &pathItem : pathList) { + std::string formattedPathItem; + if (!Utils::GetFormattedPath(pathItem, formattedPathItem)) { + std::cout << "GetFormattedPath failed for" << pathItem << std::endl; + return false; + }; + if (!IsPathValid(formattedPathItem, false)) { + return false; } - char buffer[Constants::BUF_SIZE]; - while (file.good()) { - file.read(buffer, sizeof(buffer)); - auto bytesRead = file.gcount(); - if (bytesRead <= 0) { - std::cout << "read file: " << filePath << " err, bytesRead: " << bytesRead << std::endl; - break; + fileList.push_back(formattedPathItem); + } + return true; +} + +void Packager::RemoveDuplicatePath(const std::string &path, std::list &pathList) +{ + std::string pathItem; + std::istringstream pathStream(path); + while (std::getline(pathStream, pathItem, Constants::COMMA_SPLIT)) { + pathList.push_back(pathItem); + } + std::unordered_set uniqueTokens(pathList.begin(), pathList.end()); + pathList.assign(uniqueTokens.begin(), uniqueTokens.end()); +} + +bool Packager::CompatibleProcess(const std::string &inputPath, std::list &fileList, + const std::string &suffix) +{ + if (IsPathValid(inputPath, false)) { + for (const auto& fileItem : fs::recursive_directory_iterator(inputPath)) { + std::string name = fileItem.path().filename(); + std::locale englishLocale("en_US.UTF-8"); + std::transform(name.begin(), name.end(), name.begin(), + [&englishLocale](unsigned char c) { return std::tolower(c); }); + if (Utils::EndsWith(name, suffix)) { + fileList.push_back(fileItem.path().string()); } - if (zipWriteInFileInZip(zf, buffer, bytesRead) < 0) { - std::cout << "err write to zip file: " << filePath << std::endl; - break; + } + return true; + } else { + std::string formattedPathItem; + std::list pathList; + RemoveDuplicatePath(inputPath, pathList); + for (std::string pathItem : pathList) { + if (!Utils::GetFormattedPath(pathItem, formattedPathItem)) { + std::cout << "GetFormattedPath failed for" << pathItem << std::endl; + return false; + }; + if (!IsPathValid(formattedPathItem, true, suffix)) { + return false; } + fileList.push_back(formattedPathItem); } - zipCloseFileInZip(zf); - file.close(); + return true; } } -void Packager::WriteStringToZip(zipFile zf, const std::string &content, const fs::path &zipPath, zip_fileinfo &zipfi) +bool Packager::IsOutPathValid(const std::string &outPath, const std::string &forceRewrite, const std::string &suffix) { - if (zipOpenNewFileInZip(zf, zipPath.string().c_str(), &zipfi, nullptr, 0, nullptr, 0, nullptr, 0, - Z_DEFAULT_COMPRESSION) == ZIP_OK) { - if (zipWriteInFileInZip(zf, content.data(), content.length()) < 0) { - std::cout << "zipWriteInFileInZip err: " << errno << std::endl; + fs::path filePath(outPath); + + if ("false" == forceRewrite && fs::exists(filePath)) { + std::cout << "CompressVerify::isOutPathValid out file already existed." << std::endl; + return false; + } + + if (suffix == Constants::HAP_SUFFIX) { + if (!Utils::EndsWith(filePath.filename().string(), Constants::HAP_SUFFIX)) { + std::cout << "CompressVerify::isOutPathValid out-path must end with .hap." << std::endl; + return false; + } else { + return true; + } + } else if (suffix == Constants::HAR_SUFFIX) { + if (!Utils::EndsWith(filePath.filename().string(), Constants::HAR_SUFFIX)) { + std::cout << "CompressVerify::isOutPathValid out-path must end with .har." << std::endl; + return false; + } else { + return true; + } + } else if (suffix == Constants::APP_SUFFIX) { + if (!Utils::EndsWith(filePath.filename().string(), Constants::APP_SUFFIX)) { + std::cout << "CompressVerify::isOutPathValid out-path must end with .app." << std::endl; + return false; + } else { + return true; + } + } else if (suffix == Constants::RES_SUFFIX) { + if (!Utils::EndsWith(filePath.filename().string(), Constants::RES_SUFFIX)) { + std::cout << "CompressVerify::isOutPathValid out-path must end with .res." << std::endl; + return false; + } else { + return true; + } + } else if (suffix == Constants::HSP_SUFFIX) { + if (!Utils::EndsWith(filePath.filename().string(), Constants::HSP_SUFFIX)) { + std::cout << "CompressVerify::isOutPathValid out-path must end with .hsp." << std::endl; + return false; + } else { + return true; } - zipCloseFileInZip(zf); } + return false; } -bool Packager::ParseJsonFile(nlohmann::json &jsonObject, std::string filePath) +bool Packager::SetGenerateBuildHash(std::string &jsonPath, bool &generateBuildHash, bool &buildHashFinish) { - std::ifstream i(filePath); - if (!i.is_open()) { - std::cout<<"failed to open json file, errno: " << errno << std::endl; + if (!fs::exists(jsonPath)) { + std::cout << "Compressor::setGenerateBuildHash failed for json file not exist" << std::endl; return false; } - i.seekg(0, std::ios::end); - int len = static_cast(i.tellg()); - if (len == 0) { - i.close(); - std::cout << "json file is empty" << std::endl; + ModuleJson moduleJson; + moduleJson.ParseFromFile(jsonPath); + + if (buildHashFinish || !moduleJson.GetGenerateBuildHash(generateBuildHash)) { return true; } - i.seekg(0, std::ios::beg); - jsonObject = nlohmann::json::parse(i, nullptr, false); - if (jsonObject.is_discarded()) { - i.close(); - std::cout << "ParseJsonFile failed due to data is discarded." << std::endl; + + if (!CopyFileToTempDir(jsonPath)) { + return false; + } + + if (!fs::exists(jsonPath)) { + std::cout << "Compressor::setGenerateBuildHash failed for json file not exist" << std::endl; + return false; + } + + ModuleJson moduleJsonTemp; + moduleJsonTemp.ParseFromFile(jsonPath); + if (!moduleJsonTemp.GetGenerateBuildHash(generateBuildHash)) { + std::cout << "ModuleJson::GetGenerateBuildHash failed" << std::endl; + return false; + } + + if (!moduleJsonTemp.RemoveGenerateBuildHash()) { + std::cout << "ModuleJson::RemoveGenerateBuildHash failed" << std::endl; + return false; + } + + std::string prettyJsonString = moduleJsonTemp.ToString(); + if (prettyJsonString.empty()) { + std::cout << "ModuleJson::ToString failed" << std::endl; + return false; + } + + std::ofstream outFile(jsonPath); + if (outFile.is_open()) { + outFile << prettyJsonString.c_str(); + outFile.close(); + } else { + std::cout << "Failed to open file for writing" << std::endl; return false; } - i.close(); return true; } -bool Packager::endWith(const std::string &str, const std::string &suffix) +bool Packager::CopyFileToTempDir(std::string &jsonPath) { - if (str.length() >= suffix.length()) { - return str.compare(str.length() - suffix.length(), suffix.length(), suffix); + if (!fs::exists(jsonPath)) { + std::cout << "Compressor::copyFileToTempDir failed for json file not found." << std::endl; + return false; } - return false; + fs::path oldFileParent = fs::path(jsonPath).parent_path(); + std::string tempDir = Constants::COMPRESSOR_TEMP_DIR + fs::path::preferred_separator + Utils::GenerateUUID(); + fs::path tempDirFs(tempDir); + tempDir = oldFileParent.string() + fs::path::preferred_separator + tempDirFs.string(); + fs::create_directories(tempDir); + fs::path fileName = JsonUtils::IsModuleJson(jsonPath) ? Constants::MODULE_JSON : Constants::CONFIG_JSON; + std::string tempPath = tempDir + fs::path::preferred_separator + fileName.string(); + if (!Utils::CopyFile(jsonPath, tempPath)) { + return false; + } + jsonPath = tempPath; + return true; } -bool Packager::CheckFileValid(const std::string &filePath, const std::string &filename) +bool Packager::BuildHash(bool &buildHashFinish, const bool &generateBuildHash, + const std::map ¶meterMap, const std::string &jsonPath) { - if (fs::is_regular_file(filePath)) { - std::string name = fs::path(filePath).filename(); - if (endWith(name, filename)) { - return true; - } + if (buildHashFinish || !generateBuildHash) { + return true; } - return false; + std::map::const_iterator it = parameterMap.find(Constants::PARAM_OUT_PATH); + if (it == parameterMap.end()) { + std::cout << "out-path not found" << std::endl; + return false; + } + std::string filePath = it->second; + std::string hash = Utils::GetSha256File(filePath); + return PutBuildHash(jsonPath, hash, buildHashFinish); } +bool Packager::PutBuildHash(const std::string &jsonPath, const std::string &hash, bool &buildHashFinish) +{ + if (buildHashFinish) { + return true; + } + ModuleJson moduleJson; + moduleJson.ParseFromFile(jsonPath); + moduleJson.SetBuildHash(hash); + std::string prettyJsonString = moduleJson.ToString(); + if (prettyJsonString.empty()) { + std::cout << "ModuleJson::ToString failed" << std::endl; + return false; + } + + std::ofstream outFile(jsonPath); + if (outFile.is_open()) { + outFile << prettyJsonString.c_str(); + outFile.close(); + } else { + std::cout << "Failed to open file for writing" << std::endl; + return false; + } + + buildHashFinish = true; + return true; +} + +bool Packager::IsModuleHap(const std::string& hapPath) +{ + if (!Utils::EndsWith(hapPath, Constants::HAP_SUFFIX)) { + return false; + } + if (!ZipUtils::IsFileExistsInZip(hapPath, Constants::MODULE_JSON)) { + return false; + } + return true; +} + +void Packager::CompressPackinfoIntoHap(const std::string& hapPathItem, const std::string& unzipPathString, + const std::string& outPathString, const std::string& packInfoPath) +{ + if (!fs::exists(fs::path(unzipPathString))) { + fs::create_directory(fs::path(unzipPathString)); + } + ZipUtils::Unzip(hapPathItem, unzipPathString); + for (const auto& entry : fs::directory_iterator(unzipPathString)) { + if (entry.path().filename() == Constants::PACK_INFO) { + fs::remove(entry.path()); + } + } + + std::ifstream packInfoFile(packInfoPath, std::ios::binary); + std::ofstream destFile(unzipPathString + fs::path::preferred_separator + + Constants::PACK_INFO, std::ios::binary | std::ios::trunc); + destFile << packInfoFile.rdbuf(); + destFile.close(); + packInfoFile.close(); + ZipUtils::Zip(unzipPathString, outPathString); + if (fs::exists(fs::path(unzipPathString))) { + fs::remove_all(fs::path(unzipPathString)); + } +} } // namespace AppPackingTool } // namespace OHOS \ No newline at end of file diff --git a/ohos_packing_tool/frameworks/src/shell_command.cpp b/ohos_packing_tool/frameworks/src/shell_command.cpp index f2ddea80790a53c3592c9f3bbae7eb21e5887238..f65c008f76f88b7c49335fe0af33bb334a7aec34 100644 --- a/ohos_packing_tool/frameworks/src/shell_command.cpp +++ b/ohos_packing_tool/frameworks/src/shell_command.cpp @@ -24,6 +24,7 @@ #include "packager.h" #include "hap_packager.h" #include "hsp_packager.h" +#include "fast_app_packager.h" namespace OHOS { namespace AppPackingTool { @@ -50,9 +51,9 @@ ShellCommand::~ShellCommand() {} int ShellCommand::CreateCommandMap() { commandMap_ = { - {"help", [this] { return this->RunAsHelpCommand(); } }, - {"pack", [this] { return this->RunAsPackCommand(); } }, - {"unpack", [this] { return this->RunAsUnpackCommand(); } } + {"help", std::bind(&ShellCommand::RunAsHelpCommand, this)}, + {"pack", std::bind(&ShellCommand::RunAsPackCommand, this)}, + {"unpack", std::bind(&ShellCommand::RunAsUnpackCommand, this)}, }; return ERR_OK; } @@ -148,6 +149,10 @@ std::unique_ptr ShellCommand::getPackager() std::unique_ptr packager = std::make_unique(parameterMap_, resultReceiver_); return packager; + } else if (mode == Constants::MODE_FAST_APP) { + std::unique_ptr packager = + std::make_unique(parameterMap_, resultReceiver_); + return packager; } resultReceiver_.append("not support --mode: ").append(mode).append("\n"); return nullptr;