1 /*
2  * Copyright (c) 2022-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 "quick_fix_manager_proxy.h"
17 
18 #include <cerrno>
19 #include <fcntl.h>
20 #include <unistd.h>
21 
22 #include "app_log_tag_wrapper.h"
23 #include "app_log_wrapper.h"
24 #include "appexecfwk_errors.h"
25 #include "bundle_file_util.h"
26 #include "directory_ex.h"
27 #include "hitrace_meter.h"
28 #include "ipc_types.h"
29 
30 namespace OHOS {
31 namespace AppExecFwk {
32 namespace {
33 const std::string SEPARATOR = "/";
34 const int32_t DEFAULT_BUFFER_SIZE = 65536;
35 }
36 
QuickFixManagerProxy(const sptr<IRemoteObject> & object)37 QuickFixManagerProxy::QuickFixManagerProxy(const sptr<IRemoteObject> &object) : IRemoteProxy<IQuickFixManager>(object)
38 {
39     LOG_I(BMS_TAG_DEFAULT, "create QuickFixManagerProxy");
40 }
41 
~QuickFixManagerProxy()42 QuickFixManagerProxy::~QuickFixManagerProxy()
43 {
44     LOG_I(BMS_TAG_DEFAULT, "destroy QuickFixManagerProxy");
45 }
46 
DeployQuickFix(const std::vector<std::string> & bundleFilePaths,const sptr<IQuickFixStatusCallback> & statusCallback,bool isDebug,const std::string & inputTargetPath)47 ErrCode QuickFixManagerProxy::DeployQuickFix(const std::vector<std::string> &bundleFilePaths,
48     const sptr<IQuickFixStatusCallback> &statusCallback, bool isDebug, const std::string &inputTargetPath)
49 {
50     LOG_I(BMS_TAG_DEFAULT, "begin to call DeployQuickFix");
51     HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
52 
53     if (bundleFilePaths.empty() || (statusCallback == nullptr)) {
54         LOG_E(BMS_TAG_DEFAULT, "DeployQuickFix failed due to params error");
55         return ERR_BUNDLEMANAGER_QUICK_FIX_PARAM_ERROR;
56     }
57 
58     std::string targetPath = inputTargetPath;
59     if (targetPath.find(".") != std::string::npos ||
60         targetPath.find("..") != std::string::npos ||
61         targetPath.find("/") != std::string::npos) {
62         LOG_E(BMS_TAG_DEFAULT, "input targetPath is invalid");
63         return ERR_BUNDLEMANAGER_QUICK_FIX_PARAM_ERROR;
64     }
65 
66     MessageParcel data;
67     if (!data.WriteInterfaceToken(GetDescriptor())) {
68         LOG_E(BMS_TAG_DEFAULT, "WriteInterfaceToken failed");
69         return ERR_APPEXECFWK_PARCEL_ERROR;
70     }
71     if (!data.WriteStringVector(bundleFilePaths)) {
72         LOG_E(BMS_TAG_DEFAULT, "write bundleFilePaths failed");
73         return ERR_APPEXECFWK_PARCEL_ERROR;
74     }
75     if (!data.WriteBool(isDebug)) {
76         LOG_E(BMS_TAG_DEFAULT, "write isDebug failed");
77         return ERR_APPEXECFWK_PARCEL_ERROR;
78     }
79     if (!data.WriteString(targetPath)) {
80         LOG_E(BMS_TAG_DEFAULT, "write targetPath failed");
81         return ERR_APPEXECFWK_PARCEL_ERROR;
82     }
83     if (!data.WriteRemoteObject(statusCallback->AsObject())) {
84         LOG_E(BMS_TAG_DEFAULT, "write parcel failed");
85         return ERR_APPEXECFWK_PARCEL_ERROR;
86     }
87 
88     MessageParcel reply;
89     if (!SendRequest(QuickFixManagerInterfaceCode::DEPLOY_QUICK_FIX, data, reply)) {
90         LOG_E(BMS_TAG_DEFAULT, "SendRequest failed");
91         return ERR_BUNDLEMANAGER_QUICK_FIX_SEND_REQUEST_FAILED;
92     }
93 
94     return reply.ReadInt32();
95 }
96 
SwitchQuickFix(const std::string & bundleName,bool enable,const sptr<IQuickFixStatusCallback> & statusCallback)97 ErrCode QuickFixManagerProxy::SwitchQuickFix(const std::string &bundleName, bool enable,
98     const sptr<IQuickFixStatusCallback> &statusCallback)
99 {
100     LOG_I(BMS_TAG_DEFAULT, "begin to call SwitchQuickFix");
101     HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
102 
103     if (bundleName.empty() || (statusCallback == nullptr)) {
104         LOG_E(BMS_TAG_DEFAULT, "SwitchQuickFix failed due to params error");
105         return ERR_BUNDLEMANAGER_QUICK_FIX_PARAM_ERROR;
106     }
107 
108     MessageParcel data;
109     if (!data.WriteInterfaceToken(GetDescriptor())) {
110         LOG_E(BMS_TAG_DEFAULT, "WriteInterfaceToken failed");
111         return ERR_APPEXECFWK_PARCEL_ERROR;
112     }
113     if (!data.WriteString(bundleName)) {
114         LOG_E(BMS_TAG_DEFAULT, "write bundleName failed");
115         return ERR_APPEXECFWK_PARCEL_ERROR;
116     }
117     if (!data.WriteBool(enable)) {
118         LOG_E(BMS_TAG_DEFAULT, "write enable failed");
119         return ERR_APPEXECFWK_PARCEL_ERROR;
120     }
121     if (!data.WriteRemoteObject(statusCallback->AsObject())) {
122         LOG_E(BMS_TAG_DEFAULT, "write parcel failed");
123         return ERR_APPEXECFWK_PARCEL_ERROR;
124     }
125 
126     MessageParcel reply;
127     if (!SendRequest(QuickFixManagerInterfaceCode::SWITCH_QUICK_FIX, data, reply)) {
128         LOG_E(BMS_TAG_DEFAULT, "SendRequest failed");
129         return ERR_BUNDLEMANAGER_QUICK_FIX_SEND_REQUEST_FAILED;
130     }
131 
132     return reply.ReadInt32();
133 }
134 
DeleteQuickFix(const std::string & bundleName,const sptr<IQuickFixStatusCallback> & statusCallback)135 ErrCode QuickFixManagerProxy::DeleteQuickFix(const std::string &bundleName,
136     const sptr<IQuickFixStatusCallback> &statusCallback)
137 {
138     LOG_I(BMS_TAG_DEFAULT, "begin to call DeleteQuickFix");
139     HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
140 
141     if (bundleName.empty() || (statusCallback == nullptr)) {
142         LOG_E(BMS_TAG_DEFAULT, "DeleteQuickFix failed due to params error");
143         return ERR_BUNDLEMANAGER_QUICK_FIX_PARAM_ERROR;
144     }
145 
146     MessageParcel data;
147     if (!data.WriteInterfaceToken(GetDescriptor())) {
148         LOG_E(BMS_TAG_DEFAULT, "WriteInterfaceToken failed");
149         return ERR_APPEXECFWK_PARCEL_ERROR;
150     }
151     if (!data.WriteString(bundleName)) {
152         LOG_E(BMS_TAG_DEFAULT, "write bundleName failed");
153         return ERR_APPEXECFWK_PARCEL_ERROR;
154     }
155     if (!data.WriteRemoteObject(statusCallback->AsObject())) {
156         LOG_E(BMS_TAG_DEFAULT, "write parcel failed");
157         return ERR_APPEXECFWK_PARCEL_ERROR;
158     }
159 
160     MessageParcel reply;
161     if (!SendRequest(QuickFixManagerInterfaceCode::DELETE_QUICK_FIX, data, reply)) {
162         LOG_E(BMS_TAG_DEFAULT, "SendRequest failed");
163         return ERR_BUNDLEMANAGER_QUICK_FIX_SEND_REQUEST_FAILED;
164     }
165 
166     return reply.ReadInt32();
167 }
168 
CreateFd(const std::string & fileName,int32_t & fd,std::string & path)169 ErrCode QuickFixManagerProxy::CreateFd(const std::string &fileName, int32_t &fd, std::string &path)
170 {
171     LOG_D(BMS_TAG_DEFAULT, "begin to create fd");
172     if (fileName.empty()) {
173         LOG_E(BMS_TAG_DEFAULT, "fileName is empty");
174         return ERR_BUNDLEMANAGER_QUICK_FIX_PARAM_ERROR;
175     }
176     MessageParcel data;
177     if (!data.WriteInterfaceToken(GetDescriptor())) {
178         LOG_E(BMS_TAG_DEFAULT, "write interface token failed");
179         return ERR_APPEXECFWK_PARCEL_ERROR;
180     }
181     if (!data.WriteString(fileName)) {
182         LOG_E(BMS_TAG_DEFAULT, "write fileName failed");
183         return ERR_APPEXECFWK_PARCEL_ERROR;
184     }
185     MessageParcel reply;
186     if (!SendRequest(QuickFixManagerInterfaceCode::CREATE_FD, data, reply)) {
187         LOG_E(BMS_TAG_DEFAULT, "send request failed");
188         return ERR_APPEXECFWK_PARCEL_ERROR;
189     }
190     auto ret = reply.ReadInt32();
191     if (ret != ERR_OK) {
192         LOG_E(BMS_TAG_DEFAULT, "reply return false");
193         return ret;
194     }
195     fd = reply.ReadFileDescriptor();
196     if (fd < 0) {
197         LOG_E(BMS_TAG_DEFAULT, "invalid fd");
198         return ERR_BUNDLEMANAGER_QUICK_FIX_CREATE_FD_FAILED;
199     }
200     path = reply.ReadString();
201     if (path.empty()) {
202         LOG_E(BMS_TAG_DEFAULT, "invalid path");
203         close(fd);
204         return ERR_BUNDLEMANAGER_QUICK_FIX_INVALID_TARGET_DIR;
205     }
206     LOG_D(BMS_TAG_DEFAULT, "create fd success");
207     return ERR_OK;
208 }
209 
CopyFiles(const std::vector<std::string> & sourceFiles,std::vector<std::string> & destFiles)210 ErrCode QuickFixManagerProxy::CopyFiles(
211     const std::vector<std::string> &sourceFiles, std::vector<std::string> &destFiles)
212 {
213     LOG_D(BMS_TAG_DEFAULT, "begin to copy files");
214     if (sourceFiles.empty()) {
215         LOG_E(BMS_TAG_DEFAULT, "sourceFiles empty");
216         return ERR_BUNDLEMANAGER_QUICK_FIX_PARAM_ERROR;
217     }
218     std::vector<std::string> hqfFilePaths;
219     if (!BundleFileUtil::CheckFilePath(sourceFiles, hqfFilePaths)) {
220         LOG_E(BMS_TAG_DEFAULT, "CopyFiles CheckFilePath failed");
221         return ERR_BUNDLEMANAGER_QUICK_FIX_PARAM_ERROR;
222     }
223     for (const std::string &sourcePath : hqfFilePaths) {
224         size_t pos = sourcePath.find_last_of(SEPARATOR);
225         if (pos == std::string::npos) {
226             LOG_E(BMS_TAG_DEFAULT, "invalid sourcePath");
227             return ERR_BUNDLEMANAGER_QUICK_FIX_INVALID_PATH;
228         }
229         std::string fileName = sourcePath.substr(pos + 1);
230         LOG_D(BMS_TAG_DEFAULT, "sourcePath:%{private}s fileName:%{private}s", sourcePath.c_str(), fileName.c_str());
231         int32_t sourceFd = open(sourcePath.c_str(), O_RDONLY);
232         if (sourceFd < 0) {
233             LOG_E(BMS_TAG_DEFAULT, "open file failed, errno:%{public}d", errno);
234             return ERR_BUNDLEMANAGER_QUICK_FIX_OPEN_SOURCE_FILE_FAILED;
235         }
236         int32_t destFd = -1;
237         std::string destPath;
238         auto ret = CreateFd(fileName, destFd, destPath);
239         if ((ret != ERR_OK) || (destFd < 0) || (destPath.empty())) {
240             LOG_E(BMS_TAG_DEFAULT, "create fd failed");
241             close(sourceFd);
242             return ret;
243         }
244         char buffer[DEFAULT_BUFFER_SIZE] = {0};
245         int offset = -1;
246         while ((offset = read(sourceFd, buffer, sizeof(buffer))) > 0) {
247             if (write(destFd, buffer, offset) < 0) {
248                 LOG_E(BMS_TAG_DEFAULT, "write file to the temp dir failed, errno %{public}d", errno);
249                 close(sourceFd);
250                 close(destFd);
251                 return ERR_BUNDLEMANAGER_QUICK_FIX_WRITE_FILE_FAILED;
252             }
253         }
254         destFiles.emplace_back(destPath);
255         close(sourceFd);
256         fsync(destFd);
257         close(destFd);
258     }
259     LOG_D(BMS_TAG_DEFAULT, "copy files success");
260     return ERR_OK;
261 }
262 
SendRequest(QuickFixManagerInterfaceCode code,MessageParcel & data,MessageParcel & reply)263 bool QuickFixManagerProxy::SendRequest(QuickFixManagerInterfaceCode code, MessageParcel &data, MessageParcel &reply)
264 {
265     MessageOption option(MessageOption::TF_SYNC);
266     sptr<IRemoteObject> remote = Remote();
267     if (remote == nullptr) {
268         LOG_E(BMS_TAG_DEFAULT, "failed to send request %{public}hhu due to remote object null", code);
269         return false;
270     }
271     int32_t result = remote->SendRequest(static_cast<uint32_t>(code), data, reply, option);
272     if (result != NO_ERROR) {
273         LOG_E(BMS_TAG_DEFAULT, "receive error code %{public}d in transact %{public}hhu", result, code);
274         return false;
275     }
276     return true;
277 }
278 } // AppExecFwk
279 } // OHOS