114cf0368Sopenharmony_ci/*
214cf0368Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd.
314cf0368Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
414cf0368Sopenharmony_ci * you may not use this file except in compliance with the License.
514cf0368Sopenharmony_ci * You may obtain a copy of the License at
614cf0368Sopenharmony_ci *
714cf0368Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
814cf0368Sopenharmony_ci *
914cf0368Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
1014cf0368Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
1114cf0368Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1214cf0368Sopenharmony_ci * See the License for the specific language governing permissions and
1314cf0368Sopenharmony_ci * limitations under the License.
1414cf0368Sopenharmony_ci */
1514cf0368Sopenharmony_ci#define LOG_TAG "CustomUtdStore"
1614cf0368Sopenharmony_ci#include "custom_utd_store.h"
1714cf0368Sopenharmony_ci#include <fstream>
1814cf0368Sopenharmony_ci#include <sys/stat.h>
1914cf0368Sopenharmony_ci#include "logger.h"
2014cf0368Sopenharmony_ci#include "preset_type_descriptors.h"
2114cf0368Sopenharmony_ci#include "unistd.h"
2214cf0368Sopenharmony_ci#include "utd_cfgs_checker.h"
2314cf0368Sopenharmony_ci#include "utd_graph.h"
2414cf0368Sopenharmony_ci#ifdef WITH_SELINUX
2514cf0368Sopenharmony_ci#include <policycoreutils.h>
2614cf0368Sopenharmony_ci#endif
2714cf0368Sopenharmony_cinamespace OHOS {
2814cf0368Sopenharmony_cinamespace UDMF {
2914cf0368Sopenharmony_ciconstexpr const char* UTD_CFG_FILE = "utd-adt.json";
3014cf0368Sopenharmony_ciconstexpr const char* CUSTOM_UTD_HAP_DIR = "/data/utd/utd-adt.json";
3114cf0368Sopenharmony_ciconstexpr const char* CUSTOM_UTD_SA_DIR = "/data/service/el1/";
3214cf0368Sopenharmony_ciconstexpr const char* OLD_CUSTOM_UTD_SA_SUB_DIR = "/distributeddata/utd/";
3314cf0368Sopenharmony_ciconstexpr const char* CUSTOM_UTD_SA_SUB_DIR = "/utdtypes/utd/";
3414cf0368Sopenharmony_ci
3514cf0368Sopenharmony_ciCustomUtdStore::CustomUtdStore()
3614cf0368Sopenharmony_ci{
3714cf0368Sopenharmony_ci}
3814cf0368Sopenharmony_ci
3914cf0368Sopenharmony_ciCustomUtdStore::~CustomUtdStore()
4014cf0368Sopenharmony_ci{
4114cf0368Sopenharmony_ci}
4214cf0368Sopenharmony_ci
4314cf0368Sopenharmony_ciCustomUtdStore &CustomUtdStore::GetInstance()
4414cf0368Sopenharmony_ci{
4514cf0368Sopenharmony_ci    static CustomUtdStore utdCustomPersistence;
4614cf0368Sopenharmony_ci    return utdCustomPersistence;
4714cf0368Sopenharmony_ci}
4814cf0368Sopenharmony_ci
4914cf0368Sopenharmony_cistd::vector<TypeDescriptorCfg> CustomUtdStore::GetHapTypeCfgs()
5014cf0368Sopenharmony_ci{
5114cf0368Sopenharmony_ci    LOG_DEBUG(UDMF_CLIENT, "get utdcustom from cfg, Path:%{public}s.", CUSTOM_UTD_HAP_DIR);
5214cf0368Sopenharmony_ci    std::string jsonStr;
5314cf0368Sopenharmony_ci    std::ifstream fin(CUSTOM_UTD_HAP_DIR);
5414cf0368Sopenharmony_ci    while (fin.good()) {
5514cf0368Sopenharmony_ci        std::string line;
5614cf0368Sopenharmony_ci        std::getline(fin, line);
5714cf0368Sopenharmony_ci        jsonStr += line;
5814cf0368Sopenharmony_ci    }
5914cf0368Sopenharmony_ci    std::vector<TypeDescriptorCfg> customUtdTypes;
6014cf0368Sopenharmony_ci    utdJsonParser_.ParseStoredCustomUtdJson(jsonStr, customUtdTypes);
6114cf0368Sopenharmony_ci    LOG_DEBUG(UDMF_CLIENT, "GetTypeCfgs, customUtdTypes total:%{public}zu.", customUtdTypes.size());
6214cf0368Sopenharmony_ci    return customUtdTypes;
6314cf0368Sopenharmony_ci}
6414cf0368Sopenharmony_ci
6514cf0368Sopenharmony_cistd::vector<TypeDescriptorCfg> CustomUtdStore::GetTypeCfgs(int32_t userId)
6614cf0368Sopenharmony_ci{
6714cf0368Sopenharmony_ci    std::string path = CUSTOM_UTD_SA_DIR + std::to_string(userId) + CUSTOM_UTD_SA_SUB_DIR;
6814cf0368Sopenharmony_ci    std::string old_path = CUSTOM_UTD_SA_DIR + std::to_string(userId) + OLD_CUSTOM_UTD_SA_SUB_DIR;
6914cf0368Sopenharmony_ci    std::string cfgFilePath = path;
7014cf0368Sopenharmony_ci    if (access(path.c_str(), F_OK) != 0 && access(old_path.c_str(), F_OK) == 0) {
7114cf0368Sopenharmony_ci        cfgFilePath = old_path;
7214cf0368Sopenharmony_ci    }
7314cf0368Sopenharmony_ci    cfgFilePath.append(UTD_CFG_FILE);
7414cf0368Sopenharmony_ci    LOG_DEBUG(UDMF_CLIENT, "get utdcustom from cfg, Path:%{public}s.", cfgFilePath.c_str());
7514cf0368Sopenharmony_ci    std::string jsonStr;
7614cf0368Sopenharmony_ci    std::ifstream fin(cfgFilePath);
7714cf0368Sopenharmony_ci    while (fin.good()) {
7814cf0368Sopenharmony_ci        std::string line;
7914cf0368Sopenharmony_ci        std::getline(fin, line);
8014cf0368Sopenharmony_ci        jsonStr += line;
8114cf0368Sopenharmony_ci    }
8214cf0368Sopenharmony_ci    std::vector<TypeDescriptorCfg> customUtdTypes;
8314cf0368Sopenharmony_ci    utdJsonParser_.ParseStoredCustomUtdJson(jsonStr, customUtdTypes);
8414cf0368Sopenharmony_ci    LOG_DEBUG(UDMF_CLIENT, "GetTypeCfgs, customUtdTypes total:%{public}zu.", customUtdTypes.size());
8514cf0368Sopenharmony_ci    return customUtdTypes;
8614cf0368Sopenharmony_ci}
8714cf0368Sopenharmony_ci
8814cf0368Sopenharmony_ciint32_t CustomUtdStore::SaveTypeCfgs(const std::vector<TypeDescriptorCfg> &customUtdTypes, int32_t user)
8914cf0368Sopenharmony_ci{
9014cf0368Sopenharmony_ci    LOG_DEBUG(UDMF_CLIENT, "customUtdTypes total:%{public}zu.", customUtdTypes.size());
9114cf0368Sopenharmony_ci    std::string jsonData;
9214cf0368Sopenharmony_ci    std::string cfgFileDir = CUSTOM_UTD_SA_DIR + std::to_string(user) + CUSTOM_UTD_SA_SUB_DIR;
9314cf0368Sopenharmony_ci    if (utdJsonParser_.ConvertUtdCfgsToJson(customUtdTypes, jsonData) && CreateDirectory(cfgFileDir)) {
9414cf0368Sopenharmony_ci        SavaCfgFile(jsonData, cfgFileDir.append(UTD_CFG_FILE));
9514cf0368Sopenharmony_ci    }
9614cf0368Sopenharmony_ci    return 0;
9714cf0368Sopenharmony_ci}
9814cf0368Sopenharmony_ci
9914cf0368Sopenharmony_ciint32_t CustomUtdStore::SavaCfgFile(const std::string &jsonData, const std::string &cfgFilePath)
10014cf0368Sopenharmony_ci{
10114cf0368Sopenharmony_ci    std::ofstream ofs;
10214cf0368Sopenharmony_ci    LOG_DEBUG(UDMF_CLIENT, "set cfg start, path:%{public}s ", cfgFilePath.c_str());
10314cf0368Sopenharmony_ci    ofs.open(cfgFilePath, 0x02);
10414cf0368Sopenharmony_ci    if (!ofs.is_open()) {
10514cf0368Sopenharmony_ci        LOG_ERROR(UDMF_CLIENT, "open cfg failed, path:%{public}s", cfgFilePath.c_str());
10614cf0368Sopenharmony_ci    }
10714cf0368Sopenharmony_ci    ofs << jsonData << std::endl;
10814cf0368Sopenharmony_ci    ofs.close();
10914cf0368Sopenharmony_ci    LOG_DEBUG(UDMF_CLIENT, "set cfg end.");
11014cf0368Sopenharmony_ci    return 0;
11114cf0368Sopenharmony_ci}
11214cf0368Sopenharmony_ci
11314cf0368Sopenharmony_cibool CustomUtdStore::CreateDirectory(const std::string &path) const
11414cf0368Sopenharmony_ci{
11514cf0368Sopenharmony_ci    LOG_DEBUG(UDMF_CLIENT, "CreateDirectory start, path:%{public}s ", path.c_str());
11614cf0368Sopenharmony_ci    if (access(path.c_str(), F_OK) == 0) {
11714cf0368Sopenharmony_ci        return true;
11814cf0368Sopenharmony_ci    }
11914cf0368Sopenharmony_ci
12014cf0368Sopenharmony_ci    std::string::size_type index = 0;
12114cf0368Sopenharmony_ci    do {
12214cf0368Sopenharmony_ci        std::string subPath;
12314cf0368Sopenharmony_ci        index = path.find('/', index + 1);
12414cf0368Sopenharmony_ci        if (index == std::string::npos) {
12514cf0368Sopenharmony_ci            subPath = path;
12614cf0368Sopenharmony_ci        } else {
12714cf0368Sopenharmony_ci            subPath = path.substr(0, index);
12814cf0368Sopenharmony_ci        }
12914cf0368Sopenharmony_ci
13014cf0368Sopenharmony_ci        if (access(subPath.c_str(), F_OK) != 0) {
13114cf0368Sopenharmony_ci            if (mkdir(subPath.c_str(), (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)) != 0) {
13214cf0368Sopenharmony_ci                LOG_WARN(UDMF_CLIENT, "CreateDirectory, fail. path:%{public}s, subPath:%{public}s.",
13314cf0368Sopenharmony_ci                         path.c_str(), subPath.c_str());
13414cf0368Sopenharmony_ci                return false;
13514cf0368Sopenharmony_ci            }
13614cf0368Sopenharmony_ci        }
13714cf0368Sopenharmony_ci    } while (index != std::string::npos);
13814cf0368Sopenharmony_ci
13914cf0368Sopenharmony_ci    if (access(path.c_str(), F_OK) == 0) {
14014cf0368Sopenharmony_ci#ifdef WITH_SELINUX
14114cf0368Sopenharmony_ci        Restorecon(path.c_str());
14214cf0368Sopenharmony_ci#endif
14314cf0368Sopenharmony_ci        return true;
14414cf0368Sopenharmony_ci    }
14514cf0368Sopenharmony_ci
14614cf0368Sopenharmony_ci    return false;
14714cf0368Sopenharmony_ci}
14814cf0368Sopenharmony_ci
14914cf0368Sopenharmony_cibool CustomUtdStore::InstallCustomUtds(const std::string &bundleName, const std::string &jsonStr,
15014cf0368Sopenharmony_ci    int32_t user, std::vector<TypeDescriptorCfg> &customTyepCfgs)
15114cf0368Sopenharmony_ci{
15214cf0368Sopenharmony_ci    CustomUtdCfgs typeCfgs;
15314cf0368Sopenharmony_ci    if (!utdJsonParser_.ParseUserCustomUtdJson(jsonStr, typeCfgs.first, typeCfgs.second)) {
15414cf0368Sopenharmony_ci        LOG_ERROR(UDMF_CLIENT, "Parse json failed. bundleName:%{public}s", bundleName.c_str());
15514cf0368Sopenharmony_ci        return false;
15614cf0368Sopenharmony_ci    }
15714cf0368Sopenharmony_ci    std::vector<TypeDescriptorCfg> presetTypes = PresetTypeDescriptors::GetInstance().GetPresetTypes();
15814cf0368Sopenharmony_ci
15914cf0368Sopenharmony_ci    if (!UtdCfgsChecker::GetInstance().CheckTypeDescriptors(
16014cf0368Sopenharmony_ci        typeCfgs, presetTypes, customTyepCfgs, bundleName)) {
16114cf0368Sopenharmony_ci        LOG_ERROR(UDMF_CLIENT, "check type descriptors failed, bundleName:%{public}s", bundleName.c_str());
16214cf0368Sopenharmony_ci        return false;
16314cf0368Sopenharmony_ci    }
16414cf0368Sopenharmony_ci
16514cf0368Sopenharmony_ci    ProcessUtdForSave(typeCfgs, customTyepCfgs, bundleName);
16614cf0368Sopenharmony_ci    if (CustomUtdStore::GetInstance().SaveTypeCfgs(customTyepCfgs, user) != E_OK) {
16714cf0368Sopenharmony_ci        LOG_ERROR(UDMF_CLIENT, "Save failed, bundleName: %{public}s", bundleName.c_str());
16814cf0368Sopenharmony_ci        return false;
16914cf0368Sopenharmony_ci    }
17014cf0368Sopenharmony_ci    return true;
17114cf0368Sopenharmony_ci}
17214cf0368Sopenharmony_ci
17314cf0368Sopenharmony_cibool CustomUtdStore::UninstallCustomUtds(const std::string &bundleName, int32_t user,
17414cf0368Sopenharmony_ci    std::vector<TypeDescriptorCfg> &customTyepCfgs)
17514cf0368Sopenharmony_ci{
17614cf0368Sopenharmony_ci    for (auto iter = customTyepCfgs.begin(); iter != customTyepCfgs.end();) {
17714cf0368Sopenharmony_ci        auto it = find(iter->installerBundles.begin(), iter->installerBundles.end(), bundleName);
17814cf0368Sopenharmony_ci        if (it != iter->installerBundles.end()) {
17914cf0368Sopenharmony_ci            iter->installerBundles.erase(it);
18014cf0368Sopenharmony_ci        }
18114cf0368Sopenharmony_ci        if (iter->installerBundles.empty()) {
18214cf0368Sopenharmony_ci            iter = customTyepCfgs.erase(iter);
18314cf0368Sopenharmony_ci        } else {
18414cf0368Sopenharmony_ci            iter++;
18514cf0368Sopenharmony_ci        }
18614cf0368Sopenharmony_ci    }
18714cf0368Sopenharmony_ci    std::vector<TypeDescriptorCfg> presetTypes = PresetTypeDescriptors::GetInstance().GetPresetTypes();
18814cf0368Sopenharmony_ci    if (!UtdCfgsChecker::GetInstance().CheckBelongingToTypes(customTyepCfgs, presetTypes)) {
18914cf0368Sopenharmony_ci        LOG_ERROR(UDMF_CLIENT, "belongingToTypes check failed. bundleName:%{public}s", bundleName.c_str());
19014cf0368Sopenharmony_ci        return false;
19114cf0368Sopenharmony_ci    }
19214cf0368Sopenharmony_ci    if (CustomUtdStore::GetInstance().SaveTypeCfgs(customTyepCfgs, user) != E_OK) {
19314cf0368Sopenharmony_ci        LOG_ERROR(UDMF_CLIENT, "Save type cfgs failed, bundleName: %{public}s", bundleName.c_str());
19414cf0368Sopenharmony_ci        return false;
19514cf0368Sopenharmony_ci    }
19614cf0368Sopenharmony_ci    return true;
19714cf0368Sopenharmony_ci}
19814cf0368Sopenharmony_ci
19914cf0368Sopenharmony_civoid CustomUtdStore::ProcessUtdForSave(const CustomUtdCfgs &utdTypes, std::vector<TypeDescriptorCfg> &customTyepCfgs,
20014cf0368Sopenharmony_ci    const std::string &bundleName)
20114cf0368Sopenharmony_ci{
20214cf0368Sopenharmony_ci    for (TypeDescriptorCfg declarationType : utdTypes.first) {
20314cf0368Sopenharmony_ci        for (auto iter = customTyepCfgs.begin(); iter != customTyepCfgs.end();) {
20414cf0368Sopenharmony_ci            if (iter->typeId == declarationType.typeId) {
20514cf0368Sopenharmony_ci                declarationType.installerBundles = iter->installerBundles;
20614cf0368Sopenharmony_ci                iter = customTyepCfgs.erase(iter);
20714cf0368Sopenharmony_ci            } else {
20814cf0368Sopenharmony_ci                iter++;
20914cf0368Sopenharmony_ci            }
21014cf0368Sopenharmony_ci        }
21114cf0368Sopenharmony_ci        declarationType.installerBundles.emplace(bundleName);
21214cf0368Sopenharmony_ci        declarationType.ownerBundle = bundleName;
21314cf0368Sopenharmony_ci        customTyepCfgs.push_back(declarationType);
21414cf0368Sopenharmony_ci    }
21514cf0368Sopenharmony_ci    for (TypeDescriptorCfg referenceType : utdTypes.second) {
21614cf0368Sopenharmony_ci        bool found = false;
21714cf0368Sopenharmony_ci        for (auto &typeCfg : customTyepCfgs) {
21814cf0368Sopenharmony_ci            if (typeCfg.typeId == referenceType.typeId) {
21914cf0368Sopenharmony_ci                typeCfg.installerBundles.emplace(bundleName);
22014cf0368Sopenharmony_ci                found = true;
22114cf0368Sopenharmony_ci                break;
22214cf0368Sopenharmony_ci            }
22314cf0368Sopenharmony_ci        }
22414cf0368Sopenharmony_ci        if (!found) {
22514cf0368Sopenharmony_ci            referenceType.installerBundles.emplace(bundleName);
22614cf0368Sopenharmony_ci            customTyepCfgs.push_back(referenceType);
22714cf0368Sopenharmony_ci        }
22814cf0368Sopenharmony_ci    }
22914cf0368Sopenharmony_ci}
23014cf0368Sopenharmony_ci} // namespace UDMF
23114cf0368Sopenharmony_ci} // namespace OHOS