1 /*
2 * Copyright (c) 2023 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 "module_file_repository.h"
17
18 #include <sys/types.h>
19 #include <sys/stat.h>
20 #include <fcntl.h>
21
22 #include "directory_ex.h"
23 #include "log/log.h"
24 #include "module_constants.h"
25 #include "module_error_code.h"
26 #include "scope_guard.h"
27 #include "unique_fd.h"
28
29 namespace OHOS {
30 namespace SysInstaller {
31 using namespace Updater;
32 using std::string;
33
~ModuleFileRepository()34 ModuleFileRepository::~ModuleFileRepository()
35 {
36 Clear();
37 }
38
InitRepository(const string & hmpName,const Timer & timer)39 void ModuleFileRepository::InitRepository(const string &hmpName, const Timer &timer)
40 {
41 string allPath[] = {MODULE_PREINSTALL_DIR, UPDATE_INSTALL_DIR, UPDATE_ACTIVE_DIR};
42 auto& fileMap = moduleFileMap_[hmpName];
43 for (string &path : allPath) {
44 std::vector<string> files;
45 const string checkDir = path + "/" + hmpName;
46 GetDirFiles(checkDir, files);
47 for (string &file : files) {
48 if (!CheckFileSuffix(file, MODULE_PACKAGE_SUFFIX)) {
49 continue;
50 }
51 // verifi zip before open it.
52 if (path != MODULE_PREINSTALL_DIR && VerifyModulePackageSign(file) != 0) {
53 LOG(ERROR) << "VerifyModulePackageSign failed of " << file;
54 SaveInstallerResult(path, hmpName, ModuleErrorCode::ERR_VERIFY_FAIL, "verify fail", timer);
55 continue;
56 }
57 ProcessFile(hmpName, path, file, fileMap, timer);
58 }
59 }
60 LOG(INFO) << "InitRepository all timer:" << timer;
61 }
62
SaveInstallerResult(const std::string & fpInfo,const std::string & hmpName,int result,const std::string & resultInfo,const Timer & timer) const63 void ModuleFileRepository::SaveInstallerResult(const std::string &fpInfo, const std::string &hmpName,
64 int result, const std::string &resultInfo, const Timer &timer) const
65 {
66 if (fpInfo.find(UPDATE_INSTALL_DIR) == std::string::npos &&
67 fpInfo.find(UPDATE_ACTIVE_DIR) == std::string::npos) {
68 return;
69 }
70 if (!CheckFileSuffix(fpInfo, MODULE_PACKAGE_SUFFIX) &&
71 !CheckFileSuffix(fpInfo, MODULE_IMAGE_SUFFIX)) {
72 LOG(WARNING) << "SaveInstallerResult path:" << fpInfo << "; break;";
73 return;
74 }
75 if (!CheckPathExists(MODULE_RESULT_PATH)) {
76 LOG(ERROR) << MODULE_RESULT_PATH << " not exist";
77 return;
78 }
79 LOG(INFO) << "path:" << fpInfo << "hmp:" << hmpName << "result:" << result << "Info:" << resultInfo << "\n";
80
81 UniqueFd fd(open(MODULE_RESULT_PATH, O_APPEND | O_RDWR | O_CLOEXEC));
82 if (fd.Get() == -1) {
83 LOG(ERROR) << "Failed to open file";
84 return;
85 }
86
87 std::string writeInfo = hmpName + ";" + std::to_string(result) + ";" +
88 resultInfo + "|" + std::to_string(timer.duration().count()) + "\n";
89 if (CheckAndUpdateRevertResult(hmpName, writeInfo, "mount fail")) {
90 return;
91 }
92 if (write(fd, writeInfo.data(), writeInfo.length()) <= 0) {
93 LOG(WARNING) << "write result file failed, err:" << errno;
94 }
95 fsync(fd.Get());
96 }
97
ProcessFile(const string & hmpName,const string & path,const string & file,std::unordered_map<std::string,ModuleFile> & fileMap,const Timer & timer) const98 void ModuleFileRepository::ProcessFile(const string &hmpName, const string &path, const string &file,
99 std::unordered_map<std::string, ModuleFile> &fileMap, const Timer &timer) const
100 {
101 std::unique_ptr<ModuleFile> moduleFile = ModuleFile::Open(file);
102 if (moduleFile == nullptr || moduleFile->GetVersionInfo().hmpName != hmpName) {
103 return;
104 }
105 if (!moduleFile->GetImageStat().has_value()) {
106 LOG(ERROR) << "verify failed, img is empty: " << file;
107 SaveInstallerResult(path, hmpName, ModuleErrorCode::ERR_VERIFY_FAIL, "img empty", timer);
108 return;
109 }
110 if (path != MODULE_PREINSTALL_DIR) {
111 if (!CheckFilePath(*moduleFile, path)) {
112 LOG(ERROR) << "Open " << file << " failed";
113 SaveInstallerResult(path, hmpName, ModuleErrorCode::ERR_VERIFY_FAIL, "get pub key fail", timer);
114 return;
115 }
116 }
117 LOG(INFO) << "ProcessFile " << file << " successful";
118 fileMap.insert(std::make_pair(path, std::move(*moduleFile)));
119 }
120
GetModuleFile(const std::string & pathPrefix,const string & hmpName) const121 std::unique_ptr<ModuleFile> ModuleFileRepository::GetModuleFile(const std::string &pathPrefix,
122 const string &hmpName) const
123 {
124 auto mapIter = moduleFileMap_.find(hmpName);
125 if (mapIter == moduleFileMap_.end()) {
126 LOG(ERROR) << "Invalid path hmpName= " << hmpName;
127 return nullptr;
128 }
129 std::unordered_map<std::string, ModuleFile> fileMap = mapIter->second;
130 auto fileIter = fileMap.find(pathPrefix);
131 if (fileIter == fileMap.end()) {
132 LOG(INFO) << hmpName << " not found in " << pathPrefix;
133 return nullptr;
134 }
135 ModuleFile file = fileIter->second;
136 return std::make_unique<ModuleFile>(std::move(file));
137 }
138
IsPreInstalledModule(const ModuleFile & moduleFile) const139 bool ModuleFileRepository::IsPreInstalledModule(const ModuleFile &moduleFile) const
140 {
141 std::unique_ptr<ModuleFile> preInstalledModule = GetModuleFile(MODULE_PREINSTALL_DIR,
142 moduleFile.GetVersionInfo().hmpName);
143 if (preInstalledModule == nullptr) {
144 return false;
145 }
146 return preInstalledModule->GetPath() == moduleFile.GetPath();
147 }
148
CheckFilePath(const ModuleFile & moduleFile,const string & prefix) const149 bool ModuleFileRepository::CheckFilePath(const ModuleFile &moduleFile, const string &prefix) const
150 {
151 std::unique_ptr<ModuleFile> preInstalledModule = GetModuleFile(MODULE_PREINSTALL_DIR,
152 moduleFile.GetVersionInfo().hmpName);
153 if (preInstalledModule == nullptr) {
154 return false;
155 }
156 string prePath = preInstalledModule->GetPath();
157 string curPath = moduleFile.GetPath();
158 return prePath.substr(strlen(MODULE_PREINSTALL_DIR), prePath.length()) ==
159 curPath.substr(prefix.length(), curPath.length());
160 }
161
Clear()162 void ModuleFileRepository::Clear()
163 {
164 for (auto mapIter = moduleFileMap_.begin(); mapIter != moduleFileMap_.end(); ++mapIter) {
165 std::unordered_map<std::string, ModuleFile> &fileMap = mapIter->second;
166 for (auto fileIter = fileMap.begin(); fileIter != fileMap.end(); ++fileIter) {
167 fileIter->second.ClearVerifiedData();
168 }
169 fileMap.clear();
170 }
171 moduleFileMap_.clear();
172 }
173
GetModuleMap(void)174 const std::unordered_map<string, std::unordered_map<string, ModuleFile>> &ModuleFileRepository::GetModuleMap(void)
175 {
176 return moduleFileMap_;
177 }
178 } // SysInstaller
179 } // namespace OHOS
180