• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2020 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_daemon_client.h"
17 
18 #include <cstring>
19 #include <string>
20 
21 #include "adapter.h"
22 #include "bundle_daemon_interface.h"
23 #include "bundle_log.h"
24 #include "iproxy_client.h"
25 #include "ohos_errno.h"
26 #include "samgr_lite.h"
27 #include "utils.h"
28 
29 namespace OHOS {
30 namespace {
31 constexpr unsigned SLEEP_TIME = 200000;
32 }
33 #ifdef __LINUX__
Notify(IOwner owner,int code,IpcIo * reply)34 int BundleDaemonClient::Notify(IOwner owner, int code, IpcIo *reply)
35 {
36     if ((reply == nullptr) || (owner == nullptr)) {
37         HILOG_ERROR(HILOG_MODULE_APP, "BundleManager Notify ipc is nullptr");
38         return OHOS_FAILURE;
39     }
40     BundleDaemonClient *client = reinterpret_cast<BundleDaemonClient *>(owner);
41     if (client == nullptr) {
42         return EC_INVALID;
43     }
44     client->result_ = IpcIoPopInt32(reply);
45     int value;
46     sem_getvalue(&client->sem_, &value);
47     if (value <= 0) {
48         sem_post(&client->sem_);
49     }
50     return EC_SUCCESS;
51 }
52 #else
BundleDaemonCallback(const IpcContext * context,void * ipcMsg,IpcIo * io,void * arg)53 int32_t BundleDaemonClient::BundleDaemonCallback(const IpcContext* context, void *ipcMsg, IpcIo *io, void *arg)
54 {
55     BundleDaemonClient *client = reinterpret_cast<BundleDaemonClient *>(arg);
56     if (client == nullptr) {
57         if (ipcMsg != nullptr) {
58             FreeBuffer(nullptr, ipcMsg);
59         }
60         return EC_INVALID;
61     }
62 
63     client->result_ = IpcIoPopInt32(io);
64     if (ipcMsg != nullptr) {
65         FreeBuffer(nullptr, ipcMsg);
66     }
67     int value;
68     sem_getvalue(&client->sem_, &value);
69     if (value <= 0) {
70         sem_post(&client->sem_);
71     }
72     return EC_SUCCESS;
73 }
74 #endif
75 
DeathCallback(const IpcContext * context,void * ipcMsg,IpcIo * data,void * arg)76 int32_t BundleDaemonClient::DeathCallback(const IpcContext* context, void* ipcMsg, IpcIo* data, void* arg)
77 {
78     if (ipcMsg != nullptr) {
79         FreeBuffer(nullptr, ipcMsg);
80     }
81     pthread_t pid;
82     if (pthread_create(&pid, nullptr, RegisterDeathCallback, arg) == 0) {
83         return EC_SUCCESS;
84     }
85 
86     BundleDaemonClient *client = reinterpret_cast<BundleDaemonClient *>(arg);
87     if (client != nullptr) {
88         client->result_ = EC_CANCELED;
89         int value;
90         sem_getvalue(&client->sem_, &value);
91         if (value <= 0) {
92             sem_post(&client->sem_);
93         }
94     }
95     return EC_INVALID;
96 }
97 
~BundleDaemonClient()98 BundleDaemonClient::~BundleDaemonClient()
99 {
100     if (initialized_) {
101         UnregisterIpcCallback(svcIdentity_);
102         UnregisterDeathCallback(bdsSvcIdentity_, cbid_);
103         bdsClient_->Release(reinterpret_cast<IUnknown *>(bdsClient_));
104         bdsClient_ = nullptr;
105         sem_destroy(&sem_);
106     }
107 }
108 
Initialize()109 bool BundleDaemonClient::Initialize()
110 {
111     if (initialized_) {
112         PRINTI("BundleDaemonClient", "already initialized");
113         return true;
114     }
115     if (sem_init(&sem_, 0, 0) != 0) {
116         PRINTE("BundleDaemonClient", "sem_init fail");
117         return false;
118     }
119 
120     while (bdsClient_ == nullptr) {
121         IUnknown *iUnknown = SAMGR_GetInstance()->GetDefaultFeatureApi(BDS_SERVICE);
122         if (iUnknown == nullptr) {
123             usleep(SLEEP_TIME);
124             continue;
125         }
126 
127         (void)iUnknown->QueryInterface(iUnknown, CLIENT_PROXY_VER, (void **)&bdsClient_);
128     }
129 
130     // register bundle_daemon callback
131 #ifndef __LINUX__
132     int32_t ret = RegisterIpcCallback(
133         BundleDaemonClient::BundleDaemonCallback, 0, IPC_WAIT_FOREVER, &svcIdentity_, this);
134     if (ret != EC_SUCCESS) {
135         PRINTE("BundleDaemonClient", "register bundle_daemon RegisterIpcCallback fail");
136         sem_destroy(&sem_);
137         return false;
138     }
139 #endif
140     if (RegisterCallback() != LITEIPC_OK) {
141         PRINTE("BundleDaemonClient", "register bundle_daemon callback fail");
142         sem_destroy(&sem_);
143         return false;
144     }
145 
146     // register bundle_daemon death callback
147     bdsSvcIdentity_ = SAMGR_GetRemoteIdentity(BDS_SERVICE, nullptr);
148     if (::RegisterDeathCallback(nullptr, bdsSvcIdentity_, &BundleDaemonClient::DeathCallback, this, &cbid_) !=
149         LITEIPC_OK) {
150         PRINTW("BundleDaemonClient", "register bundle_daemon death callback fail");
151         // Keep running if register death callback fail
152     }
153 
154     initialized_ = true;
155     return true;
156 }
157 
RegisterDeathCallback(void * arg)158 void *BundleDaemonClient::RegisterDeathCallback(void *arg)
159 {
160     BundleDaemonClient *client = reinterpret_cast<BundleDaemonClient *>(arg);
161     if (client == nullptr) {
162         return nullptr;
163     }
164     client->result_ = EC_CANCELED;
165     int value;
166     sem_getvalue(&client->sem_, &value);
167     if (value <= 0) {
168         sem_post(&client->sem_);
169     }
170     // Register invoke callback and death callback again
171     Lock<Mutex> lock(client->mutex_);
172     client->RegisterCallback();
173 
174     UnregisterDeathCallback(client->bdsSvcIdentity_, client->cbid_);
175     client->cbid_ = INVALID_INDEX;
176     client->bdsSvcIdentity_.handle = INVALID_INDEX;
177     client->bdsSvcIdentity_.token = INVALID_INDEX;
178 
179     client->bdsSvcIdentity_ = SAMGR_GetRemoteIdentity(BDS_SERVICE, nullptr);
180     if (::RegisterDeathCallback(nullptr, client->bdsSvcIdentity_, &BundleDaemonClient::DeathCallback,
181         client, &client->cbid_) != LITEIPC_OK) {
182         PRINTW("BundleDeamonClient", "register death callback fail");
183         // Keep running if register death callback fail
184     }
185 
186     return nullptr;
187 }
188 
WaitResultSync(int32_t result)189 int32_t BundleDaemonClient::WaitResultSync(int32_t result)
190 {
191     if (result == EC_SUCCESS) {
192         sem_wait(&sem_);
193         result = result_;
194         result_ = EC_FAILURE;
195     }
196     return result;
197 }
198 
RegisterCallback()199 int32_t BundleDaemonClient::RegisterCallback()
200 {
201     IpcIo request;
202     char data[IPC_IO_DATA_MAX];
203     IpcIoInit(&request, data, IPC_IO_DATA_MAX, 1);
204     IpcIoPushSvc(&request, &svcIdentity_);
205 #ifdef __LINUX__
206     while (bdsClient_->Invoke(bdsClient_, REGISTER_CALLBACK, &request, this, Notify) != EC_SUCCESS) {
207 #else
208     while (bdsClient_->Invoke(bdsClient_, REGISTER_CALLBACK, &request, nullptr, nullptr) != EC_SUCCESS) {
209 #endif
210         PRINTI("BundleDaemonClient", "register bundle_daemon callback fail");
211         usleep(SLEEP_TIME);
212     }
213     return WaitResultSync(EC_SUCCESS);
214 }
215 
216 int32_t BundleDaemonClient::CallClientInvoke(int32_t funcId, const char *firstPath, const char *secondPath)
217 {
218     IpcIo request;
219     char data[IPC_IO_DATA_MAX];
220 #ifdef __LINUX__
221     IpcIoInit(&request, data, IPC_IO_DATA_MAX, 0);
222 #else
223     IpcIoInit(&request, data, IPC_IO_DATA_MAX, 1);
224 #endif
225     std::string innerStr = firstPath;
226     innerStr += secondPath;
227 #ifdef __LINUX__
228     IpcIoPushString(&request, innerStr.c_str());
229 #else
230     BuffPtr dataBuff = {
231         .buffSz = innerStr.length() + 1,
232         .buff = const_cast<char *>(innerStr.c_str())
233     };
234     IpcIoPushDataBuff(&request, &dataBuff);
235 #endif
236     IpcIoPushUint16(&request, strlen(firstPath));
237     if (!IpcIoAvailable(&request)) {
238         PRINTE("BundleDaemonClient", "BundleDaemonClient GenerateRequest ipc failed");
239         return EC_FAILURE;
240     }
241 
242     Lock<Mutex> lock(mutex_);
243 #ifdef __LINUX__
244     return WaitResultSync(bdsClient_->Invoke(bdsClient_, funcId, &request, this, Notify));
245 #else
246     return WaitResultSync(bdsClient_->Invoke(bdsClient_, funcId, &request, nullptr, nullptr));
247 #endif
248 }
249 
250 int32_t BundleDaemonClient::ExtractHap(const char *hapFile, const char *codePath)
251 {
252     if (!initialized_) {
253         return EC_NOINIT;
254     }
255     if (hapFile == nullptr || codePath == nullptr) {
256         PRINTE("BundleDaemonClient", "invalid params: hapFile or codePath is nullptr");
257         return EC_INVALID;
258     }
259 
260     return CallClientInvoke(EXTRACT_HAP, hapFile, codePath);
261 }
262 
263 int32_t BundleDaemonClient::RenameFile(const char *oldFile, const char *newFile)
264 {
265     if (!initialized_) {
266         return EC_NOINIT;
267     }
268     if (oldFile == nullptr || newFile == nullptr) {
269         PRINTE("BundleDaemonClient", "invalid params: oldDir or newDir is nullptr");
270         return EC_INVALID;
271     }
272 
273     return CallClientInvoke(RENAME_DIR, oldFile, newFile);
274 }
275 
276 int32_t BundleDaemonClient::CreatePermissionDir()
277 {
278     if (!initialized_) {
279         return EC_NOINIT;
280     }
281     Lock<Mutex> lock(mutex_);
282 #ifdef __LINUX__
283     return WaitResultSync(bdsClient_->Invoke(bdsClient_, CREATE_PERMISSION_DIR, nullptr, this, Notify));
284 #else
285     return WaitResultSync(bdsClient_->Invoke(bdsClient_, CREATE_PERMISSION_DIR, nullptr, nullptr, nullptr));
286 #endif
287 }
288 
289 int32_t BundleDaemonClient::CreateDataDirectory(const char *dataPath, int32_t uid, int32_t gid, bool isChown)
290 {
291     if (!initialized_) {
292         return EC_NOINIT;
293     }
294     if (dataPath == nullptr) {
295         PRINTE("BundleDaemonClient", "invalid params: bundleName is nullptr");
296         return EC_INVALID;
297     }
298     IpcIo request;
299     char data[IPC_IO_DATA_MAX];
300     IpcIoInit(&request, data, IPC_IO_DATA_MAX, 0);
301     IpcIoPushString(&request, dataPath);
302     IpcIoPushInt32(&request, uid);
303     IpcIoPushInt32(&request, gid);
304     IpcIoPushBool(&request, isChown);
305 
306     Lock<Mutex> lock(mutex_);
307 #ifdef __LINUX__
308     return WaitResultSync(bdsClient_->Invoke(bdsClient_, CREATE_DATA_DIRECTORY, &request, this, Notify));
309 #else
310     return WaitResultSync(bdsClient_->Invoke(bdsClient_, CREATE_DATA_DIRECTORY, &request, nullptr, nullptr));
311 #endif
312 }
313 
314 int32_t BundleDaemonClient::StoreContentToFile(const char *file, const void *buffer, uint32_t size)
315 {
316     if (!initialized_) {
317         return EC_NOINIT;
318     }
319     if (file == nullptr || buffer == nullptr || size == 0) {
320         PRINTE("BundleDaemonClient", "invalid params");
321         return EC_INVALID;
322     }
323     IpcIo request;
324     char data[IPC_IO_DATA_MAX];
325 #ifdef __LINUX__
326     IpcIoInit(&request, data, IPC_IO_DATA_MAX, 0);
327 #else
328     IpcIoInit(&request, data, IPC_IO_DATA_MAX, 1);
329 #endif
330     IpcIoPushString(&request, file);
331 #ifdef __LINUX__
332     IpcIoPushString(&request, static_cast<const char *>(buffer));
333 #else
334     BuffPtr dataBuff = {
335         .buffSz = size, // include \0
336         .buff = const_cast<void *>(buffer)
337     };
338     IpcIoPushDataBuff(&request, &dataBuff);
339 #endif
340     Lock<Mutex> lock(mutex_);
341 #ifdef __LINUX__
342     return WaitResultSync(bdsClient_->Invoke(bdsClient_, STORE_CONTENT_TO_FILE, &request, this, Notify));
343 #else
344     return WaitResultSync(bdsClient_->Invoke(bdsClient_, STORE_CONTENT_TO_FILE, &request, nullptr, nullptr));
345 #endif
346 }
347 
348 int32_t BundleDaemonClient::MoveFile(const char *oldFile, const char *newFile)
349 {
350     if (!initialized_) {
351         return EC_NOINIT;
352     }
353     if ((oldFile == nullptr) || (newFile == nullptr)) {
354         PRINTE("BundleDaemonClient", "invalid params");
355         return EC_INVALID;
356     }
357     IpcIo request;
358     char data[IPC_IO_DATA_MAX];
359     IpcIoInit(&request, data, IPC_IO_DATA_MAX, 0);
360     IpcIoPushString(&request, oldFile);
361     IpcIoPushString(&request, newFile);
362 
363     Lock<Mutex> lock(mutex_);
364 #ifdef __LINUX__
365     return WaitResultSync(bdsClient_->Invoke(bdsClient_, MOVE_FILE, &request, this, Notify));
366 #else
367     return WaitResultSync(bdsClient_->Invoke(bdsClient_, MOVE_FILE, &request, nullptr, nullptr));
368 #endif
369 }
370 
371 int32_t BundleDaemonClient::RemoveFile(const char *file)
372 {
373     if (!initialized_) {
374         return EC_NOINIT;
375     }
376     if (file == nullptr) {
377         PRINTE("BundleDaemonClient", "invalid params");
378         return EC_INVALID;
379     }
380     IpcIo request;
381     char data[IPC_IO_DATA_MAX];
382     IpcIoInit(&request, data, IPC_IO_DATA_MAX, 0);
383     IpcIoPushString(&request, file);
384 
385     Lock<Mutex> lock(mutex_);
386 #ifdef __LINUX__
387     return WaitResultSync(bdsClient_->Invoke(bdsClient_, REMOVE_FILE, &request, this, Notify));
388 #else
389     return WaitResultSync(bdsClient_->Invoke(bdsClient_, REMOVE_FILE, &request, nullptr, nullptr));
390 #endif
391 }
392 
393 int32_t BundleDaemonClient::RemoveInstallDirectory(const char *codePath, const char *dataPath, bool keepData)
394 {
395     if (!initialized_) {
396         return EC_NOINIT;
397     }
398     if (codePath == nullptr || dataPath == nullptr) {
399         PRINTE("BundleDaemonClient", "invalid params: bundleName is nullptr");
400         return EC_INVALID;
401     }
402 
403     return CallClientInvoke(REMOVE_INSTALL_DIRECTORY, codePath, dataPath);
404 }
405 } // OHOS
406