9f256a9c17403b53856cf49835fbc6ff4ed3c488
[platform/core/appfw/pkgmgr-info.git] / parser / src / pkgmgr_parser_db.c
1 /*
2  * Copyright (c) 2000 - 2017 Samsung Electronics Co., Ltd. All rights reserved.
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 <fcntl.h>
19 #include <stdio.h>
20 #include <stdbool.h>
21 #include <string.h>
22 #include <sys/types.h>
23 #include <sys/stat.h>
24 #include <sys/smack.h>
25 #include <sys/sysmacros.h>
26 #include <linux/limits.h>
27 #include <unistd.h>
28 #include <pwd.h>
29
30 #include <glib.h>
31 #include <gio/gio.h>
32
33 #include <tzplatform_config.h>
34 #include <system_info.h>
35
36 #include "pkgmgr-info.h"
37 #include "pkgmgrinfo_basic.h"
38 #include "pkgmgr_parser.h"
39 #include "pkgmgr_parser_debug.h"
40 #include "pkgmgr_parser_internal.h"
41 #include "manager/pkginfo_manager.h"
42 #include "pkgmgr_query_index.h"
43
44 #ifndef OWNER_ROOT
45 #define OWNER_ROOT 0
46 #endif
47 #ifndef GLOBAL_USER
48 #define GLOBAL_USER tzplatform_getuid(TZ_SYS_GLOBALAPP_USER)
49 #endif
50 #ifndef APPFW_USER
51 #define APPFW_USER "app_fw"
52 #endif
53
54 #define BUFSIZE 4096
55
56 #define LDPI "ldpi"
57 #define MDPI "mdpi"
58 #define HDPI "hdpi"
59 #define XHDPI "xhdpi"
60 #define XXHDPI "xxhdpi"
61
62 #define LDPI_MIN 0
63 #define LDPI_MAX 240
64 #define MDPI_MIN 241
65 #define MDPI_MAX 300
66 #define HDPI_MIN 301
67 #define HDPI_MAX 380
68 #define XHDPI_MIN 381
69 #define XHDPI_MAX 480
70 #define XXHDPI_MIN 481
71 #define XXHDPI_MAX 600
72
73 #define MAX_UID_LENGTH 64
74
75 /* app background category value */
76 #define APP_BG_CATEGORY_USER_DISABLE_FALSE_VAL 0x00000
77 #define APP_BG_CATEGORY_USER_DISABLE_TRUE_VAL  0x00001
78 #define APP_BG_CATEGORY_MEDIA_VAL              0x00002
79 #define APP_BG_CATEGORY_DOWNLOAD_VAL           0x00004
80 #define APP_BG_CATEGORY_BGNETWORK_VAL          0x00008
81 #define APP_BG_CATEGORY_LOCATION_VAL           0x00010
82 #define APP_BG_CATEGORY_SENSOR_VAL             0x00020
83 #define APP_BG_CATEGORY_IOTCOMM_VAL            0x00040
84 #define APP_BG_CATEGORY_SYSTEM_VAL             0x00080
85
86 #define APP_BG_CATEGORY_USER_DISABLE_FALSE_STR "enable"
87 #define APP_BG_CATEGORY_USER_DISABLE_TRUE_STR  "disable"
88 #define APP_BG_CATEGORY_MEDIA_STR              "media"
89 #define APP_BG_CATEGORY_DOWNLOAD_STR           "download"
90 #define APP_BG_CATEGORY_BGNETWORK_STR          "background-network"
91 #define APP_BG_CATEGORY_LOCATION_STR           "location"
92 #define APP_BG_CATEGORY_SENSOR_STR             "sensor"
93 #define APP_BG_CATEGORY_IOTCOMM_STR            "iot-communication"
94 #define APP_BG_CATEGORY_SYSTEM                 "system"
95
96 #define REGULAR_USER 5000
97 static inline uid_t __getuid(void)
98 {
99         uid_t uid = getuid();
100
101         if (uid < REGULAR_USER)
102                 return tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
103         else
104                 return uid;
105 }
106
107 API int pkgmgr_parser_create_and_initialize_db(uid_t uid)
108 {
109         int ret;
110         struct passwd pwd;
111         struct passwd *result;
112         char buf[BUFSIZE];
113
114         ret = getpwnam_r(APPFW_USER, &pwd, buf, sizeof(buf), &result);
115         if (result == NULL) {
116                 if (ret == 0)
117                         _LOGE("no such user: %s", APPFW_USER);
118                 else
119                         _LOGE("getpwnam_r failed: %d", errno);
120                 return PM_PARSER_R_ERROR;
121         }
122
123         if (getuid() != OWNER_ROOT && getuid() != pwd.pw_uid) {
124                 _LOGE("Only root or app_fw user is allowed");
125                 return PM_PARSER_R_EINVAL;
126         }
127
128         if (_parser_create_and_initialize_db(uid))
129                 return PM_PARSER_R_ERROR;
130
131         return PM_PARSER_R_OK;
132 }
133
134 /* TODO: move to installer */
135
136 /* TODO: refactor inserting localized info */
137
138 static int __insert_package_plugin_execution_info(
139                 manifest_x *mfx, uid_t uid)
140 {
141         GList *tmp;
142         plugin_x *plugin;
143         int idx = 0;
144         const char ***args;
145         int i;
146         int ret = PM_PARSER_R_ERROR;
147
148         if (!mfx->plugin)
149                 return PM_PARSER_R_OK;
150
151         int len = g_list_length(mfx->plugin);
152
153         args = calloc(len, sizeof(char **));
154         if (args == NULL) {
155                 _LOGE("Out of memory");
156                 return PM_PARSER_R_ERROR;
157         }
158
159         for (i = 0; i < len; i++) {
160                 args[i] = calloc(4, sizeof(char *));
161                 if (args[i] == NULL) {
162                         _LOGE("Out of memory");
163                         goto clear;
164                 }
165         }
166
167         for (tmp = mfx->plugin; tmp; tmp = tmp->next) {
168                 plugin = (plugin_x *)tmp->data;
169                 if (plugin == NULL)
170                         continue;
171
172                 args[idx][0] = plugin->pkgid;
173                 args[idx][1] = plugin->appid;
174                 args[idx][2] = plugin->plugin_type;
175                 args[idx][3] = plugin->plugin_name;
176                 idx++;
177         }
178
179         if (_parser_execute_write_queries(QUERY_INDEX_INSERT_PACKAGE_PLUGIN_EXECUTION_INFO,
180                         args, 4, idx, uid) < 0) {
181                 _LOGE("Fail to write to db");
182                 goto clear;
183                 return PM_PARSER_R_ERROR;
184         }
185
186         ret = PM_PARSER_R_OK;
187 clear:
188         for (i = 0; i < len; i++)
189                 free(args[i]);
190
191         free(args);
192
193         return ret;
194 }
195
196 static int __delete_package_plugin_execution_info(const char *pkgid, uid_t uid)
197 {
198         const char *args[1] = { pkgid };
199
200         if (_parser_execute_write_query(QUERY_INDEX_DELETE_PACKAGE_PLUGIN_EXECUTION_INFO,
201                         args, 1, uid) < 0) {
202                 _LOGE("Fail to write to db");
203                 return PM_PARSER_R_ERROR;
204         }
205
206         return PM_PARSER_R_OK;
207 }
208
209 API int pkgmgr_parser_insert_manifest_info_in_usr_db(manifest_x *mfx, uid_t uid)
210 {
211         if (_parser_insert_manifest_info(mfx, uid) < 0) {
212                 _LOGE("Fail to insert manifest uid[%d]", uid);
213                 return PM_PARSER_R_ERROR;
214         }
215
216         return PM_PARSER_R_OK;
217 }
218
219 API int pkgmgr_parser_insert_manifest_info_in_db(manifest_x *mfx)
220 {
221         return pkgmgr_parser_insert_manifest_info_in_usr_db(mfx, __getuid());
222 }
223
224 API int pkgmgr_parser_delete_manifest_info_from_usr_db(manifest_x *mfx,
225         uid_t uid)
226 {
227         if (_parser_delete_manifest_info(mfx, uid) < 0) {
228                 _LOGE("Fail to update manifest uid[%d]", uid);
229                 return PM_PARSER_R_ERROR;
230         }
231
232         return PM_PARSER_R_OK;
233 }
234
235 API int pkgmgr_parser_delete_manifest_info_from_db(manifest_x *mfx)
236 {
237         return pkgmgr_parser_delete_manifest_info_from_usr_db(mfx, __getuid());
238 }
239
240 API int pkgmgr_parser_update_manifest_info_in_usr_db(manifest_x *mfx, uid_t uid)
241 {
242         if (_parser_update_manifest_info(mfx, uid) < 0) {
243                 _LOGE("Fail to update manifest uid[%d]", uid);
244                 return PM_PARSER_R_ERROR;
245         }
246
247         return PM_PARSER_R_OK;
248 }
249
250 API int pkgmgr_parser_update_manifest_info_in_db(manifest_x *mfx)
251 {
252         return pkgmgr_parser_update_manifest_info_in_usr_db(mfx, __getuid());
253 }
254
255 API int pkgmgr_parser_update_global_app_disable_for_uid_info_in_db(
256                 const char *appid, uid_t uid, int is_disable)
257 {
258         char uid_str[MAX_UID_LENGTH] = { 0, };
259         const char *args[4];
260         int r;
261
262         r = snprintf(uid_str, sizeof(uid_str), "%d", uid);
263         if (r < 0 || r >= sizeof(uid_str))
264                 return PM_PARSER_R_ERROR;
265         args[0] = appid;
266         args[1] = uid_str;
267         args[2] = is_disable ? "true" : "false";
268         args[3] = appid;
269
270         if (_parser_execute_write_query(QUERY_INDEX_UPDATE_GLOBAL_APP_DISABLE,
271                         args, 4, GLOBAL_USER) < 0) {
272                 _LOGE("Fail to write to db");
273                 return PM_PARSER_R_ERROR;
274         }
275
276         return PM_PARSER_R_OK;
277 }
278
279 API int pkgmgr_parser_update_app_disable_info_in_usr_db(const char *appid,
280                 uid_t uid, int is_disable)
281 {
282         const char *args[2];
283         args[0] = is_disable ? "true" : "false";
284         args[1] = appid;
285
286         if (_parser_execute_write_query(QUERY_INDEX_UPDATE_APP_DISABLE_INFO,
287                         args, 2, uid) < 0) {
288                 _LOGE("Fail to write to db");
289                 return PM_PARSER_R_ERROR;
290         }
291
292         return PM_PARSER_R_OK;
293 }
294
295 API int pkgmgr_parser_update_app_disable_info_in_db(const char *appid,
296                 int is_disable)
297 {
298         return pkgmgr_parser_update_app_disable_info_in_usr_db(appid,
299                         __getuid(), is_disable);
300 }
301
302 API int pkgmgr_parser_update_pkg_disable_info_in_usr_db(const char *pkgid,
303                 uid_t uid, int is_disable)
304 {
305         const char *args[2];
306         args[0] = is_disable ? "true" : "false";
307         args[1] = pkgid;
308
309         if (_parser_execute_write_query(QUERY_INDEX_UPDATE_PKG_DISABLE_INFO,
310                         args, 2, uid) < 0) {
311                 _LOGE("Fail to write to db");
312                 return PM_PARSER_R_ERROR;
313         }
314
315         return PM_PARSER_R_OK;
316 }
317
318 API int pkgmgr_parser_update_pkg_disable_info_in_db(const char *pkgid,
319                 int is_disable)
320 {
321         return pkgmgr_parser_update_pkg_disable_info_in_usr_db(pkgid,
322                         __getuid(), is_disable);
323 }
324
325 API int pkgmgr_parser_update_global_app_splash_screen_display_info_in_usr_db(
326                 const char *appid, uid_t uid, int flag)
327 {
328         const char *args[3];
329         char uid_str[MAX_UID_LENGTH] = { 0, };
330         int r;
331
332         r = snprintf(uid_str, sizeof(uid_str), "%d", uid);
333         if (r < 0 || r >= sizeof(uid_str))
334                 return PM_PARSER_R_ERROR;
335         args[0] = appid;
336         args[1] = uid_str;
337         args[2] = (flag == 1 ? "true" : "false");
338
339         if (_parser_execute_write_query(
340                         QUERY_INDEX_UPDATE_GLOBAL_APP_SPLASH_SCREEN_DISPLAY_INFO,
341                         args, 3, uid) < 0) {
342                 _LOGE("Fail to write to db");
343                 return PM_PARSER_R_ERROR;
344         }
345
346         return PM_PARSER_R_OK;
347 }
348
349 API int pkgmgr_parser_update_app_splash_screen_display_info_in_usr_db(
350                 const char *appid, uid_t uid, int flag)
351 {
352         const char *args[2];
353
354         args[0] = (flag == 1 ? "true" : "false");
355         args[1] = appid;
356
357         if (_parser_execute_write_query(
358                         QUERY_INDEX_UPDATE_APP_SPLASH_SCREEN_DISPLAY_INFO,
359                         args, 2, uid) < 0) {
360                 _LOGE("Fail to write to db");
361                 return PM_PARSER_R_ERROR;
362         }
363
364         return PM_PARSER_R_OK;
365 }
366
367 API int pkgmgr_parser_update_app_splash_screen_display_info_in_db(
368                 const char *appid, int flag)
369 {
370         return pkgmgr_parser_update_app_splash_screen_display_info_in_usr_db(
371                         appid, __getuid(), flag);
372 }
373
374 API int pkgmgr_parser_update_app_label_info_in_usr_db(const char *appid,
375                 uid_t uid, const char *label)
376 {
377         const char *args[2] = { label, appid };
378
379         if (_parser_execute_write_query(QUERY_INDEX_UPDATE_APP_LABEL_INFO,
380                         args, 2, uid) < 0) {
381                 _LOGE("Fail to write to db");
382                 return PM_PARSER_R_ERROR;
383         }
384
385         return PM_PARSER_R_OK;
386 }
387
388 API int pkgmgr_parser_update_app_label_info_in_db(const char *appid,
389                 const char *label)
390 {
391         return pkgmgr_parser_update_app_label_info_in_usr_db(appid, __getuid(),
392                         label);
393 }
394
395 API int pkgmgr_parser_update_app_icon_info_in_usr_db(const char *appid,
396                 uid_t uid, const char *icon_path)
397 {
398         const char *args[2] = { icon_path, appid };
399
400         if (_parser_execute_write_query(QUERY_INDEX_UPDATE_APP_ICON_INFO,
401                         args, 2, uid) < 0) {
402                 _LOGE("Fail to write to db");
403                 return PM_PARSER_R_ERROR;
404         }
405
406         return PM_PARSER_R_OK;
407 }
408
409 API int pkgmgr_parser_update_app_icon_info_in_db(const char *appid,
410                 const char *icon_path)
411 {
412         return pkgmgr_parser_update_app_icon_info_in_usr_db(appid, __getuid(),
413                         icon_path);
414 }
415
416 API int pkgmgr_parser_update_tep_info_in_usr_db(const char *pkgid,
417                 const char *tep_path, uid_t uid)
418 {
419         const char *args[2] = { tep_path, pkgid };
420
421         if (_parser_execute_write_query(QUERY_INDEX_UPDATE_TEP_INFO,
422                         args, 2, uid) < 0) {
423                 _LOGE("Fail to write to db");
424                 return PM_PARSER_R_ERROR;
425         }
426
427         return PM_PARSER_R_OK;
428 }
429
430 API int pkgmgr_parser_update_tep_info_in_db(const char *pkgid,
431                 const char *tep_path)
432 {
433         return pkgmgr_parser_update_tep_info_in_usr_db(pkgid, tep_path,
434                         __getuid());
435 }
436
437 static int __convert_update_type(pkgmgrinfo_updateinfo_update_type type,
438                 const char **update_type)
439 {
440         if (type == PMINFO_UPDATEINFO_NONE)
441                 *update_type = PMINFO_UPDATEINFO_TYPE_NONE;
442         else if (type == PMINFO_UPDATEINFO_FORCE)
443                 *update_type = PMINFO_UPDATEINFO_TYPE_FORCE;
444         else if (type == PMINFO_UPDATEINFO_OPTIONAL)
445                 *update_type = PMINFO_UPDATEINFO_TYPE_OPTIONAL;
446         else
447                 return -1;
448         return 0;
449 }
450
451 static int __register_pkg_update_info(updateinfo_x *info,
452                 const char *update_type, uid_t uid)
453 {
454         const char *args[3] = { info->version, update_type, info->pkgid };
455
456         if (_parser_execute_write_query(QUERY_INDEX_REGISTER_PKG_UPDATE_INFO,
457                         args, 3, uid) < 0) {
458                 _LOGE("Fail to write to db");
459                 return PM_PARSER_R_ERROR;
460         }
461
462         return PM_PARSER_R_OK;
463 }
464
465 API int pkgmgr_parser_register_pkg_update_info_in_usr_db(
466                 pkgmgrinfo_updateinfo_h handle, uid_t uid)
467 {
468         int ret;
469         updateinfo_x *update_info;
470         updateinfo_x *prev_update_info;
471         pkgmgrinfo_updateinfo_h prev_update_handle;
472         pkgmgrinfo_pkginfo_h pkginfo;
473         pkgmgrinfo_version_compare_type compare_result;
474         bool is_global_pkg;
475         const char *update_type;
476
477         if (handle == NULL) {
478                 _LOGE("invalid parameter");
479                 return PM_PARSER_R_EINVAL;
480         }
481
482         update_info = (updateinfo_x *)handle;
483         if (update_info->pkgid == NULL || update_info->version == NULL)
484                 return PM_PARSER_R_EINVAL;
485         if (__convert_update_type(update_info->type, &update_type) != 0)
486                 return PM_PARSER_R_EINVAL;
487
488         ret = pkgmgrinfo_updateinfo_get_usr_updateinfo(update_info->pkgid,
489                         &prev_update_handle, uid);
490         if (ret != PMINFO_R_OK)
491                 return PM_PARSER_R_ERROR;
492
493         prev_update_info = (updateinfo_x *)prev_update_handle;
494         ret = pkgmgrinfo_compare_package_version(update_info->version,
495                         prev_update_info->version, &compare_result);
496         if (ret != PMINFO_R_OK) {
497                 pkgmgrinfo_updateinfo_destroy(prev_update_handle);
498                 return PM_PARSER_R_ERROR;
499         }
500
501         if (compare_result == PMINFO_VERSION_SAME &&
502                         prev_update_info->type == PMINFO_UPDATEINFO_NONE) {
503                 _LOGI("Given update info version[%s] of pkgid[%s] "
504                                 "will be ignored",
505                                 update_info->version, update_info->pkgid);
506                 pkgmgrinfo_updateinfo_destroy(prev_update_handle);
507                 return PM_PARSER_R_OK;
508         }
509         pkgmgrinfo_updateinfo_destroy(prev_update_handle);
510
511         ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(update_info->pkgid, uid,
512                         &pkginfo);
513         if (ret != PMINFO_R_OK)
514                 return PM_PARSER_R_ERROR;
515
516         ret = pkgmgrinfo_pkginfo_is_global(pkginfo, &is_global_pkg);
517         if (ret != PMINFO_R_OK) {
518                 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo);
519                 return PM_PARSER_R_ERROR;
520         }
521         pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo);
522
523         return __register_pkg_update_info(update_info, update_type, uid);
524 }
525
526 API int pkgmgr_parser_register_pkg_update_info_in_db(
527                 pkgmgrinfo_updateinfo_h handle)
528 {
529         return pkgmgr_parser_register_pkg_update_info_in_usr_db(handle,
530                         __getuid());
531 }
532
533 static int __unregister_pkg_update_info(const char *pkgid, uid_t uid)
534 {
535         const char *args[1] = { pkgid };
536
537         if (_parser_execute_write_query(QUERY_INDEX_UNREGISTER_PKG_UPDATE_INFO,
538                         args, 1, uid) < 0) {
539                 _LOGE("Fail to write to db");
540                 return PM_PARSER_R_ERROR;
541         }
542
543         return PM_PARSER_R_OK;
544 }
545
546 API int pkgmgr_parser_unregister_pkg_update_info_in_usr_db(const char *pkgid,
547                 uid_t uid)
548 {
549         int ret;
550         pkgmgrinfo_pkginfo_h pkginfo;
551         bool is_global_pkg;
552         uid_t target_uid;
553
554         if (pkgid == NULL) {
555                 _LOGE("invalid parameter");
556                 return PM_PARSER_R_EINVAL;
557         }
558
559         ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(pkgid, uid, &pkginfo);
560         if (ret != PMINFO_R_OK)
561                 return PM_PARSER_R_EINVAL;
562
563         ret = pkgmgrinfo_pkginfo_is_global(pkginfo, &is_global_pkg);
564         pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo);
565         if (ret != PMINFO_R_OK)
566                 return PM_PARSER_R_ERROR;
567
568         target_uid = is_global_pkg ? GLOBAL_USER : uid;
569
570         // TODO: what we do with is_global_pkg?
571         return __unregister_pkg_update_info(pkgid, target_uid);
572 }
573
574 API int pkgmgr_parser_unregister_pkg_update_info_in_db(const char *pkgid)
575 {
576         return pkgmgr_parser_unregister_pkg_update_info_in_usr_db(pkgid,
577                         __getuid());
578 }
579
580 API int pkgmgr_parser_unregister_all_pkg_update_info_in_usr_db(uid_t uid)
581 {
582         if (_parser_execute_write_query(QUERY_INDEX_UNREGISTER_ALL_PKG_UPDATE_INFO,
583                 NULL, 0, uid) < 0) {
584                 _LOGE("Fail to write to db");
585                 return PM_PARSER_R_ERROR;
586         }
587
588         return PM_PARSER_R_OK;
589 }
590
591 API int pkgmgr_parser_unregister_all_pkg_update_info_in_db(void)
592 {
593         return pkgmgr_parser_unregister_all_pkg_update_info_in_usr_db(
594                         __getuid());
595 }
596
597 API int pkgmgr_parser_register_pkg_plugin_info_in_usr_db(
598                 manifest_x *mfx, uid_t uid)
599 {
600         return __insert_package_plugin_execution_info(mfx, uid);
601 }
602
603 API int pkgmgr_parser_register_pkg_plugin_info_in_db(manifest_x *mfx)
604 {
605         return pkgmgr_parser_register_pkg_plugin_info_in_usr_db(mfx, __getuid());
606 }
607
608 API int pkgmgr_parser_update_pkg_plugin_info_in_usr_db(
609                 manifest_x *mfx, uid_t uid)
610 {
611         // TODO: construct query and send to server
612         int ret;
613
614         ret = __delete_package_plugin_execution_info(mfx->package, uid);
615         if (ret != PM_PARSER_R_OK)
616                 return ret;
617         ret = __insert_package_plugin_execution_info(mfx, uid);
618         if (ret != PM_PARSER_R_OK)
619                 return ret;
620
621         return PM_PARSER_R_OK;
622 }
623
624 API int pkgmgr_parser_update_pkg_plugin_info_in_db(manifest_x *mfx)
625 {
626         return pkgmgr_parser_update_pkg_plugin_info_in_usr_db(mfx, __getuid());
627 }
628
629 API int pkgmgr_parser_unregister_pkg_plugin_info_in_usr_db(
630                 const char *pkgid, uid_t uid)
631 {
632         return __delete_package_plugin_execution_info(pkgid, uid);
633 }
634
635 API int pkgmgr_parser_unregister_pkg_plugin_info_in_db(const char *pkgid)
636 {
637         return pkgmgr_parser_unregister_pkg_plugin_info_in_usr_db(pkgid, __getuid());
638 }
639
640 API int pkgmgr_parser_clear_cache_usr_memory_db(uid_t uid)
641 {
642         return _parser_clear_cache_memory_db(uid);
643 }
644
645 API int pkgmgr_parser_clear_cache_memory_db(void)
646 {
647         return pkgmgr_parser_clear_cache_usr_memory_db(__getuid());
648 }
649
650 API int pkgmgr_parser_update_pending_cache(const char *pkgid)
651 {
652         return _parser_update_pending_cache(pkgid);
653 }