Clean up repository
[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
32 #include "app2sd_client_interface.h"
33 #include "app2sd_utils.h"
34
35 #define CONNECTION_RETRY_MAX 5
36 #define CONNECTION_WAIT_USEC (1000000 / 2) /* 0.5 sec */
37
38 static int app2sd_gdbus_shared_connection(GDBusConnection **connection)
39 {
40         GError *error = NULL;
41
42 #if (GLIB_MAJOR_VERSION <= 2 && GLIB_MINOR_VERSION < 36)
43         g_type_init();
44 #endif
45
46         *connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
47         if (*connection == NULL) {
48                 if (error != NULL) {
49                         _E("app2sd error : failed to get "
50                                 "system dbus [%s]", error->message);
51                         g_error_free(error);
52                 }
53                 return APP2EXT_ERROR_DBUS_FAILED;
54         }
55
56         return APP2EXT_SUCCESS;
57 }
58
59 static int __app2sd_call_server_method(const gchar *method_name,
60                 GVariant *param)
61 {
62         int ret = APP2EXT_SUCCESS;
63         int result = 0;
64         int retry_cnt = 0;
65         GDBusConnection *conn = NULL;
66         GDBusProxy *proxy = NULL;
67         GError *error = NULL;
68         GVariant *value = NULL;
69
70         /* get gdbus connection */
71         ret = app2sd_gdbus_shared_connection(&conn);
72         if (ret) {
73                 _E("app2sd error : dbus connection error");
74                 return ret;
75         }
76
77         /* method call */
78         do {
79                 proxy = g_dbus_proxy_new_sync(conn,
80                         G_DBUS_PROXY_FLAGS_NONE, NULL,
81                         APP2SD_BUS_NAME, APP2SD_OBJECT_PATH,
82                         APP2SD_INTERFACE_NAME,
83                         NULL, &error);
84                 if (proxy == NULL) {
85                         _E("failed to create new proxy, error(%s)",
86                                 error->message);
87                         g_error_free(error);
88                         ret = APP2EXT_ERROR_DBUS_FAILED;
89                         retry_cnt++;
90                         usleep(CONNECTION_WAIT_USEC);
91                         continue;
92                 }
93
94                 value = g_dbus_proxy_call_sync(proxy, method_name, param,
95                         G_DBUS_CALL_FLAGS_NONE, G_MAXINT, NULL, &error);
96                 g_object_unref(proxy);
97                 if (error != NULL) {
98                         _E("proxy call sync error(%s)", error->message);
99                         g_error_free(error);
100                         ret = APP2EXT_ERROR_DBUS_FAILED;
101                         retry_cnt++;
102                         usleep(CONNECTION_WAIT_USEC);
103                         continue;
104                 }
105
106                 g_variant_get(value, "(i)", &result);
107                 g_variant_unref(value);
108
109                 _D("result(%d)", result);
110                 if (result)
111                         ret = result;
112
113                 break;
114         } while (retry_cnt <= CONNECTION_RETRY_MAX);
115
116         if (conn)
117                 g_object_unref(conn);
118
119         return ret;
120 }
121
122 static void __app2sd_create_dir_list_builder(gpointer data, gpointer user_data)
123 {
124         app2ext_dir_details *item = (app2ext_dir_details *)data;
125         GVariantBuilder *builder = (GVariantBuilder *)user_data;
126
127         g_variant_builder_add(builder, "(si)", item->name, item->type);
128 }
129
130 static int __app2sd_delete_temp_directories(const char *pkgid,
131                 app2sd_cmd cmd, uid_t uid)
132 {
133         int ret = 0;
134         char temp_path[FILENAME_MAX] = { 0, };
135
136         if (cmd != APP2SD_PRE_UPGRADE)
137                 return APP2EXT_SUCCESS;
138
139         if (_is_global(uid)) {
140                 snprintf(temp_path, FILENAME_MAX - 1, "%s/%s.new",
141                         tzplatform_getenv(TZ_SYS_RW_APP), pkgid);
142         } else {
143                 tzplatform_set_user(uid);
144                 snprintf(temp_path, FILENAME_MAX - 1, "%s/%s.new",
145                         tzplatform_getenv(TZ_USER_APP), pkgid);
146                 tzplatform_reset_user();
147         }
148
149         /* this will delete all files under temp_path */
150         ret = _app2sd_delete_directory(temp_path);
151         if (ret) {
152                 _E("unable to delete (%s)", temp_path);
153                 return APP2EXT_ERROR_DELETE_DIRECTORY;
154         }
155
156         return APP2EXT_SUCCESS;
157 }
158
159 static int __app2sd_create_default_directories(const char *pkgid,
160                 app2sd_cmd cmd, uid_t uid)
161 {
162         int ret = 0;
163         mode_t mode = DIR_PERMS;
164         char application_path[FILENAME_MAX] = { 0, };
165         char application_mmc_path[FILENAME_MAX] = { 0, };
166         char temp_path[FILENAME_MAX] = { 0, };
167
168         if (_is_global(uid)) {
169                 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
170                         tzplatform_getenv(TZ_SYS_RW_APP), pkgid);
171         } else {
172                 tzplatform_set_user(uid);
173                 snprintf(application_path, FILENAME_MAX - 1, "%s/%s",
174                         tzplatform_getenv(TZ_USER_APP), pkgid);
175                 tzplatform_reset_user();
176         }
177
178         ret = mkdir(application_path, mode);
179         if (ret) {
180                 if (errno != EEXIST) {
181                         _E("create directory failed," \
182                                 " error no is (%d)", errno);
183                         return APP2EXT_ERROR_CREATE_DIRECTORY;
184                 }
185         }
186
187         snprintf(application_mmc_path, FILENAME_MAX - 1, "%s/.mmc",
188                 application_path);
189
190         ret = mkdir(application_mmc_path, mode);
191         if (ret) {
192                 if (errno != EEXIST) {
193                         _E("create directory failed," \
194                                 " error no is (%d)", errno);
195                         return APP2EXT_ERROR_CREATE_DIRECTORY;
196                 }
197         }
198
199         if (cmd == APP2SD_PRE_UPGRADE) {
200                 /* application_path for {pkgid}.new */
201                 snprintf(temp_path, FILENAME_MAX - 1, "%s.new",
202                         application_path);
203                 ret = mkdir(temp_path, mode);
204                 if (ret) {
205                         if (errno != EEXIST) {
206                                 _E("create directory failed," \
207                                         " error no is (%d)", errno);
208                                 return APP2EXT_ERROR_CREATE_DIRECTORY;
209                         }
210                 }
211                 /* application_mmc_path for {pkgid}.new */
212                 snprintf(application_mmc_path, FILENAME_MAX - 1, "%s/.mmc",
213                         temp_path);
214                 ret = mkdir(application_mmc_path, mode);
215                 if (ret) {
216                         if (errno != EEXIST) {
217                                 _E("create directory failed," \
218                                         " error no is (%d)", errno);
219                                 return APP2EXT_ERROR_CREATE_DIRECTORY;
220                         }
221                 }
222         }
223
224         return APP2EXT_SUCCESS;
225 }
226
227 int app2sd_client_usr_pre_app_install(const char *pkgid, GList *dir_list,
228                 int size, uid_t uid)
229 {
230         int ret = 0;
231         GVariantBuilder *builder = NULL;
232         GVariant *param = NULL;
233
234         /* validate the function parameter recieved */
235         if (pkgid == NULL || dir_list == NULL || size <= 0) {
236                 _E("invalid function arguments");
237                 return APP2EXT_ERROR_INVALID_ARGUMENTS;
238         }
239
240         ret = __app2sd_create_default_directories(pkgid,
241                 APP2SD_PRE_INSTALL, uid);
242         if (ret)
243                 return ret;
244
245         builder = g_variant_builder_new(G_VARIANT_TYPE("a(si)"));
246         g_list_foreach(dir_list, __app2sd_create_dir_list_builder, builder);
247
248         param = g_variant_new("(sia(si)i)", pkgid, size, builder, uid);
249         ret = __app2sd_call_server_method("PreAppInstall", param);
250
251         if (builder)
252                 g_variant_builder_unref(builder);
253
254         return ret;
255 }
256 int app2sd_client_pre_app_install(const char *pkgid, GList *dir_list,
257                 int size)
258 {
259         int ret = 0;
260
261         ret = app2sd_client_usr_pre_app_install(pkgid,
262                 dir_list, size, getuid());
263
264         return ret;
265 }
266
267 int app2sd_client_usr_post_app_install(const char *pkgid,
268                 app2ext_status install_status, uid_t uid)
269 {
270         int ret = 0;
271         GVariant *param = NULL;
272
273         /* validate the function parameter recieved */
274         if (pkgid == NULL || install_status < APP2EXT_STATUS_FAILED
275                 || install_status > APP2EXT_STATUS_SUCCESS) {
276                 _E("invalid func parameters");
277                 return APP2EXT_ERROR_INVALID_ARGUMENTS;
278         }
279
280         param = g_variant_new("(sii)", pkgid, install_status, uid);
281         ret = __app2sd_call_server_method("PostAppInstall", param);
282
283         return ret;
284 }
285 int app2sd_client_post_app_install(const char *pkgid,
286                 app2ext_status install_status)
287 {
288         int ret = 0;
289
290         ret = app2sd_client_usr_post_app_install(pkgid,
291                 install_status, getuid());
292
293         return ret;
294 }
295
296 int app2sd_client_usr_pre_app_upgrade(const char *pkgid, GList *dir_list,
297                 int size, uid_t uid)
298 {
299         int ret = 0;
300         GVariantBuilder *builder = NULL;
301         GVariant *param = NULL;
302
303         /* validate the function parameter recieved */
304         if (pkgid == NULL || dir_list == NULL || size <= 0) {
305                 _E("invalid function arguments");
306                 return APP2EXT_ERROR_INVALID_ARGUMENTS;
307         }
308
309         ret = __app2sd_create_default_directories(pkgid,
310                 APP2SD_PRE_UPGRADE, uid);
311         if (ret)
312                 return ret;
313
314         builder = g_variant_builder_new(G_VARIANT_TYPE("a(si)"));
315         g_list_foreach(dir_list, __app2sd_create_dir_list_builder, builder);
316
317         param = g_variant_new("(sia(si)i)", pkgid, size, builder, uid);
318         ret = __app2sd_call_server_method("PreAppUpgrade", param);
319
320         if (builder)
321                 g_variant_builder_unref(builder);
322
323         __app2sd_delete_temp_directories(pkgid, APP2SD_PRE_UPGRADE, uid);
324
325         return ret;
326 }
327 int app2sd_client_pre_app_upgrade(const char *pkgid, GList *dir_list,
328                 int size)
329 {
330         int ret = 0;
331
332         ret = app2sd_client_usr_pre_app_upgrade(pkgid,
333                 dir_list, size, getuid());
334
335         return ret;
336 }
337
338 int app2sd_client_usr_post_app_upgrade(const char *pkgid,
339                 app2ext_status install_status, uid_t uid)
340 {
341         int ret = 0;
342         GVariant *param = NULL;
343
344         /* validate the function parameter recieved */
345         if (pkgid == NULL || install_status < APP2EXT_STATUS_FAILED
346                 || install_status > APP2EXT_STATUS_SUCCESS) {
347                 _E("invalid func parameters");
348                 return APP2EXT_ERROR_INVALID_ARGUMENTS;
349         }
350
351         param = g_variant_new("(sii)", pkgid, install_status, uid);
352         ret = __app2sd_call_server_method("PostAppUpgrade", param);
353
354         return ret;
355 }
356 int app2sd_client_post_app_upgrade(const char *pkgid,
357                 app2ext_status install_status)
358 {
359         int ret = 0;
360
361         ret = app2sd_client_usr_post_app_upgrade(pkgid,
362                 install_status, getuid());
363
364         return ret;
365 }
366
367 int app2sd_client_usr_pre_app_uninstall(const char *pkgid, uid_t uid)
368 {
369         int ret = 0;
370         GVariant *param = NULL;
371
372         /* validate the function parameter recieved */
373         if (pkgid == NULL) {
374                 _E("invalid func parameters");
375                 return APP2EXT_ERROR_INVALID_ARGUMENTS;
376         }
377
378         param = g_variant_new("(si)", pkgid, uid);
379         ret = __app2sd_call_server_method("PreAppUninstall", param);
380
381         return ret;
382 }
383 int app2sd_client_pre_app_uninstall(const char *pkgid)
384 {
385         int ret = 0;
386
387         ret = app2sd_client_usr_pre_app_uninstall(pkgid,
388                 getuid());
389
390         return ret;
391 }
392
393 int app2sd_client_usr_post_app_uninstall(const char *pkgid, uid_t uid)
394 {
395         int ret = 0;
396         GVariant *param = NULL;
397
398         /* validate the function parameter recieved */
399         if (pkgid == NULL) {
400                 _E("invalid func parameters");
401                 return APP2EXT_ERROR_INVALID_ARGUMENTS;
402         }
403
404         param = g_variant_new("(si)", pkgid, uid);
405         ret = __app2sd_call_server_method("PostAppUninstall", param);
406
407         return ret;
408 }
409 int app2sd_client_post_app_uninstall(const char *pkgid)
410 {
411         int ret = 0;
412
413         ret = app2sd_client_usr_post_app_uninstall(pkgid,
414                 getuid());
415
416         return ret;
417 }
418
419 int app2sd_client_usr_force_clean(const char *pkgid, uid_t uid)
420 {
421         int ret = 0;
422         GVariant *param = NULL;
423
424         /* validate the function parameter recieved */
425         if (pkgid == NULL) {
426                 _E("invalid func parameters");
427                 return APP2EXT_ERROR_INVALID_ARGUMENTS;
428         }
429
430         param = g_variant_new("(si)", pkgid, uid);
431         ret = __app2sd_call_server_method("ForceClean", param);
432
433         return ret;
434 }
435 int app2sd_client_force_clean(const char *pkgid)
436 {
437         int ret = 0;
438
439         ret = app2sd_client_usr_force_clean(pkgid, getuid());
440
441         return ret;
442 }
443
444 int app2sd_client_enable_full_pkg(void)
445 {
446         int ret = 0;
447
448         ret = __app2sd_call_server_method("EnableFullPkg", NULL);
449
450         return ret;
451 }
452
453 int app2sd_client_disable_full_pkg(void)
454 {
455         int ret = 0;
456
457         ret = __app2sd_call_server_method("DisableFullPkg", NULL);
458
459         return ret;
460 }
461
462 int app2sd_client_usr_on_demand_setup_init(const char *pkgid, uid_t uid)
463 {
464         int ret = 0;
465         GVariant *param = NULL;
466
467         /* validate the function parameter recieved */
468         if (pkgid == NULL) {
469                 _E("invalid func parameters");
470                 return APP2EXT_ERROR_INVALID_ARGUMENTS;
471         }
472
473         param = g_variant_new("(si)", pkgid, uid);
474         ret = __app2sd_call_server_method("OndemandSetupInit", param);
475
476         return ret;
477 }
478 int app2sd_client_on_demand_setup_init(const char *pkgid)
479 {
480         int ret = 0;
481
482         ret = app2sd_client_usr_on_demand_setup_init(pkgid,
483                 getuid());
484
485         return ret;
486 }
487
488 int app2sd_client_usr_on_demand_setup_exit(const char *pkgid, uid_t uid)
489 {
490         int ret = 0;
491         GVariant *param = NULL;
492
493         /* validate the function parameter recieved */
494         if (pkgid == NULL) {
495                 _E("invalid func parameters");
496                 return APP2EXT_ERROR_INVALID_ARGUMENTS;
497         }
498
499         param = g_variant_new("(si)", pkgid, uid);
500         ret = __app2sd_call_server_method("OndemandSetupExit", param);
501
502         return ret;
503 }
504 int app2sd_client_on_demand_setup_exit(const char *pkgid)
505 {
506         int ret = 0;
507
508         ret = app2sd_client_usr_on_demand_setup_exit(pkgid,
509                 getuid());
510
511         return ret;
512 }
513
514 int app2sd_client_usr_pre_move_installed_app(const char *pkgid, GList *dir_list,
515                 app2ext_move_type move_type, uid_t uid)
516 {
517         int ret = 0;
518         GVariantBuilder *builder = NULL;
519         GVariant *param = NULL;
520         app2sd_cmd cmd = APP2SD_MOVE_APP_TO_PHONE;
521         pkgmgrinfo_pkginfo_h info_handle = NULL;
522         pkgmgrinfo_installed_storage storage = PMINFO_INTERNAL_STORAGE;
523
524         /* validate the function parameter recieved */
525         if (pkgid == NULL || dir_list == NULL
526                 || move_type < APP2EXT_MOVE_TO_EXT
527                 || move_type > APP2EXT_MOVE_TO_PHONE) {
528                 _E("invalid function arguments");
529                 return APP2EXT_ERROR_INVALID_ARGUMENTS;
530         }
531
532         ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(pkgid, uid, &info_handle);
533         if (ret < 0) {
534                 _E("failed to get pkginfo for pkg(%s), uid(%d), ret(%d)",
535                         pkgid, uid, ret);
536                 return APP2EXT_ERROR_PKGMGR_ERROR;
537         }
538         ret = pkgmgrinfo_pkginfo_get_installed_storage(info_handle, &storage);
539         if (ret < 0) {
540                 _E("failed to get installed storage for pkg(%s) of uid(%d), ret(%d)",
541                         pkgid, uid, ret);
542                 pkgmgrinfo_pkginfo_destroy_pkginfo(info_handle);
543                 return APP2EXT_ERROR_PKGMGR_ERROR;
544         }
545
546         if ((move_type == APP2EXT_MOVE_TO_EXT && storage == PMINFO_EXTERNAL_STORAGE)
547                 || (move_type == APP2EXT_MOVE_TO_PHONE && storage == PMINFO_INTERNAL_STORAGE)) {
548                         _E("PKG_EXISTS in [%d] STORAGE", storage);
549                         pkgmgrinfo_pkginfo_destroy_pkginfo(info_handle);
550                         return APP2EXT_ERROR_PKG_EXISTS;
551         } else {
552                 _D("pkgid[%s] move to STORAGE [%d]", pkgid, storage);
553         }
554         pkgmgrinfo_pkginfo_destroy_pkginfo(info_handle);
555
556         if (move_type == APP2EXT_MOVE_TO_EXT)
557                 cmd = APP2SD_MOVE_APP_TO_MMC;
558
559         if (cmd == APP2SD_MOVE_APP_TO_MMC) {
560                 ret = __app2sd_create_default_directories(pkgid, cmd, uid);
561                 if (ret)
562                         return ret;
563         }
564
565         builder = g_variant_builder_new(G_VARIANT_TYPE("a(si)"));
566         g_list_foreach(dir_list, __app2sd_create_dir_list_builder, builder);
567
568         param = g_variant_new("(sia(si)i)", pkgid, move_type, builder, uid);
569         ret = __app2sd_call_server_method("PreMoveInstalledApp", param);
570
571         if (builder)
572                 g_variant_builder_unref(builder);
573
574         return ret;
575 }
576 int app2sd_client_pre_move_installed_app(const char *pkgid, GList *dir_list,
577                 app2ext_move_type move_type)
578 {
579         int ret = 0;
580
581         ret = app2sd_client_usr_pre_move_installed_app(pkgid,
582                 dir_list, move_type, getuid());
583
584         return ret;
585 }
586
587 int app2sd_client_usr_post_move_installed_app(const char *pkgid,
588                 app2ext_move_type move_type, uid_t uid)
589 {
590         int ret = 0;
591         GVariant *param = NULL;
592
593         /* validate the function parameter recieved */
594         if (pkgid == NULL || move_type < APP2EXT_MOVE_TO_EXT
595                 || move_type > APP2EXT_MOVE_TO_PHONE) {
596                 _E("invalid function arguments");
597                 return APP2EXT_ERROR_INVALID_ARGUMENTS;
598         }
599
600         param = g_variant_new("(sii)", pkgid, move_type, uid);
601         ret = __app2sd_call_server_method("PostMoveInstalledApp", param);
602
603         return ret;
604 }
605 int app2sd_client_post_move_installed_app(const char *pkgid,
606                 app2ext_move_type move_type)
607 {
608         int ret = 0;
609
610         ret = app2sd_client_usr_post_move_installed_app(pkgid,
611                 move_type, getuid());
612
613         return ret;
614 }
615
616 void app2ext_on_load(app2ext_interface *interface)
617 {
618         /* Plug-in Binding.*/
619         interface->client_pre_install = app2sd_client_pre_app_install;
620         interface->client_post_install = app2sd_client_post_app_install;
621         interface->client_pre_upgrade = app2sd_client_pre_app_upgrade;
622         interface->client_post_upgrade = app2sd_client_post_app_upgrade;
623         interface->client_pre_uninstall = app2sd_client_pre_app_uninstall;
624         interface->client_post_uninstall = app2sd_client_post_app_uninstall;
625         interface->client_force_clean = app2sd_client_force_clean;
626         interface->client_enable = app2sd_client_on_demand_setup_init;
627         interface->client_disable = app2sd_client_on_demand_setup_exit;
628         interface->client_enable_full_pkg = app2sd_client_enable_full_pkg;
629         interface->client_disable_full_pkg = app2sd_client_disable_full_pkg;
630         interface->client_pre_move = app2sd_client_pre_move_installed_app;
631         interface->client_post_move = app2sd_client_post_move_installed_app;
632
633         interface->client_usr_pre_install = app2sd_client_usr_pre_app_install;
634         interface->client_usr_post_install = app2sd_client_usr_post_app_install;
635         interface->client_usr_pre_upgrade = app2sd_client_usr_pre_app_upgrade;
636         interface->client_usr_post_upgrade = app2sd_client_usr_post_app_upgrade;
637         interface->client_usr_pre_uninstall = app2sd_client_usr_pre_app_uninstall;
638         interface->client_usr_post_uninstall = app2sd_client_usr_post_app_uninstall;
639         interface->client_usr_force_clean = app2sd_client_usr_force_clean;
640         interface->client_usr_enable = app2sd_client_usr_on_demand_setup_init;
641         interface->client_usr_disable = app2sd_client_usr_on_demand_setup_exit;
642         interface->client_usr_pre_move = app2sd_client_usr_pre_move_installed_app;
643         interface->client_usr_post_move = app2sd_client_usr_post_move_installed_app;
644 }