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