• 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 "command_parser.h"
17 
18 #include <climits>
19 #include <cstdint>
20 #include <getopt.h>
21 #include <iostream>
22 #include <pthread.h>
23 #include <semaphore.h>
24 
25 #include "adapter.h"
26 #include "appexecfwk_errors.h"
27 #include "bundle_info.h"
28 #include "bundle_inner_interface.h"
29 #include "bundle_manager.h"
30 #include "convert_utils.h"
31 #include "iproxy_client.h"
32 #include "liteipc_adapter.h"
33 #include "parameter.h"
34 #include "samgr_lite.h"
35 #include "securec.h"
36 
37 using namespace std;
38 
39 namespace OHOS {
40 namespace {
41 const int32_t MIN_ARGUMENT_NUMBER = 2;
42 const int32_t MAX_ARGUMENT_NUMBER = 4;
43 const int32_t MAX_LOG_LEN = 1024;
44 const int32_t MAX_DUMP_LIST_NUMBER = 3;
45 const int32_t UDID_STRING_LEN = 64;
46 const uint32_t INITIAL_CBID = 1;
47 
48 static sem_t g_sem;
49 static IClientProxy *g_bmsInnerClient = nullptr;
50 static InstallParam g_installParam = { .installLocation = 1, .keepData = false };
51 
52 const std::string CMD_INSTALL = "install";
53 const std::string CMD_UNINSTALL = "uninstall";
54 const std::string CMD_DUMP = "dump";
55 const std::string CMD_ENABLE = "set";
56 const std::string CMD_GET_UDID = "getudid";
57 
58 const std::string INSTALL_HELP_MESSAGE = "Usage: install hap-path [options]\n"
59                                    "Description:\n"
60                                    "\t--help|-h                   help menu\n"
61                                    "\t--happath|-p           location of the hap to install\n";
62 const std::string UNINSTALL_HELP_MESSAGE = "Usage: uninstall bundle-name [options]\n"
63                                      "Description:\n"
64                                      "\t--help|-h                   help menu\n"
65                                      "\t--bundlename|-n           name of the bundle to uninstall\n";
66 const std::string DUMP_HELP_MESSAGE = "Usage: dump [options]\n"
67                                       "Option Description:\n"
68                                       "\t--help|-h                   help menu\n"
69                                       "\t--list|-l                   app list\n"
70                                       "\t--bundlename|-n           dump installed hap's info\n"
71                                       "\t--metadatakey|-m           dump bundleNames match metaData key\n";
72 const std::string ENABLE_HELP_MESSAGE = "Usage: set [options]\n"
73                                         "Option Description:\n"
74                                         "\t--externalmode|-e status    enable externalmode\n"
75                                         "\t--debugmode|-d  status      enable debugmode\n"
76                                         "\t--signmode|-s  status      enable signmode\n";
77 
78 const std::string HELP_MESSAGE = INSTALL_HELP_MESSAGE + UNINSTALL_HELP_MESSAGE + DUMP_HELP_MESSAGE +
79     ENABLE_HELP_MESSAGE;
80 const std::string ERROR_COMMAND = "error command!\n";
81 const std::string ERROR_OPTION = "error option!\n";
82 const std::string ERROR_INSTALL_PATH = "invalid path!\n";
83 const std::string ERROR_EXTRA_PARAMETER = "extra parameter!\n";
84 const std::string ERROR_SEM_ERROR = "sem init failed!\n";
85 const std::string ERROR_DUMP_FAIL = "no bundle info!\n";
86 const std::string ERROR_DUMP_ERROR = "dump info error!\n";
87 
88 const std::string SHORT_OPTIONS = "n:hlp:m:";
89 const struct option LONG_OPTIONS[] = {
90     {"help", no_argument, nullptr, 'h'},
91     {"list", no_argument, nullptr, 'l'},
92     {"bundlename", required_argument, nullptr, 'n'},
93     {"happath", required_argument, nullptr, 'p'},
94     {"metadatakey", required_argument, nullptr, 'm'},
95     {nullptr, 0, nullptr, 0}
96 };
97 
98 #ifdef OHOS_DEBUG
99 const std::string ENABLE_SHORT_OPTIONS = "he:d:s:";
100 const struct option ENABLE_LONG_OPTIONS[] = {
101     {"help", no_argument, nullptr, 'h'},
102     {"externalmode", required_argument, nullptr, 'e'},
103     {"debugmode", required_argument, nullptr, 'd'},
104     {"signmode", required_argument, nullptr, 's'},
105     {nullptr, 0, nullptr, 0}
106 };
107 #endif
108 
GetBmsInnerClient()109 IClientProxy *GetBmsInnerClient()
110 {
111     IUnknown *iUnknown = SAMGR_GetInstance()->GetFeatureApi(BMS_SERVICE, BMS_INNER_FEATURE);
112     if (iUnknown == nullptr) {
113         printf("get feature api fail!\n");
114         return nullptr;
115     }
116     IClientProxy *bmsClient = nullptr;
117     int result = iUnknown->QueryInterface(iUnknown, CLIENT_PROXY_VER, reinterpret_cast<void **>(&bmsClient));
118     if (result != 0) {
119         printf("query interface fail!\n");
120         return nullptr;
121     }
122     return bmsClient;
123 }
124 } // namespace
125 
HandleCommands(int32_t argc,char * argv[]) const126 void CommandParser::HandleCommands(int32_t argc, char *argv[]) const
127 {
128     if (argc < MIN_ARGUMENT_NUMBER) {
129         printf("%s\n", HELP_MESSAGE.c_str());
130         return;
131     }
132     g_bmsInnerClient = GetBmsInnerClient();
133     std::string cmd = argv[1];
134     if (cmd == CMD_INSTALL) {
135         RunAsInstallCommand(argc, argv);
136     } else if (cmd == CMD_UNINSTALL) {
137         RunAsUninstallCommand(argc, argv);
138     } else if (cmd == CMD_DUMP) {
139         RunAsDumpCommand(argc, argv);
140     } else if (cmd == CMD_GET_UDID) {
141         RunAsGetUdidCommand(argc, argv);
142 #ifdef OHOS_DEBUG
143     } else if (cmd == CMD_ENABLE) {
144         RunAsEnableCommand(argc, argv);
145 #endif
146     } else {
147         printf("%s\n", (ERROR_COMMAND + HELP_MESSAGE).c_str());
148     }
149 }
150 
ReceiveCallback(const uint8_t resultCode,const void * resultMessage)151 static void ReceiveCallback(const uint8_t resultCode, const void *resultMessage)
152 {
153     std::string strMessage = reinterpret_cast<const char *>(resultMessage);
154     if (!strMessage.empty()) {
155         printf("resultMessage is %s\n", strMessage.c_str());
156     }
157     sem_post(&g_sem);
158 }
159 
BmToolDeathNotify(const IpcContext * context,void * ipcMsg,IpcIo * data,void * arg)160 static int32 BmToolDeathNotify(const IpcContext* context, void *ipcMsg, IpcIo *data, void *arg)
161 {
162     FreeBuffer(nullptr, ipcMsg);
163     printf("error message: %s\n", "Bundle Manager Service is dead");
164     exit(-1);
165 }
166 
RunAsInstallCommand(int32_t argc,char * argv[]) const167 void CommandParser::RunAsInstallCommand(int32_t argc, char *argv[]) const
168 {
169     if (argc > MAX_ARGUMENT_NUMBER) {
170         printf("%s\n", (ERROR_EXTRA_PARAMETER + INSTALL_HELP_MESSAGE).c_str());
171         return;
172     }
173 
174     int32_t option;
175     char realPath[PATH_MAX + 1] = { 0 };
176     uint32_t cbId = INITIAL_CBID;
177     SvcIdentity sid = SAMGR_GetRemoteIdentity(BMS_SERVICE, BMS_INNER_FEATURE);
178     while ((option = getopt_long_only(argc, argv, SHORT_OPTIONS.c_str(), LONG_OPTIONS, nullptr)) != -1) {
179         switch (option) {
180             case 'h':
181                 printf("%s\n", INSTALL_HELP_MESSAGE.c_str());
182                 break;
183             case 'p':
184                 if (sem_init(&g_sem, 0, 0)) {
185                     printf("error message: %s\n", ERROR_SEM_ERROR.c_str());
186                     return;
187                 }
188                 if (optarg == nullptr || strlen(optarg) > PATH_MAX) {
189                     printf("error message: %s\n", ERROR_INSTALL_PATH.c_str());
190                     return;
191                 }
192                 if (realpath(optarg, realPath) == nullptr) {
193                     printf("error message: %s\n", ERROR_INSTALL_PATH.c_str());
194                     return;
195                 }
196                 if (RegisterDeathCallback(nullptr, sid, BmToolDeathNotify, nullptr, &cbId) != LITEIPC_OK) {
197                     printf("error message: %s\n", "death callback is registered unsuccessfully");
198                     return;
199                 }
200                 Install(realPath, &g_installParam, ReceiveCallback);
201                 sem_wait(&g_sem);
202                 break;
203             default:
204                 printf("%s\n", (ERROR_OPTION + INSTALL_HELP_MESSAGE).c_str());
205                 break;
206         }
207     }
208 }
209 
RunAsUninstallCommand(int32_t argc,char * argv[]) const210 void CommandParser::RunAsUninstallCommand(int32_t argc, char *argv[]) const
211 {
212     if (argc > MAX_ARGUMENT_NUMBER) {
213         printf("%s\n", (ERROR_EXTRA_PARAMETER + UNINSTALL_HELP_MESSAGE).c_str());
214         return;
215     }
216 
217     int32_t option;
218     uint32_t cbId = INITIAL_CBID;
219     SvcIdentity sid = SAMGR_GetRemoteIdentity(BMS_SERVICE, BMS_INNER_FEATURE);
220     while ((option = getopt_long_only(argc, argv, SHORT_OPTIONS.c_str(), LONG_OPTIONS, nullptr)) != -1) {
221         switch (option) {
222             case 'h':
223                 printf("%s\n", UNINSTALL_HELP_MESSAGE.c_str());
224                 break;
225             case 'n':
226                 if (sem_init(&g_sem, 0, 0)) {
227                     printf("error message: %s\n", ERROR_SEM_ERROR.c_str());
228                     return;
229                 }
230                 if (RegisterDeathCallback(nullptr, sid, BmToolDeathNotify, nullptr, &cbId) != LITEIPC_OK) {
231                     printf("error message: %s\n", "death callback is registered unsuccessfully");
232                     return;
233                 }
234                 Uninstall(optarg, &g_installParam, ReceiveCallback);
235                 sem_wait(&g_sem);
236                 break;
237             default:
238                 printf("%s\n", (ERROR_OPTION + UNINSTALL_HELP_MESSAGE).c_str());
239                 break;
240         }
241     }
242 }
243 
RunAsDumpCommand(int32_t argc,char * argv[]) const244 void CommandParser::RunAsDumpCommand(int32_t argc, char *argv[]) const
245 {
246     if (argc > MAX_ARGUMENT_NUMBER) {
247         printf("%s\n", (ERROR_EXTRA_PARAMETER + DUMP_HELP_MESSAGE).c_str());
248         return;
249     }
250 
251     int32_t option = getopt_long_only(argc, argv, SHORT_OPTIONS.c_str(), LONG_OPTIONS, nullptr);
252     switch (option) {
253         case 'h':
254             printf("%s\n", DUMP_HELP_MESSAGE.c_str());
255             break;
256         case 'n':
257             GetInstallBundleInfo(optarg);
258             break;
259         case 'l':
260             GetInstallBundleInfos(argc);
261             break;
262         case 'm':
263             GetBundleInfosByMetaDataKey(optarg);
264             break;
265         default:
266             printf("%s\n", (ERROR_OPTION + DUMP_HELP_MESSAGE).c_str());
267             break;
268     }
269 }
270 
RunAsGetUdidCommand(int32_t argc,char * argv[]) const271 void CommandParser::RunAsGetUdidCommand(int32_t argc, char *argv[]) const
272 {
273     if (argc > MAX_ARGUMENT_NUMBER) {
274         printf("%s\n", (ERROR_EXTRA_PARAMETER + DUMP_HELP_MESSAGE).c_str());
275         return;
276     }
277 
278     char udid[UDID_STRING_LEN + 1] = {0};
279     if (memset_s(udid, sizeof(udid), 0, sizeof(udid)) != EOK) {
280         printf("GetUdid error memset\n");
281         return;
282     }
283     char *devUdid = udid;
284     int ret = GetDevUdid(devUdid, sizeof(udid));
285     if (ret == EOK) {
286         cout << devUdid << endl;
287     } else {
288         cout << "Get Udid error ret = " << ret << endl;
289     }
290 }
291 
292 #ifdef OHOS_DEBUG
RunAsEnableCommand(int32_t argc,char * argv[]) const293 void CommandParser::RunAsEnableCommand(int32_t argc, char *argv[]) const
294 {
295     if (argc > MAX_ARGUMENT_NUMBER) {
296         printf("%s\n", (ERROR_EXTRA_PARAMETER + ENABLE_HELP_MESSAGE).c_str());
297         return;
298     }
299 
300     int32_t option = getopt_long_only(argc, argv, ENABLE_SHORT_OPTIONS.c_str(), ENABLE_LONG_OPTIONS, nullptr);
301     switch (option) {
302         case 'h':
303             printf("%s\n", ENABLE_HELP_MESSAGE.c_str());
304             break;
305         case 'd':
306             SetDebugMode(optarg, SET_SIGN_DEBUG_MODE);
307             break;
308         case 'e':
309             SetDebugMode(optarg, SET_EXTERNAL_INSTALL_MODE);
310             break;
311         case 's':
312             SetDebugMode(optarg, SET_SIGN_MODE);
313             break;
314         default:
315             printf("%s\n", (ERROR_OPTION + ENABLE_HELP_MESSAGE).c_str());
316             break;
317     }
318 }
319 #endif
320 
GetInstallBundleInfo(const std::string & bundleName) const321 void CommandParser::GetInstallBundleInfo(const std::string &bundleName) const
322 {
323     BundleInfo bundleInfo;
324     if (memset_s(&bundleInfo, sizeof(BundleInfo), 0, sizeof(BundleInfo)) != EOK) {
325         printf("error message: %s\n", ERROR_DUMP_ERROR.c_str());
326         return;
327     }
328     if (GetBundleInfo(bundleName.c_str(), 1, &bundleInfo) != OHOS_SUCCESS) {
329         printf("error message: %s\n", ERROR_DUMP_FAIL.c_str());
330         return;
331     }
332 
333     cJSON *root = ConvertUtils::GetJsonBundleInfo(&bundleInfo);
334     if (root == nullptr) {
335         ClearBundleInfo(&bundleInfo);
336         printf("error message: %s\n", ERROR_DUMP_ERROR.c_str());
337         return;
338     }
339 
340     char *str = cJSON_PrintUnformatted(root);
341     cJSON_Delete(root);
342     ClearBundleInfo(&bundleInfo);
343     if (str != nullptr) {
344         InfoPrint(str);
345         cJSON_free(str);
346         str = nullptr;
347     } else {
348         printf("error message: %s\n", ERROR_DUMP_ERROR.c_str());
349     }
350 }
351 
InfoPrint(const std::string & str) const352 void CommandParser::InfoPrint(const std::string &str) const
353 {
354     int32_t len = str.size();
355     if (len == 0) {
356         return;
357     }
358     int32_t times = len / MAX_LOG_LEN;
359     int32_t remains = len % MAX_LOG_LEN;
360     for (int32_t i = 0; i < times; i++) {
361         printf("%s\n", str.substr(i * MAX_LOG_LEN, MAX_LOG_LEN).c_str());
362     }
363     printf("%s\n", str.substr(times * MAX_LOG_LEN, remains).c_str());
364 }
365 
GetInstallBundleInfos(int32_t argc) const366 void CommandParser::GetInstallBundleInfos(int32_t argc) const
367 {
368     if (argc > MAX_DUMP_LIST_NUMBER) {
369         printf("error message: %s\n", ERROR_OPTION.c_str());
370         return;
371     }
372 
373     BundleInfo *bundleInfo = nullptr;
374     int32_t len = 0;
375     if (GetBundleInfos(1, &bundleInfo, &len) != OHOS_SUCCESS) {
376         printf("error message: %s\n", ERROR_DUMP_FAIL.c_str());
377         return;
378     }
379 
380     cJSON *root = ConvertUtils::GetJsonBundleInfos(&bundleInfo, len);
381     if (root == nullptr) {
382         printf("error message: %s\n", ERROR_DUMP_ERROR.c_str());
383         BundleInfoUtils::FreeBundleInfos(bundleInfo, len);
384         return;
385     }
386 
387     char *str = cJSON_PrintUnformatted(root);
388     cJSON_Delete(root);
389     BundleInfoUtils::FreeBundleInfos(bundleInfo, len);
390     if (str != nullptr) {
391         InfoPrint(str);
392         cJSON_free(str);
393         str = nullptr;
394     } else {
395         printf("error message: %s\n", ERROR_DUMP_ERROR.c_str());
396     }
397 }
398 
GetBundleInfosByMetaDataKey(const std::string & metaDataKey) const399 void CommandParser::GetBundleInfosByMetaDataKey(const std::string &metaDataKey) const
400 {
401     int32_t len = 0;
402     BundleInfo *bundleInfos = nullptr;
403 
404     if (metaDataKey.empty()) {
405         printf("query param is invalid!\n");
406         return;
407     }
408     if (GetBundleInfosByMetaData(metaDataKey.c_str(), &bundleInfos, &len) != OHOS_SUCCESS) {
409         printf("error message: %s\n", ERROR_DUMP_FAIL.c_str());
410         return;
411     }
412 
413     printf("bundleNames match metaData key, len: %d\n", len);
414     for (int32_t i = 0; i < len; ++i) {
415         printf("bundleName: %s", bundleInfos[i].bundleName);
416         if (i != len - 1) {
417             printf("%s\n", "; ");
418         } else {
419             printf("%s\n", "\n");
420         }
421     }
422     BundleInfoUtils::FreeBundleInfos(bundleInfos, len);
423 }
424 
425 #ifdef OHOS_DEBUG
BmsToolNotify(IOwner owner,int code,IpcIo * reply)426 static int BmsToolNotify(IOwner owner, int code, IpcIo *reply)
427 {
428     if ((reply == nullptr) || (owner == nullptr)) {
429         printf("%s\n", "Bm tool Notify ipc is nullptr");
430         return OHOS_FAILURE;
431     }
432     switch (IpcIoPopUint8(reply)) {
433         case SET_EXTERNAL_INSTALL_MODE:
434         case SET_SIGN_DEBUG_MODE:
435         case SET_SIGN_MODE: {
436             uint8_t *ret = reinterpret_cast<uint8_t *>(owner);
437             *ret = IpcIoPopUint8(reply);
438             break;
439         }
440         default: {
441             break;
442         }
443     }
444     return ERR_OK;
445 }
446 
SetMode(int32_t mode,bool enable)447 uint8_t SetMode(int32_t mode, bool enable)
448 {
449     if (g_bmsInnerClient == nullptr) {
450         printf("%s\n", "Bm tool client is nullptr");
451         return ERR_APPEXECFWK_OBJECT_NULL;
452     }
453     IpcIo ipcIo;
454     char data[IPC_IO_DATA_MAX];
455     IpcIoInit(&ipcIo, data, IPC_IO_DATA_MAX, 0);
456     IpcIoPushBool(&ipcIo, enable);
457     if (!IpcIoAvailable(&ipcIo)) {
458         printf("%s\n", "Bm tool ipc failed");
459         return ERR_APPEXECFWK_SERIALIZATION_FAILED;
460     }
461     uint8_t setModeResult = 0;
462     int32_t ret = g_bmsInnerClient->Invoke(g_bmsInnerClient, mode, &ipcIo, &setModeResult, BmsToolNotify);
463     if (ret != ERR_OK) {
464         printf("Bm tool invoke failed: %d\n", ret);
465         return ERR_APPEXECFWK_INVOKE_ERROR;
466     }
467     return setModeResult;
468 }
469 
SetDebugMode(const std::string & enable,int32_t mode) const470 void CommandParser::SetDebugMode(const std::string &enable, int32_t mode) const
471 {
472     bool isEnable = false;
473     if (enable == "enable") {
474         isEnable = true;
475     } else if (enable == "disable") {
476         isEnable =  false;
477     } else {
478         printf("%s\n", "wrong param");
479         return;
480     }
481     uint8_t ret = SetMode(mode, isEnable);
482     if (ret == 0) {
483         printf("%s\n", "success");
484     } else {
485         printf("%s\n", "fail");
486     }
487 }
488 #endif
489 } // namespace OHOS
490