• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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