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 "driver_installer.h"
17
18 #include "base_bundle_installer.h"
19 #include "installd_client.h"
20
21 namespace OHOS {
22 namespace AppExecFwk {
23 namespace {
24 const std::vector<std::string> DRIVER_PROPERTIES {
25 "cupsFilter", "cupsBackend", "cupsPpd", "saneConfig", "saneBackend"
26 };
27 const std::string TEMP_PREFIX = "temp_";
28 } // namespace
29
CopyAllDriverFile(const std::unordered_map<std::string,InnerBundleInfo> & newInfos,const InnerBundleInfo & oldInfo) const30 ErrCode DriverInstaller::CopyAllDriverFile(const std::unordered_map<std::string, InnerBundleInfo> &newInfos,
31 const InnerBundleInfo &oldInfo) const
32 {
33 ErrCode result = ERR_OK;
34 for (const auto &info : newInfos) {
35 bool isModuleExisted = oldInfo.FindModule(info.second.GetCurrentModulePackage());
36 result = CopyDriverSoFile(info.second, info.first, isModuleExisted);
37 CHECK_RESULT(result, "copy all driver files failed due to error %{public}d");
38 }
39
40 RemoveAndReNameDriverFile(newInfos, oldInfo);
41 return result;
42 }
43
CopyDriverSoFile(const InnerBundleInfo & info,const std::string & srcPath,bool isModuleExisted) const44 ErrCode DriverInstaller::CopyDriverSoFile(const InnerBundleInfo &info, const std::string &srcPath,
45 bool isModuleExisted) const
46 {
47 APP_LOGD("begin");
48 auto extensionAbilityInfos = info.GetInnerExtensionInfos();
49 // key is the orignial dir in hap of driver so file
50 // value is the destination dir of driver so file
51 std::unordered_multimap<std::string, std::string> dirMap;
52 // 1. filter driver so files
53 ErrCode result = ERR_OK;
54 for (const auto &extAbilityInfo : extensionAbilityInfos) {
55 if (extAbilityInfo.second.type != ExtensionAbilityType::DRIVER) {
56 continue;
57 }
58
59 auto &metadata = extAbilityInfo.second.metadata;
60 auto filterFunc = [this, &result, &info, &dirMap, &isModuleExisted](const Metadata &meta) {
61 result = FilterDriverSoFile(info, meta, dirMap, isModuleExisted);
62 return result != ERR_OK;
63 };
64 std::any_of(metadata.begin(), metadata.end(), filterFunc);
65 CHECK_RESULT(result, "driver so path is invalid, error is %{public}d");
66 }
67 if (dirMap.empty()) {
68 APP_LOGD("no driver so file needs to be cpoied");
69 return ERR_OK;
70 }
71 // 2. copy driver so file to destined dir
72 return InstalldClient::GetInstance()->ExtractDriverSoFiles(srcPath, dirMap);
73 }
74
FilterDriverSoFile(const InnerBundleInfo & info,const Metadata & meta,std::unordered_multimap<std::string,std::string> & dirMap,bool isModuleExisted) const75 ErrCode DriverInstaller::FilterDriverSoFile(const InnerBundleInfo &info, const Metadata &meta,
76 std::unordered_multimap<std::string, std::string> &dirMap, bool isModuleExisted) const
77 {
78 APP_LOGD("begin");
79 // find driver metadata name in driver properties
80 if (std::find(DRIVER_PROPERTIES.cbegin(), DRIVER_PROPERTIES.cend(), meta.name) ==
81 DRIVER_PROPERTIES.cend()) {
82 APP_LOGD("metadata name %{public}s is not existed in driver properties", meta.name.c_str());
83 return ERR_OK;
84 }
85
86 // check dir and obtain name of the file which needs to be copied
87 std::string originalDir = meta.resource;
88 std::string destinedDir = meta.value;
89 if (originalDir.find(ServiceConstants::RELATIVE_PATH) != std::string::npos ||
90 destinedDir.find(ServiceConstants::RELATIVE_PATH) != std::string::npos) {
91 APP_LOGW("metadata value %{public}s, resource %{public}s cannot support path",
92 destinedDir.c_str(), originalDir.c_str());
93 return ERR_APPEXECFWK_INSTALL_FILE_PATH_INVALID;
94 }
95
96 // create destined dir of driver files
97 std::vector<std::string> originalDirVec;
98 SplitStr(originalDir, ServiceConstants::PATH_SEPARATOR, originalDirVec, false, false);
99 if (originalDirVec.empty()) {
100 APP_LOGW("original dir is invalid");
101 return ERR_APPEXECFWK_INSTALL_FILE_PATH_INVALID;
102 }
103 auto fileName = originalDirVec.back();
104 APP_LOGD("fileName is %{public}s", fileName.c_str());
105 const auto &moduleName = info.GetModuleName(info.GetCurrentModulePackage());
106 destinedDir = CreateDriverSoDestinedDir(info.GetBundleName(), moduleName, fileName, destinedDir, isModuleExisted);
107 APP_LOGD("metadata destined dir is %{public}s", destinedDir.c_str());
108 dirMap.emplace(originalDir, destinedDir);
109 return ERR_OK;
110 }
111
RemoveAndReNameDriverFile(const std::unordered_map<std::string,InnerBundleInfo> & newInfos,const InnerBundleInfo & oldInfo) const112 void DriverInstaller::RemoveAndReNameDriverFile(const std::unordered_map<std::string, InnerBundleInfo> &newInfos,
113 const InnerBundleInfo &oldInfo) const
114 {
115 for (const auto &info : newInfos) {
116 std::string packageName = info.second.GetCurrentModulePackage();
117 if (!oldInfo.FindModule(packageName)) {
118 continue;
119 }
120 RemoveDriverSoFile(oldInfo, info.second.GetModuleName(packageName), false);
121 RenameDriverFile(info.second);
122 }
123 }
124
RemoveDriverSoFile(const InnerBundleInfo & info,const std::string & moduleName,bool isModuleExisted) const125 void DriverInstaller::RemoveDriverSoFile(const InnerBundleInfo &info, const std::string &moduleName,
126 bool isModuleExisted) const
127 {
128 APP_LOGD("begin");
129 auto extensionAbilityInfos = info.GetInnerExtensionInfos();
130 for (const auto &extAbilityInfo : extensionAbilityInfos) {
131 // find module name from the extAbilityInfo
132 std::string extModuleName = extAbilityInfo.second.moduleName;
133 APP_LOGD("extModuleName is %{public}s", extModuleName.c_str());
134 if ((!moduleName.empty() && moduleName.compare(extModuleName) != 0) ||
135 (extAbilityInfo.second.type != ExtensionAbilityType::DRIVER)) {
136 APP_LOGD("no driver extension(%{public}d) or moduleName(%{public}s) is not matched",
137 static_cast<int32_t>(extAbilityInfo.second.type), moduleName.c_str());
138 continue;
139 }
140 const auto &metadata = extAbilityInfo.second.metadata;
141 for (const auto &meta : metadata) {
142 if (std::find(DRIVER_PROPERTIES.cbegin(), DRIVER_PROPERTIES.cend(), meta.name) ==
143 DRIVER_PROPERTIES.cend()) {
144 APP_LOGD("metadata name %{public}s is not existed in driver properties", meta.name.c_str());
145 continue;
146 }
147 std::vector<std::string> originalDirVec;
148 SplitStr(meta.resource, ServiceConstants::PATH_SEPARATOR, originalDirVec, false, false);
149 if (originalDirVec.empty()) {
150 APP_LOGW("invalid metadata resource %{public}s", meta.resource.c_str());
151 return;
152 }
153 auto fileName = originalDirVec.back();
154 APP_LOGD("fileName is %{public}s", fileName.c_str());
155 std::string destinedDir = CreateDriverSoDestinedDir(info.GetBundleName(), extModuleName, fileName,
156 meta.value, isModuleExisted);
157 APP_LOGD("Remove driver so file path is %{public}s", destinedDir.c_str());
158 std::string systemServiceDir = ServiceConstants::SYSTEM_SERVICE_DIR;
159 InstalldClient::GetInstance()->RemoveDir(systemServiceDir + destinedDir);
160 }
161 }
162 APP_LOGD("end");
163 }
164
CreateDriverSoDestinedDir(const std::string & bundleName,const std::string & moduleName,const std::string & fileName,const std::string & destinedDir,bool isModuleExisted) const165 std::string DriverInstaller::CreateDriverSoDestinedDir(const std::string &bundleName, const std::string &moduleName,
166 const std::string &fileName, const std::string &destinedDir, bool isModuleExisted) const
167 {
168 APP_LOGD("bundleName is %{public}s, moduleName is %{public}s, fileName is %{public}s, destinedDir is %{public}s",
169 bundleName.c_str(), moduleName.c_str(), fileName.c_str(), destinedDir.c_str());
170 if (bundleName.empty() || moduleName.empty() || fileName.empty() || destinedDir.empty()) {
171 APP_LOGW("parameters are invalid");
172 return "";
173 }
174 std::string resStr = destinedDir;
175 if (resStr.back() != ServiceConstants::PATH_SEPARATOR[0]) {
176 resStr += ServiceConstants::PATH_SEPARATOR;
177 }
178 if (isModuleExisted) {
179 resStr.append(TEMP_PREFIX);
180 }
181 resStr.append(bundleName).append(Constants::FILE_UNDERLINE).append(moduleName)
182 .append(Constants::FILE_UNDERLINE).append(fileName);
183 return resStr;
184 }
185
RenameDriverFile(const InnerBundleInfo & info) const186 void DriverInstaller::RenameDriverFile(const InnerBundleInfo &info) const
187 {
188 APP_LOGD("begin");
189 auto extensionAbilityInfos = info.GetInnerExtensionInfos();
190 for (const auto &extAbilityInfo : extensionAbilityInfos) {
191 if (extAbilityInfo.second.type != ExtensionAbilityType::DRIVER) {
192 continue;
193 }
194 std::string extModuleName = extAbilityInfo.second.moduleName;
195 APP_LOGD("extModuleName is %{public}s", extModuleName.c_str());
196 const auto &metadata = extAbilityInfo.second.metadata;
197 for (const auto &meta : metadata) {
198 if (std::find(DRIVER_PROPERTIES.cbegin(), DRIVER_PROPERTIES.cend(), meta.name) ==
199 DRIVER_PROPERTIES.cend()) {
200 APP_LOGD("metadata name %{public}s is not existed in driver properties", meta.name.c_str());
201 continue;
202 }
203 std::vector<std::string> originalDirVec;
204 SplitStr(meta.resource, ServiceConstants::PATH_SEPARATOR, originalDirVec, false, false);
205 if (originalDirVec.empty()) {
206 APP_LOGW("invalid metadata resource %{public}s", meta.resource.c_str());
207 return;
208 }
209 auto fileName = originalDirVec.back();
210 APP_LOGD("fileName is %{public}s", fileName.c_str());
211 std::string tempDestinedDir = CreateDriverSoDestinedDir(info.GetBundleName(), extModuleName, fileName,
212 meta.value, true);
213 APP_LOGD("driver so file temp path is %{public}s", tempDestinedDir.c_str());
214
215 std::string realDestinedDir = CreateDriverSoDestinedDir(info.GetBundleName(), extModuleName, fileName,
216 meta.value, false);
217 APP_LOGD("driver so file real path is %{public}s", realDestinedDir.c_str());
218
219 std::string systemServiceDir = ServiceConstants::SYSTEM_SERVICE_DIR;
220 InstalldClient::GetInstance()->MoveFile(systemServiceDir + tempDestinedDir,
221 systemServiceDir + realDestinedDir);
222 }
223 }
224 APP_LOGD("end");
225 }
226 } // namespace AppExecFwk
227 } // namespace OHOS