Refactor slp-pkgmgr with tidl
[platform/core/appfw/slp-pkgmgr.git] / installer / src / control.cc
1 /*
2  * Copyright (c) 2022 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17
18 #include "control.hh"
19
20 #include <getopt.h>
21 #include <sys/socket.h>
22 #include <sys/types.h>
23 #include <sys/un.h>
24 #include <unistd.h>
25
26 #include <glib.h>
27
28 #include "pkgmgr_installer.h"
29 #include "pkgmgr_installer_debug.h"
30 #include "pkgmgr_installer_type.h"
31
32 namespace {
33
34 constexpr int OPTVAL_PRELOAD = 1000;
35 constexpr int OPTVAL_FORCE_REMOVAL = 1001;
36 constexpr int OPTVAL_PRELOAD_RW = 1002;
37 constexpr int OPTVAL_NO_REMOVAL = 1003;
38 constexpr int OPTVAL_KEEP_RWDATA = 1004;
39 constexpr int OPTVAL_PARTIAL_RW = 1005;
40 constexpr int OPTVAL_MIGRATE_EXTIMG = 1006;
41 constexpr int OPTVAL_SKIP_CHECK_REFERENCE = 1007;
42 constexpr int OPTVAL_RECOVER_DB = 1008;
43 constexpr int OPTVAL_RECOVERY_CLEANUP = 1009;
44
45 constexpr const char short_opts[] = "k:l:i:d:c:m:t:o:r:p:s:b:e:M:y:u:w:D:A:qGS";
46 constexpr const struct option long_opts[] = {
47   { "session-id", 1, nullptr, 'k' },
48   { "license-path", 1, nullptr, 'l' },
49   { "install", 1, nullptr, 'i' },
50   { "uninstall", 1, nullptr, 'd' },
51   { "clear", 1, nullptr, 'c' },
52   { "move", 1, nullptr, 'm' },
53   { "move-type", 1, nullptr, 't' },
54   { "optional-data", 0, nullptr, 'o' },
55   { "reinstall", 0, nullptr, 'r' },
56   { "caller-pkgid", 1, nullptr, 'p' },
57   { "tep-path", 1, nullptr, 'e' },
58   { "tep-move", 1, nullptr, 'M' },
59   { "smack", 1, nullptr, 's' },
60   { "manifest-direct-install", 1, nullptr, 'y' },
61   { "mount-install", 1, nullptr, 'w' },
62   { "recovery", 1, nullptr, 'b' },
63   { "debug-mode", 0, nullptr, 'G' },
64   { "skip-optimization", 0, nullptr, 'S' },
65   { "preload", 0, nullptr, OPTVAL_PRELOAD },
66   { "force-remove", 0, nullptr, OPTVAL_FORCE_REMOVAL },
67   { "preload-rw", 0, nullptr, OPTVAL_PRELOAD_RW },
68   { "no-remove", 0, nullptr, OPTVAL_NO_REMOVAL },
69   { "keep-rwdata", 0, nullptr, OPTVAL_KEEP_RWDATA },
70   { "partial-rw", 0, nullptr, OPTVAL_PARTIAL_RW },
71   { "migrate-extimg", 1, nullptr, OPTVAL_MIGRATE_EXTIMG },
72   { "skip-check-reference", 0, nullptr, OPTVAL_SKIP_CHECK_REFERENCE },
73   { "recover-db", 1, nullptr, OPTVAL_RECOVER_DB },
74   { "recovery-cleanup", 0, nullptr, OPTVAL_RECOVERY_CLEANUP },
75   { 0, 0, 0, 0 }
76 };
77
78 static const char* __get_signal_name(
79     const std::unique_ptr<pkgmgr::installer::Request>& req,
80     const char* key, const char* pkg_type) {
81   if (strcmp(key, PKGMGR_INSTALLER_INSTALL_PERCENT_KEY_STR) == 0)
82     return key;
83   else if (strcmp(key, PKGMGR_INSTALLER_GET_SIZE_KEY_STR) == 0)
84     return key;
85   else if (strcmp(key, PKGMGR_INSTALLER_APPID_KEY_STR) == 0)
86     return PKGMGR_INSTALLER_UNINSTALL_EVENT_STR;
87   else if (strcmp(pkg_type, PKGMGR_INSTALLER_CLEAR_CACHE_KEY_STR) == 0)
88     return pkg_type;
89   else if (req->IsUpgrade())
90     return PKGMGR_INSTALLER_UPGRADE_EVENT_STR;
91
92
93   switch (req->GetRequestType()) {
94   case PKGMGR_REQ_INSTALL:
95   case PKGMGR_REQ_MANIFEST_DIRECT_INSTALL:
96   case PKGMGR_REQ_MOUNT_INSTALL:
97   case PKGMGR_REQ_REINSTALL:
98   case PKGMGR_REQ_ENABLE_PKG:
99   case PKGMGR_REQ_RECOVER:
100     return PKGMGR_INSTALLER_INSTALL_EVENT_STR;
101   case PKGMGR_REQ_UNINSTALL:
102   case PKGMGR_REQ_DISABLE_PKG:
103     return PKGMGR_INSTALLER_UNINSTALL_EVENT_STR;
104   case PKGMGR_REQ_UPGRADE:
105     return PKGMGR_INSTALLER_UPGRADE_EVENT_STR;
106   case PKGMGR_REQ_MOVE:
107     return PKGMGR_INSTALLER_MOVE_EVENT_STR;
108   case PKGMGR_REQ_ENABLE_APP:
109     return PKGMGR_INSTALLER_APP_ENABLE_EVENT_STR;
110   case PKGMGR_REQ_DISABLE_APP:
111     return PKGMGR_INSTALLER_APP_DISABLE_EVENT_STR;
112   case PKGMGR_REQ_ENABLE_APP_SPLASH_SCREEN:
113     return PKGMGR_INSTALLER_APP_ENABLE_SPLASH_SCREEN_EVENT_STR;
114   case PKGMGR_REQ_DISABLE_APP_SPLASH_SCREEN:
115     return PKGMGR_INSTALLER_APP_DISABLE_SPLASH_SCREEN_EVENT_STR;
116   case PKGMGR_REQ_CLEAR:
117     return PKGMGR_INSTALLER_CLEAR_EVENT_STR;
118   case PKGMGR_REQ_GETSIZE:
119     return PKGMGR_INSTALLER_GET_SIZE_KEY_STR;
120   case PKGMGR_REQ_RES_COPY:
121     return PKGMGR_INSTALLER_RES_COPY_EVENT_STR;
122   case PKGMGR_REQ_RES_CREATE_DIR:
123     return PKGMGR_INSTALLER_RES_CREATE_DIR_EVENT_STR;
124   case PKGMGR_REQ_RES_REMOVE:
125     return PKGMGR_INSTALLER_RES_REMOVE_EVENT_STR;
126   case PKGMGR_REQ_RES_UNINSTALL:
127     return PKGMGR_INSTALLER_RES_UNINSTALL_EVENT_STR;
128   }
129
130   _E("cannot find type");
131
132   return NULL;
133 }
134
135 }
136
137 namespace pkgmgr {
138 namespace installer {
139
140 Control::Control(bool offline) {
141   if (!offline) {
142     signal_.reset(new pkg_group::PkgSignal("", true));
143   }
144
145   request_ = std::make_unique<Request>();
146
147   option_map_[OPTVAL_PRELOAD] = [](const std::unique_ptr<Request>& req) {
148     req->is_preload_ = true;
149     _D("preload request [%d]", req->is_preload_);
150     return 0;
151   };
152
153   option_map_[OPTVAL_FORCE_REMOVAL] = [](const std::unique_ptr<Request>& req) {
154     req->force_removal_ = true;
155     _D("force-remove request [%d]", req->force_removal_);
156     return 0;
157   };
158
159   option_map_[OPTVAL_PRELOAD_RW] = [](const std::unique_ptr<Request>& req) {
160     req->is_preload_rw_ = true;
161     _D("preload-rw request [%d]", req->is_preload_rw_);
162     return 0;
163   };
164
165   option_map_[OPTVAL_NO_REMOVAL] = [](const std::unique_ptr<Request>& req) {
166     req->no_removal_ = true;
167     _D("no-remove request [%d]", req->no_removal_);
168     return 0;
169   };
170
171   option_map_[OPTVAL_KEEP_RWDATA] = [](const std::unique_ptr<Request>& req) {
172     req->keep_rwdata_ = true;
173     _D("keep-rwdata request [%d]", req->keep_rwdata_);
174     return 0;
175   };
176
177   option_map_[OPTVAL_PARTIAL_RW] = [](const std::unique_ptr<Request>& req) {
178     req->partial_rw_ = true;
179     _D("partial-rw request [%d]", req->partial_rw_);
180     return 0;
181   };
182
183   option_map_[OPTVAL_MIGRATE_EXTIMG] = [this](const std::unique_ptr<Request>& req) {
184     if (mode_)
185       return -EINVAL;
186     mode_ = OPTVAL_MIGRATE_EXTIMG;
187     req->request_type_ = PKGMGR_REQ_MIGRATE_EXTIMG;
188     req->pkgmgr_info_ = optarg;
189     ParseMultiplePkgs(req);
190     _D("legacy extimg migration requested");
191     return 0;
192   };
193
194   option_map_[OPTVAL_SKIP_CHECK_REFERENCE] = [](const std::unique_ptr<Request>& req) {
195     req->skip_check_reference_ = true;
196     return 0;
197   };
198
199   option_map_[OPTVAL_RECOVER_DB] = [this](const std::unique_ptr<Request>& req) {
200     req->request_type_ = PKGMGR_REQ_RECOVER_DB;
201     req->pkgmgr_info_ = optarg;
202     ParseMultiplePkgs(req);
203     return 0;
204   };
205
206   option_map_[OPTVAL_RECOVERY_CLEANUP] = [](const std::unique_ptr<Request>& req) {
207     req->recovery_cleanup_ = true;
208     return 0;
209   };
210
211   option_map_['k'] = [](const std::unique_ptr<Request>& req) {
212     req->session_id_ = optarg;
213     return 0;
214   };
215
216   option_map_['l'] = [](const std::unique_ptr<Request>& req) {
217     req->license_path_ = optarg;
218     return 0;
219   };
220
221   option_map_['i'] = [this](const std::unique_ptr<Request>& req) {
222     if (mode_)
223       return -EINVAL;
224     mode_ = 'i';
225     req->request_type_ = PKGMGR_REQ_INSTALL;
226     req->pkgmgr_info_ = optarg;
227     ParseMultiplePkgs(req);
228     _D("option is [i] pkgid[%s]", req->pkgmgr_info_.c_str());
229     return 0;
230   };
231
232   option_map_['e'] = [](const std::unique_ptr<Request>& req) {
233     req->tep_path_ = optarg;
234     _D("option is [e] tep_path[%s]", req->tep_path_.c_str());
235     return 0;
236   };
237
238   option_map_['M'] = [](const std::unique_ptr<Request>& req) {
239     if (strcmp(optarg, "tep_move") == 0)
240       req->tep_move_ = true;
241     else
242       req->tep_move_ = false;
243     _D("option is [M] tep_move[%d]", req->tep_move_);
244     return 0;
245   };
246
247   option_map_['d'] = [this](const std::unique_ptr<Request>& req) {
248     if (mode_)
249       return -EINVAL;
250     mode_ = 'd';
251     req->request_type_ = PKGMGR_REQ_UNINSTALL;
252     req->pkgmgr_info_ = optarg;
253     ParseMultiplePkgs(req);
254     return 0;
255   };
256
257   option_map_['c'] = [this](const std::unique_ptr<Request>& req) {
258     if (mode_)
259       return -EINVAL;
260     mode_ = 'c';
261     req->request_type_ = PKGMGR_REQ_CLEAR;
262     req->pkgmgr_info_ = optarg;
263     ParseMultiplePkgs(req);
264     return 0;
265   };
266
267   option_map_['m'] = [this](const std::unique_ptr<Request>& req) {
268     if (mode_)
269       return -EINVAL;
270     mode_ = 'm';
271     req->request_type_ = PKGMGR_REQ_MOVE;
272     req->pkgmgr_info_ = optarg;
273     ParseMultiplePkgs(req);
274     return 0;
275   };
276
277   option_map_['r'] = [this](const std::unique_ptr<Request>& req) {
278     if (mode_)
279       return -EINVAL;
280     mode_ = 'r';
281     req->request_type_ = PKGMGR_REQ_REINSTALL;
282     req->pkgmgr_info_ = optarg;
283     ParseMultiplePkgs(req);
284     return 0;
285   };
286
287   option_map_['t'] = [](const std::unique_ptr<Request>& req) {
288     req->move_type_ = atoi(optarg);
289     return 0;
290   };
291
292   option_map_['p'] = [](const std::unique_ptr<Request>& req) {
293     req->caller_pkgid_ = optarg;
294     return 0;
295   };
296
297   option_map_['s'] = [this](const std::unique_ptr<Request>& req) {
298     if (mode_)
299       return -EINVAL;
300     mode_ = 's';
301     req->request_type_ = PKGMGR_REQ_SMACK;
302     req->pkgmgr_info_ = optarg;
303     ParseMultiplePkgs(req);
304     return 0;
305   };
306
307   option_map_['o'] = [](const std::unique_ptr<Request>& req) {
308     req->optional_data_ = optarg;
309     return 0;
310   };
311
312   option_map_['y'] = [this](const std::unique_ptr<Request>& req) {
313     req->request_type_ = PKGMGR_REQ_MANIFEST_DIRECT_INSTALL;
314     req->pkgmgr_info_ = optarg;
315     ParseMultiplePkgs(req);
316     return 0;
317   };
318
319   option_map_['w'] = [this](const std::unique_ptr<Request>& req) {
320     req->request_type_ = PKGMGR_REQ_MOUNT_INSTALL;
321     req->pkgmgr_info_ = optarg;
322     ParseMultiplePkgs(req);
323     return 0;
324   };
325
326   option_map_['b'] = [this](const std::unique_ptr<Request>& req) {
327     if (mode_)
328       return -EINVAL;
329     mode_ = 'b';
330     req->request_type_ = PKGMGR_REQ_RECOVER;
331     req->pkgmgr_info_ = optarg;
332     ParseMultiplePkgs(req);
333     return 0;
334   };
335
336   option_map_['D'] = [this](const std::unique_ptr<Request>& req) {
337     req->request_type_ = PKGMGR_REQ_DISABLE_PKG;
338     req->pkgmgr_info_ = optarg;
339     ParseMultiplePkgs(req);
340     return 0;
341   };
342
343   option_map_['A'] = [this](const std::unique_ptr<Request>& req) {
344     req->request_type_ = PKGMGR_REQ_ENABLE_PKG;
345     req->pkgmgr_info_ = optarg;
346     ParseMultiplePkgs(req);
347     return 0;
348   };
349
350   option_map_['u'] = [](const std::unique_ptr<Request>& req) {
351     req->target_uid_ = (uid_t)atoi(optarg);
352     return 0;
353   };
354
355   option_map_['G'] = [](const std::unique_ptr<Request>& req) {
356     req->debug_mode_ = true;
357     return 0;
358   };
359
360   option_map_['S'] = [](const std::unique_ptr<Request>& req) {
361     req->skip_optimization_ = true;
362     return 0;
363   };
364 }
365
366 Control::~Control() = default;
367
368 void Control::ParseMultiplePkgs(const std::unique_ptr<Request>& req) {
369   while ((optind <= argc_) && (*argv_[optind - 1] != '-')) {
370     req->pkgs_.push_back(argv_[optind - 1]);
371     optind++;
372   }
373   optind--;
374 }
375
376 const std::unique_ptr<Request>& Control::GetRequest() const {
377   return request_;
378 }
379
380 int Control::SendSignal(std::string pkg_type, std::string pkgid,
381     std::string appid, std::string key, std::string val) {
382   if (!signal_) {
383     _E("offline mode");
384     return -1;
385   }
386   auto& req = GetRequest();
387   std::vector<rpc_port::PkgSignal::PkgInfo> pkgs;
388   pkgs.emplace_back(std::move(pkgid), std::move(appid), std::move(pkg_type));
389   signal_->AsyncResult("", req->GetUid(), req->GetSessionId(), std::move(pkgs),
390       key, val);
391   return 0;
392 }
393
394 int Control::SendSignals(std::string key, std::string val) {
395   if (!signal_) {
396     _E("offline mode");
397     return -1;
398   }
399   auto& req = GetRequest();
400   signal_->AsyncResult("", req->GetUid(), req->GetSessionId(), pkgs_, key, val);
401   return 0;
402 }
403
404 int Control::SendSignalForResource(std::string pkgid, std::string status,
405     rpc_port::PkgSignal::ExtraData* event_info) {
406   if (!signal_) {
407     _E("offline mode");
408     return -1;
409   }
410
411   auto& req = GetRequest();
412   const char* signal_name = __get_signal_name(req, "", "");
413   if (!signal_name) {
414     _E("unknown signal type");
415     return -1;
416   }
417
418   signal_->AsyncResultForResource(signal_name, req->GetUid(),
419       req->GetSessionId(), std::move(pkgid), std::move(status), *event_info);
420   return 0;
421 }
422
423 static int __send_signal_to_agent(uid_t uid, void* data, size_t len) {
424   int fd;
425   struct sockaddr_un sa;
426   int r;
427
428   fd = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0);
429   if (fd == -1) {
430     _E("failed to create socket: %d", errno);
431     return -1;
432   }
433
434   sa.sun_family = AF_UNIX;
435   snprintf(sa.sun_path, sizeof(sa.sun_path), "/run/pkgmgr/agent/%d", uid);
436
437   r = connect(fd, (struct sockaddr*)&sa, sizeof(sa));
438   if (r == -1) {
439     _E("failed to connect socket(%s): %d", sa.sun_path, errno);
440     close(fd);
441     return -1;
442   }
443
444   r = send(fd, data, len, MSG_NOSIGNAL);
445   if (r < 0) {
446     _E("failed to send data: %d", errno);
447     close(fd);
448     return -1;
449   }
450
451   close(fd);
452
453   return 0;
454 }
455
456 int Control::SendSignalForUid(uid_t uid, std::string pkg_type,
457     std::string pkgid, std::string appid, std::string key, std::string val) {
458   if (!signal_) {
459     _E("offline mode");
460     return -1;
461   }
462
463   const auto& req = GetRequest();
464   const char* sid = req->GetSessionId().c_str();
465
466   const char* signal_name;
467   size_t name_size;
468   GVariantBuilder* builder;
469   GVariant* gv;
470   gsize gv_len;
471   gpointer gv_data;
472   void* data;
473   void* ptr;
474   size_t data_len;
475
476   data_len = sizeof(size_t) + sizeof(gsize);
477
478   signal_name = __get_signal_name(req, key.c_str(), pkg_type.c_str());
479   if (!signal_name) {
480     _E("unknown signal name");
481     return -1;
482   }
483
484   /* including null byte */
485   name_size = strlen(signal_name) + 1;
486   data_len += name_size;
487
488   builder = g_variant_builder_new(G_VARIANT_TYPE("a(sss)"));
489   g_variant_builder_add(builder, "(sss)", pkgid.c_str(),
490       appid.c_str(), pkg_type.c_str());
491   gv = g_variant_new("(usa(sss)ss)", req->GetUid(), sid,
492       builder, key.c_str(), val.c_str());
493   g_variant_builder_unref(builder);
494   if (gv == NULL) {
495     _E("failed to create GVariant instance");
496     return -1;
497   }
498   gv_len = g_variant_get_size(gv);
499   gv_data = g_malloc(gv_len);
500   g_variant_store(gv, gv_data);
501   g_variant_unref(gv);
502   data_len += gv_len;
503
504   data = malloc(data_len);
505   if (data == NULL) {
506     _E("out of memory");
507     g_free(gv_data);
508     return -1;
509   }
510   ptr = data;
511   memcpy(ptr, &name_size, sizeof(size_t));
512   ptr += sizeof(size_t);
513   memcpy(ptr, &gv_len, sizeof(gsize));
514   ptr += sizeof(gsize);
515   memcpy(ptr, signal_name, name_size);
516   ptr += name_size;
517   memcpy(ptr, gv_data, gv_len);
518   g_free(gv_data);
519
520   if (__send_signal_to_agent(uid, data, data_len)) {
521     _E("failed to send signal to agent");
522     free(data);
523     return -1;
524   }
525
526   free(data);
527
528   return 0;
529 }
530
531 int Control::SendSignalsForUid(uid_t uid, std::string key, std::string val) {
532   if (!signal_) {
533     _E("offline mode");
534     return -1;
535   }
536
537   const auto& req = GetRequest();
538   const char* sid = req->GetSessionId().c_str();
539
540   const char* signal_name;
541   size_t name_size;
542   GVariantBuilder* builder;
543   GVariant* gv;
544   gsize gv_len;
545   gpointer gv_data;
546   void* data;
547   void* ptr;
548   size_t data_len;
549
550   data_len = sizeof(size_t) + sizeof(gsize);
551
552   signal_name = __get_signal_name(req, key.c_str(), "");
553   if (!signal_name) {
554     _E("unknown signal name");
555     return -1;
556   }
557
558   /* including null byte */
559   name_size = strlen(signal_name) + 1;
560   data_len += name_size;
561
562   builder = g_variant_builder_new(G_VARIANT_TYPE("a(sss)"));
563   for (const auto& pkg : pkgs_)
564     g_variant_builder_add(builder, "(sss)", pkg.GetPkgid().c_str(),
565         pkg.GetAppid().c_str(), pkg.GetPkgType().c_str());
566   gv = g_variant_new("(usa(sss)ss)", req->GetUid(), sid,
567       builder, key.c_str(), val.c_str());
568   g_variant_builder_unref(builder);
569   if (gv == NULL) {
570     _E("failed to create GVariant instance");
571     return -1;
572   }
573   gv_len = g_variant_get_size(gv);
574   gv_data = g_malloc(gv_len);
575   g_variant_store(gv, gv_data);
576   g_variant_unref(gv);
577   data_len += gv_len;
578
579   data = malloc(data_len);
580   if (data == NULL) {
581     _E("out of memory");
582     g_free(gv_data);
583     return -1;
584   }
585   ptr = data;
586   memcpy(ptr, &name_size, sizeof(size_t));
587   ptr += sizeof(size_t);
588   memcpy(ptr, &gv_len, sizeof(gsize));
589   ptr += sizeof(gsize);
590   memcpy(ptr, signal_name, name_size);
591   ptr += name_size;
592   memcpy(ptr, gv_data, gv_len);
593   g_free(gv_data);
594
595   if (__send_signal_to_agent(uid, data, data_len)) {
596     _E("failed to send signal to agent");
597     free(data);
598     return -1;
599   }
600
601   free(data);
602
603   return 0;
604 }
605
606 static GVariant* __get_gvariant_from_event_info(
607     pkgmgr_res_event_info* event_info) {
608   rpc_port::PkgSignal::ExtraData* info =
609       reinterpret_cast<rpc_port::PkgSignal::ExtraData*>(event_info);
610   GVariantBuilder* builder;
611   GVariant* result;
612   GList* path_states;
613   res_event_path_state_t* path_state;
614
615   builder = g_variant_builder_new(G_VARIANT_TYPE("a(si)"));
616   if (builder == NULL) {
617     _E("out of memory");
618     return NULL;
619   }
620
621   for (const auto& p : info->GetPaths())
622     g_variant_builder_add(builder, "(si)", p.GetPath(), p.GetState());
623
624   result = g_variant_new("(ia(si))", info->GetErrCode(), builder);
625   g_variant_builder_unref(builder);
626
627   if (result == NULL) {
628     _E("Fail to create extra data");
629     return NULL;
630   }
631
632   return result;
633 }
634
635 int Control::SendSignalForResourceForUid(uid_t uid, std::string pkgid,
636     std::string status, rpc_port::PkgSignal::ExtraData* event_info) {
637   if (!signal_) {
638     _E("offline mode");
639     return -1;
640   }
641
642   const auto& req = GetRequest();
643   const char* sid = req->GetSessionId().c_str();
644
645   const char* signal_name;
646   size_t name_size;
647   GVariant* gv;
648   gsize gv_len;
649   gpointer gv_data;
650   void* data;
651   void* ptr;
652   size_t data_len;
653   GVariant* extra_param;
654
655   data_len = sizeof(size_t) + sizeof(gsize);
656
657   signal_name = __get_signal_name(req, "", "");
658   if (!signal_name) {
659     _E("unknown signal name");
660     return -1;
661   }
662
663   /* including null byte */
664   name_size = strlen(signal_name) + 1;
665   data_len += name_size;
666
667   extra_param = __get_gvariant_from_event_info(event_info);
668   if (extra_param == NULL) {
669     _E("Fail to get extra parameter");
670     return -1;
671   }
672
673   gv = g_variant_new("(usssv)", req->GetUid(), sid,
674       pkgid.c_str(), status.c_str(), extra_param);
675   if (gv == NULL) {
676     _E("failed to create GVariant instance");
677     return -1;
678   }
679
680   gv_len = g_variant_get_size(gv);
681   gv_data = g_malloc(gv_len);
682   g_variant_store(gv, gv_data);
683   g_variant_unref(gv);
684   data_len += gv_len;
685
686   data = malloc(data_len);
687   if (data == NULL) {
688     _E("out of memory");
689     g_free(gv_data);
690     return -1;
691   }
692   ptr = data;
693   memcpy(ptr, &name_size, sizeof(size_t));
694   ptr += sizeof(size_t);
695   memcpy(ptr, &gv_len, sizeof(gsize));
696   ptr += sizeof(gsize);
697   memcpy(ptr, signal_name, name_size);
698   ptr += name_size;
699   memcpy(ptr, gv_data, gv_len);
700   g_free(gv_data);
701
702   if (__send_signal_to_agent(uid, data, data_len)) {
703     _E("failed to send signal to agent");
704     free(data);
705     return -1;
706   }
707
708   free(data);
709
710   return 0;
711 }
712
713 void Control::AddPkg(std::string pkgid, std::string pkg_type) {
714   pkgs_.emplace_back(rpc_port::PkgSignal::PkgInfo(std::move(pkgid),
715       "", std::move(pkg_type)));
716 }
717
718 int Control::SetRequestFromArgv(const int argc, char** argv) {
719   int opt_idx = 0;
720   optind = 1;
721   argc_ = argc;
722   argv_ = argv;
723   mode_ = 0;
724
725   while (true) {
726     int c = getopt_long(argc, argv, short_opts, long_opts, &opt_idx);
727     if (c == -1)
728       break;
729
730     if (option_map_.find(c) != option_map_.end()) {
731       int ret = option_map_[c](request_);
732       if (ret < 0)
733         return ret;
734     }
735   }
736
737   return 0;
738 }
739
740 }  // namespace installer
741 }  // namespace pkgmgr