Fix usage of GVariant in "g_dbus_proxy_call_sync"
[platform/core/appfw/app2sd.git] / plugin / app2sd / lib / app2sd_client_interface.c
1 /*
2  * app2ext
3  *
4  * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Garima Shrivastava<garima.s@samsung.com>
7  *      Jyotsna Dhumale <jyotsna.a@samsung.com>
8  *      Venkatesha Sarpangala <sarpangala.v@samsung.com>
9  *
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  *
14  * http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  *
22  */
23
24 #include <stdio.h>
25 #include <errno.h>
26 #include <sys/types.h>
27 #include <sys/wait.h>
28 #include <gio/gio.h>
29
30 #include <pkgmgr-info.h>
31 #include <sqlite3.h>
32 #include <tzplatform_config.h>
33
34 #include "app2sd_client_interface.h"
35 #include "app2sd_utils.h"
36
37 #define CONNECTION_RETRY_MAX 5
38 #define CONNECTION_WAIT_USEC (1000000 / 2) /* 0.5 sec */
39
40 static int app2sd_gdbus_shared_connection(GDBusConnection **connection)
41 {
42         GError *error = NULL;
43
44 #if (GLIB_MAJOR_VERSION <= 2 && GLIB_MINOR_VERSION < 36)
45         g_type_init();
46 #endif
47
48         *connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
49         if (*connection == NULL) {
50                 if (error != NULL) {
51                         _E("app2sd error : failed to get "
52                                 "system dbus [%s]", error->message);
53                         g_error_free(error);
54                 }
55                 return APP2EXT_ERROR_DBUS_FAILED;
56         }
57
58         return APP2EXT_SUCCESS;
59 }
60
61 static int __app2sd_call_server_method(const gchar *method_name,
62                 GVariant *param)
63 {
64         int ret = APP2EXT_SUCCESS;
65         int result = 0;
66         int retry_cnt = 0;
67         GDBusConnection *conn = NULL;
68         GDBusProxy *proxy = NULL;
69         GError *error = NULL;
70         GVariant *value = NULL;
71
72         if (param)
73                 g_variant_ref_sink(param);
74
75         /* get gdbus connection */
76         ret = app2sd_gdbus_shared_connection(&conn);
77         if (ret) {
78                 _E("app2sd error : dbus connection error");
79                 if (param)
80                         g_variant_unref(param);
81                 return ret;
82         }
83
84         /* method call */
85         do {
86                 proxy = g_dbus_proxy_new_sync(conn,
87                         G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, NULL,
88                         APP2SD_BUS_NAME, APP2SD_OBJECT_PATH,
89                         APP2SD_INTERFACE_NAME,
90                         NULL, &error);
91                 if (proxy == NULL) {
92                         _E("failed to create new proxy, error(%s)",
93                                 error->message);
94                         g_error_free(error);
95                         error = NULL;
96                         ret = APP2EXT_ERROR_DBUS_FAILED;
97                         retry_cnt++;
98                         usleep(CONNECTION_WAIT_USEC);
99                         continue;
100                 }
101
102                 value = g_dbus_proxy_call_sync(proxy, method_name, param,
103                         G_DBUS_CALL_FLAGS_NONE, G_MAXINT, NULL, &error);
104                 g_object_unref(proxy);
105                 if (error != NULL) {
106                         _E("proxy call sync error(%s)", error->message);
107                         g_error_free(error);
108                         error = NULL;
109                         ret = APP2EXT_ERROR_DBUS_FAILED;
110                         retry_cnt++;
111                         usleep(CONNECTION_WAIT_USEC);
112                         continue;
113                 }
114
115                 g_variant_get(value, "(i)", &result);
116                 g_variant_unref(value);
117
118                 _D("result(%d)", result);
119                 if (result)
120                         ret = result;
121
122                 break;
123         } while (retry_cnt <= CONNECTION_RETRY_MAX);
124
125         if (conn)
126                 g_object_unref(conn);
127         if (param)
128                 g_variant_unref(param);
129
130         return ret;
131 }
132
133 static void __app2sd_create_dir_list_builder(gpointer data, gpointer user_data)
134 {
135         app2ext_dir_details *item = (app2ext_dir_details *)data;
136         GVariantBuilder *builder = (GVariantBuilder *)user_data;
137
138         g_variant_builder_add(builder, "(si)", item->name, item->type);
139 }
140
141 static int __app2sd_delete_temp_directories(const char *pkgid,
142                 app2sd_cmd cmd, uid_t uid)
143 {
144         int ret = 0;
145         char app_path[FILENAME_MAX] = { 0, };
146         char temp_path[FILENAME_MAX] = { 0, };
147
148         if (cmd != APP2SD_PRE_UPGRADE)
149                 return APP2EXT_SUCCESS;
150
151         _app2sd_set_application_path(pkgid, uid, app_path, sizeof(app_path));
152         ret = snprintf(temp_path, sizeof(temp_path), "%s.new", app_path);
153         if (ret < 0 || ret > sizeof(temp_path)) {
154                 _E("snprintf fail");
155                 return APP2EXT_ERROR_DELETE_DIRECTORY;
156         }
157
158         /* this will delete all files under temp_path */
159         ret = _app2sd_delete_directory(temp_path);
160         if (ret) {
161                 _E("unable to delete (%s)", temp_path);
162                 return APP2EXT_ERROR_DELETE_DIRECTORY;
163         }
164
165         return APP2EXT_SUCCESS;
166 }
167
168 static int __app2sd_create_default_directories(const char *pkgid,
169                 app2sd_cmd cmd, uid_t uid)
170 {
171         int ret = 0;
172         mode_t mode = DIR_PERMS;
173         char application_path[FILENAME_MAX] = { 0, };
174         char app_mmc_path[FILENAME_MAX] = { 0, };
175         char temp_path[FILENAME_MAX] = { 0, };
176
177         _app2sd_set_application_path(pkgid, uid, application_path,
178                 sizeof(application_path));
179         ret = mkdir(application_path, mode);
180         if (ret) {
181                 if (errno != EEXIST) {
182                         _E("create directory failed," \
183                                 " error no is (%d)", errno);
184                         return APP2EXT_ERROR_CREATE_DIRECTORY;
185                 }
186         }
187
188         ret = snprintf(app_mmc_path, sizeof(app_mmc_path), "%s/.mmc",
189                 application_path);
190         if (ret < 0 || ret > sizeof(app_mmc_path)) {
191                 _E("snprintf fail");
192                 return APP2EXT_ERROR_CREATE_DIRECTORY;
193         }
194         ret = mkdir(app_mmc_path, mode);
195         if (ret) {
196                 if (errno != EEXIST) {
197                         _E("create directory failed," \
198                                 " error no is (%d)", errno);
199                         return APP2EXT_ERROR_CREATE_DIRECTORY;
200                 }
201         }
202
203         if (cmd == APP2SD_PRE_UPGRADE) {
204                 /* application_path for {pkgid}.new */
205                 ret = snprintf(temp_path, sizeof(temp_path), "%s.new",
206                         application_path);
207                 if (ret < 0 || ret > sizeof(temp_path)) {
208                         _E("snprintf fail");
209                         return APP2EXT_ERROR_CREATE_DIRECTORY;
210                 }
211                 ret = mkdir(temp_path, mode);
212                 if (ret) {
213                         if (errno != EEXIST) {
214                                 _E("create directory failed," \
215                                         " error no is (%d)", errno);
216                                 return APP2EXT_ERROR_CREATE_DIRECTORY;
217                         }
218                 }
219                 /* app_mmc_path for {pkgid}.new */
220                 ret = snprintf(app_mmc_path, sizeof(app_mmc_path), "%s/.mmc",
221                         temp_path);
222                 if (ret < 0 || ret > sizeof(app_mmc_path)) {
223                         _E("snprintf fail");
224                         return APP2EXT_ERROR_CREATE_DIRECTORY;
225                 }
226                 ret = mkdir(app_mmc_path, mode);
227                 if (ret) {
228                         if (errno != EEXIST) {
229                                 _E("create directory failed," \
230                                         " error no is (%d)", errno);
231                                 return APP2EXT_ERROR_CREATE_DIRECTORY;
232                         }
233                 }
234         }
235
236         return APP2EXT_SUCCESS;
237 }
238
239 int app2sd_client_usr_pre_app_install(const char *pkgid, GList *dir_list,
240                 int size, uid_t uid)
241 {
242         int ret = 0;
243         GVariantBuilder *builder = NULL;
244         GVariant *param = NULL;
245
246         /* validate the function parameter recieved */
247         if (pkgid == NULL || dir_list == NULL || size <= 0) {
248                 _E("invalid function arguments");
249                 return APP2EXT_ERROR_INVALID_ARGUMENTS;
250         }
251
252         ret = __app2sd_create_default_directories(pkgid,
253                 APP2SD_PRE_INSTALL, uid);
254         if (ret)
255                 return ret;
256
257         builder = g_variant_builder_new(G_VARIANT_TYPE("a(si)"));
258         g_list_foreach(dir_list, __app2sd_create_dir_list_builder, builder);
259
260         param = g_variant_new("(sia(si)i)", pkgid, size, builder, uid);
261         ret = __app2sd_call_server_method("PreAppInstall", param);
262
263         if (builder)
264                 g_variant_builder_unref(builder);
265
266         return ret;
267 }
268 int app2sd_client_pre_app_install(const char *pkgid, GList *dir_list,
269                 int size)
270 {
271         int ret = 0;
272
273         ret = app2sd_client_usr_pre_app_install(pkgid,
274                 dir_list, size, getuid());
275
276         return ret;
277 }
278
279 int app2sd_client_usr_post_app_install(const char *pkgid,
280                 app2ext_status install_status, uid_t uid)
281 {
282         int ret = 0;
283         GVariant *param = NULL;
284
285         /* validate the function parameter recieved */
286         if (pkgid == NULL || install_status < APP2EXT_STATUS_FAILED
287                 || install_status > APP2EXT_STATUS_SUCCESS) {
288                 _E("invalid func parameters");
289                 return APP2EXT_ERROR_INVALID_ARGUMENTS;
290         }
291
292         param = g_variant_new("(sii)", pkgid, install_status, uid);
293         ret = __app2sd_call_server_method("PostAppInstall", param);
294
295         return ret;
296 }
297 int app2sd_client_post_app_install(const char *pkgid,
298                 app2ext_status install_status)
299 {
300         int ret = 0;
301
302         ret = app2sd_client_usr_post_app_install(pkgid,
303                 install_status, getuid());
304
305         return ret;
306 }
307
308 int app2sd_client_usr_pre_app_upgrade(const char *pkgid, GList *dir_list,
309                 int size, uid_t uid)
310 {
311         int ret = 0;
312         GVariantBuilder *builder = NULL;
313         GVariant *param = NULL;
314
315         /* validate the function parameter recieved */
316         if (pkgid == NULL || dir_list == NULL || size <= 0) {
317                 _E("invalid function arguments");
318                 return APP2EXT_ERROR_INVALID_ARGUMENTS;
319         }
320
321         ret = __app2sd_create_default_directories(pkgid,
322                 APP2SD_PRE_UPGRADE, uid);
323         if (ret)
324                 return ret;
325
326         builder = g_variant_builder_new(G_VARIANT_TYPE("a(si)"));
327         g_list_foreach(dir_list, __app2sd_create_dir_list_builder, builder);
328
329         param = g_variant_new("(sia(si)i)", pkgid, size, builder, uid);
330         ret = __app2sd_call_server_method("PreAppUpgrade", param);
331
332         if (builder)
333                 g_variant_builder_unref(builder);
334
335         __app2sd_delete_temp_directories(pkgid, APP2SD_PRE_UPGRADE, uid);
336
337         return ret;
338 }
339 int app2sd_client_pre_app_upgrade(const char *pkgid, GList *dir_list,
340                 int size)
341 {
342         int ret = 0;
343
344         ret = app2sd_client_usr_pre_app_upgrade(pkgid,
345                 dir_list, size, getuid());
346
347         return ret;
348 }
349
350 int app2sd_client_usr_post_app_upgrade(const char *pkgid,
351                 app2ext_status install_status, uid_t uid)
352 {
353         int ret = 0;
354         GVariant *param = NULL;
355
356         /* validate the function parameter recieved */
357         if (pkgid == NULL || install_status < APP2EXT_STATUS_FAILED
358                 || install_status > APP2EXT_STATUS_SUCCESS) {
359                 _E("invalid func parameters");
360                 return APP2EXT_ERROR_INVALID_ARGUMENTS;
361         }
362
363         param = g_variant_new("(sii)", pkgid, install_status, uid);
364         ret = __app2sd_call_server_method("PostAppUpgrade", param);
365
366         return ret;
367 }
368 int app2sd_client_post_app_upgrade(const char *pkgid,
369                 app2ext_status install_status)
370 {
371         int ret = 0;
372
373         ret = app2sd_client_usr_post_app_upgrade(pkgid,
374                 install_status, getuid());
375
376         return ret;
377 }
378
379 int app2sd_client_usr_pre_app_uninstall(const char *pkgid, uid_t uid)
380 {
381         int ret = 0;
382         GVariant *param = NULL;
383
384         /* validate the function parameter recieved */
385         if (pkgid == NULL) {
386                 _E("invalid func parameters");
387                 return APP2EXT_ERROR_INVALID_ARGUMENTS;
388         }
389
390         param = g_variant_new("(si)", pkgid, uid);
391         ret = __app2sd_call_server_method("PreAppUninstall", param);
392
393         return ret;
394 }
395 int app2sd_client_pre_app_uninstall(const char *pkgid)
396 {
397         int ret = 0;
398
399         ret = app2sd_client_usr_pre_app_uninstall(pkgid,
400                 getuid());
401
402         return ret;
403 }
404
405 int app2sd_client_usr_post_app_uninstall(const char *pkgid, uid_t uid)
406 {
407         int ret = 0;
408         GVariant *param = NULL;
409
410         /* validate the function parameter recieved */
411         if (pkgid == NULL) {
412                 _E("invalid func parameters");
413                 return APP2EXT_ERROR_INVALID_ARGUMENTS;
414         }
415
416         param = g_variant_new("(si)", pkgid, uid);
417         ret = __app2sd_call_server_method("PostAppUninstall", param);
418
419         return ret;
420 }
421 int app2sd_client_post_app_uninstall(const char *pkgid)
422 {
423         int ret = 0;
424
425         ret = app2sd_client_usr_post_app_uninstall(pkgid,
426                 getuid());
427
428         return ret;
429 }
430
431 int app2sd_client_usr_force_clean(const char *pkgid, uid_t uid)
432 {
433         int ret = 0;
434         GVariant *param = NULL;
435
436         /* validate the function parameter recieved */
437         if (pkgid == NULL) {
438                 _E("invalid func parameters");
439                 return APP2EXT_ERROR_INVALID_ARGUMENTS;
440         }
441
442         param = g_variant_new("(si)", pkgid, uid);
443         ret = __app2sd_call_server_method("ForceClean", param);
444
445         return ret;
446 }
447 int app2sd_client_force_clean(const char *pkgid)
448 {
449         int ret = 0;
450
451         ret = app2sd_client_usr_force_clean(pkgid, getuid());
452
453         return ret;
454 }
455
456 int app2sd_client_enable_full_pkg(void)
457 {
458         int ret = 0;
459
460         ret = __app2sd_call_server_method("EnableFullPkg", NULL);
461
462         return ret;
463 }
464
465 int app2sd_client_disable_full_pkg(void)
466 {
467         int ret = 0;
468
469         ret = __app2sd_call_server_method("DisableFullPkg", NULL);
470
471         return ret;
472 }
473
474 int app2sd_client_usr_on_demand_setup_init(const char *pkgid, uid_t uid)
475 {
476         int ret = 0;
477         GVariant *param = NULL;
478
479         /* validate the function parameter recieved */
480         if (pkgid == NULL) {
481                 _E("invalid func parameters");
482                 return APP2EXT_ERROR_INVALID_ARGUMENTS;
483         }
484
485         param = g_variant_new("(si)", pkgid, uid);
486         ret = __app2sd_call_server_method("OndemandSetupInit", param);
487
488         return ret;
489 }
490 int app2sd_client_on_demand_setup_init(const char *pkgid)
491 {
492         int ret = 0;
493
494         ret = app2sd_client_usr_on_demand_setup_init(pkgid,
495                 getuid());
496
497         return ret;
498 }
499
500 int app2sd_client_usr_on_demand_setup_exit(const char *pkgid, uid_t uid)
501 {
502         int ret = 0;
503         GVariant *param = NULL;
504
505         /* validate the function parameter recieved */
506         if (pkgid == NULL) {
507                 _E("invalid func parameters");
508                 return APP2EXT_ERROR_INVALID_ARGUMENTS;
509         }
510
511         param = g_variant_new("(si)", pkgid, uid);
512         ret = __app2sd_call_server_method("OndemandSetupExit", param);
513
514         return ret;
515 }
516 int app2sd_client_on_demand_setup_exit(const char *pkgid)
517 {
518         int ret = 0;
519
520         ret = app2sd_client_usr_on_demand_setup_exit(pkgid,
521                 getuid());
522
523         return ret;
524 }
525
526 int app2sd_client_usr_pre_move_installed_app(const char *pkgid, GList *dir_list,
527                 app2ext_move_type move_type, uid_t uid)
528 {
529         int ret = 0;
530         GVariantBuilder *builder = NULL;
531         GVariant *param = NULL;
532         app2sd_cmd cmd = APP2SD_MOVE_APP_TO_PHONE;
533         pkgmgrinfo_pkginfo_h info_handle = NULL;
534         pkgmgrinfo_installed_storage storage = PMINFO_INTERNAL_STORAGE;
535
536         /* validate the function parameter recieved */
537         if (pkgid == NULL || dir_list == NULL
538                 || move_type < APP2EXT_MOVE_TO_EXT
539                 || move_type > APP2EXT_MOVE_TO_PHONE) {
540                 _E("invalid function arguments");
541                 return APP2EXT_ERROR_INVALID_ARGUMENTS;
542         }
543
544         ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(pkgid, uid, &info_handle);
545         if (ret < 0) {
546                 _E("failed to get pkginfo for pkg(%s), uid(%d), ret(%d)",
547                         pkgid, uid, ret);
548                 return APP2EXT_ERROR_PKGMGR_ERROR;
549         }
550         ret = pkgmgrinfo_pkginfo_get_installed_storage(info_handle, &storage);
551         if (ret < 0) {
552                 _E("failed to get installed storage for pkg(%s) " \
553                         "of uid(%d), ret(%d)", pkgid, uid, ret);
554                 pkgmgrinfo_pkginfo_destroy_pkginfo(info_handle);
555                 return APP2EXT_ERROR_PKGMGR_ERROR;
556         }
557
558         if ((move_type == APP2EXT_MOVE_TO_EXT && storage ==
559                         PMINFO_EXTERNAL_STORAGE)
560                 || (move_type == APP2EXT_MOVE_TO_PHONE &&
561                         storage == PMINFO_INTERNAL_STORAGE)) {
562                         _E("PKG_EXISTS in [%d] STORAGE", storage);
563                         pkgmgrinfo_pkginfo_destroy_pkginfo(info_handle);
564                         return APP2EXT_ERROR_PKG_EXISTS;
565         } else {
566                 _D("pkgid[%s] move to STORAGE [%d]", pkgid, storage);
567         }
568         pkgmgrinfo_pkginfo_destroy_pkginfo(info_handle);
569
570         if (move_type == APP2EXT_MOVE_TO_EXT)
571                 cmd = APP2SD_MOVE_APP_TO_MMC;
572
573         if (cmd == APP2SD_MOVE_APP_TO_MMC) {
574                 ret = __app2sd_create_default_directories(pkgid, cmd, uid);
575                 if (ret)
576                         return ret;
577         }
578
579         builder = g_variant_builder_new(G_VARIANT_TYPE("a(si)"));
580         g_list_foreach(dir_list, __app2sd_create_dir_list_builder, builder);
581
582         param = g_variant_new("(sia(si)i)", pkgid, move_type, builder, uid);
583         ret = __app2sd_call_server_method("PreMoveInstalledApp", param);
584
585         if (builder)
586                 g_variant_builder_unref(builder);
587
588         return ret;
589 }
590 int app2sd_client_pre_move_installed_app(const char *pkgid, GList *dir_list,
591                 app2ext_move_type move_type)
592 {
593         int ret = 0;
594
595         ret = app2sd_client_usr_pre_move_installed_app(pkgid,
596                 dir_list, move_type, getuid());
597
598         return ret;
599 }
600
601 int app2sd_client_usr_post_move_installed_app(const char *pkgid,
602                 app2ext_move_type move_type, uid_t uid)
603 {
604         int ret = 0;
605         GVariant *param = NULL;
606
607         /* validate the function parameter recieved */
608         if (pkgid == NULL || move_type < APP2EXT_MOVE_TO_EXT
609                 || move_type > APP2EXT_MOVE_TO_PHONE) {
610                 _E("invalid function arguments");
611                 return APP2EXT_ERROR_INVALID_ARGUMENTS;
612         }
613
614         param = g_variant_new("(sii)", pkgid, move_type, uid);
615         ret = __app2sd_call_server_method("PostMoveInstalledApp", param);
616
617         return ret;
618 }
619 int app2sd_client_post_move_installed_app(const char *pkgid,
620                 app2ext_move_type move_type)
621 {
622         int ret = 0;
623
624         ret = app2sd_client_usr_post_move_installed_app(pkgid,
625                 move_type, getuid());
626
627         return ret;
628 }
629
630 int app2sd_client_usr_pre_migrate_legacy(const char *pkgid, uid_t uid)
631 {
632         int ret = 0;
633         GVariant *param = NULL;
634
635         /* validate the function parameter recieved */
636         if (pkgid == NULL) {
637                 _E("invalid function arguments");
638                 return APP2EXT_ERROR_INVALID_ARGUMENTS;
639         }
640
641         param = g_variant_new("(si)", pkgid, uid);
642         ret = __app2sd_call_server_method("PreMigrateLegacy", param);
643
644         return ret;
645 }
646
647 int app2sd_client_usr_post_migrate_legacy(const char *pkgid, uid_t uid)
648 {
649         int ret = 0;
650         GVariant *param = NULL;
651
652         /* validate the function parameter recieved */
653         if (pkgid == NULL) {
654                 _E("invalid function arguments");
655                 return APP2EXT_ERROR_INVALID_ARGUMENTS;
656         }
657
658         param = g_variant_new("(si)", pkgid, uid);
659         ret = __app2sd_call_server_method("PostMigrateLegacy", param);
660
661         return ret;
662 }
663
664 int app2sd_client_migrate_legacy_all()
665 {
666         int ret = 0;
667
668         ret = __app2sd_call_server_method("MigrateLegacyAll", NULL);
669
670         return ret;
671 }
672
673 char *app2sd_client_usr_getname_image(const char *pkgid, uid_t uid)
674 {
675         return _app2sd_get_encoded_name(pkgid, uid);
676 }
677
678 char *app2sd_client_usr_get_image_path(const char *pkgid, uid_t uid)
679 {
680         static const char query[] =
681                 "SELECT filename FROM app2sd_info WHERE pkgid=? AND uid=?";
682         int ret;
683         sqlite3 *db;
684         sqlite3_stmt *stmt;
685         const char *dbpath;
686         char *image_path = NULL;
687
688         dbpath = tzplatform_mkpath(TZ_SYS_DB, ".app2sd.db");
689         if (dbpath == NULL)
690                 return NULL;
691
692         ret = sqlite3_open_v2(dbpath, &db, SQLITE_OPEN_READONLY, NULL);
693         if (ret != SQLITE_OK) {
694                 LOGE("open failed: %s", sqlite3_errmsg(db));
695                 sqlite3_close_v2(db);
696                 return NULL;
697         }
698
699         ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
700         if (ret != SQLITE_OK) {
701                 LOGE("prepare failed: %s", sqlite3_errmsg(db));
702                 sqlite3_close_v2(db);
703                 return NULL;
704         }
705
706         ret = sqlite3_bind_text(stmt, 1, pkgid, -1, SQLITE_STATIC);
707         if (ret != SQLITE_OK) {
708                 LOGE("bind failed: %s", sqlite3_errmsg(db));
709                 sqlite3_finalize(stmt);
710                 sqlite3_close_v2(db);
711                 return NULL;
712         }
713
714         ret = sqlite3_bind_int(stmt, 2, uid);
715         if (ret != SQLITE_OK) {
716                 LOGE("bind failed: %s", sqlite3_errmsg(db));
717                 sqlite3_finalize(stmt);
718                 sqlite3_close_v2(db);
719                 return NULL;
720         }
721
722         ret = sqlite3_step(stmt);
723         if (ret == SQLITE_ROW)
724                 image_path = strdup((char *)sqlite3_column_text(stmt, 0));
725
726         sqlite3_finalize(stmt);
727         sqlite3_close_v2(db);
728
729         return image_path;
730 }
731
732 void app2ext_on_load(app2ext_interface *interface)
733 {
734         /* Plug-in Binding.*/
735         interface->client_pre_install = app2sd_client_pre_app_install;
736         interface->client_post_install = app2sd_client_post_app_install;
737         interface->client_pre_upgrade = app2sd_client_pre_app_upgrade;
738         interface->client_post_upgrade = app2sd_client_post_app_upgrade;
739         interface->client_pre_uninstall = app2sd_client_pre_app_uninstall;
740         interface->client_post_uninstall = app2sd_client_post_app_uninstall;
741         interface->client_force_clean = app2sd_client_force_clean;
742         interface->client_enable = app2sd_client_on_demand_setup_init;
743         interface->client_disable = app2sd_client_on_demand_setup_exit;
744         interface->client_enable_full_pkg = app2sd_client_enable_full_pkg;
745         interface->client_disable_full_pkg = app2sd_client_disable_full_pkg;
746         interface->client_pre_move = app2sd_client_pre_move_installed_app;
747         interface->client_post_move = app2sd_client_post_move_installed_app;
748         interface->client_migrate_legacy_all = app2sd_client_migrate_legacy_all;
749
750         interface->client_usr_pre_install = app2sd_client_usr_pre_app_install;
751         interface->client_usr_post_install = app2sd_client_usr_post_app_install;
752         interface->client_usr_pre_upgrade = app2sd_client_usr_pre_app_upgrade;
753         interface->client_usr_post_upgrade = app2sd_client_usr_post_app_upgrade;
754         interface->client_usr_pre_uninstall = app2sd_client_usr_pre_app_uninstall;
755         interface->client_usr_post_uninstall = app2sd_client_usr_post_app_uninstall;
756         interface->client_usr_force_clean = app2sd_client_usr_force_clean;
757         interface->client_usr_enable = app2sd_client_usr_on_demand_setup_init;
758         interface->client_usr_disable = app2sd_client_usr_on_demand_setup_exit;
759         interface->client_usr_pre_move = app2sd_client_usr_pre_move_installed_app;
760         interface->client_usr_post_move = app2sd_client_usr_post_move_installed_app;
761         interface->client_usr_getname_image = app2sd_client_usr_getname_image;
762         interface->client_usr_pre_migrate_legacy = app2sd_client_usr_pre_migrate_legacy;
763         interface->client_usr_post_migrate_legacy = app2sd_client_usr_post_migrate_legacy;
764         interface->client_usr_get_image_path = app2sd_client_usr_get_image_path;
765 }