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