Improve performance
[platform/core/appfw/pkgmgr-info.git] / src / manager / pkginfo_manager.cc
1 /*
2  * Copyright (c) 2021 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 #include "manager/pkginfo_manager.h"
18
19 #include <sys/types.h>
20
21 #include <sqlite3.h>
22 #include <glib.h>
23
24 #include <parcel.hh>
25
26 #include <map>
27 #include <memory>
28 #include <string>
29 #include <utility>
30 #include <vector>
31
32 #include "pkgmgr_parser.h"
33 #include "pkgmgrinfo_private.h"
34 #include "pkgmgr_query_index.h"
35
36 #include "client/pkginfo_client.hh"
37 #include "common/database/abstract_db_handler.hh"
38 #include "common/database/pkg_set_db_handler.hh"
39 #include "common/parcel/appinfo_parcelable.hh"
40 #include "common/parcel/certinfo_parcelable.hh"
41 #include "common/parcel/command_parcelable.hh"
42 #include "common/parcel/depinfo_parcelable.hh"
43 #include "common/parcel/filter_parcelable.hh"
44 #include "common/parcel/pkginfo_parcelable.hh"
45 #include "common/parcel/query_parcelable.hh"
46 #include "common/parcel/result_parcelable.hh"
47 #include "logging.hh"
48
49
50 #ifdef LOG_TAG
51 #undef LOG_TAG
52 #endif
53 #define LOG_TAG "PKGMGR_INFO"
54
55 #ifdef EXPORT_API
56 #undef EXPORT_API
57 #endif
58 #define EXPORT_API __attribute__((visibility("default")))
59
60 namespace pcp = pkgmgr_common::parcel;
61 namespace pcd = pkgmgr_common::database;
62
63 extern "C" EXPORT_API int _pkginfo_get_packages(uid_t uid,
64     pkgmgrinfo_filter_x* filter, int flag, GHashTable* packages) {
65   std::shared_ptr<pcp::AbstractParcelable> parcelable(
66       new pcp::FilterParcelable(uid,
67           static_cast<pkgmgrinfo_filter_x*>(filter), flag, false));
68
69   pkgmgr_client::PkgInfoClient client(parcelable, uid,
70       pkgmgr_common::ReqType::GET_PKG_INFO);
71   if (!client.SendRequest())
72     return PMINFO_R_ERROR;
73
74   auto ptr = client.GetResultParcel();
75   if (ptr == nullptr) {
76     LOG(ERROR) << "Fail to get return parcelable";
77     return PMINFO_R_ERROR;
78   }
79
80   if (ptr->GetRequestResult() != PMINFO_R_OK) {
81     if (ptr->GetRequestResult() == PMINFO_R_ERROR)
82       LOG(ERROR) << "Request fail";
83     return ptr->GetRequestResult();
84   }
85
86   if (ptr->GetType() != pcp::ParcelableType::PkgInfo) {
87     LOG(ERROR) << "Invalid parcelable type";
88     return PMINFO_R_ERROR;
89   }
90
91   std::shared_ptr<pcp::PkgInfoParcelable> return_parcel(
92       std::static_pointer_cast<pcp::PkgInfoParcelable>(
93           ptr));
94
95   auto result_list = return_parcel->ExtractPkgInfo();
96   if (result_list.size() == 0) {
97     LOG(DEBUG) << "No packages meets given condition for user " << uid;
98     return PMINFO_R_ENOENT;
99   }
100   for (auto pkginfo : result_list)
101     g_hash_table_insert(packages, (gpointer)pkginfo->package,
102                         (gpointer)pkginfo);
103
104   return PMINFO_R_OK;
105 }
106
107 extern "C" EXPORT_API int _pkginfo_get_depends_on(uid_t uid,
108     const char* pkgid, GList** dependencies) {
109   std::shared_ptr<pcp::AbstractParcelable> parcelable(
110       new pcp::DepInfoParcelable(std::string(pkgid)));
111
112   pkgmgr_client::PkgInfoClient client(parcelable, uid,
113       pkgmgr_common::ReqType::GET_PKG_DEP_INFO);
114   if (!client.SendRequest())
115     return PMINFO_R_ERROR;
116
117   auto ptr = client.GetResultParcel();
118   if (ptr == nullptr) {
119     LOG(ERROR) << "Fail to get return parcelable";
120     return PMINFO_R_ERROR;
121   }
122
123   if (ptr->GetRequestResult() != PMINFO_R_OK) {
124     LOG(ERROR) << "Request fail";
125     return ptr->GetRequestResult();
126   }
127
128   if (ptr->GetType() != pcp::ParcelableType::DepInfo) {
129     LOG(ERROR) << "Invalid parcelable type";
130     return PMINFO_R_ERROR;
131   }
132
133   std::shared_ptr<pcp::DepInfoParcelable> return_parcel(
134       std::static_pointer_cast<pcp::DepInfoParcelable>(ptr));
135
136   auto dependency_list = return_parcel->ExtractDependencyInfo();
137   for (auto dependency : dependency_list)
138     *dependencies = g_list_prepend(*dependencies, dependency);
139   return PMINFO_R_OK;
140 }
141
142 extern "C" EXPORT_API int _appinfo_get_applications(uid_t uid,
143     pkgmgrinfo_filter_x* filter, int flag, GHashTable* packages) {
144   std::shared_ptr<pcp::AbstractParcelable> parcelable(
145       new pcp::FilterParcelable(uid,
146           static_cast<pkgmgrinfo_filter_x*>(filter), flag, false));
147
148   pkgmgr_client::PkgInfoClient client(
149       parcelable, uid, pkgmgr_common::ReqType::GET_APP_INFO);
150   if (!client.SendRequest())
151     return PMINFO_R_ERROR;
152
153   auto ptr = client.GetResultParcel();
154   if (ptr == nullptr) {
155     LOG(ERROR) << "Fail to get return parcelable";
156     return PMINFO_R_ERROR;
157   }
158
159   int ret = ptr->GetRequestResult();
160   if (ret != PMINFO_R_OK) {
161     if (ret == PMINFO_R_ENOENT)
162       LOG(DEBUG) << "No such application";
163     else
164       LOG(ERROR) << "Request fail";
165     return ret;
166   }
167
168   if (ptr->GetType() != pcp::ParcelableType::AppInfo) {
169     LOG(ERROR) << "Invalid parcelable type";
170     return PMINFO_R_ERROR;
171   }
172
173   std::shared_ptr<pcp::AppInfoParcelable> return_parcel(
174       std::static_pointer_cast<pcp::AppInfoParcelable>(ptr));
175
176   std::vector<application_x*> result_list = return_parcel->ExtractAppInfo();
177   for (application_x* app : result_list)
178     g_hash_table_insert(packages, (gpointer)app->appid,
179         (gpointer)app);
180
181   return PMINFO_R_OK;
182 }
183
184 extern "C" EXPORT_API char* _appinfo_get_localed_label(
185     const char* appid, const char* locale, uid_t uid) {
186   std::shared_ptr<pcp::AbstractParcelable> parcelable(
187       new pcp::QueryParcelable(uid,
188           { QUERY_INDEX_APPINFO_GET_LOCALED_LABEL, { appid, locale, appid } },
189           pcd::AbstractDBHandler::DBType::DB_TYPE_FILE_PKGDB,
190           pcd::AbstractDBHandler::OperationType::OPERATION_TYPE_READ));
191
192   pkgmgr_client::PkgInfoClient client(parcelable, uid,
193       pkgmgr_common::ReqType::QUERY);
194   if (!client.SendRequest())
195     return nullptr;
196   auto ptr = client.GetResultParcel();
197   if (ptr == nullptr) {
198     LOG(ERROR) << "Fail to get return parcelable";
199     return nullptr;
200   }
201
202   if (ptr->GetRequestResult() != PMINFO_R_OK) {
203     LOG(ERROR) << "Request fail";
204     return nullptr;
205   }
206
207   if (ptr->GetType() != pcp::ParcelableType::Result) {
208     LOG(ERROR) << "Invalid parcelable type";
209     return nullptr;
210   }
211
212   std::shared_ptr<pcp::ResultParcelable> return_parcel(
213       std::static_pointer_cast<pcp::ResultParcelable>(ptr));
214
215   // result_list is vector of string vector
216   char* label = nullptr;
217   auto result_list = return_parcel->GetResult();
218   for (auto& result : result_list) {
219     // result is string vector
220     // it only has one string or not.
221     if (result.front().empty())
222       return nullptr;
223     label = strdup(result.front().c_str());
224     if (label == nullptr) {
225       LOG(ERROR) << "Out of memory";
226       return nullptr;
227     }
228     return label;
229   }
230
231   return label;
232 }
233
234 extern "C" EXPORT_API int _appinfo_get_datacontrol_info(
235     const char* providerid, const char* type, uid_t uid,
236     char** appid, char** access) {
237   std::shared_ptr<pcp::AbstractParcelable> parcelable(
238       new pcp::QueryParcelable(uid,
239           { QUERY_INDEX_APPINFO_GET_DATACONTROL_INFO, { providerid, type } },
240           pcd::AbstractDBHandler::DBType::DB_TYPE_FILE_PKGDB,
241           pcd::AbstractDBHandler::OperationType::OPERATION_TYPE_READ));
242
243   pkgmgr_client::PkgInfoClient client(parcelable, uid,
244       pkgmgr_common::ReqType::QUERY);
245   if (!client.SendRequest())
246     return PMINFO_R_ERROR;
247
248   auto ptr = client.GetResultParcel();
249   if (ptr == nullptr) {
250     LOG(ERROR) << "Fail to get return parcelable";
251     return PMINFO_R_ERROR;
252   }
253
254   if (ptr->GetRequestResult() != PMINFO_R_OK) {
255     LOG(ERROR) << "Request fail";
256     return ptr->GetRequestResult();
257   }
258
259   if (ptr->GetType() != pcp::ParcelableType::Result) {
260     LOG(ERROR) << "Invalid parcelable type";
261     return PMINFO_R_ERROR;
262   }
263
264   std::shared_ptr<pcp::ResultParcelable> return_parcel(
265       std::static_pointer_cast<pcp::ResultParcelable>(ptr));
266
267   auto result_list = return_parcel->GetResult();
268   if (result_list.size() == 0)
269     return PMINFO_R_ENOENT;
270   for (auto& result : result_list) {
271     if (result.size() != 2 || result.front().empty() || result.back().empty())
272       return PMINFO_R_ERROR;
273     *appid = strdup(result.front().c_str());
274     *access = strdup(result.back().c_str());
275     if (*appid == nullptr || *access == nullptr) {
276       LOG(ERROR) << "Out of memory";
277       return PMINFO_R_ERROR;
278     }
279   }
280
281   return PMINFO_R_OK;
282 }
283
284 extern "C" EXPORT_API int _appinfo_get_datacontrol_appid(
285     const char* providerid, uid_t uid, char** appid) {
286   std::shared_ptr<pcp::AbstractParcelable> parcelable(
287       new pcp::QueryParcelable(uid,
288           { QUERY_INDEX_APPINFO_GET_DATACONTROL_APPID, { providerid } },
289           pcd::AbstractDBHandler::DBType::DB_TYPE_FILE_PKGDB,
290           pcd::AbstractDBHandler::OperationType::OPERATION_TYPE_READ));
291
292   pkgmgr_client::PkgInfoClient client(parcelable, uid,
293       pkgmgr_common::ReqType::QUERY);
294   if (!client.SendRequest())
295     return PMINFO_R_ERROR;
296
297   auto ptr = client.GetResultParcel();
298   if (ptr == nullptr) {
299     LOG(ERROR) << "Fail to get return parcelable";
300     return PMINFO_R_ERROR;
301   }
302
303   if (ptr->GetRequestResult() != PMINFO_R_OK) {
304     LOG(ERROR) << "Request fail";
305     return ptr->GetRequestResult();
306   }
307
308   if (ptr->GetType() != pcp::ParcelableType::Result) {
309     LOG(ERROR) << "Invalid parcelable type";
310     return PMINFO_R_ERROR;
311   }
312
313   std::shared_ptr<pcp::ResultParcelable> return_parcel(
314       std::static_pointer_cast<pcp::ResultParcelable>(ptr));
315
316   // result_list is vector of string vector
317   auto result_list = return_parcel->GetResult();
318   if (result_list.size() == 0)
319     return PMINFO_R_ENOENT;
320   for (auto& result : result_list) {
321     if (result.size() != 1 || result.front().empty())
322       return PMINFO_R_ERROR;
323     *appid = strdup(result.front().c_str());
324     if (*appid == nullptr) {
325       LOG(ERROR) << "Out of memory";
326       return PMINFO_R_ERROR;
327     }
328   }
329
330   return PMINFO_R_OK;
331 }
332
333 extern "C" EXPORT_API int _appinfo_get_datacontrol_trusted_info(
334     const char* providerid, const char* type, uid_t uid,
335     char** appid, char** trusted) {
336   std::shared_ptr<pcp::AbstractParcelable> parcelable(
337       new pcp::QueryParcelable(uid,
338           { QUERY_INDEX_APPINFO_GET_DATACONTROL_TRUSTED_INFO,
339               { providerid, type } },
340           pcd::AbstractDBHandler::DBType::DB_TYPE_FILE_PKGDB,
341           pcd::AbstractDBHandler::OperationType::OPERATION_TYPE_READ));
342
343   pkgmgr_client::PkgInfoClient client(parcelable, uid,
344       pkgmgr_common::ReqType::QUERY);
345   if (!client.SendRequest())
346     return PMINFO_R_ERROR;
347
348   auto ptr = client.GetResultParcel();
349   if (ptr == nullptr) {
350     LOG(ERROR) << "Fail to get return parcelable";
351     return PMINFO_R_ERROR;
352   }
353
354   if (ptr->GetRequestResult() != PMINFO_R_OK) {
355     LOG(ERROR) << "Request fail";
356     return ptr->GetRequestResult();
357   }
358
359   if (ptr->GetType() != pcp::ParcelableType::Result) {
360     LOG(ERROR) << "Invalid parcelable type";
361     return PMINFO_R_ERROR;
362   }
363
364   std::shared_ptr<pcp::ResultParcelable> return_parcel(
365       std::static_pointer_cast<pcp::ResultParcelable>(ptr));
366
367   // result_list is vector of string vector
368   auto result_list = return_parcel->GetResult();
369   if (result_list.size() == 0)
370     return PMINFO_R_ENOENT;
371   for (auto& result : result_list) {
372     if (result.size() != 2 || result.front().empty() || result.back().empty())
373       return PMINFO_R_ERROR;
374     *appid = strdup(result.front().c_str());
375     *trusted = strdup(result.back().c_str());
376     if (*appid == nullptr || *trusted == nullptr) {
377       LOG(ERROR) << "Out of memory";
378       return PMINFO_R_ERROR;
379     }
380   }
381
382   return PMINFO_R_OK;
383 }
384
385 extern "C" EXPORT_API int _appinfo_get_datacontrol_privileges(
386     const char* providerid, const char* type, uid_t uid, GList** privileges) {
387   std::shared_ptr<pcp::AbstractParcelable> parcelable(
388       new pcp::QueryParcelable(uid,
389           { QUERY_INDEX_APPINFO_GET_DATACONTROL_PRIVILEGES,
390               { providerid, type } },
391           pcd::AbstractDBHandler::DBType::DB_TYPE_FILE_PKGDB,
392           pcd::AbstractDBHandler::OperationType::OPERATION_TYPE_READ));
393
394   pkgmgr_client::PkgInfoClient client(parcelable, uid,
395       pkgmgr_common::ReqType::QUERY);
396   if (!client.SendRequest())
397     return PMINFO_R_ERROR;
398
399   auto ptr = client.GetResultParcel();
400   if (ptr == nullptr) {
401     LOG(ERROR) << "Fail to get return parcelable";
402     return PMINFO_R_ERROR;
403   }
404
405   if (ptr->GetRequestResult() != PMINFO_R_OK) {
406     LOG(ERROR) << "Request fail";
407     return ptr->GetRequestResult();
408   }
409
410   if (ptr->GetType() != pcp::ParcelableType::Result) {
411     LOG(ERROR) << "Invalid parcelable type";
412     return PMINFO_R_ERROR;
413   }
414
415   std::shared_ptr<pcp::ResultParcelable> return_parcel(
416       std::static_pointer_cast<pcp::ResultParcelable>(ptr));
417
418   // result_list is vector of string vector
419   auto result_list = return_parcel->GetResult();
420   if (result_list.size() == 0)
421     return PMINFO_R_ENOENT;
422
423   for (auto& result : result_list) {
424     if (result.size() != 1 || result.front().empty())
425       return PMINFO_R_ERROR;
426     char* privilege = strdup(result.front().c_str());
427     if (privilege == nullptr) {
428       LOG(ERROR) << "Out of memory";
429       return PMINFO_R_ERROR;
430     }
431     *privileges = g_list_append(*privileges, privilege);
432   }
433
434   return PMINFO_R_OK;
435 }
436
437 extern "C" EXPORT_API int _appinfo_get_appcontrol_privileges(
438     const char* appid, const char* operation, uid_t uid, GList** privileges) {
439   std::shared_ptr<pcp::AbstractParcelable> parcelable(
440       new pcp::QueryParcelable(uid,
441           { QUERY_INDEX_APPINFO_GET_APPCONTROL_PRIVILEGES, { appid } },
442           pcd::AbstractDBHandler::DBType::DB_TYPE_FILE_PKGDB,
443           pcd::AbstractDBHandler::OperationType::OPERATION_TYPE_READ));
444
445   pkgmgr_client::PkgInfoClient client(parcelable, uid,
446       pkgmgr_common::ReqType::QUERY);
447   if (!client.SendRequest())
448     return PMINFO_R_ERROR;
449
450   auto ptr = client.GetResultParcel();
451   if (ptr == nullptr) {
452     LOG(ERROR) << "Fail to get return parcelable";
453     return PMINFO_R_ERROR;
454   }
455
456   if (ptr->GetRequestResult() != PMINFO_R_OK) {
457     LOG(ERROR) << "Request fail";
458     return ptr->GetRequestResult();
459   }
460
461   if (ptr->GetType() != pcp::ParcelableType::Result) {
462     LOG(ERROR) << "Invalid parcelable type";
463     return PMINFO_R_ERROR;
464   }
465
466   std::shared_ptr<pcp::ResultParcelable> return_parcel(
467       std::static_pointer_cast<pcp::ResultParcelable>(ptr));
468
469   // result_list is vector of string vector
470   auto result_list = return_parcel->GetResult();
471   if (result_list.size() == 0)
472     return PMINFO_R_ENOENT;
473
474   for (auto& result : result_list) {
475     if (result.size() != 2 || result.front().empty() || result.back().empty())
476       return PMINFO_R_ERROR;
477     std::stringstream ss(result.front());
478     std::string token;
479     while (std::getline(ss, token, '|')) {
480       if (token.compare(std::string(operation))) {
481         char* privilege = strdup(result.back().c_str());
482         if (privilege == nullptr) {
483           LOG(ERROR) << "Out of memory";
484           return PMINFO_R_ERROR;
485         }
486         *privileges = g_list_append(*privileges, privilege);
487       }
488     }
489   }
490   return PMINFO_R_OK;
491 }
492
493 extern "C" EXPORT_API int _plugininfo_get_appids(
494     const char* pkgid, const char* plugin_type,
495     const char* plugin_name, GList** list) {
496   if (!pkgid || !plugin_type || !plugin_name || !list) {
497     LOG(ERROR) << "Invalid parameter";
498     return PMINFO_R_EINVAL;
499   }
500
501   std::shared_ptr<pcp::AbstractParcelable> parcelable(
502       new pcp::QueryParcelable(_getuid(),
503           { QUERY_INDEX_PLUGININFO_GET_APPIDS,
504               { pkgid, plugin_type, plugin_name } },
505           pcd::AbstractDBHandler::DBType::DB_TYPE_FILE_PKGDB,
506           pcd::AbstractDBHandler::OperationType::OPERATION_TYPE_READ));
507
508   pkgmgr_client::PkgInfoClient client(parcelable, _getuid(),
509       pkgmgr_common::ReqType::QUERY);
510   if (!client.SendRequest())
511     return PMINFO_R_ERROR;
512
513   auto ptr = client.GetResultParcel();
514   if (ptr == nullptr) {
515     LOG(ERROR) << "Fail to get return parcelable";
516     return PMINFO_R_ERROR;
517   }
518
519   if (ptr->GetRequestResult() != PMINFO_R_OK) {
520     LOG(ERROR) << "Request fail";
521     return ptr->GetRequestResult();
522   }
523
524   if (ptr->GetType() != pcp::ParcelableType::Result) {
525     LOG(ERROR) << "Invalid parcelable type";
526     return PMINFO_R_ERROR;
527   }
528
529   std::shared_ptr<pcp::ResultParcelable> return_parcel(
530       std::static_pointer_cast<pcp::ResultParcelable>(ptr));
531
532   if (return_parcel->GetCol() != 1) {
533     LOG(ERROR) << "Invalid result";
534     return PMINFO_R_ERROR;
535   }
536   // result_list is vector of string vector
537   auto &result_list = return_parcel->GetResult();
538   if (result_list.size() == 0)
539     return PMINFO_R_ENOENT;
540
541   for (auto& result : result_list) {
542     if (result.size() != 1) {
543       LOG(ERROR) << "Invalid result";
544       g_list_free_full(*list, free);
545       return PMINFO_R_ERROR;
546     }
547     *list = g_list_append(*list, strdup(result[0].c_str()));
548   }
549
550   return PMINFO_R_OK;
551 }
552
553 static int __convert_update_type(const char* type,
554     pkgmgrinfo_updateinfo_update_type* convert_type) {
555   if (strncasecmp(type, PMINFO_UPDATEINFO_TYPE_NONE,
556       strlen(PMINFO_UPDATEINFO_TYPE_NONE)) == 0)
557     *convert_type = PMINFO_UPDATEINFO_NONE;
558   else if (strncasecmp(type, PMINFO_UPDATEINFO_TYPE_FORCE,
559       strlen(PMINFO_UPDATEINFO_TYPE_FORCE)) == 0)
560     *convert_type = PMINFO_UPDATEINFO_FORCE;
561   else if (strncasecmp(type, PMINFO_UPDATEINFO_TYPE_OPTIONAL,
562       strlen(PMINFO_UPDATEINFO_TYPE_OPTIONAL)) == 0)
563     *convert_type = PMINFO_UPDATEINFO_OPTIONAL;
564   else
565     return -1;
566   return 0;
567 }
568
569 static void __free_update_info(gpointer data) {
570   updateinfo_x* update_info = reinterpret_cast<updateinfo_x*>(data);
571   if (update_info == nullptr)
572     return;
573
574   if (update_info->pkgid)
575     free(reinterpret_cast<void*>(update_info->pkgid));
576   if (update_info->version)
577     free(reinterpret_cast<void*>(update_info->version));
578   free(reinterpret_cast<void*>(update_info));
579 }
580
581 extern "C" EXPORT_API int _get_pkg_updateinfo(const char* pkgid,
582     GSList** update_info_list, uid_t uid) {
583   int ret;
584
585   std::pair<int, std::vector<std::string>> info;
586
587   if (pkgid == nullptr) {
588     info = std::pair<int, std::vector<std::string>>(
589               QUERY_INDEX_GET_PKG_UPDATEINFO_1, {});
590   } else {
591     info = std::pair<int, std::vector<std::string>>(
592               QUERY_INDEX_GET_PKG_UPDATEINFO_2, { pkgid });
593   }
594
595   std::shared_ptr<pcp::AbstractParcelable> parcelable(
596       new pcp::QueryParcelable(uid, std::move(info),
597           pcd::AbstractDBHandler::DBType::DB_TYPE_FILE_PKGDB,
598           pcd::AbstractDBHandler::OperationType::OPERATION_TYPE_READ));
599
600   pkgmgr_client::PkgInfoClient client(parcelable, uid,
601       pkgmgr_common::ReqType::QUERY);
602   if (!client.SendRequest())
603     return PMINFO_R_ERROR;
604
605   auto ptr = client.GetResultParcel();
606   if (ptr == nullptr) {
607     LOG(ERROR) << "Fail to get return parcelable";
608     return PMINFO_R_ERROR;
609   }
610
611   if (ptr->GetRequestResult() != PMINFO_R_OK) {
612     LOG(ERROR) << "Request fail";
613     return ptr->GetRequestResult();
614   }
615
616   if (ptr->GetType() != pcp::ParcelableType::Result) {
617     LOG(ERROR) << "Invalid parcelable type";
618     return PMINFO_R_ERROR;
619   }
620
621   std::shared_ptr<pcp::ResultParcelable> return_parcel(
622       std::static_pointer_cast<pcp::ResultParcelable>(ptr));
623
624   if (return_parcel->GetCol() != 3) {
625     LOG(ERROR) << "Invalid result";
626     return PMINFO_R_ERROR;
627   }
628
629   auto result_list = return_parcel->GetResult();
630   if (result_list.size() == 0)
631     return PMINFO_R_ENOENT;
632
633   for (auto& result : result_list) {
634     if (result.size() != 3) {
635       LOG(ERROR) << "Invalid result";
636       g_slist_free_full(*update_info_list, __free_update_info);
637       return PMINFO_R_ERROR;
638     }
639     updateinfo_x* update_info = reinterpret_cast<updateinfo_x*>(
640         calloc(1, sizeof(updateinfo_x)));
641     if (update_info == nullptr) {
642       LOG(ERROR) << "Out of memory";
643       return PMINFO_R_ERROR;
644     }
645     update_info->pkgid = strdup(result[0].c_str());
646     update_info->version = strdup(result[1].c_str());
647     pkgmgrinfo_updateinfo_update_type convert_type;
648     ret = __convert_update_type(result[2].c_str(), &convert_type);
649     if (ret != 0) {
650       __free_update_info(update_info);
651       g_slist_free_full(*update_info_list, __free_update_info);
652       return PMINFO_R_ERROR;
653     }
654     update_info->type = static_cast<int>(convert_type);
655     *update_info_list = g_slist_prepend(*update_info_list,
656         update_info);
657   }
658
659   return PMINFO_R_OK;
660 }
661
662 extern "C" EXPORT_API int _pkginfo_set_usr_installed_storage(const char* pkgid,
663     INSTALL_LOCATION location, const char* external_pkg_path, uid_t uid) {
664   const char* location_str;
665
666   if (location == INSTALL_INTERNAL)
667     location_str = "installed_internal";
668   else if (location == INSTALL_EXTERNAL)
669     location_str = "installed_external";
670   else
671     location_str = "installed_extended";
672
673   std::shared_ptr<pcp::AbstractParcelable> parcelable(
674       new pcp::QueryParcelable(uid, { {
675               QUERY_INDEX_PKGINFO_SET_USR_INSTALLED_STORAGE_1, {
676                 location_str,
677                 external_pkg_path,
678                 pkgid
679               }
680             }, {
681               QUERY_INDEX_PKGINFO_SET_USR_INSTALLED_STORAGE_2, {
682                 location_str,
683                 external_pkg_path,
684                 pkgid
685               }
686             },
687           },
688           pcd::AbstractDBHandler::DBType::DB_TYPE_FILE_PKGDB,
689           pcd::AbstractDBHandler::OperationType::OPERATION_TYPE_WRITE));
690
691   pkgmgr_client::PkgInfoClient client(parcelable, uid,
692       pkgmgr_common::ReqType::QUERY);
693   if (!client.SendRequest())
694     return PMINFO_R_ERROR;
695
696   auto ptr = client.GetResultParcel();
697   if (ptr == nullptr) {
698     LOG(ERROR) << "Fail to get return parcelable";
699     return PMINFO_R_ERROR;
700   }
701
702   if (ptr->GetRequestResult() != PMINFO_R_OK) {
703     LOG(ERROR) << "Request fail";
704     return ptr->GetRequestResult();
705   }
706
707   if (ptr->GetType() != pcp::ParcelableType::Result) {
708     LOG(ERROR) << "Invalid parcelable type";
709     return PMINFO_R_ERROR;
710   }
711
712   return PMINFO_R_OK;
713 }
714
715 extern "C" EXPORT_API int _certinfo_compare_pkg_certinfo(const char* l_pkgid,
716     const char* r_pkgid, pkgmgrinfo_cert_compare_result_type_e* result) {
717   std::shared_ptr<pcp::AbstractParcelable> parcelable(
718       new pcp::QueryParcelable(0,
719           { QUERY_INDEX_CERTINFO_COMPARE_PKG_CERTINFO, { l_pkgid, r_pkgid } },
720           pcd::AbstractDBHandler::DBType::DB_TYPE_FILE_CERTDB,
721           pcd::AbstractDBHandler::OperationType::OPERATION_TYPE_READ));
722   pkgmgr_client::PkgInfoClient client(parcelable, 0,
723       pkgmgr_common::ReqType::QUERY);
724   if (!client.SendRequest())
725     return PMINFO_R_ERROR;
726
727   auto ptr = client.GetResultParcel();
728   if (ptr == nullptr) {
729     LOG(ERROR) << "Fail to get return parcelable";
730     return PMINFO_R_ERROR;
731   }
732
733   if (ptr->GetRequestResult() != PMINFO_R_OK) {
734     LOG(ERROR) << "Request fail";
735     return ptr->GetRequestResult();
736   }
737
738   if (ptr->GetType() != pcp::ParcelableType::Result) {
739     LOG(ERROR) << "Invalid parcelable type";
740     return PMINFO_R_ERROR;
741   }
742
743   std::shared_ptr<pcp::ResultParcelable> return_parcel(
744       std::static_pointer_cast<pcp::ResultParcelable>(
745           ptr));
746
747   auto certinfo_list = return_parcel->GetResult();
748
749   std::map<std::string, std::string> result_map;
750   result_map.insert(make_pair(std::string(l_pkgid), "-1"));
751   result_map.insert(make_pair(std::string(r_pkgid), "-1"));
752
753   for (auto& certinfo : certinfo_list)
754     result_map[certinfo.front()] = certinfo.back();
755
756   auto l_iter = result_map.find(l_pkgid);
757   auto r_iter = result_map.find(r_pkgid);
758   if (l_iter->second == "-1" && r_iter->second == "-1")
759     *result = PMINFO_CERT_COMPARE_BOTH_NO_CERT;
760   else if (l_iter->second == "-1")
761     *result = PMINFO_CERT_COMPARE_LHS_NO_CERT;
762   else if (r_iter->second == "-1")
763     *result = PMINFO_CERT_COMPARE_RHS_NO_CERT;
764   else if (l_iter->second == r_iter->second)
765     *result = PMINFO_CERT_COMPARE_MATCH;
766   else
767     *result = PMINFO_CERT_COMPARE_MISMATCH;
768
769   return PMINFO_R_OK;
770 }
771
772 extern "C" EXPORT_API int _certinfo_compare_app_certinfo(uid_t uid,
773     const char* l_appid, const char* r_appid,
774     pkgmgrinfo_cert_compare_result_type_e* result) {
775   std::shared_ptr<pcp::AbstractParcelable> parcelable(
776       new pcp::QueryParcelable(uid,
777           { QUERY_INDEX_CERTINFO_COMPARE_APP_CERTINFO, { l_appid, r_appid } },
778           pcd::AbstractDBHandler::DBType::DB_TYPE_FILE_PKGDB,
779           pcd::AbstractDBHandler::OperationType::OPERATION_TYPE_READ));
780   pkgmgr_client::PkgInfoClient client(parcelable, uid,
781       pkgmgr_common::ReqType::QUERY);
782   if (!client.SendRequest())
783     return PMINFO_R_ERROR;
784
785   auto ptr = client.GetResultParcel();
786   if (ptr == nullptr) {
787     LOG(ERROR) << "Fail to get return parcelable";
788     return PMINFO_R_ERROR;
789   }
790
791   if (ptr->GetRequestResult() != PMINFO_R_OK) {
792     LOG(ERROR) << "Request fail";
793     return ptr->GetRequestResult();
794   }
795
796   if (ptr->GetType() != pcp::ParcelableType::Result) {
797     LOG(ERROR) << "Invalid parcelable type";
798     return PMINFO_R_ERROR;
799   }
800
801   std::shared_ptr<pcp::ResultParcelable> return_parcel(
802       std::static_pointer_cast<pcp::ResultParcelable>(ptr));
803
804   auto pkgid_list = return_parcel->GetResult();
805   std::map<std::string, std::string> result_map;
806   for (auto& pkgid : pkgid_list)
807     result_map.insert(make_pair(pkgid.front(), pkgid.back()));
808
809   auto l_iter = result_map.find(l_appid);
810   if (l_iter == result_map.end()) {
811     LOG(ERROR) << "Cannot find pkgid of app " << l_appid
812         << " for uid " << uid;
813     return PMINFO_R_ENOENT;
814   }
815   auto r_iter = result_map.find(r_appid);
816   if (r_iter == result_map.end()) {
817     LOG(ERROR) << "Cannot find pkgid of app " << r_appid
818         << " for uid " << uid;
819     return PMINFO_R_ENOENT;
820   }
821
822   const char* l_pkgid = l_iter->second.c_str();
823   const char* r_pkgid = r_iter->second.c_str();
824
825   return _certinfo_compare_pkg_certinfo(l_pkgid, r_pkgid, result);
826 }
827
828 extern "C" EXPORT_API int _parser_execute_write_query(
829     int query_index, const char** query_args, unsigned int arg_cnt, uid_t uid) {
830   std::vector<std::string> args;
831
832   for (unsigned int i = 0; i < arg_cnt; i++) {
833     if (query_args[i])
834       args.push_back(query_args[i]);
835     else
836       args.push_back("");
837   }
838
839   std::shared_ptr<pcp::AbstractParcelable> parcelable(
840       new pcp::QueryParcelable(uid, { query_index, std::move(args) },
841           pcd::AbstractDBHandler::DBType::DB_TYPE_FILE_PKGDB,
842           pcd::AbstractDBHandler::OperationType::OPERATION_TYPE_WRITE));
843
844   pkgmgr_client::PkgInfoClient client(parcelable, uid,
845                                       pkgmgr_common::ReqType::QUERY);
846   if (!client.SendRequest())
847     return -1;
848
849   auto ptr = client.GetResultParcel();
850   if (ptr == nullptr) {
851     LOG(ERROR) << "Fail to get return parcelable";
852     return -1;
853   }
854
855   if (ptr->GetRequestResult() != PMINFO_R_OK) {
856     LOG(ERROR) << "Request fail";
857     return -1;
858   }
859
860   if (ptr->GetType() != pcp::ParcelableType::Result) {
861     LOG(ERROR) << "Invalid parcelable type";
862     return -1;
863   }
864   return 0;
865 }
866
867 extern "C" EXPORT_API int _parser_execute_write_queries(
868     int query_index, const char*** query_args, unsigned int arg_cnt,
869     unsigned int query_cnt, uid_t uid) {
870   std::vector<std::pair<int, std::vector<std::string>>> queries;
871
872   for (unsigned int i = 0; i < query_cnt; i++) {
873     std::vector<std::string> args;
874     for (unsigned int j = 0; j < arg_cnt; j++) {
875       if (query_args[i][j])
876         args.push_back(query_args[i][j]);
877       else
878         args.push_back("");
879     }
880     queries.push_back({ query_index, std::move(args) });
881   }
882
883   std::shared_ptr<pcp::AbstractParcelable> parcelable(
884       new pcp::QueryParcelable(uid, std::move(queries),
885           pcd::AbstractDBHandler::DBType::DB_TYPE_FILE_PKGDB,
886           pcd::AbstractDBHandler::OperationType::OPERATION_TYPE_WRITE));
887
888   pkgmgr_client::PkgInfoClient client(parcelable, uid,
889       pkgmgr_common::ReqType::QUERY);
890   if (!client.SendRequest())
891     return -1;
892
893   auto ptr = client.GetResultParcel();
894   if (ptr == nullptr) {
895     LOG(ERROR) << "Fail to get return parcelable";
896     return -1;
897   }
898
899   if (ptr->GetRequestResult() != PMINFO_R_OK) {
900     LOG(ERROR) << "Request fail";
901     return -1;
902   }
903
904   if (ptr->GetType() != pcp::ParcelableType::Result) {
905     LOG(ERROR) << "Invalid parcelable type";
906     return -1;
907   }
908
909   return 0;
910 }
911
912 extern "C" EXPORT_API int _parser_insert_manifest_info(
913     manifest_x* mfx, uid_t uid) {
914   auto parcelable =
915       std::make_shared<pcp::PkgInfoParcelable>(uid,
916           std::vector<package_x*>{mfx}, WriteType::Insert, false);
917
918   pkgmgr_client::PkgInfoClient client(parcelable, uid,
919       pkgmgr_common::ReqType::SET_PKG_INFO);
920   if (!client.SendRequest())
921     return -1;
922
923   auto ptr = client.GetResultParcel();
924   if (ptr == nullptr) {
925     LOG(ERROR) << "Fail to get return parcelable";
926     return -1;
927   }
928
929   if (ptr->GetRequestResult() != PMINFO_R_OK) {
930     LOG(ERROR) << "Request fail";
931     return -1;
932   }
933
934   if (ptr->GetType() != pcp::ParcelableType::Result) {
935     LOG(ERROR) << "Invalid parcelable type";
936     return -1;
937   }
938
939   return 0;
940 }
941
942 extern "C" EXPORT_API int _parser_update_manifest_info(
943     manifest_x* mfx, uid_t uid) {
944   auto parcelable =
945       std::make_shared<pcp::PkgInfoParcelable>(uid,
946           std::vector<package_x*>{mfx}, WriteType::Update, false);
947
948   pkgmgr_client::PkgInfoClient client(parcelable, uid,
949       pkgmgr_common::ReqType::SET_PKG_INFO);
950   if (!client.SendRequest())
951     return -1;
952
953   auto ptr = client.GetResultParcel();
954   if (ptr == nullptr) {
955     LOG(ERROR) << "Fail to get return parcelable";
956     return -1;
957   }
958
959   if (ptr->GetRequestResult() != PMINFO_R_OK) {
960     LOG(ERROR) << "Request fail";
961     return -1;
962   }
963
964   if (ptr->GetType() != pcp::ParcelableType::Result) {
965     LOG(ERROR) << "Invalid parcelable type";
966     return -1;
967   }
968
969   return 0;
970 }
971
972 extern "C" EXPORT_API int _parser_delete_manifest_info(
973     manifest_x* mfx, uid_t uid) {
974   auto parcelable =
975       std::make_shared<pcp::PkgInfoParcelable>(uid,
976           std::vector<package_x*>{mfx}, WriteType::Delete, false);
977
978   pkgmgr_client::PkgInfoClient client(parcelable, uid,
979       pkgmgr_common::ReqType::SET_PKG_INFO);
980   if (!client.SendRequest())
981     return -1;
982
983   auto ptr = client.GetResultParcel();
984   if (ptr == nullptr) {
985     LOG(ERROR) << "Fail to get return parcelable";
986     return -1;
987   }
988
989   if (ptr->GetRequestResult() != PMINFO_R_OK) {
990     LOG(ERROR) << "Request fail";
991     return -1;
992   }
993
994   if (ptr->GetType() != pcp::ParcelableType::Result) {
995     LOG(ERROR) << "Invalid parcelable type";
996     return -1;
997   }
998
999   return 0;
1000 }
1001
1002 extern "C" EXPORT_API int _pkginfo_insert_certinfo(const char* pkgid,
1003     pkgmgr_certinfo_x* cert, uid_t uid) {
1004   std::shared_ptr<pcp::AbstractParcelable> parcelable(
1005       new pcp::CertInfoParcelable(uid, cert, false));
1006   pkgmgr_client::PkgInfoClient client(parcelable, uid,
1007       pkgmgr_common::ReqType::SET_CERT_INFO);
1008
1009   if (!client.SendRequest())
1010     return PMINFO_R_ERROR;
1011
1012   auto ptr = client.GetResultParcel();
1013   if (ptr == nullptr) {
1014     LOG(ERROR) << "Fail to get return parcelable";
1015     return PMINFO_R_ERROR;
1016   }
1017
1018   if (ptr->GetRequestResult() != PMINFO_R_OK) {
1019     LOG(ERROR) << "Request fail";
1020     return ptr->GetRequestResult();
1021   }
1022
1023   if (ptr->GetType() != pcp::ParcelableType::Result) {
1024     LOG(ERROR) << "Invalid parcelable type";
1025     return PMINFO_R_ERROR;
1026   }
1027
1028   return PMINFO_R_OK;
1029 }
1030
1031 extern "C" EXPORT_API int _pkginfo_get_certinfo(const char* pkgid,
1032     pkgmgr_certinfo_x* cert, uid_t uid) {
1033   std::shared_ptr<pcp::AbstractParcelable> parcelable(
1034       new pcp::CertInfoParcelable(uid,
1035           std::string(pkgid)));
1036
1037   pkgmgr_client::PkgInfoClient client(parcelable, uid,
1038                                       pkgmgr_common::ReqType::GET_CERT_INFO);
1039   if (!client.SendRequest())
1040     return PMINFO_R_ERROR;
1041
1042   auto ptr = client.GetResultParcel();
1043   if (ptr == nullptr) {
1044     LOG(ERROR) << "Fail to get return parcelable";
1045     return PMINFO_R_ERROR;
1046   }
1047
1048   if (ptr->GetRequestResult() != PMINFO_R_OK) {
1049     LOG(ERROR) << "Request fail";
1050     return ptr->GetRequestResult();
1051   }
1052
1053   if (ptr->GetType() != pcp::ParcelableType::CertInfo) {
1054     LOG(ERROR) << "Invalid parcelable type";
1055     return PMINFO_R_ERROR;
1056   }
1057
1058   std::shared_ptr<pcp::CertInfoParcelable> return_parcel(
1059       std::static_pointer_cast<pcp::CertInfoParcelable>(ptr));
1060
1061   pkgmgr_certinfo_x* certinfo = return_parcel->ExtractCertInfo();
1062   if (certinfo == nullptr)
1063     return PMINFO_R_ERROR;
1064
1065   cert->for_all_users = certinfo->for_all_users;
1066   cert->pkgid = certinfo->pkgid;
1067   certinfo->pkgid = nullptr;
1068   cert->cert_value = certinfo->cert_value;
1069   certinfo->cert_value = nullptr;
1070   for (int i = 0; i < MAX_CERT_TYPE; i++) {
1071     cert->cert_info[i] = certinfo->cert_info[i];
1072     certinfo->cert_info[i] = nullptr;
1073   }
1074   for (int i = 0; i < MAX_CERT_TYPE; i++)
1075     cert->cert_id[i] = certinfo->cert_id[i];
1076
1077   free(certinfo);
1078
1079   return PMINFO_R_OK;
1080 }
1081
1082 extern "C" EXPORT_API int _pkginfo_delete_certinfo(const char* pkgid) {
1083   std::shared_ptr<pcp::AbstractParcelable> parcelable(
1084       new pcp::QueryParcelable(0,
1085           { QUERY_INDEX_PKGINFO_DELETE_CERTINFO, { pkgid } },
1086           pcd::AbstractDBHandler::DBType::DB_TYPE_FILE_CERTDB,
1087           pcd::AbstractDBHandler::OperationType::OPERATION_TYPE_WRITE));
1088
1089   pkgmgr_client::PkgInfoClient client(parcelable, 0,
1090                                       pkgmgr_common::ReqType::QUERY);
1091   if (!client.SendRequest())
1092     return PMINFO_R_ERROR;
1093
1094   auto ptr = client.GetResultParcel();
1095   if (ptr == nullptr) {
1096     LOG(ERROR) << "Fail to get return parcelable";
1097     return PMINFO_R_ERROR;
1098   }
1099
1100   if (ptr->GetRequestResult() != PMINFO_R_OK) {
1101     LOG(ERROR) << "Request fail";
1102     return PMINFO_R_ERROR;
1103   }
1104
1105   if (ptr->GetType() != pcp::ParcelableType::Result) {
1106     LOG(ERROR) << "Invalid parcelable type";
1107     return PMINFO_R_ERROR;
1108   }
1109
1110   return PMINFO_R_OK;
1111 }
1112
1113 extern "C" EXPORT_API int _parser_clear_cache_memory_db(uid_t uid) {
1114   std::shared_ptr<pcp::AbstractParcelable> parcelable(
1115       new pcp::CommandParcelable(uid, CommandType::RemoveCache));
1116
1117   pkgmgr_client::PkgInfoClient client(parcelable, uid,
1118                                       pkgmgr_common::ReqType::COMMAND);
1119
1120   if (!client.SendRequest())
1121     return PMINFO_R_ERROR;
1122
1123   auto ptr = client.GetResultParcel();
1124   if (ptr == nullptr) {
1125     LOG(ERROR) << "Fail to get return parcelable";
1126     return PMINFO_R_ERROR;
1127   }
1128
1129   if (ptr->GetRequestResult() != PMINFO_R_OK) {
1130     LOG(ERROR) << "Request fail";
1131     return PMINFO_R_ERROR;
1132   }
1133
1134   if (ptr->GetType() != pcp::ParcelableType::Result) {
1135     LOG(ERROR) << "Invalid parcelable type";
1136     return PMINFO_R_ERROR;
1137   }
1138
1139   return PMINFO_R_OK;
1140 }