1 /*
2  * Copyright (c) 2021-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 "bundle_installer_proxy.h"
17 
18 #include <cerrno>
19 #include <fcntl.h>
20 #include <sys/sendfile.h>
21 #include <sys/stat.h>
22 #include <unistd.h>
23 
24 #include "app_log_tag_wrapper.h"
25 #include "app_log_wrapper.h"
26 #include "appexecfwk_errors.h"
27 #include "bundle_file_util.h"
28 #include "directory_ex.h"
29 #include "hitrace_meter.h"
30 #include "ipc_types.h"
31 #include "parcel.h"
32 #include "string_ex.h"
33 
34 namespace OHOS {
35 namespace AppExecFwk {
36 namespace {
37 const char* SEPARATOR = "/";
38 } // namespace
39 
BundleInstallerProxy(const sptr<IRemoteObject> & object)40 BundleInstallerProxy::BundleInstallerProxy(const sptr<IRemoteObject> &object) : IRemoteProxy<IBundleInstaller>(object)
41 {
42     LOG_D(BMS_TAG_INSTALLER, "create bundle installer proxy instance");
43 }
44 
~BundleInstallerProxy()45 BundleInstallerProxy::~BundleInstallerProxy()
46 {
47     LOG_D(BMS_TAG_INSTALLER, "destroy bundle installer proxy instance");
48 }
49 
Install(const std::string & bundlePath,const InstallParam & installParam,const sptr<IStatusReceiver> & statusReceiver)50 bool BundleInstallerProxy::Install(
51     const std::string &bundlePath, const InstallParam &installParam, const sptr<IStatusReceiver> &statusReceiver)
52 {
53     HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
54     MessageParcel data;
55     MessageParcel reply;
56     MessageOption option(MessageOption::TF_SYNC);
57 
58     PARCEL_WRITE_INTERFACE_TOKEN(data, GetDescriptor());
59     PARCEL_WRITE(data, String16, Str8ToStr16(bundlePath));
60     PARCEL_WRITE(data, Parcelable, &installParam);
61 
62     if (statusReceiver == nullptr) {
63         LOG_E(BMS_TAG_INSTALLER, "fail to install, for statusReceiver is nullptr");
64         return false;
65     }
66     if (!data.WriteRemoteObject(statusReceiver->AsObject())) {
67         LOG_E(BMS_TAG_INSTALLER, "write parcel failed");
68         return false;
69     }
70 
71     return SendInstallRequest(BundleInstallerInterfaceCode::INSTALL, data, reply, option);
72 }
73 
Install(const std::vector<std::string> & bundleFilePaths,const InstallParam & installParam,const sptr<IStatusReceiver> & statusReceiver)74 bool BundleInstallerProxy::Install(const std::vector<std::string> &bundleFilePaths, const InstallParam &installParam,
75     const sptr<IStatusReceiver> &statusReceiver)
76 {
77     HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
78     MessageParcel data;
79     MessageParcel reply;
80     MessageOption option(MessageOption::TF_SYNC);
81 
82     PARCEL_WRITE_INTERFACE_TOKEN(data, GetDescriptor());
83     auto size = bundleFilePaths.size();
84     PARCEL_WRITE(data, Int32, size);
85     for (uint32_t i = 0; i < size; ++i) {
86         PARCEL_WRITE(data, String16, Str8ToStr16(bundleFilePaths[i]));
87     }
88     PARCEL_WRITE(data, Parcelable, &installParam);
89 
90     if (statusReceiver == nullptr) {
91         LOG_E(BMS_TAG_INSTALLER, "fail to install, for statusReceiver is nullptr");
92         return false;
93     }
94     if (!data.WriteRemoteObject(statusReceiver->AsObject())) {
95         LOG_E(BMS_TAG_INSTALLER, "write parcel failed");
96         return false;
97     }
98 
99     return SendInstallRequest(BundleInstallerInterfaceCode::INSTALL_MULTIPLE_HAPS, data, reply,
100         option);
101 }
102 
Recover(const std::string & bundleName,const InstallParam & installParam,const sptr<IStatusReceiver> & statusReceiver)103 bool BundleInstallerProxy::Recover(const std::string &bundleName,
104     const InstallParam &installParam, const sptr<IStatusReceiver> &statusReceiver)
105 {
106     MessageParcel data;
107     MessageParcel reply;
108     MessageOption option(MessageOption::TF_SYNC);
109 
110     PARCEL_WRITE_INTERFACE_TOKEN(data, GetDescriptor());
111     PARCEL_WRITE(data, String16, Str8ToStr16(bundleName));
112     PARCEL_WRITE(data, Parcelable, &installParam);
113 
114     if (statusReceiver == nullptr) {
115         LOG_E(BMS_TAG_INSTALLER, "fail to install, for statusReceiver is nullptr");
116         return false;
117     }
118     if (!data.WriteRemoteObject(statusReceiver->AsObject())) {
119         LOG_E(BMS_TAG_INSTALLER, "write parcel failed");
120         return false;
121     }
122 
123     return SendInstallRequest(BundleInstallerInterfaceCode::RECOVER, data, reply,
124         option);
125 }
126 
Uninstall(const std::string & bundleName,const InstallParam & installParam,const sptr<IStatusReceiver> & statusReceiver)127 bool BundleInstallerProxy::Uninstall(
128     const std::string &bundleName, const InstallParam &installParam, const sptr<IStatusReceiver> &statusReceiver)
129 {
130     HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
131     MessageParcel data;
132     MessageParcel reply;
133     MessageOption option(MessageOption::TF_SYNC);
134 
135     PARCEL_WRITE_INTERFACE_TOKEN(data, GetDescriptor());
136     PARCEL_WRITE(data, String16, Str8ToStr16(bundleName));
137     PARCEL_WRITE(data, Parcelable, &installParam);
138     if (statusReceiver == nullptr) {
139         LOG_E(BMS_TAG_INSTALLER, "fail to uninstall, for statusReceiver is nullptr");
140         return false;
141     }
142     if (!data.WriteRemoteObject(statusReceiver->AsObject())) {
143         LOG_E(BMS_TAG_INSTALLER, "write parcel failed");
144         return false;
145     }
146 
147     return SendInstallRequest(BundleInstallerInterfaceCode::UNINSTALL, data, reply, option);
148 }
149 
Uninstall(const std::string & bundleName,const std::string & modulePackage,const InstallParam & installParam,const sptr<IStatusReceiver> & statusReceiver)150 bool BundleInstallerProxy::Uninstall(const std::string &bundleName, const std::string &modulePackage,
151     const InstallParam &installParam, const sptr<IStatusReceiver> &statusReceiver)
152 {
153     HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
154     MessageParcel data;
155     MessageParcel reply;
156     MessageOption option(MessageOption::TF_SYNC);
157 
158     PARCEL_WRITE_INTERFACE_TOKEN(data, GetDescriptor());
159     PARCEL_WRITE(data, String16, Str8ToStr16(bundleName));
160     PARCEL_WRITE(data, String16, Str8ToStr16(modulePackage));
161     PARCEL_WRITE(data, Parcelable, &installParam);
162     if (statusReceiver == nullptr) {
163         LOG_E(BMS_TAG_INSTALLER, "fail to uninstall, for statusReceiver is nullptr");
164         return false;
165     }
166     if (!data.WriteRemoteObject(statusReceiver->AsObject())) {
167         LOG_E(BMS_TAG_INSTALLER, "write parcel failed");
168         return false;
169     }
170 
171     return SendInstallRequest(BundleInstallerInterfaceCode::UNINSTALL_MODULE, data, reply, option);
172 }
173 
Uninstall(const UninstallParam & uninstallParam,const sptr<IStatusReceiver> & statusReceiver)174 bool BundleInstallerProxy::Uninstall(const UninstallParam &uninstallParam,
175     const sptr<IStatusReceiver> &statusReceiver)
176 {
177     MessageParcel data;
178     MessageParcel reply;
179     MessageOption option(MessageOption::TF_SYNC);
180     PARCEL_WRITE_INTERFACE_TOKEN(data, GetDescriptor());
181     PARCEL_WRITE(data, Parcelable, &uninstallParam);
182     if (statusReceiver == nullptr) {
183         LOG_E(BMS_TAG_INSTALLER, "fail to uninstall, for statusReceiver is nullptr");
184         return false;
185     }
186     if (!data.WriteRemoteObject(statusReceiver->AsObject())) {
187         LOG_E(BMS_TAG_INSTALLER, "write parcel failed");
188         return false;
189     }
190     return SendInstallRequest(BundleInstallerInterfaceCode::UNINSTALL_BY_UNINSTALL_PARAM, data, reply, option);
191 }
192 
InstallSandboxApp(const std::string & bundleName,int32_t dlpType,int32_t userId,int32_t & appIndex)193 ErrCode BundleInstallerProxy::InstallSandboxApp(const std::string &bundleName, int32_t dlpType, int32_t userId,
194     int32_t &appIndex)
195 {
196     HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
197     MessageParcel data;
198     MessageParcel reply;
199     MessageOption option(MessageOption::TF_SYNC);
200 
201     if (!data.WriteInterfaceToken(GetDescriptor())) {
202         LOG_E(BMS_TAG_INSTALLER, "failed to InstallSandboxApp due to write MessageParcel fail");
203         return ERR_APPEXECFWK_SANDBOX_INSTALL_WRITE_PARCEL_ERROR;
204     }
205     if (!data.WriteString16(Str8ToStr16(bundleName))) {
206         LOG_E(BMS_TAG_INSTALLER, "failed to InstallSandboxApp due to write bundleName fail");
207         return ERR_APPEXECFWK_SANDBOX_INSTALL_WRITE_PARCEL_ERROR;
208     }
209     if (!data.WriteInt32(dlpType)) {
210         LOG_E(BMS_TAG_INSTALLER, "failed to InstallSandboxApp due to write appIndex fail");
211         return ERR_APPEXECFWK_SANDBOX_INSTALL_WRITE_PARCEL_ERROR;
212     }
213     if (!data.WriteInt32(userId)) {
214         LOG_E(BMS_TAG_INSTALLER, "failed to InstallSandboxApp due to write userId fail");
215         return ERR_APPEXECFWK_SANDBOX_INSTALL_WRITE_PARCEL_ERROR;
216     }
217 
218     auto ret =
219         SendInstallRequest(BundleInstallerInterfaceCode::INSTALL_SANDBOX_APP, data, reply, option);
220     if (!ret) {
221         LOG_E(BMS_TAG_INSTALLER, "install sandbox app failed due to send request fail");
222         return ERR_APPEXECFWK_SANDBOX_INSTALL_SEND_REQUEST_ERROR;
223     }
224 
225     auto res = reply.ReadInt32();
226     if (res == ERR_OK) {
227         appIndex = reply.ReadInt32();
228     }
229     return res;
230 }
231 
UninstallSandboxApp(const std::string & bundleName,int32_t appIndex,int32_t userId)232 ErrCode BundleInstallerProxy::UninstallSandboxApp(const std::string &bundleName, int32_t appIndex, int32_t userId)
233 {
234     HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
235     MessageParcel data;
236     MessageParcel reply;
237     MessageOption option(MessageOption::TF_SYNC);
238 
239     if (!data.WriteInterfaceToken(GetDescriptor())) {
240         LOG_E(BMS_TAG_INSTALLER, "failed to InstallSandboxApp due to write MessageParcel fail");
241         return ERR_APPEXECFWK_SANDBOX_INSTALL_WRITE_PARCEL_ERROR;
242     }
243     if (!data.WriteString16(Str8ToStr16(bundleName))) {
244         LOG_E(BMS_TAG_INSTALLER, "failed to InstallSandboxApp due to write bundleName fail");
245         return ERR_APPEXECFWK_SANDBOX_INSTALL_WRITE_PARCEL_ERROR;
246     }
247     if (!data.WriteInt32(appIndex)) {
248         LOG_E(BMS_TAG_INSTALLER, "failed to InstallSandboxApp due to write appIndex fail");
249         return ERR_APPEXECFWK_SANDBOX_INSTALL_WRITE_PARCEL_ERROR;
250     }
251     if (!data.WriteInt32(userId)) {
252         LOG_E(BMS_TAG_INSTALLER, "failed to InstallSandboxApp due to write userId fail");
253         return ERR_APPEXECFWK_SANDBOX_INSTALL_WRITE_PARCEL_ERROR;
254     }
255 
256     auto ret =
257         SendInstallRequest(BundleInstallerInterfaceCode::UNINSTALL_SANDBOX_APP, data, reply, option);
258     if (!ret) {
259         LOG_E(BMS_TAG_INSTALLER, "uninstall sandbox app failed due to send request fail");
260         return ERR_APPEXECFWK_SANDBOX_INSTALL_SEND_REQUEST_ERROR;
261     }
262     return reply.ReadInt32();
263 }
264 
CreateStreamInstaller(const InstallParam & installParam,const sptr<IStatusReceiver> & statusReceiver,const std::vector<std::string> & originHapPaths)265 sptr<IBundleStreamInstaller> BundleInstallerProxy::CreateStreamInstaller(const InstallParam &installParam,
266     const sptr<IStatusReceiver> &statusReceiver, const std::vector<std::string> &originHapPaths)
267 {
268     LOG_D(BMS_TAG_INSTALLER, "create stream installer begin");
269     HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
270     MessageParcel data;
271     MessageParcel reply;
272     MessageOption option(MessageOption::TF_SYNC);
273 
274     if (statusReceiver == nullptr) {
275         LOG_E(BMS_TAG_INSTALLER, "fail to install, for receiver is nullptr");
276         return nullptr;
277     }
278 
279     bool ret = data.WriteInterfaceToken(GetDescriptor());
280     if (!ret) {
281         LOG_E(BMS_TAG_INSTALLER, "fail to write interface token into the parcel");
282         statusReceiver->OnFinished(ERR_APPEXECFWK_INSTALL_INTERNAL_ERROR, "");
283         return nullptr;
284     }
285     ret = data.WriteParcelable(&installParam);
286     if (!ret) {
287         LOG_E(BMS_TAG_INSTALLER, "fail to write parameter into the parcel");
288         statusReceiver->OnFinished(ERR_APPEXECFWK_INSTALL_INTERNAL_ERROR, "");
289         return nullptr;
290     }
291     if (!data.WriteRemoteObject(statusReceiver->AsObject())) {
292         LOG_E(BMS_TAG_INSTALLER, "write parcel failed");
293         statusReceiver->OnFinished(ERR_APPEXECFWK_INSTALL_INTERNAL_ERROR, "");
294         return nullptr;
295     }
296     if (!data.WriteStringVector(originHapPaths)) {
297         LOG_E(BMS_TAG_INSTALLER, "write parcel failed");
298         statusReceiver->OnFinished(ERR_APPEXECFWK_INSTALL_INTERNAL_ERROR, "");
299         return nullptr;
300     }
301     bool res = SendInstallRequest(BundleInstallerInterfaceCode::CREATE_STREAM_INSTALLER, data, reply, option);
302     if (!res) {
303         LOG_E(BMS_TAG_INSTALLER, "CreateStreamInstaller failed due to send request fail");
304         statusReceiver->OnFinished(ERR_APPEXECFWK_INSTALL_INTERNAL_ERROR, "");
305         return nullptr;
306     }
307     if (!reply.ReadBool()) {
308         LOG_E(BMS_TAG_INSTALLER, "CreateStreamInstaller failed");
309         return nullptr;
310     }
311     uint32_t streamInstallerId = reply.ReadUint32();
312     sptr<IRemoteObject> object = reply.ReadRemoteObject();
313     if (object == nullptr) {
314         LOG_E(BMS_TAG_INSTALLER, "CreateStreamInstaller create nullptr remote object");
315         return nullptr;
316     }
317     sptr<IBundleStreamInstaller> streamInstaller = iface_cast<IBundleStreamInstaller>(object);
318     if (streamInstaller == nullptr) {
319         LOG_E(BMS_TAG_INSTALLER, "CreateStreamInstaller failed");
320         return streamInstaller;
321     }
322     streamInstaller->SetInstallerId(streamInstallerId);
323     LOG_D(BMS_TAG_INSTALLER, "create stream installer successfully");
324     return streamInstaller;
325 }
326 
DestoryBundleStreamInstaller(uint32_t streamInstallerId)327 bool BundleInstallerProxy::DestoryBundleStreamInstaller(uint32_t streamInstallerId)
328 {
329     LOG_D(BMS_TAG_INSTALLER, "destory stream installer begin");
330     HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
331     MessageParcel data;
332     MessageParcel reply;
333     MessageOption option(MessageOption::TF_SYNC);
334 
335     PARCEL_WRITE_INTERFACE_TOKEN(data, GetDescriptor());
336     PARCEL_WRITE(data, Uint32, streamInstallerId);
337     bool res = SendInstallRequest(BundleInstallerInterfaceCode::DESTORY_STREAM_INSTALLER, data, reply, option);
338     if (!res) {
339         LOG_E(BMS_TAG_INSTALLER, "CreateStreamInstaller failed due to send request fail");
340         return false;
341     }
342     LOG_D(BMS_TAG_INSTALLER, "destory stream installer successfully");
343     return true;
344 }
345 
UninstallAndRecover(const std::string & bundleName,const InstallParam & installParam,const sptr<IStatusReceiver> & statusReceiver)346 bool BundleInstallerProxy::UninstallAndRecover(const std::string &bundleName, const InstallParam &installParam,
347     const sptr<IStatusReceiver> &statusReceiver)
348 {
349     HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
350     MessageParcel reply;
351     MessageParcel data;
352     MessageOption option(MessageOption::TF_SYNC);
353 
354     PARCEL_WRITE_INTERFACE_TOKEN(data, GetDescriptor());
355     PARCEL_WRITE(data, String16, Str8ToStr16(bundleName));
356     PARCEL_WRITE(data, Parcelable, &installParam);
357     if (statusReceiver == nullptr) {
358         LOG_E(BMS_TAG_INSTALLER, "fail to uninstall quick fix, for statusReceiver is nullptr");
359         return false;
360     }
361     if (!data.WriteRemoteObject(statusReceiver->AsObject())) {
362         LOG_E(BMS_TAG_INSTALLER, "write parcel failed");
363         return false;
364     }
365 
366     return SendInstallRequest(BundleInstallerInterfaceCode::UNINSTALL_AND_RECOVER, data, reply, option);
367 }
368 
StreamInstall(const std::vector<std::string> & bundleFilePaths,const InstallParam & installParam,const sptr<IStatusReceiver> & statusReceiver)369 ErrCode BundleInstallerProxy::StreamInstall(const std::vector<std::string> &bundleFilePaths,
370     const InstallParam &installParam, const sptr<IStatusReceiver> &statusReceiver)
371 {
372     HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
373     LOG_D(BMS_TAG_INSTALLER, "stream install start");
374     if (statusReceiver == nullptr) {
375         LOG_E(BMS_TAG_INSTALLER, "stream install failed due to nullptr status receiver");
376         return ERR_APPEXECFWK_INSTALL_PARAM_ERROR;
377     }
378 
379     std::vector<std::string> realPaths;
380     if (!bundleFilePaths.empty() && !BundleFileUtil::CheckFilePath(bundleFilePaths, realPaths)) {
381         LOG_E(BMS_TAG_INSTALLER, "stream install failed due to check file failed");
382         return ERR_APPEXECFWK_INSTALL_FILE_PATH_INVALID;
383     }
384 
385     sptr<IBundleStreamInstaller> streamInstaller = CreateStreamInstaller(installParam, statusReceiver, realPaths);
386     if (streamInstaller == nullptr) {
387         LOG_E(BMS_TAG_INSTALLER, "stream install failed due to nullptr stream installer");
388         return ERR_OK;
389     }
390     ErrCode res = ERR_OK;
391     // copy hap or hsp file to bms service
392     if (!installParam.IsRenameInstall()) {
393         for (const auto &path : realPaths) {
394             res = WriteHapFileToStream(streamInstaller, path);
395             if (res != ERR_OK) {
396                 DestoryBundleStreamInstaller(streamInstaller->GetInstallerId());
397                 LOG_E(BMS_TAG_INSTALLER, "WriteHapFileToStream failed due to %{public}d", res);
398                 return res;
399             }
400         }
401     }
402     // copy sig file to bms service
403     if (!realPaths.empty() && !installParam.verifyCodeParams.empty() &&
404         (realPaths.size() != installParam.verifyCodeParams.size())) {
405         DestoryBundleStreamInstaller(streamInstaller->GetInstallerId());
406         LOG_E(BMS_TAG_INSTALLER, "size of hapFiles is not same with size of verifyCodeParams");
407         return ERR_BUNDLEMANAGER_INSTALL_CODE_SIGNATURE_FILE_IS_INVALID;
408     }
409     if ((res = CopySignatureFileToService(streamInstaller, installParam)) != ERR_OK) {
410         DestoryBundleStreamInstaller(streamInstaller->GetInstallerId());
411         LOG_E(BMS_TAG_INSTALLER, "CopySignatureFileToService failed due to %{public}d", res);
412         return res;
413     }
414     // copy pgo file to bms service
415     res = CopyPgoFileToService(streamInstaller, installParam);
416     if (res != ERR_OK) {
417         LOG_W(BMS_TAG_INSTALLER, "CopyPgoFileToService failed due to %{public}d", res);
418     }
419 
420     // write shared bundles
421     uint32_t size = static_cast<uint32_t>(installParam.sharedBundleDirPaths.size());
422     for (uint32_t i = 0; i < size; ++i) {
423         realPaths.clear();
424         std::vector<std::string> sharedBundleDir = {installParam.sharedBundleDirPaths[i]};
425         if (!BundleFileUtil::CheckFilePath(sharedBundleDir, realPaths)) {
426             LOG_E(BMS_TAG_INSTALLER, "stream install failed due to check shared package files failed");
427             DestoryBundleStreamInstaller(streamInstaller->GetInstallerId());
428             return ERR_APPEXECFWK_INSTALL_FILE_PATH_INVALID;
429         }
430         for (const auto &path : realPaths) {
431             res = WriteSharedFileToStream(streamInstaller, path, i);
432             if (res != ERR_OK) {
433                 DestoryBundleStreamInstaller(streamInstaller->GetInstallerId());
434                 LOG_E(BMS_TAG_INSTALLER, "WriteSharedFileToStream(sharedBundleDirPaths) failed due to %{public}d", res);
435                 return res;
436             }
437         }
438     }
439 
440     // start install haps
441     if (!streamInstaller->Install()) {
442         LOG_E(BMS_TAG_INSTALLER, "stream install failed");
443         DestoryBundleStreamInstaller(streamInstaller->GetInstallerId());
444         statusReceiver->OnFinished(ERR_APPEXECFWK_INSTALL_INTERNAL_ERROR, "");
445         return ERR_APPEXECFWK_INSTALL_INTERNAL_ERROR;
446     }
447     LOG_D(BMS_TAG_INSTALLER, "stream install end");
448     return ERR_OK;
449 }
450 
WriteFile(const std::string & path,int32_t outputFd)451 ErrCode BundleInstallerProxy::WriteFile(const std::string &path, int32_t outputFd)
452 {
453     LOG_D(BMS_TAG_INSTALLER, "write file stream to service terminal start");
454     std::string realPath;
455     if (!PathToRealPath(path, realPath)) {
456         LOG_E(BMS_TAG_INSTALLER, "file is not real path, file path: %{private}s", path.c_str());
457         return ERR_APPEXECFWK_INSTALL_FILE_PATH_INVALID;
458     }
459     int32_t inputFd = open(realPath.c_str(), O_RDONLY);
460     if (inputFd < 0) {
461         LOG_E(BMS_TAG_INSTALLER, "write file to stream failed due to open the hap file, errno:%{public}d", errno);
462         return ERR_APPEXECFWK_INSTALL_FILE_PATH_INVALID;
463     }
464 
465     struct stat sourceStat;
466     if (fstat(inputFd, &sourceStat) == -1) {
467         LOG_E(BMS_TAG_INSTALLER, "fstat failed, errno : %{public}d", errno);
468         close(inputFd);
469         return ERR_APPEXECFWK_INSTALL_DISK_MEM_INSUFFICIENT;
470     }
471     if (sourceStat.st_size < 0) {
472         LOG_E(BMS_TAG_INSTALLER, "invalid st_size");
473         close(inputFd);
474         return ERR_APPEXECFWK_INSTALL_DISK_MEM_INSUFFICIENT;
475     }
476 
477     size_t buffer = 524288; // 0.5M
478     size_t transferCount = 0;
479     ssize_t singleTransfer = 0;
480     while ((singleTransfer = sendfile(outputFd, inputFd, nullptr, buffer)) > 0) {
481         transferCount += static_cast<size_t>(singleTransfer);
482     }
483 
484     if (singleTransfer == -1 || transferCount != static_cast<size_t>(sourceStat.st_size)) {
485         LOG_E(BMS_TAG_INSTALLER, "errno: %{public}d, send count: %{public}zu, file size: %{public}zu",
486             errno, transferCount, static_cast<size_t>(sourceStat.st_size));
487         close(inputFd);
488         return ERR_APPEXECFWK_INSTALL_DISK_MEM_INSUFFICIENT;
489     }
490 
491     close(inputFd);
492     fsync(outputFd);
493 
494     LOG_D(BMS_TAG_INSTALLER, "write file stream to service terminal end");
495     return ERR_OK;
496 }
497 
WriteHapFileToStream(sptr<IBundleStreamInstaller> & streamInstaller,const std::string & path)498 ErrCode BundleInstallerProxy::WriteHapFileToStream(sptr<IBundleStreamInstaller> &streamInstaller,
499     const std::string &path)
500 {
501     if (streamInstaller == nullptr) {
502         LOG_E(BMS_TAG_INSTALLER, "write file to stream failed due to nullptr stream installer");
503         return ERR_APPEXECFWK_INSTALL_INTERNAL_ERROR;
504     }
505     std::string fileName;
506     ErrCode ret = ERR_OK;
507     ret = GetFileNameByFilePath(path, fileName);
508     if (ret != ERR_OK) {
509         LOG_E(BMS_TAG_INSTALLER, "invalid file path");
510         return ret;
511     }
512     LOG_D(BMS_TAG_INSTALLER, "write file stream of hap path %{public}s", path.c_str());
513 
514     int32_t outputFd = streamInstaller->CreateStream(fileName);
515     if (outputFd < 0) {
516         LOG_E(BMS_TAG_INSTALLER, "write file to stream failed due to invalid file descriptor");
517         return ERR_APPEXECFWK_INSTALL_FILE_PATH_INVALID;
518     }
519 
520     ret = WriteFile(path, outputFd);
521     close(outputFd);
522 
523     return ret;
524 }
525 
WriteSignatureFileToStream(sptr<IBundleStreamInstaller> & streamInstaller,const std::string & path,const std::string & moduleName)526 ErrCode BundleInstallerProxy::WriteSignatureFileToStream(sptr<IBundleStreamInstaller> &streamInstaller,
527     const std::string &path, const std::string &moduleName)
528 {
529     if (streamInstaller == nullptr) {
530         LOG_E(BMS_TAG_INSTALLER, "write file to stream failed due to nullptr stream installer");
531         return ERR_APPEXECFWK_INSTALL_INTERNAL_ERROR;
532     }
533     std::string fileName;
534     ErrCode ret = ERR_OK;
535     ret = GetFileNameByFilePath(path, fileName);
536     if (ret != ERR_OK) {
537         LOG_E(BMS_TAG_INSTALLER, "invalid file path");
538         return ret;
539     }
540     LOG_D(BMS_TAG_INSTALLER, "write file stream of signature path %{public}s", path.c_str());
541 
542     int32_t outputFd = streamInstaller->CreateSignatureFileStream(moduleName, fileName);
543     if (outputFd < 0) {
544         LOG_E(BMS_TAG_INSTALLER, "write file to stream failed due to invalid file descriptor");
545         return ERR_APPEXECFWK_INSTALL_FILE_PATH_INVALID;
546     }
547 
548     ret = WriteFile(path, outputFd);
549     close(outputFd);
550 
551     return ret;
552 }
553 
WriteSharedFileToStream(sptr<IBundleStreamInstaller> & streamInstaller,const std::string & path,uint32_t index)554 ErrCode BundleInstallerProxy::WriteSharedFileToStream(sptr<IBundleStreamInstaller> &streamInstaller,
555     const std::string &path, uint32_t index)
556 {
557     if (streamInstaller == nullptr) {
558         LOG_E(BMS_TAG_INSTALLER, "write file to stream failed due to nullptr stream installer");
559         return ERR_APPEXECFWK_INSTALL_INTERNAL_ERROR;
560     }
561 
562     std::string hspName;
563     ErrCode ret = ERR_OK;
564     ret = GetFileNameByFilePath(path, hspName);
565     if (ret != ERR_OK) {
566         LOG_E(BMS_TAG_INSTALLER, "invalid file path");
567         return ret;
568     }
569 
570     LOG_D(BMS_TAG_INSTALLER, "write file stream of shared path %{public}s", path.c_str());
571     int32_t outputFd = streamInstaller->CreateSharedBundleStream(hspName, index);
572     if (outputFd < 0) {
573         LOG_E(BMS_TAG_INSTALLER, "write file to stream failed due to invalid file descriptor");
574         return ERR_APPEXECFWK_INSTALL_FILE_PATH_INVALID;
575     }
576 
577     ret = WriteFile(path, outputFd);
578     close(outputFd);
579 
580     return ret;
581 }
582 
WritePgoFileToStream(sptr<IBundleStreamInstaller> & streamInstaller,const std::string & path,const std::string & moduleName)583 ErrCode BundleInstallerProxy::WritePgoFileToStream(sptr<IBundleStreamInstaller> &streamInstaller,
584     const std::string &path, const std::string &moduleName)
585 {
586     if (streamInstaller == nullptr) {
587         LOG_E(BMS_TAG_INSTALLER, "write file to stream failed due to nullptr stream installer");
588         return ERR_APPEXECFWK_INSTALL_INTERNAL_ERROR;
589     }
590 
591     std::string fileName;
592     ErrCode ret = ERR_OK;
593     ret = GetFileNameByFilePath(path, fileName);
594     if (ret != ERR_OK) {
595         LOG_E(BMS_TAG_INSTALLER, "invalid file path");
596         return ret;
597     }
598     LOG_D(BMS_TAG_INSTALLER, "write file stream of pgo path %{public}s", path.c_str());
599 
600     int32_t outputFd = streamInstaller->CreatePgoFileStream(moduleName, fileName);
601     if (outputFd < 0) {
602         LOG_E(BMS_TAG_INSTALLER, "write file to stream failed due to invalid file descriptor");
603         return ERR_APPEXECFWK_INSTALL_FILE_PATH_INVALID;
604     }
605 
606     ret = WriteFile(path, outputFd);
607     close(outputFd);
608 
609     return ret;
610 }
611 
CopySignatureFileToService(sptr<IBundleStreamInstaller> & streamInstaller,const InstallParam & installParam)612 ErrCode BundleInstallerProxy::CopySignatureFileToService(sptr<IBundleStreamInstaller> &streamInstaller,
613     const InstallParam &installParam)
614 {
615     if (streamInstaller == nullptr) {
616         LOG_E(BMS_TAG_INSTALLER, "copy file failed due to nullptr stream installer");
617         return ERR_APPEXECFWK_INSTALL_INTERNAL_ERROR;
618     }
619 
620     if (installParam.verifyCodeParams.empty()) {
621         return ERR_OK;
622     }
623     for (const auto &param : installParam.verifyCodeParams) {
624         std::string realPath;
625         if (param.first.empty() || !BundleFileUtil::CheckFilePath(param.second, realPath)) {
626             LOG_E(BMS_TAG_INSTALLER, "CheckFilePath signature file dir %{public}s failed", param.second.c_str());
627             DestoryBundleStreamInstaller(streamInstaller->GetInstallerId());
628             return ERR_BUNDLEMANAGER_INSTALL_CODE_SIGNATURE_FILE_IS_INVALID;
629         }
630         ErrCode res = WriteSignatureFileToStream(streamInstaller, realPath, param.first);
631         if (res != ERR_OK) {
632             DestoryBundleStreamInstaller(streamInstaller->GetInstallerId());
633             LOG_E(BMS_TAG_INSTALLER, "WriteSignatureFileToStream failed due to %{public}d", res);
634             return ERR_BUNDLEMANAGER_INSTALL_CODE_SIGNATURE_FILE_IS_INVALID;
635         }
636     }
637 
638     return ERR_OK;
639 }
640 
CopyPgoFileToService(sptr<IBundleStreamInstaller> & streamInstaller,const InstallParam & installParam)641 ErrCode BundleInstallerProxy::CopyPgoFileToService(sptr<IBundleStreamInstaller> &streamInstaller,
642     const InstallParam &installParam)
643 {
644     if (streamInstaller == nullptr) {
645         LOG_E(BMS_TAG_INSTALLER, "copy file failed due to nullptr stream installer");
646         return ERR_APPEXECFWK_INSTALL_INTERNAL_ERROR;
647     }
648     if (installParam.pgoParams.empty()) {
649         return ERR_OK;
650     }
651     for (const auto &param : installParam.pgoParams) {
652         std::string realPath;
653         if (param.first.empty() || !BundleFileUtil::CheckFilePath(param.second, realPath)) {
654             LOG_W(BMS_TAG_INSTALLER, "CheckFilePath pgo file path %{public}s failed", param.second.c_str());
655             continue;
656         }
657         ErrCode res = WritePgoFileToStream(streamInstaller, realPath, param.first);
658         if (res != ERR_OK) {
659             LOG_W(BMS_TAG_INSTALLER, "WritePgoFileToStream failed due to %{public}d", res);
660             continue;
661         }
662     }
663 
664     return ERR_OK;
665 }
666 
GetFileNameByFilePath(const std::string & filePath,std::string & fileName)667 ErrCode BundleInstallerProxy::GetFileNameByFilePath(const std::string &filePath, std::string &fileName)
668 {
669     size_t pos = filePath.find_last_of(SEPARATOR);
670     if (pos == std::string::npos) {
671         LOG_E(BMS_TAG_INSTALLER, "write file to stream failed due to invalid file path");
672         return ERR_APPEXECFWK_INSTALL_FILE_PATH_INVALID;
673     }
674     fileName = filePath.substr(pos + 1);
675     if (fileName.empty()) {
676         LOG_E(BMS_TAG_INSTALLER, "write file to stream failed due to invalid file path");
677         return ERR_APPEXECFWK_INSTALL_FILE_PATH_INVALID;
678     }
679     return ERR_OK;
680 }
681 
SendInstallRequest(BundleInstallerInterfaceCode code,MessageParcel & data,MessageParcel & reply,MessageOption & option)682 bool BundleInstallerProxy::SendInstallRequest(
683     BundleInstallerInterfaceCode code, MessageParcel& data, MessageParcel& reply, MessageOption& option)
684 {
685     sptr<IRemoteObject> remote = Remote();
686     if (remote == nullptr) {
687         LOG_E(BMS_TAG_INSTALLER, "fail to uninstall, for Remote() is nullptr");
688         return false;
689     }
690 
691     int32_t ret = remote->SendRequest(static_cast<uint32_t>(code), data, reply, option);
692     if (ret != NO_ERROR) {
693         LOG_E(BMS_TAG_INSTALLER, "fail to sendRequest, for transact is failed and error code is: %{public}d", ret);
694         return false;
695     }
696     return true;
697 }
698 
InstallCloneApp(const std::string & bundleName,int32_t userId,int32_t & appIndex)699 ErrCode BundleInstallerProxy::InstallCloneApp(const std::string &bundleName, int32_t userId, int32_t& appIndex)
700 {
701     HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
702     MessageParcel data;
703     MessageParcel reply;
704     MessageOption option(MessageOption::TF_SYNC);
705 
706     if (!data.WriteInterfaceToken(GetDescriptor())) {
707         LOG_E(BMS_TAG_INSTALLER, "failed to InstallCloneApp due to write MessageParcel fail");
708         return ERR_APPEXECFWK_CLONE_INSTALL_WRITE_PARCEL_ERROR;
709     }
710     if (!data.WriteString16(Str8ToStr16(bundleName))) {
711         LOG_E(BMS_TAG_INSTALLER, "failed to InstallCloneApp due to write bundleName fail");
712         return ERR_APPEXECFWK_CLONE_INSTALL_WRITE_PARCEL_ERROR;
713     }
714     if (!data.WriteInt32(userId)) {
715         LOG_E(BMS_TAG_INSTALLER, "failed to InstallCloneApp due to write userId fail");
716         return ERR_APPEXECFWK_CLONE_INSTALL_WRITE_PARCEL_ERROR;
717     }
718     if (!data.WriteInt32(appIndex)) {
719         LOG_E(BMS_TAG_INSTALLER, "failed to InstallCloneApp due to write appIndex fail");
720         return ERR_APPEXECFWK_CLONE_INSTALL_WRITE_PARCEL_ERROR;
721     }
722 
723     auto ret =
724         SendInstallRequest(BundleInstallerInterfaceCode::INSTALL_CLONE_APP, data, reply, option);
725     if (!ret) {
726         LOG_E(BMS_TAG_INSTALLER, "install clone app failed due to send request fail");
727         return ERR_APPEXECFWK_CLONE_INSTALL_SEND_REQUEST_ERROR;
728     }
729 
730     auto res = reply.ReadInt32();
731     if (res == ERR_OK) {
732         appIndex = reply.ReadInt32();
733     }
734     return res;
735 }
736 
UninstallCloneApp(const std::string & bundleName,int32_t userId,int32_t appIndex)737 ErrCode BundleInstallerProxy::UninstallCloneApp(const std::string &bundleName, int32_t userId, int32_t appIndex)
738 {
739     HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
740     MessageParcel data;
741     MessageParcel reply;
742     MessageOption option(MessageOption::TF_SYNC);
743 
744     if (!data.WriteInterfaceToken(GetDescriptor())) {
745         LOG_E(BMS_TAG_INSTALLER, "failed to UninstallCloneApp due to write MessageParcel fail");
746         return ERR_APPEXECFWK_CLONE_UNINSTALL_WRITE_PARCEL_ERROR;
747     }
748     if (!data.WriteString16(Str8ToStr16(bundleName))) {
749         LOG_E(BMS_TAG_INSTALLER, "failed to UninstallCloneApp due to write bundleName fail");
750         return ERR_APPEXECFWK_CLONE_UNINSTALL_WRITE_PARCEL_ERROR;
751     }
752     if (!data.WriteInt32(userId)) {
753         LOG_E(BMS_TAG_INSTALLER, "failed to UninstallCloneApp due to write userId fail");
754         return ERR_APPEXECFWK_CLONE_UNINSTALL_WRITE_PARCEL_ERROR;
755     }
756     if (!data.WriteInt32(appIndex)) {
757         LOG_E(BMS_TAG_INSTALLER, "failed to UninstallCloneApp due to write appIndex fail");
758         return ERR_APPEXECFWK_CLONE_UNINSTALL_WRITE_PARCEL_ERROR;
759     }
760 
761     auto ret =
762         SendInstallRequest(BundleInstallerInterfaceCode::UNINSTALL_CLONE_APP, data, reply, option);
763     if (!ret) {
764         LOG_E(BMS_TAG_INSTALLER, "uninstall clone app failed due to send request fail");
765         return ERR_APPEXECFWK_CLONE_UNINSTALL_SEND_REQUEST_ERROR;
766     }
767     return reply.ReadInt32();
768 }
769 
InstallExisted(const std::string & bundleName,int32_t userId)770 ErrCode BundleInstallerProxy::InstallExisted(const std::string &bundleName, int32_t userId)
771 {
772     HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__);
773     MessageParcel data;
774     MessageParcel reply;
775     MessageOption option(MessageOption::TF_SYNC);
776 
777     if (!data.WriteInterfaceToken(GetDescriptor())) {
778         LOG_E(BMS_TAG_INSTALLER, "failed to write descriptor");
779         return ERR_APPEXECFWK_INSTALL_EXISTED_WRITE_PARCEL_ERROR;
780     }
781     if (!data.WriteString16(Str8ToStr16(bundleName))) {
782         LOG_E(BMS_TAG_INSTALLER, "failed to write bundleName");
783         return ERR_APPEXECFWK_INSTALL_EXISTED_WRITE_PARCEL_ERROR;
784     }
785     if (!data.WriteInt32(userId)) {
786         LOG_E(BMS_TAG_INSTALLER, "failed to write userId");
787         return ERR_APPEXECFWK_INSTALL_EXISTED_WRITE_PARCEL_ERROR;
788     }
789 
790     auto ret =
791         SendInstallRequest(BundleInstallerInterfaceCode::INSTALL_EXISTED, data, reply, option);
792     if (!ret) {
793         LOG_E(BMS_TAG_INSTALLER, "installExisted failed due to send request fail");
794         return ERR_APPEXECFWK_INSTALL_EXISTED_WRITE_PARCEL_ERROR;
795     }
796 
797     return reply.ReadInt32();
798 }
799 }  // namespace AppExecFwk
800 }  // namespace OHOS
801