Revert 11533 merge feature_data_clone_install_11267

Signed-off-by: wanghang <wanghang26@huawei.com>

AI[100%] Human Fixed[0%] Human[0%] AI Adopted[100%]
Co-authored-by: claude (glm-5.2) <ai@local>

Change-Id: Ia7108ae751f32c9d3596ca5f72480eba9a42555f
This commit is contained in:
wanghang
2026-08-11 17:29:55 +08:00
parent 983b35dd21
commit 4e96b16d39
13 changed files with 29 additions and 734 deletions
-1
View File
@@ -29,7 +29,6 @@ public:
static bool CheckFileName(const std::string &fileName);
static bool CheckFileSize(const std::string &bundlePath, const int64_t fileSize);
static bool GetHapFilesFromBundlePath(const std::string &currentBundlePath, std::vector<std::string> &hapFileList);
static bool GetHapFilesFromCloneDir(const std::string &currentBundlePath, std::vector<std::string> &hapFileList);
static bool DeleteDir(const std::string &path);
static bool IsExistFile(const std::string &filePath);
static bool IsExistDir(const std::string &dirPath);
-51
View File
@@ -171,57 +171,6 @@ bool BundleFileUtil::CheckFileSize(const std::string &bundlePath, const int64_t
return true;
}
bool BundleFileUtil::GetHapFilesFromCloneDir(const std::string &currentBundlePath,
std::vector<std::string> &hapFileList)
{
APP_LOGD("GetHapFilesFromCloneDir with path is %{public}s", currentBundlePath.c_str());
if (currentBundlePath.empty()) {
return false;
}
std::string realBundlePath = "";
if (!PathToRealPath(currentBundlePath, realBundlePath)) {
APP_LOGE("PathToRealPath failed for %{public}s", currentBundlePath.c_str());
return false;
}
DIR* dir = opendir(realBundlePath.c_str());
if (dir == nullptr) {
char errMsg[256] = {0};
strerror_r(errno, errMsg, sizeof(errMsg));
APP_LOGE("open %{public}s failure due to %{public}s errno %{public}d",
realBundlePath.c_str(), errMsg, errno);
return false;
}
std::string bundlePath = realBundlePath;
if (bundlePath.back() != FILE_SEPARATOR_CHAR) {
bundlePath.append(PATH_SEPARATOR);
}
struct dirent *entry = nullptr;
while ((entry = readdir(dir)) != nullptr) {
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
continue;
}
const std::string hapFilePath = bundlePath + entry->d_name;
std::string realFilePath = "";
if (!CheckFilePath(hapFilePath, realFilePath)) {
APP_LOGW("invalid hap path %{public}s", hapFilePath.c_str());
continue;
}
hapFileList.emplace_back(realFilePath);
APP_LOGD("find hap path %{public}s", realFilePath.c_str());
if (hapFileList.size() > MAX_HAP_NUMBER) {
APP_LOGE("max hap number %{public}hhu, stop add", MAX_HAP_NUMBER);
closedir(dir);
return false;
}
}
closedir(dir);
return true;
}
bool BundleFileUtil::GetHapFilesFromBundlePath(const std::string &currentBundlePath,
std::vector<std::string> &hapFileList)
{
@@ -122,7 +122,6 @@ private:
public:
static constexpr const char* RENAME_INSTALL_KEY = "ohos.bms.param.renameInstall";
static constexpr const char* ENTERPRISE_FOR_ALL_USER_KEY = "ohos.bms.param.enterpriseForAllUser";
static constexpr const char* SUPPORT_DATA_CLONE_INSTALL_KEY = "ohos.bms.para.supportDataCloneInstall";
static constexpr const char* PARAMETERS_VALUE_TRUE = "true";
bool GetForceExecuted() const
@@ -179,12 +178,6 @@ public:
parameters.at(ENTERPRISE_FOR_ALL_USER_KEY) == PARAMETERS_VALUE_TRUE;
}
bool IsSupportDataCloneInstall() const
{
return parameters.find(SUPPORT_DATA_CLONE_INSTALL_KEY) != parameters.end() &&
parameters.at(SUPPORT_DATA_CLONE_INSTALL_KEY) == PARAMETERS_VALUE_TRUE;
}
bool IsForcedUninstall() const
{
return parameters.find(Constants::VERIFY_UNINSTALL_FORCED_KEY) != parameters.end() &&
@@ -459,20 +459,9 @@ ErrCode BundleInstallerProxy::StreamInstall(const std::vector<std::string> &bund
}
std::vector<std::string> realPaths;
if (!bundleFilePaths.empty()) {
if (!installParam.IsSupportDataCloneInstall() && !BundleFileUtil::CheckFilePath(bundleFilePaths, realPaths)) {
LOG_E(BMS_TAG_INSTALLER, "stream install failed due to check file failed");
return ERR_APPEXECFWK_INSTALL_FILE_PATH_INVALID;
} else if (installParam.IsSupportDataCloneInstall()) {
if (bundleFilePaths.size() != 1) {
LOG_E(BMS_TAG_INSTALLER, "stream install failed due to data clone install only support one hap file");
return ERR_APPEXECFWK_INSTALL_FILE_PATH_INVALID;
}
if (!BundleFileUtil::GetHapFilesFromCloneDir(bundleFilePaths[0], realPaths)) {
LOG_E(BMS_TAG_INSTALLER, "stream install failed due to get hap files from clone dir failed");
return ERR_APPEXECFWK_INSTALL_FILE_PATH_INVALID;
}
}
if (!bundleFilePaths.empty() && !BundleFileUtil::CheckFilePath(bundleFilePaths, realPaths)) {
LOG_E(BMS_TAG_INSTALLER, "stream install failed due to check file failed");
return ERR_APPEXECFWK_INSTALL_FILE_PATH_INVALID;
}
sptr<IBundleStreamInstaller> streamInstaller = CreateStreamInstaller(installParam, statusReceiver, realPaths);
@@ -59,7 +59,6 @@ bundle_install_sources = [
"${services_path}/bundlemgr/src/bundle_verify_mgr.cpp",
"${services_path}/bundlemgr/src/data/inner_ability_info.cpp",
"${services_path}/bundlemgr/src/data/inner_extension_info.cpp",
"${services_path}/bundlemgr/src/data_clone_install_helper.cpp",
"${services_path}/bundlemgr/src/driver/driver_installer.cpp",
"${services_path}/bundlemgr/src/driver_install_ext.cpp",
"${services_path}/bundlemgr/src/event_report.cpp",
@@ -1083,7 +1083,6 @@ private:
bool isBundleCrossAppSharedConfig_ = false;
bool isHnpInstalled_ = false;
bool isKeepTokenId_ = false;
bool supportDataCloneInstall_ = false;
bool hasShareFilesProcessed_ = false;
bool hasOldShareFilesJsonSaved_ = false;
InstallerState state_ = InstallerState::INSTALL_START;
@@ -1,48 +0,0 @@
/*
* Copyright (c) 2026 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 FOUNDATION_APPEXECFWK_SERVICES_BUNDLEMGR_INCLUDE_DATA_CLONE_INSTALL_HELPER_H
#define FOUNDATION_APPEXECFWK_SERVICES_BUNDLEMGR_INCLUDE_DATA_CLONE_INSTALL_HELPER_H
#include <string>
#include <vector>
#include <filesystem>
#include "app_log_wrapper.h"
#include "bundle_service_constants.h"
namespace OHOS {
namespace AppExecFwk {
class DataCloneInstallHelper {
public:
/**
* @brief Check if all paths in the list have the required clone install prefix.
* @param bundlePaths The list of bundle paths to check (must contain exactly 1 path).
* @return Returns true if the path has the clone install prefix, false otherwise.
*/
static bool AreAllCloneInstallPaths(const std::vector<std::string> &bundlePaths);
static std::string RenameDirToSecurityDir(const std::string &dirPath, std::vector<std::string> &bundlePaths,
std::vector<std::string> &toDeletePaths, int32_t userId);
static ErrCode RenameToRealCodePath(const std::vector<std::string> bundlePaths,
const std::string &bundleName);
};
} // namespace AppExecFwk
} // namespace OHOS
#endif // FOUNDATION_APPEXECFWK_SERVICES_BUNDLEMGR_INCLUDE_DATA_CLONE_INSTALL_HELPER_H
@@ -286,8 +286,6 @@ public:
static bool ChangeDirOwnerRecursively(const std::string &path, const int uid, const int gid);
static bool ChangeDirModeRecursively(const std::string &path, mode_t fileMode, mode_t dirMode);
static bool IsDiffFiles(const std::string &entryName,
const std::string &targetPath, const std::string &cpuAbi);
@@ -48,13 +48,11 @@
#include "bms_update_selinux_mgr.h"
#include "bundle_cli_sandbox_installer.h"
#include "bundle_clone_installer.h"
#include "bundle_file_util.h"
#include "bundle_permission_mgr.h"
#include "bundle_resource_helper.h"
#include "bundle_parser.h"
#include "bundle_util.h"
#include "code_protect_bundle_info.h"
#include "data_clone_install_helper.h"
#include "datetime_ex.h"
#include "driver_installer.h"
#include "dual_mode_helper.h"
@@ -1606,23 +1604,17 @@ ErrCode BaseBundleInstaller::ProcessBundleInstall(const std::vector<std::string>
userId_ = GetUserId(installParam.userId);
result = CheckUserId(userId_);
CHECK_RESULT(result, "userId check failed %{public}d");
supportDataCloneInstall_ = installParam.IsSupportDataCloneInstall();
if (supportDataCloneInstall_ && !DataCloneInstallHelper::AreAllCloneInstallPaths(inBundlePaths)) {
LOG_E(BMS_TAG_INSTALLER, "not all paths are valid for clone install");
return ERR_APPEXECFWK_INSTALL_FILE_PATH_INVALID;
}
std::vector<std::string> parsedPaths;
result = ParseHapPaths(installParam, inBundlePaths, parsedPaths);
CHECK_RESULT(result, "hap file parse failed %{public}d");
std::vector<std::string> bundlePaths;
if (supportDataCloneInstall_) {
bundlePaths = parsedPaths;
} else {
// check hap paths
result = BundleUtil::CheckFilePath(parsedPaths, bundlePaths);
CHECK_RESULT(result, "hap file check failed %{public}d");
UpdateInstallerState(InstallerState::INSTALL_BUNDLE_CHECKED); // ---- 5%
}
// check hap paths
result = BundleUtil::CheckFilePath(parsedPaths, bundlePaths);
CHECK_RESULT(result, "hap file check failed %{public}d");
UpdateInstallerState(InstallerState::INSTALL_BUNDLE_CHECKED); // ---- 5%
// copy the haps to the dir which cannot be accessed from caller
result = CopyHapsToSecurityDir(installParam, bundlePaths);
CHECK_RESULT(result, "copy file failed %{public}d");
@@ -1808,10 +1800,6 @@ ErrCode BaseBundleInstaller::ProcessBundleInstall(const std::vector<std::string>
result = bundleInstallChecker_->CalculateInstallInodes(newInfos, !isAppExist_);
CHECK_RESULT(result, "check inode requirements failed %{public}d");
}
if (supportDataCloneInstall_ && isAppExist_) {
LOG_E(BMS_TAG_INSTALLER, "data clone install does not support app update");
return ERR_APPEXECFWK_INSTALL_ALREADY_EXIST;
}
bool oldAppHasKey = oldInfo.GetApplicationReservedFlag() &
static_cast<uint32_t>(ApplicationReservedFlag::ENCRYPTED_KEY_EXISTED);
ScopeGuard encrytedKeyGuard([&] { dataMgr_->UpdateAppEncryptedStatus(bundleName_, oldAppHasKey, 0, false); });
@@ -1846,18 +1834,10 @@ ErrCode BaseBundleInstaller::ProcessBundleInstall(const std::vector<std::string>
// copy hap or hsp to real install dir
SaveHapPathToRecords(installParam.isPreInstallApp, newInfos);
if (installParam.copyHapToInstallPath) {
if (supportDataCloneInstall_) {
for (const auto &hapPath : bundlePaths) {
result = VerifyCodeSignatureForHap(newInfos, hapPath, hapPath);
CHECK_RESULT_WITH_ROLLBACK(result, "verify code signature for hap failed %{public}d", newInfos, oldInfo);
}
} else {
LOG_D(BMS_TAG_INSTALLER, "begin to copy hap to install path");
result = SaveHapToInstallPath(newInfos, oldInfo);
CHECK_RESULT_WITH_ROLLBACK(result, "copy hap to install path failed %{public}d", newInfos, oldInfo);
}
}
if (!installParam.copyHapToInstallPath || supportDataCloneInstall_) {
LOG_D(BMS_TAG_INSTALLER, "begin to copy hap to install path");
result = SaveHapToInstallPath(newInfos, oldInfo);
CHECK_RESULT_WITH_ROLLBACK(result, "copy hap to install path failed %{public}d", newInfos, oldInfo);
} else {
if ((result = CheckHapEncryption(newInfos, oldInfo, false)) != ERR_OK) {
LOG_E(BMS_TAG_INSTALLER, "check encryption of pre-hap failed %{public}d", result);
}
@@ -2011,9 +1991,6 @@ ErrCode BaseBundleInstaller::ProcessBundleInstall(const std::vector<std::string>
CheckAddResultMsg(cacheInfo, isContainEntry_);
PrintDataStat();
ProcessAOT(installParam);
if (supportDataCloneInstall_) {
LOG_D(BMS_TAG_INSTALLER, "support data clone install successfully, bundleName:%{public}s", bundleName_.c_str());
}
return result;
}
@@ -4511,20 +4488,17 @@ ErrCode BaseBundleInstaller::ExtractModule(InnerBundleInfo &info, const std::str
}
}
// data clone install no need to extract res files
if (!supportDataCloneInstall_) {
ExtractResourceFiles(info, modulePath);
auto needFakeDecompression =
BundleUtil::IsResFileSupportFakeDecompression(info.GetBundleName(), info.GetIsKeepAlive());
auto isSystemApp = info.IsSystemApp();
result = ExtractResFileDir(modulePath, needFakeDecompression, isSystemApp);
if (result != ERR_OK) {
LOG_E(BMS_TAG_INSTALLER, "fail to ExtractResFileDir, error is %{public}d", result);
return result;
}
sysEventInfo_.isResourceFileFakeDecompression = sysEventInfo_.isResourceFileFakeDecompression ||
needFakeDecompression;
ExtractResourceFiles(info, modulePath);
auto needFakeDecompression =
BundleUtil::IsResFileSupportFakeDecompression(info.GetBundleName(), info.GetIsKeepAlive());
auto isSystemApp = info.IsSystemApp();
result = ExtractResFileDir(modulePath, needFakeDecompression, isSystemApp);
if (result != ERR_OK) {
LOG_E(BMS_TAG_INSTALLER, "fail to ExtractResFileDir, error is %{public}d", result);
return result;
}
sysEventInfo_.isResourceFileFakeDecompression = sysEventInfo_.isResourceFileFakeDecompression ||
needFakeDecompression;
if (auto hnpPackageInfos = info.GetInnerModuleInfoHnpInfo(info.GetCurModuleName())) {
std::map<std::string, std::string> hnpPackageInfoMap;
@@ -7337,13 +7311,7 @@ void BaseBundleInstaller::RestoreHaps(const std::vector<std::string> &bundlePath
LOG_W(BMS_TAG_INSTALLER, "Invalid bundle path: %{public}s", bundlePaths.front().c_str());
return;
}
if (installParam.IsSupportDataCloneInstall()) {
if (!BundleUtil::RenameFile(bundlePaths_[0],targetDir)) {
LOG_W(BMS_TAG_INSTALLER, "data clone install failed: %{public}s -> %{public}s",
bundlePaths_[0].c_str(), targetDir.c_str());
}
return;
}
for (const auto &originPath : bundlePaths_) {
std::string targetPath = targetDir + originPath.substr(originPath.find_last_of('/') + 1);
LOG_I(BMS_TAG_INSTALLER, "Restore hap: %{public}s -> %{public}s", originPath.c_str(), targetPath.c_str());
@@ -7665,13 +7633,10 @@ ErrCode BaseBundleInstaller::InnerProcessNativeLibs(InnerBundleInfo &info, const
return ret;
}
if (isCompressNativeLibrary) {
// data clone install no need to extract so
if (!supportDataCloneInstall_) {
auto result = ExtractModuleFiles(info, modulePath, targetSoPath, cpuAbi);
CHECK_RESULT(result, "fail to extract module dir, error is %{public}d");
}
auto result = ExtractModuleFiles(info, modulePath, targetSoPath, cpuAbi);
CHECK_RESULT(result, "fail to extract module dir, error is %{public}d");
// verify hap or hsp code signature for compressed so files
auto result = VerifyCodeSignatureForNativeFiles(info, cpuAbi, targetSoPath, signatureFileDir);
result = VerifyCodeSignatureForNativeFiles(info, cpuAbi, targetSoPath, signatureFileDir);
CHECK_RESULT(result, "fail to VerifyCodeSignature, error is %{public}d");
// check whether the hap or hsp is encrypted
result = CheckSoEncryption(info, cpuAbi, targetSoPath);
@@ -7867,31 +7832,6 @@ ErrCode BaseBundleInstaller::CopyHapsToSecurityDir(const InstallParam &installPa
LOG_D(BMS_TAG_INSTALLER, "no need to copy preInstallApp to secure dir");
return ERR_OK;
}
if (supportDataCloneInstall_) {
if (bundlePaths.empty()) {
LOG_E(BMS_TAG_INSTALLER, "bundle path empty");
return ERR_APPEXECFWK_INSTALL_FILE_PATH_INVALID;
}
size_t pos = bundlePaths[0].rfind(ServiceConstants::PATH_SEPARATOR);
std::string dirPath = (pos != std::string::npos) ? bundlePaths[0].substr(0, pos) : bundlePaths[0];
std::string destination = DataCloneInstallHelper::RenameDirToSecurityDir(dirPath, bundlePaths,
toDeleteTempHapPath_, userId_);
if (!BundleUtil::RenameFile(dirPath, destination)) {
LOG_E(BMS_TAG_INSTALLER, "rename dir %{private}s to %{private}s failed", dirPath.c_str(),
destination.c_str());
return ERR_APPEXECFWK_INSTALL_COPY_HAP_FAILED;
}
bundlePaths_.clear();
bundlePaths.clear();
if (!destination.empty()) {
bundlePaths_.push_back(destination);
}
if (!BundleFileUtil::GetHapFilesFromCloneDir(destination, bundlePaths)) {
LOG_E(BMS_TAG_INSTALLER, "GetHapFilesFromCloneDir failed for %{public}s", destination.c_str());
return ERR_APPEXECFWK_INSTALL_COPY_HAP_FAILED;
}
return ERR_OK;
}
for (size_t index = 0; index < bundlePaths.size(); ++index) {
if (!BundleUtil::CheckSystemSize(bundlePaths[index], APP_INSTALL_PATH)) {
LOG_E(BMS_TAG_INSTALLER, "install %{private}s failed insufficient disk memory", bundlePaths[index].c_str());
@@ -7917,7 +7857,7 @@ ErrCode BaseBundleInstaller::ParseHapPaths(const InstallParam &installParam,
parsedPaths.assign(inBundlePaths.begin(), inBundlePaths.end());
return ERR_OK;
}
LOG_I(BMS_TAG_INSTALLER, "rename install, supportDataCloneInstall:%{public}d", supportDataCloneInstall_);
LOG_I(BMS_TAG_INSTALLER, "rename install");
int32_t userId = sysEventInfo_.callingUid / Constants::BASE_USER_RANGE;
const std::string newPrefix = std::string(ServiceConstants::BUNDLE_MANAGER_SERVICE_PATH) +
ServiceConstants::GALLERY_DOWNLOAD_PATH + std::to_string(userId);
@@ -9795,10 +9735,6 @@ ErrCode BaseBundleInstaller::ProcessBundleCodePath(
const InnerBundleInfo &oldInfo, const std::string &bundleName,
const bool isBundleUpdate, const bool needCopyHap)
{
if (supportDataCloneInstall_) {
// rename to real code path
return DataCloneInstallHelper::RenameToRealCodePath(bundlePaths_, bundleName);
}
if (!isBundleUpdate) {
// move so file to real installation dir
bool needDeleteOldLibraryPath = NeedDeleteOldNativeLib(newInfos, oldInfo);
@@ -10044,15 +9980,6 @@ void BaseBundleInstaller::InnerProcessTargetSoPath(const InnerBundleInfo &info,
const std::string &modulePath, std::string &nativeLibraryPath, std::string &targetSoPath)
{
bool isLibIsolated = info.IsLibIsolated(info.GetCurModuleName());
// for data clone install
if (supportDataCloneInstall_) {
if (!bundlePaths_.empty()) {
targetSoPath = bundlePaths_[0] + ServiceConstants::PATH_SEPARATOR + nativeLibraryPath;
} else {
LOG_NOFUNC_E(BMS_TAG_INSTALLER, "data clone install bundlePaths empty -n %{public}s", bundleName_.c_str());
}
return;
}
// extract so file: if hap so is not isolated, then extract so to tmp path.
if (isLibIsolated) {
if (BundleUtil::EndWith(modulePath, ServiceConstants::TMP_SUFFIX)) {
@@ -1,99 +0,0 @@
/*
* Copyright (c) 2026 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 "data_clone_install_helper.h"
#include "bundle_constants.h"
#include "bundle_util.h"
#include "bundle_service_constants.h"
#include <dirent.h>
#include "installd_client.h"
#include <sys/stat.h>
#include <unistd.h>
#include "app_log_tag_wrapper.h"
#include "directory_ex.h"
namespace OHOS {
namespace AppExecFwk {
bool DataCloneInstallHelper::AreAllCloneInstallPaths(const std::vector<std::string> &bundlePaths)
{
if (bundlePaths.empty()) {
LOG_W(BMS_TAG_INSTALLER, "bundlePaths is empty");
return false;
}
if (bundlePaths.size() != 1) {
LOG_W(BMS_TAG_INSTALLER, "bundlePaths size must be 1, but got %{public}zu", bundlePaths.size());
return false;
}
const auto &path = bundlePaths[0];
if (path.empty() || path.find(ServiceConstants::APP_CLONE_SANDBOX_PATH) != 0) {
LOG_W(BMS_TAG_INSTALLER, "Path does not have required prefix %{public}s: %{public}s",
ServiceConstants::APP_CLONE_SANDBOX_PATH, path.c_str());
return false;
}
LOG_D(BMS_TAG_INSTALLER, "Path has valid clone install prefix with %{public}s",
ServiceConstants::APP_CLONE_SANDBOX_PATH);
return true;
}
std::string DataCloneInstallHelper::RenameDirToSecurityDir(const std::string &dirPath,
std::vector<std::string> &bundlePaths, std::vector<std::string> &toDeletePaths, int32_t userId)
{
std::string destination = ServiceConstants::HAP_COPY_PATH;
std::string bundleName = dirPath.substr(dirPath.rfind(ServiceConstants::PATH_SEPARATOR) + 1);
destination.append(ServiceConstants::PATH_SEPARATOR).append(ServiceConstants::SECURITY_STREAM_INSTALL_PATH);
mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
CreateDirParam createDirParam;
createDirParam.bundleDirScene = BundleDirScene::SERVICE_BMS_SECURITY_STREAM_INSTALL_DIR;
if (InstalldClient::GetInstance()->Mkdir(
destination, mode, Constants::FOUNDATION_UID, ServiceConstants::BMS_GID, createDirParam) != ERR_OK) {
LOG_E(BMS_TAG_INSTALLER, "Failed to create security directory: %{public}s", destination.c_str());
}
destination.append(ServiceConstants::PATH_SEPARATOR);
destination.append("+app_clone").append(bundleName).append(ServiceConstants::PLUS_SIGN)
.append(std::to_string(userId)).append(ServiceConstants::PLUS_SIGN);
static std::atomic<uint64_t> installCount = 0;
destination.append(std::to_string(BundleUtil::GetCurrentTime()) + "_" + std::to_string(++installCount));
toDeletePaths.emplace_back(destination);
LOG_D(BMS_TAG_INSTALLER, "Renaming directory %{public}s to security directory %{public}s",
dirPath.c_str(), destination.c_str());
return destination;
}
ErrCode DataCloneInstallHelper::RenameToRealCodePath(
const std::vector<std::string> bundlePaths,
const std::string &bundleName)
{
if (bundlePaths.empty()) {
LOG_E(BMS_TAG_INSTALLER, "-n %{public}s rename failed due to bundlePaths empty", bundleName.c_str());
return ERR_APPEXECFWK_INSTALL_FILE_PATH_INVALID;
}
std::string codePath = std::string(Constants::BUNDLE_CODE_DIR) + ServiceConstants::PATH_SEPARATOR + bundleName;
ErrCode ret = InstalldClient::GetInstance()->RenameModuleDir(bundlePaths[0], codePath,
bundleName, BundleDirScene::COPY_HAP_TO_INSTALL_PATH);
if (ret != ERR_OK) {
LOG_E(BMS_TAG_INSTALLER, "-n %{public}s rename to real code path failed", bundleName.c_str());
return ret;
}
return ret;
}
} // namespace AppExecFwk
} // namespace OHOS
@@ -18,7 +18,6 @@
#include <chrono>
#include <cinttypes>
#include <cstdio>
#include <dirent.h>
#include <filesystem>
#include <fstream>
#include <future>
@@ -117,76 +116,6 @@ constexpr int64_t BLOCK_SIZE = 512;
#if defined(CODE_SIGNATURE_ENABLE)
using namespace OHOS::Security::CodeSign;
#endif
static ErrCode ApplyCloneInstallPerms(const std::string &path)
{
mode_t targetFileMode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
mode_t resourceFileMode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
mode_t dirMode = S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
DIR *dir = opendir(path.c_str());
if (dir == nullptr) {
LOG_E(BMS_TAG_INSTALLD, "fail to opendir:%{public}s, errno:%{public}d", path.c_str(), errno);
return ERR_APPEXECFWK_INSTALLD_CHMOD_FAILED;
}
// Lambda to handle sub-path permissions, capturing mode variables to reduce parameter count
auto handleSubPathPermission = [&](const std::string &subPath, bool isDir, const char* name) -> ErrCode {
if (isDir) {
// libs dir uses resourceFileMode, other dirs (e.g., entry) use targetFileMode
mode_t mode = (strcmp(name, "libs") == 0) ? resourceFileMode : targetFileMode;
if (!InstalldOperator::ChangeDirModeRecursively(subPath, mode, dirMode)) {
LOG_E(BMS_TAG_INSTALLD, "change dir mode failed, path: %{public}s", subPath.c_str());
return ERR_APPEXECFWK_INSTALLD_CHMOD_FAILED;
}
} else {
// Files directly under the root path use resourceFileMode
if (chmod(subPath.c_str(), resourceFileMode) != 0) {
LOG_E(BMS_TAG_INSTALLD, "change mode for file %{public}s failed, errno:%{public}d",
subPath.c_str(), errno);
}
}
return ERR_OK;
};
struct dirent *entryPtr = nullptr;
while ((entryPtr = readdir(dir)) != nullptr) {
if (strcmp(entryPtr->d_name, ".") == 0 || strcmp(entryPtr->d_name, "..") == 0) {
continue;
}
std::string subPath = path + ServiceConstants::PATH_SEPARATOR + entryPtr->d_name;
bool isDir = (entryPtr->d_type == DT_DIR);
ErrCode ret = handleSubPathPermission(subPath, isDir, entryPtr->d_name);
if (ret != ERR_OK) {
closedir(dir);
return ret;
}
}
closedir(dir);
// Set permission for the root directory itself
if (chmod(path.c_str(), dirMode) != 0) {
LOG_E(BMS_TAG_INSTALLD, "change mode for dir %{public}s failed, errno:%{public}d", path.c_str(), errno);
return ERR_APPEXECFWK_INSTALLD_CHMOD_FAILED;
}
return ERR_OK;
}
ErrCode ProcessCopyHapToInstallPath(const std::string &oldPath, const std::string &newPath)
{
if (!InstalldOperator::RenameFile(oldPath, newPath)) {
LOG_E(BMS_TAG_INSTALLD, "rename file %{public}s to %{public}s failed errno:%{public}d",
oldPath.c_str(), newPath.c_str(), errno);
return ERR_APPEXECFWK_INSTALLD_RNAME_DIR_FAILED;
}
if (!InstalldOperator::ChangeDirOwnerRecursively(newPath, INSTALLS_UID, INSTALLS_UID)) {
LOG_E(BMS_TAG_INSTALLD, "change dir owner failed, path: %{public}s", newPath.c_str());
return ERR_APPEXECFWK_INSTALLD_CHMOD_FAILED;
}
return ApplyCloneInstallPerms(newPath);
}
}
InstalldHostImpl::InstalldHostImpl()
@@ -493,10 +422,6 @@ ErrCode InstalldHostImpl::RenameModuleDir(
return ERR_APPEXECFWK_INSTALLD_PARAM_ERROR;
}
if (scene == BundleDirScene::COPY_HAP_TO_INSTALL_PATH) {
return ProcessCopyHapToInstallPath(oldPath, newPath);
}
if (!InstalldOperator::IsValidBundleName(bundleName) ||
!InstalldOperator::IsValidPathByRenameModuleDir(oldPath, newPath, bundleName, scene)) {
LOG_E(BMS_TAG_INSTALLD,
@@ -1580,64 +1580,6 @@ std::string InstalldOperator::GetPathDir(const std::string &path)
return path.substr(0, pos + 1);
}
bool InstalldOperator::ChangeDirModeRecursively(const std::string &path, mode_t fileMode, mode_t dirMode)
{
DIR *dir = opendir(path.c_str());
if (dir == nullptr) {
LOG_D(BMS_TAG_INSTALLD, "fail to opendir:%{public}s, errno:%{public}d", path.c_str(), errno);
return false;
}
// Lambda to ensure resource safety on exit
auto failAndClose = [&]() {
closedir(dir);
return false;
};
#ifdef WITH_SELINUX
constexpr const char* SELINUX_CONTEXT = "u:object_r:data_app_el1_file:s0";
if (lsetfilecon(path.c_str(), SELINUX_CONTEXT) < 0) {
LOG_E(BMS_TAG_INSTALLD, "setcon %{public}s failed errno:%{public}d", path.c_str(), errno);
return failAndClose();
}
#endif
struct dirent *ptr = nullptr;
while ((ptr = readdir(dir)) != nullptr) {
if (strcmp(ptr->d_name, ".") == 0 || strcmp(ptr->d_name, "..") == 0) {
continue;
}
std::string subPath = path + ServiceConstants::PATH_SEPARATOR + ptr->d_name;
#ifdef WITH_SELINUX
if (lsetfilecon(subPath.c_str(), SELINUX_CONTEXT) < 0) {
LOG_E(BMS_TAG_INSTALLD, "setcon %{public}s failed errno:%{public}d", subPath.c_str(), errno);
return failAndClose();
}
#endif
if (ptr->d_type == DT_DIR) {
if (!ChangeDirModeRecursively(subPath, fileMode, dirMode)) {
return failAndClose();
}
}
if (chmod(subPath.c_str(), ptr->d_type == DT_DIR ? dirMode : fileMode) != 0) {
LOG_E(BMS_TAG_INSTALLD, "change mode for %{public}s failed, errno:%{public}d", subPath.c_str(), errno);
return failAndClose();
}
}
closedir(dir);
if (chmod(path.c_str(), dirMode) != 0) {
LOG_E(BMS_TAG_INSTALLD, "change mode for %{public}s failed, errno:%{public}d", path.c_str(), errno);
return false;
}
return true;
}
bool InstalldOperator::ChangeDirOwnerRecursively(const std::string &path, const int uid, const int gid)
{
std::string subPath;
@@ -36,7 +36,6 @@
#include "app_domain_verify_mgr_client.h"
#endif
#include "app_service_fwk/app_service_fwk_installer.h"
#include "bundle_file_util.h"
#include "bundle_info.h"
#include "bundle_installer.h"
#include "bundle_installer_host.h"
@@ -44,7 +43,6 @@
#include "bundle_multiuser_installer.h"
#include "bundle_resource_helper.h"
#include "bundle_resource_manager.h"
#include "data_clone_install_helper.h"
#include "directory_ex.h"
#include "file_ex.h"
#include "hmp_bundle_installer.h"
@@ -18208,282 +18206,6 @@ HWTEST_F(BmsBundleInstallerTest, InnerShared_VerifyCodeSignatureForNativeFiles_0
EXPECT_EQ(ret, ERR_OK);
}
/**
* @tc.number: InstallParam_IsSupportDataCloneInstall_001
* @tc.name: InstallParam IsSupportDataCloneInstall
* @tc.desc: test parameter parsing
*/
HWTEST_F(BmsBundleInstallerTest, InstallParam_IsSupportDataCloneInstall_001, TestSize.Level1)
{
InstallParam installParam;
// Default false
EXPECT_FALSE(installParam.IsSupportDataCloneInstall());
// Set true
installParam.parameters[InstallParam::SUPPORT_DATA_CLONE_INSTALL_KEY] = "true";
EXPECT_TRUE(installParam.IsSupportDataCloneInstall());
// Set false explicitly
installParam.parameters[InstallParam::SUPPORT_DATA_CLONE_INSTALL_KEY] = "false";
EXPECT_FALSE(installParam.IsSupportDataCloneInstall());
}
/**
* @tc.number: InstallParam_IsSupportDataCloneInstall_002
* @tc.name: InstallParam IsSupportDataCloneInstall
* @tc.desc: test parameter parsing with false value
*/
HWTEST_F(BmsBundleInstallerTest, InstallParam_IsSupportDataCloneInstall_002, TestSize.Level1)
{
InstallParam installParam;
installParam.parameters[InstallParam::SUPPORT_DATA_CLONE_INSTALL_KEY] = "false";
EXPECT_FALSE(installParam.IsSupportDataCloneInstall());
}
/**
* @tc.number: InstallParam_IsSupportDataCloneInstall_003
* @tc.name: InstallParam IsSupportDataCloneInstall
* @tc.desc: test parameter parsing with non-true value
*/
HWTEST_F(BmsBundleInstallerTest, InstallParam_IsSupportDataCloneInstall_003, TestSize.Level1)
{
InstallParam installParam;
installParam.parameters[InstallParam::SUPPORT_DATA_CLONE_INSTALL_KEY] = "1";
EXPECT_FALSE(installParam.IsSupportDataCloneInstall());
}
/**
* @tc.number: DataCloneInstallHelper_AreAllCloneInstallPaths_001
* @tc.name: DataCloneInstallHelper AreAllCloneInstallPaths
* @tc.desc: test empty paths
*/
HWTEST_F(BmsBundleInstallerTest, DataCloneInstallHelper_AreAllCloneInstallPaths_001, TestSize.Level1)
{
std::vector<std::string> paths;
bool result = DataCloneInstallHelper::AreAllCloneInstallPaths(paths);
EXPECT_FALSE(result);
}
/**
* @tc.number: DataCloneInstallHelper_AreAllCloneInstallPaths_002
* @tc.name: DataCloneInstallHelper AreAllCloneInstallPaths
* @tc.desc: test multiple paths
*/
HWTEST_F(BmsBundleInstallerTest, DataCloneInstallHelper_AreAllCloneInstallPaths_002, TestSize.Level1)
{
std::vector<std::string> paths;
paths.emplace_back("/data/bms_app_clone/test1/");
paths.emplace_back("/data/bms_app_clone/test2/");
bool result = DataCloneInstallHelper::AreAllCloneInstallPaths(paths);
EXPECT_FALSE(result);
}
/**
* @tc.number: DataCloneInstallHelper_AreAllCloneInstallPaths_003
* @tc.name: DataCloneInstallHelper AreAllCloneInstallPaths
* @tc.desc: test invalid prefix
*/
HWTEST_F(BmsBundleInstallerTest, DataCloneInstallHelper_AreAllCloneInstallPaths_003, TestSize.Level1)
{
std::vector<std::string> paths;
paths.emplace_back("/data/invalid_prefix/test/");
bool result = DataCloneInstallHelper::AreAllCloneInstallPaths(paths);
EXPECT_FALSE(result);
}
/**
* @tc.number: DataCloneInstallHelper_AreAllCloneInstallPaths_004
* @tc.name: DataCloneInstallHelper AreAllCloneInstallPaths
* @tc.desc: test valid prefix
*/
HWTEST_F(BmsBundleInstallerTest, DataCloneInstallHelper_AreAllCloneInstallPaths_004, TestSize.Level1)
{
std::vector<std::string> paths;
paths.emplace_back(ServiceConstants::APP_CLONE_SANDBOX_PATH + std::string("com.test.app/"));
bool result = DataCloneInstallHelper::AreAllCloneInstallPaths(paths);
EXPECT_TRUE(result);
}
/**
* @tc.number: DataCloneInstallHelper_AreAllCloneInstallPaths_005
* @tc.name: DataCloneInstallHelper AreAllCloneInstallPaths
* @tc.desc: test empty string path
*/
HWTEST_F(BmsBundleInstallerTest, DataCloneInstallHelper_AreAllCloneInstallPaths_005, TestSize.Level1)
{
std::vector<std::string> paths;
paths.emplace_back("");
EXPECT_FALSE(DataCloneInstallHelper::AreAllCloneInstallPaths(paths));
}
/**
* @tc.number: DataCloneInstallHelper_AreAllCloneInstallPaths_006
* @tc.name: DataCloneInstallHelper AreAllCloneInstallPaths
* @tc.desc: test invalid prefix
*/
HWTEST_F(BmsBundleInstallerTest, DataCloneInstallHelper_AreAllCloneInstallPaths_006, TestSize.Level1)
{
std::vector<std::string> paths;
paths.emplace_back("/data/invalid_prefix/com.test/");
EXPECT_FALSE(DataCloneInstallHelper::AreAllCloneInstallPaths(paths));
}
/**
* @tc.number: DataCloneInstallHelper_AreAllCloneInstallPaths_007
* @tc.name: DataCloneInstallHelper AreAllCloneInstallPaths
* @tc.desc: test valid prefix
*/
HWTEST_F(BmsBundleInstallerTest, DataCloneInstallHelper_AreAllCloneInstallPaths_007, TestSize.Level1)
{
std::vector<std::string> paths;
paths.emplace_back(ServiceConstants::APP_CLONE_SANDBOX_PATH + std::string("com.test.app/"));
EXPECT_TRUE(DataCloneInstallHelper::AreAllCloneInstallPaths(paths));
}
/**
* @tc.number: DataCloneInstallHelper_AreAllCloneInstallPaths_008
* @tc.name: DataCloneInstallHelper AreAllCloneInstallPaths
* @tc.desc: test path contains prefix but not start with it
*/
HWTEST_F(BmsBundleInstallerTest, DataCloneInstallHelper_AreAllCloneInstallPaths_008, TestSize.Level1)
{
std::vector<std::string> paths;
paths.emplace_back("/data/other" + std::string(ServiceConstants::APP_CLONE_SANDBOX_PATH) + "com.test/");
EXPECT_FALSE(DataCloneInstallHelper::AreAllCloneInstallPaths(paths));
}
/**
* @tc.number: DataCloneInstallHelper_RenameToRealCodePath_001
* @tc.name: DataCloneInstallHelper RenameToRealCodePath
* @tc.desc: test empty paths
*/
HWTEST_F(BmsBundleInstallerTest, DataCloneInstallHelper_RenameToRealCodePath_001, TestSize.Level1)
{
std::vector<std::string> paths;
ErrCode result = DataCloneInstallHelper::RenameToRealCodePath(paths, "com.test");
EXPECT_EQ(result, ERR_APPEXECFWK_INSTALL_FILE_PATH_INVALID);
}
/**
* @tc.number: BundleFileUtil_GetHapFilesFromCloneDir_001
* @tc.name: BundleFileUtil GetHapFilesFromCloneDir
* @tc.desc: test empty path
*/
HWTEST_F(BmsBundleInstallerTest, BundleFileUtil_GetHapFilesFromCloneDir_001, TestSize.Level1)
{
std::vector<std::string> hapFiles;
bool result = BundleFileUtil::GetHapFilesFromCloneDir("", hapFiles);
EXPECT_FALSE(result);
EXPECT_TRUE(hapFiles.empty());
}
/**
* @tc.number: BundleFileUtil_GetHapFilesFromCloneDir_002
* @tc.name: BundleFileUtil GetHapFilesFromCloneDir
* @tc.desc: test invalid path
*/
HWTEST_F(BmsBundleInstallerTest, BundleFileUtil_GetHapFilesFromCloneDir_002, TestSize.Level1)
{
std::vector<std::string> hapFiles;
bool result = BundleFileUtil::GetHapFilesFromCloneDir("/non/existent/path", hapFiles);
EXPECT_FALSE(result);
EXPECT_TRUE(hapFiles.empty());
}
/**
* @tc.number: BaseBundleInstaller_ProcessBundleInstall_CloneUpdateCheck_001
* @tc.name: BaseBundleInstaller ProcessBundleInstall
* @tc.desc: test clone install blocked when app exists
*/
HWTEST_F(BmsBundleInstallerTest, BaseBundleInstaller_ProcessBundleInstall_CloneUpdateCheck_001, TestSize.Level1)
{
BaseBundleInstaller installer;
installer.supportDataCloneInstall_ = true;
installer.isAppExist_ = true; // Simulate app already exists
installer.userId_ = 100;
// Verify the condition that blocks clone install for updates
bool shouldBlock = installer.supportDataCloneInstall_ && installer.isAppExist_;
EXPECT_TRUE(shouldBlock);
}
/**
* @tc.number: CopyHapsToSecurityDir_0020
* @tc.name: CopyHapsToSecurityDir
* @tc.desc: test CopyHapsToSecurityDir with empty path in data clone install
*/
HWTEST_F(BmsBundleInstallerTest, CopyHapsToSecurityDir_0020, TestSize.Level1)
{
BaseBundleInstaller installer;
InstallParam installParam;
installParam.withCopyHaps = true;
std::vector<std::string> bundlePaths;
installer.supportDataCloneInstall_ = true;
ErrCode result = installer.CopyHapsToSecurityDir(installParam, bundlePaths);
EXPECT_EQ(result, ERR_APPEXECFWK_INSTALL_FILE_PATH_INVALID);
}
/**
* @tc.number: BaseBundleInstaller_InnerProcessTargetSoPath_Clone_001
* @tc.name: BaseBundleInstaller InnerProcessTargetSoPath
* @tc.desc: test clone install with valid bundlePaths_
*/
HWTEST_F(BmsBundleInstallerTest, BaseBundleInstaller_InnerProcessTargetSoPath_Clone_001, TestSize.Level1)
{
BaseBundleInstaller installer;
installer.supportDataCloneInstall_ = true;
installer.bundlePaths_ = {"/data/security/test_dir"};
InnerBundleInfo info;
std::string modulePath = "/data/test/module";
std::string nativeLibraryPath = "libs/arm64-v8a";
std::string targetSoPath;
installer.InnerProcessTargetSoPath(info, false, modulePath, nativeLibraryPath, targetSoPath);
EXPECT_EQ(targetSoPath, "/data/security/test_dir/libs/arm64-v8a");
}
/**
* @tc.number: BaseBundleInstaller_InnerProcessTargetSoPath_Clone_002
* @tc.name: BaseBundleInstaller InnerProcessTargetSoPath
* @tc.desc: test clone install with empty bundlePaths_
*/
HWTEST_F(BmsBundleInstallerTest, BaseBundleInstaller_InnerProcessTargetSoPath_Clone_002, TestSize.Level1)
{
BaseBundleInstaller installer;
installer.supportDataCloneInstall_ = true;
installer.bundlePaths_.clear();
InnerBundleInfo info;
std::string modulePath = "/data/test/module";
std::string nativeLibraryPath = "libs/arm64-v8a";
std::string targetSoPath = "initial";
installer.InnerProcessTargetSoPath(info, false, modulePath, nativeLibraryPath, targetSoPath);
EXPECT_EQ(targetSoPath, "initial");
}
/**
* @tc.number: BaseBundleInstaller_InnerProcessTargetSoPath_Clone_003
* @tc.name: BaseBundleInstaller InnerProcessTargetSoPath
* @tc.desc: test clone install uses only first element of bundlePaths_
*/
HWTEST_F(BmsBundleInstallerTest, BaseBundleInstaller_InnerProcessTargetSoPath_Clone_003, TestSize.Level1)
{
BaseBundleInstaller installer;
installer.supportDataCloneInstall_ = true;
installer.bundlePaths_ = {"/data/security/test_dir", "/data/security/other_dir"};
InnerBundleInfo info;
std::string modulePath = "/data/test/module";
std::string nativeLibraryPath = "libs/arm64-v8a";
std::string targetSoPath;
installer.InnerProcessTargetSoPath(info, false, modulePath, nativeLibraryPath, targetSoPath);
// Should use bundlePaths_[0]
EXPECT_EQ(targetSoPath, "/data/security/test_dir/libs/arm64-v8a");
}
/**
* @tc.number: UpdateDeveloperIdAndOdid_0001
* @tc.name: first install should not call GenerateOdid