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 std::string cpuAbi = "";
55 std::string nativeLibraryPath = "";
56 info.FetchNativeSoAttrs(info.GetCurrentModulePackage(), cpuAbi, nativeLibraryPath);
57 for (const auto &extAbilityInfo : extensionAbilityInfos) {
58 if (extAbilityInfo.second.type != ExtensionAbilityType::DRIVER) {
59 continue;
60 }
61
62 auto &metadata = extAbilityInfo.second.metadata;
63 auto filterFunc = [this, &result, &info, &dirMap, &isModuleExisted](const Metadata &meta) {
64 result = FilterDriverSoFile(info, meta, dirMap, isModuleExisted);
65 return result != ERR_OK;
66 };
67 std::any_of(metadata.begin(), metadata.end(), filterFunc);
68 CHECK_RESULT(result, "driver so path is invalid, error is %{public}d");
69 }
70 if (dirMap.empty()) {
71 APP_LOGD("no driver so file needs to be cpoied");
72 return ERR_OK;
73 }
74 // 2. copy driver so file to destined dir
75 std::string realSoDir;
76 realSoDir.append(Constants::BUNDLE_CODE_DIR).append(ServiceConstants::PATH_SEPARATOR)
77 .append(info.GetBundleName()).append(ServiceConstants::PATH_SEPARATOR)
78 .append(nativeLibraryPath);
79 return InstalldClient::GetInstance()->ExtractDriverSoFiles(realSoDir, dirMap);
80 }
81
FilterDriverSoFile(const InnerBundleInfo & info,const Metadata & meta,std::unordered_multimap<std::string,std::string> & dirMap,bool isModuleExisted) const82 ErrCode DriverInstaller::FilterDriverSoFile(const InnerBundleInfo &info, const Metadata &meta,
83 std::unordered_multimap<std::string, std::string> &dirMap, bool isModuleExisted) const
84 {
85 APP_LOGD("begin");
86 // find driver metadata name in driver properties
87 if (std::find(DRIVER_PROPERTIES.cbegin(), DRIVER_PROPERTIES.cend(), meta.name) ==
88 DRIVER_PROPERTIES.cend()) {
89 APP_LOGD("metadata name %{public}s is not existed in driver properties", meta.name.c_str());
90 return ERR_OK;
91 }
92
93 // check dir and obtain name of the file which needs to be copied
94 std::string originalDir = meta.resource;
95 std::string destinedDir = meta.value;
96 if (originalDir.find(ServiceConstants::RELATIVE_PATH) != std::string::npos ||
97 destinedDir.find(ServiceConstants::RELATIVE_PATH) != std::string::npos) {
98 APP_LOGW("metadata value %{public}s, resource %{public}s cannot support path",
99 destinedDir.c_str(), originalDir.c_str());
100 return ERR_APPEXECFWK_INSTALL_FILE_PATH_INVALID;
101 }
102
103 // create destined dir of driver files
104 std::vector<std::string> originalDirVec;
105 SplitStr(originalDir, ServiceConstants::PATH_SEPARATOR, originalDirVec, false, false);
106 if (originalDirVec.empty()) {
107 APP_LOGW("original dir is invalid");
108 return ERR_APPEXECFWK_INSTALL_FILE_PATH_INVALID;
109 }
110 auto fileName = originalDirVec.back();
111 APP_LOGD("fileName is %{public}s", fileName.c_str());
112 const auto &moduleName = info.GetModuleName(info.GetCurrentModulePackage());
113 destinedDir = CreateDriverSoDestinedDir(info.GetBundleName(), moduleName, fileName, destinedDir, isModuleExisted);
114 APP_LOGD("metadata destined dir is %{public}s", destinedDir.c_str());
115 dirMap.emplace(originalDir, destinedDir);
116 return ERR_OK;
117 }
118
RemoveAndReNameDriverFile(const std::unordered_map<std::string,InnerBundleInfo> & newInfos,const InnerBundleInfo & oldInfo) const119 void DriverInstaller::RemoveAndReNameDriverFile(const std::unordered_map<std::string, InnerBundleInfo> &newInfos,
120 const InnerBundleInfo &oldInfo) const
121 {
122 for (const auto &info : newInfos) {
123 std::string packageName = info.second.GetCurrentModulePackage();
124 if (!oldInfo.FindModule(packageName)) {
125 continue;
126 }
127 RemoveDriverSoFile(oldInfo, info.second.GetModuleName(packageName), false);
128 RenameDriverFile(info.second);
129 }
130 }
131
RemoveDriverSoFile(const InnerBundleInfo & info,const std::string & moduleName,bool isModuleExisted) const132 void DriverInstaller::RemoveDriverSoFile(const InnerBundleInfo &info, const std::string &moduleName,
133 bool isModuleExisted) const
134 {
135 APP_LOGD("begin");
136 auto extensionAbilityInfos = info.GetInnerExtensionInfos();
137 for (const auto &extAbilityInfo : extensionAbilityInfos) {
138 // find module name from the extAbilityInfo
139 std::string extModuleName = extAbilityInfo.second.moduleName;
140 APP_LOGD("extModuleName is %{public}s", extModuleName.c_str());
141 if ((!moduleName.empty() && moduleName.compare(extModuleName) != 0) ||
142 (extAbilityInfo.second.type != ExtensionAbilityType::DRIVER)) {
143 APP_LOGD("no driver extension(%{public}d) or moduleName(%{public}s) is not matched",
144 static_cast<int32_t>(extAbilityInfo.second.type), moduleName.c_str());
145 continue;
146 }
147 const auto &metadata = extAbilityInfo.second.metadata;
148 for (const auto &meta : metadata) {
149 if (std::find(DRIVER_PROPERTIES.cbegin(), DRIVER_PROPERTIES.cend(), meta.name) ==
150 DRIVER_PROPERTIES.cend()) {
151 APP_LOGD("metadata name %{public}s is not existed in driver properties", meta.name.c_str());
152 continue;
153 }
154 std::vector<std::string> originalDirVec;
155 SplitStr(meta.resource, ServiceConstants::PATH_SEPARATOR, originalDirVec, false, false);
156 if (originalDirVec.empty()) {
157 APP_LOGW("invalid metadata resource %{public}s", meta.resource.c_str());
158 return;
159 }
160 auto fileName = originalDirVec.back();
161 APP_LOGD("fileName is %{public}s", fileName.c_str());
162 std::string destinedDir = CreateDriverSoDestinedDir(info.GetBundleName(), extModuleName, fileName,
163 meta.value, isModuleExisted);
164 APP_LOGD("Remove driver so file path is %{public}s", destinedDir.c_str());
165 if (!destinedDir.empty()) {
166 std::string systemServiceDir = ServiceConstants::SYSTEM_SERVICE_DIR;
167 InstalldClient::GetInstance()->RemoveDir(systemServiceDir + destinedDir);
168 }
169 }
170 }
171 APP_LOGD("end");
172 }
173
CreateDriverSoDestinedDir(const std::string & bundleName,const std::string & moduleName,const std::string & fileName,const std::string & destinedDir,bool isModuleExisted) const174 std::string DriverInstaller::CreateDriverSoDestinedDir(const std::string &bundleName, const std::string &moduleName,
175 const std::string &fileName, const std::string &destinedDir, bool isModuleExisted) const
176 {
177 APP_LOGD("bundleName is %{public}s, moduleName is %{public}s, fileName is %{public}s, destinedDir is %{public}s",
178 bundleName.c_str(), moduleName.c_str(), fileName.c_str(), destinedDir.c_str());
179 if (bundleName.empty() || moduleName.empty() || fileName.empty() || destinedDir.empty()) {
180 APP_LOGW("parameters are invalid");
181 return "";
182 }
183 if (destinedDir.find("..") != std::string::npos) {
184 APP_LOGW("destinedDir %{public}s invalid", destinedDir.c_str());
185 return "";
186 }
187 std::string resStr = destinedDir;
188 if (resStr.back() != ServiceConstants::PATH_SEPARATOR[0]) {
189 resStr += ServiceConstants::PATH_SEPARATOR;
190 }
191 if (isModuleExisted) {
192 resStr.append(TEMP_PREFIX);
193 }
194 resStr.append(bundleName).append(Constants::FILE_UNDERLINE).append(moduleName)
195 .append(Constants::FILE_UNDERLINE).append(fileName);
196 return resStr;
197 }
198
RenameDriverFile(const InnerBundleInfo & info) const199 void DriverInstaller::RenameDriverFile(const InnerBundleInfo &info) const
200 {
201 APP_LOGD("begin");
202 auto extensionAbilityInfos = info.GetInnerExtensionInfos();
203 for (const auto &extAbilityInfo : extensionAbilityInfos) {
204 if (extAbilityInfo.second.type != ExtensionAbilityType::DRIVER) {
205 continue;
206 }
207 std::string extModuleName = extAbilityInfo.second.moduleName;
208 APP_LOGD("extModuleName is %{public}s", extModuleName.c_str());
209 const auto &metadata = extAbilityInfo.second.metadata;
210 for (const auto &meta : metadata) {
211 if (std::find(DRIVER_PROPERTIES.cbegin(), DRIVER_PROPERTIES.cend(), meta.name) ==
212 DRIVER_PROPERTIES.cend()) {
213 APP_LOGD("metadata name %{public}s is not existed in driver properties", meta.name.c_str());
214 continue;
215 }
216 std::vector<std::string> originalDirVec;
217 SplitStr(meta.resource, ServiceConstants::PATH_SEPARATOR, originalDirVec, false, false);
218 if (originalDirVec.empty()) {
219 APP_LOGW("invalid metadata resource %{public}s", meta.resource.c_str());
220 return;
221 }
222 auto fileName = originalDirVec.back();
223 APP_LOGD("fileName is %{public}s", fileName.c_str());
224 std::string tempDestinedDir = CreateDriverSoDestinedDir(info.GetBundleName(), extModuleName, fileName,
225 meta.value, true);
226 APP_LOGD("driver so file temp path is %{public}s", tempDestinedDir.c_str());
227
228 std::string realDestinedDir = CreateDriverSoDestinedDir(info.GetBundleName(), extModuleName, fileName,
229 meta.value, false);
230 APP_LOGD("driver so file real path is %{public}s", realDestinedDir.c_str());
231
232 std::string systemServiceDir = ServiceConstants::SYSTEM_SERVICE_DIR;
233 InstalldClient::GetInstance()->MoveFile(systemServiceDir + tempDestinedDir,
234 systemServiceDir + realDestinedDir);
235 }
236 }
237 APP_LOGD("end");
238 }
239 } // namespace AppExecFwk
240 } // namespace OHOS