1 /*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "hiview_config_util.h"
17
18 #include <algorithm>
19
20 #include "file_util.h"
21 #include "hiview_logger.h"
22 #include "hiview_zip_util.h"
23
24 namespace OHOS {
25 namespace HiviewDFX {
26 namespace HiViewConfigUtil {
27 namespace {
28 DEFINE_LOG_TAG("HiViewConfigUtil");
29 constexpr char CFG_VERSION_FILE_NAME[] = "hiview_config_version";
30 constexpr char LOCAL_CFG_PATH[] = "/system/etc/hiview/";
31 constexpr char CLOUD_CFG_PATH[] = "/data/system/hiview/";
32 constexpr char LOCAL_CFG_UNZIP_DIR[] = "unzip_configs/";
33
GetConfigFilePath(const std::string & configFileName,bool isLocal)34 inline std::string GetConfigFilePath(const std::string& configFileName, bool isLocal)
35 {
36 if (isLocal) {
37 return LOCAL_CFG_PATH + configFileName;
38 }
39 return CLOUD_CFG_PATH + configFileName;
40 }
41
GetConfigFilePathByVersion(const std::string & localVer,const std::string & cloudVer,const std::string & configFileName)42 inline std::string GetConfigFilePathByVersion(const std::string& localVer, const std::string& cloudVer,
43 const std::string& configFileName)
44 {
45 std::string cloudConfigFilePath = GetConfigFilePath(configFileName, false);
46 if ((cloudVer > localVer) && FileUtil::FileExists(cloudConfigFilePath)) {
47 return cloudConfigFilePath;
48 }
49 return GetConfigFilePath(configFileName, true);
50 }
51
GetConfigVersion(bool isLocal)52 inline std::string GetConfigVersion(bool isLocal)
53 {
54 std::string versionFile = GetConfigFilePath(CFG_VERSION_FILE_NAME, isLocal);
55 std::string version;
56 (void)FileUtil::LoadStringFromFile(versionFile, version);
57 return version;
58 }
59
CopyConfigVersionFile(const std::string & destConfigDir,bool isLocal)60 bool CopyConfigVersionFile(const std::string& destConfigDir, bool isLocal)
61 {
62 if (!FileUtil::FileExists(destConfigDir) && !FileUtil::ForceCreateDirectory(destConfigDir)) {
63 HIVIEW_LOGE("%{public}s isn't exist and failed to create it", destConfigDir.c_str());
64 return false;
65 }
66 std::string originVersionFile = GetConfigFilePath(CFG_VERSION_FILE_NAME, isLocal);
67 std::string destVersionFile = destConfigDir + CFG_VERSION_FILE_NAME;
68 if (FileUtil::CopyFile(originVersionFile, destVersionFile) != 0) {
69 HIVIEW_LOGE("failed to copy %{public}s to %{public}s", originVersionFile.c_str(), destVersionFile.c_str());
70 return false;
71 }
72 return true;
73 }
74
GetUnZipConfigDir()75 inline std::string GetUnZipConfigDir()
76 {
77 return std::string(CLOUD_CFG_PATH) + LOCAL_CFG_UNZIP_DIR;
78 }
79
UnZipConfigFile(const std::string & srcDir,const std::string & zipFileName,const std::string & destDir,const std::string & configFileName)80 bool UnZipConfigFile(const std::string& srcDir, const std::string& zipFileName, const std::string& destDir,
81 const std::string& configFileName)
82 {
83 if (!FileUtil::FileExists(destDir) && !FileUtil::ForceCreateDirectory(destDir)) {
84 HIVIEW_LOGE("%{public}s isn't exist and failed to create it", destDir.c_str());
85 return false;
86 }
87 std::string zipConfigFile = srcDir + zipFileName;
88 if (!FileUtil::FileExists(zipConfigFile)) {
89 HIVIEW_LOGW("%{public}s isn't exist", zipConfigFile.c_str());
90 std::string srcFile = srcDir + configFileName;
91 std::string destFile = destDir + configFileName;
92 if (FileUtil::CopyFile(srcFile, destFile) != 0) {
93 HIVIEW_LOGE("failed to copy %{public}s to %{public}s", srcFile.c_str(), destFile.c_str());
94 return false;
95 }
96 return true;
97 }
98 HiviewUnzipUnit unzipUnit(zipConfigFile, destDir);
99 if (!unzipUnit.UnzipFile()) {
100 HIVIEW_LOGE("failed to unzip %{public}s to %{public}s", zipConfigFile.c_str(), destDir.c_str());
101 return false;
102 }
103 return true;
104 }
105 }
106
GetConfigFilePath(const std::string & configFileName)107 std::string GetConfigFilePath(const std::string& configFileName)
108 {
109 std::string localVer = GetConfigVersion(true);
110 std::string cloudVer = GetConfigVersion(false);
111 return GetConfigFilePathByVersion(localVer, cloudVer, configFileName);
112 }
113
GetConfigFilePath(const std::string & configZipFileName,const std::string & configDir,const std::string & configFileName)114 std::string GetConfigFilePath(const std::string& configZipFileName, const std::string& configDir,
115 const std::string& configFileName)
116 {
117 std::string destConfigDir = FileUtil::IncludeTrailingPathDelimiter(GetUnZipConfigDir() + configDir);
118 std::string destVer;
119 (void)FileUtil::LoadStringFromFile(destConfigDir + CFG_VERSION_FILE_NAME, destVer);
120
121 std::string localVer = GetConfigVersion(true);
122 std::string cloudVer = GetConfigVersion(false);
123 std::string destConfigFilePath = destConfigDir + configFileName;
124 HIVIEW_LOGI("versions:[%{public}s|%{public}s|%{public}s]", localVer.c_str(), cloudVer.c_str(), destVer.c_str());
125 // if dest version is newest, return dest config file path directly
126 if (!destVer.empty() && destVer >= std::max(cloudVer, localVer) && FileUtil::FileExists(destConfigFilePath)) {
127 return destConfigFilePath;
128 }
129 // do cloud update if cloud version is newer than local version
130 if ((cloudVer > localVer) &&
131 UnZipConfigFile(CLOUD_CFG_PATH, configZipFileName, destConfigDir, configFileName) &&
132 CopyConfigVersionFile(destConfigDir, false)) {
133 HIVIEW_LOGI("succeed to do cloud update for %{public}s", configFileName.c_str());
134 return destConfigFilePath;
135 }
136 // do local update if local version is newer than cloud version or cloud update is failed
137 if (UnZipConfigFile(LOCAL_CFG_PATH, configZipFileName, destConfigDir, configFileName) &&
138 CopyConfigVersionFile(destConfigDir, true)) {
139 HIVIEW_LOGI("succeed to do local update for %{public}s", configFileName.c_str());
140 return destConfigFilePath;
141 }
142 // return file path directly if dest config file exist
143 if (FileUtil::FileExists(destConfigFilePath)) {
144 return destConfigFilePath;
145 }
146 return GetConfigFilePathByVersion(localVer, cloudVer, configFileName);
147 }
148 } // namespace ConfigUtil
149 } // namespace HiviewDFX
150 } // namespace OHOS
151