4 * Copyright (c) 2016 Samsung Electronics Co., Ltd. All rights reserved.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
22 #include "app2sd_internals.h"
24 GMainLoop *app2sd_mainloop = NULL;
26 gboolean __exit_app2sd_server(void *data)
28 _D("exit app2sd_server");
30 g_main_loop_quit(app2sd_mainloop);
35 static int __app2sd_get_sender_unixinfo(GDBusConnection *conn,
36 const char *sender_name, const char *type)
38 GDBusMessage *msg = NULL;
39 GDBusMessage *reply = NULL;
45 msg = g_dbus_message_new_method_call("org.freedesktop.DBus",
46 "/org/freedesktop/DBus", "org.freedesktop.DBus", type);
48 _E("Can't allocate new method call");
52 g_dbus_message_set_body(msg, g_variant_new("(s)", sender_name));
53 reply = g_dbus_connection_send_message_with_reply_sync(conn, msg,
54 G_DBUS_SEND_MESSAGE_FLAGS_NONE, -1, NULL, NULL, &err);
58 _E("Failed to get info [%s]", err->message);
64 body = g_dbus_message_get_body(reply);
65 g_variant_get(body, "(u)", &value);
72 g_object_unref(reply);
78 static int __app2sd_get_sender_pid(GDBusConnection *conn,
79 const char *sender_name)
83 pid = __app2sd_get_sender_unixinfo(conn, sender_name,
84 "GetConnectionUnixProcessID");
86 _E("failed to get pid");
90 _D("sender_name(%s), pid(%d)", sender_name, pid);
96 static int __app2sd_get_sender_uid(GDBusConnection *conn,
97 const char *sender_name)
101 uid = __app2sd_get_sender_unixinfo(conn, sender_name,
102 "GetConnectionUnixUser");
104 _E("failed to get uid");
106 _D("sender_name(%s), uid(%d)", sender_name, uid);
111 static GDBusNodeInfo *introspection_data;
112 static const gchar introspection_xml[] =
114 " <interface name='org.tizen.app2sd'>"
115 " <method name='PreAppInstall'>"
116 " <arg type='s' name='pkgid' direction='in'/>"
117 " <arg type='i' name='size' direction='in'/>"
118 " <arg type='a(si)' name='dir_list' direction='in'/>"
119 " <arg type='i' name='uid' direction='in'/>"
120 " <arg type='i' name='result' direction='out'/>"
122 " <method name='PostAppInstall'>"
123 " <arg type='s' name='pkgid' direction='in'/>"
124 " <arg type='i' name='install_status' direction='in'/>"
125 " <arg type='i' name='uid' direction='in'/>"
126 " <arg type='i' name='result' direction='out'/>"
128 " <method name='PreAppUpgrade'>"
129 " <arg type='s' name='pkgid' direction='in'/>"
130 " <arg type='i' name='size' direction='in'/>"
131 " <arg type='a(si)' name='dir_list' direction='in'/>"
132 " <arg type='i' name='uid' direction='in'/>"
133 " <arg type='i' name='result' direction='out'/>"
135 " <method name='PostAppUpgrade'>"
136 " <arg type='s' name='pkgid' direction='in'/>"
137 " <arg type='i' name='install_status' direction='in'/>"
138 " <arg type='i' name='uid' direction='in'/>"
139 " <arg type='i' name='result' direction='out'/>"
141 " <method name='PreAppUninstall'>"
142 " <arg type='s' name='pkgid' direction='in'/>"
143 " <arg type='i' name='uid' direction='in'/>"
144 " <arg type='i' name='result' direction='out'/>"
146 " <method name='PostAppUninstall'>"
147 " <arg type='s' name='pkgid' direction='in'/>"
148 " <arg type='i' name='uid' direction='in'/>"
149 " <arg type='i' name='result' direction='out'/>"
151 " <method name='OndemandSetupInit'>"
152 " <arg type='s' name='pkgid' direction='in'/>"
153 " <arg type='i' name='uid' direction='in'/>"
154 " <arg type='i' name='result' direction='out'/>"
156 " <method name='OndemandSetupExit'>"
157 " <arg type='s' name='pkgid' direction='in'/>"
158 " <arg type='i' name='uid' direction='in'/>"
159 " <arg type='i' name='result' direction='out'/>"
161 " <method name='MoveInstalledApp'>"
162 " <arg type='s' name='pkgid' direction='in'/>"
163 " <arg type='i' name='move_type' direction='in'/>"
164 " <arg type='a(si)' name='dir_list' direction='in'/>"
165 " <arg type='i' name='uid' direction='in'/>"
166 " <arg type='i' name='result' direction='out'/>"
168 " <method name='ForceClean'>"
169 " <arg type='s' name='pkgid' direction='in'/>"
170 " <arg type='i' name='uid' direction='in'/>"
171 " <arg type='i' name='result' direction='out'/>"
173 " <method name='EnableFullPkg'>"
174 " <arg type='i' name='result' direction='out'/>"
176 " <method name='DisableFullPkg'>"
177 " <arg type='i' name='result' direction='out'/>"
182 static void _app2sd_server_return_method_error(GDBusMethodInvocation *invocation, int result)
184 GVariant *param = NULL;
186 param = g_variant_new("(i)", result);
187 g_dbus_method_invocation_return_value(invocation, param);
190 static void _app2sd_server_pre_app_install(GDBusConnection *connection, const gchar *sender,
191 GVariant *parameters, GDBusMethodInvocation *invocation, uid_t sender_uid)
193 GVariant *param = NULL;
194 int result = APP2EXT_SUCCESS;
201 uid_t target_uid = -1;
202 GList *dir_list = NULL;
204 app2ext_dir_details *dir_detail = NULL;
206 g_variant_get(parameters, "(&sia(si)i)", &pkgid, &size, &iter, &target_uid);
208 _D("pkgid(%s), size(%d),sender_uid(%d), target_uid(%d)",
209 pkgid, size, sender_uid, target_uid);
211 if (sender_uid != 0 && sender_uid != target_uid) {
212 _E("Not permitted user!");
213 g_variant_iter_free(iter);
214 _app2sd_server_return_method_error(invocation,
215 APP2EXT_ERROR_OPERATION_NOT_PERMITTED);
219 while (g_variant_iter_loop(iter, "(si)", &str, &type)) {
221 _D("str(%s), type(%d)", str, type);
223 /* generate dir_list */
224 dir_detail = (app2ext_dir_details *)calloc(1, sizeof(app2ext_dir_details));
225 if (dir_detail == NULL) {
226 _E("memory allocation failed");
227 result = APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
231 dir_detail->name = strdup((char *)str);
232 if (dir_detail->name == NULL) {
235 result = APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
239 dir_detail->type = type;
240 list = g_list_append(list, dir_detail);
243 g_variant_iter_free(iter);
245 dir_list = g_list_first(list);
246 ret = app2sd_usr_pre_app_install(pkgid, dir_list, size, target_uid);
248 _E("error(%d)", ret);
252 param = g_variant_new("(i)", result);
253 g_dbus_method_invocation_return_value(invocation, param);
256 static void _app2sd_server_post_app_install(GDBusConnection *connection, const gchar *sender,
257 GVariant *parameters, GDBusMethodInvocation *invocation, uid_t sender_uid)
259 GVariant *param = NULL;
260 int result = APP2EXT_SUCCESS;
262 int install_status = 0;
266 g_variant_get(parameters, "(&sii)", &pkgid, &install_status, &target_uid);
268 _D("pkgid(%s), install_status(%d), sender_uid(%d), target_uid(%d)",
269 pkgid, install_status, sender_uid, target_uid);
271 if (sender_uid != 0 && sender_uid != target_uid) {
272 _E("Not permitted user!");
273 _app2sd_server_return_method_error(invocation,
274 APP2EXT_ERROR_OPERATION_NOT_PERMITTED);
278 ret = app2sd_usr_post_app_install(pkgid, install_status, target_uid);
280 _E("error(%d)", ret);
284 param = g_variant_new("(i)", result);
285 g_dbus_method_invocation_return_value(invocation, param);
288 static void _app2sd_server_pre_app_upgrade(GDBusConnection *connection, const gchar *sender,
289 GVariant *parameters, GDBusMethodInvocation *invocation, uid_t sender_uid)
291 GVariant *param = NULL;
292 int result = APP2EXT_SUCCESS;
298 uid_t target_uid = -1;
300 GList *dir_list = NULL;
302 app2ext_dir_details *dir_detail = NULL;
304 g_variant_get(parameters, "(&sia(si)i)", &pkgid, &size, &iter, &target_uid);
306 _D("pkgid(%s), size(%d), sender_uid(%d), target_uid(%d)",
307 pkgid, size, sender_uid, target_uid);
309 if (sender_uid != 0 && sender_uid != target_uid) {
310 _E("Not permitted user!");
311 g_variant_iter_free(iter);
312 _app2sd_server_return_method_error(invocation,
313 APP2EXT_ERROR_OPERATION_NOT_PERMITTED);
317 while (g_variant_iter_loop(iter, "(si)", &str, &type)) {
319 _D("str(%s), type(%d)", str, type);
321 /* generate dir_list */
322 dir_detail = (app2ext_dir_details *)calloc(1, sizeof(app2ext_dir_details));
323 if (dir_detail == NULL) {
324 _E("memory allocation failed");
325 result = APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
329 dir_detail->name = strdup((char *)str);
330 if (dir_detail->name == NULL) {
333 result = APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
337 dir_detail->type = type;
338 list = g_list_append(list, dir_detail);
341 g_variant_iter_free(iter);
343 dir_list = g_list_first(list);
344 ret = app2sd_usr_pre_app_upgrade(pkgid, dir_list, size, target_uid);
346 _E("error(%d)", ret);
350 param = g_variant_new("(i)", result);
351 g_dbus_method_invocation_return_value(invocation, param);
354 static void _app2sd_server_post_app_upgrade(GDBusConnection *connection, const gchar *sender,
355 GVariant *parameters, GDBusMethodInvocation *invocation, uid_t sender_uid)
357 GVariant *param = NULL;
358 int result = APP2EXT_SUCCESS;
360 int install_status = 0;
361 uid_t target_uid = -1;
364 g_variant_get(parameters, "(&sii)", &pkgid, &install_status, &target_uid);
366 _D("pkgid(%s), install_status(%d), sender_uid(%d), target_uid(%d)",
367 pkgid, install_status, sender_uid, target_uid);
369 if (sender_uid != 0 && sender_uid != target_uid) {
370 _E("Not permitted user!");
371 _app2sd_server_return_method_error(invocation,
372 APP2EXT_ERROR_OPERATION_NOT_PERMITTED);
376 ret = app2sd_usr_post_app_upgrade(pkgid, install_status, target_uid);
378 _E("error(%d)", ret);
382 param = g_variant_new("(i)", result);
383 g_dbus_method_invocation_return_value(invocation, param);
386 static void _app2sd_server_pre_app_uninstall(GDBusConnection *connection, const gchar *sender,
387 GVariant *parameters, GDBusMethodInvocation *invocation, uid_t sender_uid)
389 GVariant *param = NULL;
390 int result = APP2EXT_SUCCESS;
392 uid_t target_uid = -1;
395 g_variant_get(parameters, "(&si)", &pkgid, &target_uid);
397 _D("pkgid(%s), sender_uid(%d), target_uid(%d)",
398 pkgid, sender_uid, target_uid);
400 if (sender_uid != 0 && sender_uid != target_uid) {
401 _E("Not permitted user!");
402 _app2sd_server_return_method_error(invocation,
403 APP2EXT_ERROR_OPERATION_NOT_PERMITTED);
407 ret = app2sd_usr_pre_app_uninstall(pkgid, target_uid);
409 _E("error(%d)", ret);
413 param = g_variant_new("(i)", result);
414 g_dbus_method_invocation_return_value(invocation, param);
417 static void _app2sd_server_post_app_uninstall(GDBusConnection *connection, const gchar *sender,
418 GVariant *parameters, GDBusMethodInvocation *invocation, uid_t sender_uid)
420 GVariant *param = NULL;
421 int result = APP2EXT_SUCCESS;
423 uid_t target_uid = -1;
426 g_variant_get(parameters, "(&si)", &pkgid, &target_uid);
428 _D("pkgid(%s), sender_uid(%d), target_uid(%d)",
429 pkgid, sender_uid, target_uid);
431 if (sender_uid != 0 && sender_uid != target_uid) {
432 _E("Not permitted user!");
433 _app2sd_server_return_method_error(invocation,
434 APP2EXT_ERROR_OPERATION_NOT_PERMITTED);
438 ret = app2sd_usr_post_app_uninstall(pkgid, target_uid);
440 _E("error(%d)", ret);
444 param = g_variant_new("(i)", result);
445 g_dbus_method_invocation_return_value(invocation, param);
448 static void _app2sd_server_ondemand_setup_init(GDBusConnection *connection, const gchar *sender,
449 GVariant *parameters, GDBusMethodInvocation *invocation, uid_t sender_uid)
451 GVariant *param = NULL;
452 int result = APP2EXT_SUCCESS;
454 uid_t target_uid = -1;
457 g_variant_get(parameters, "(&si)", &pkgid, &target_uid);
459 _D("pkgid(%s), sender_uid(%d), target_uid(%d)",
460 pkgid, sender_uid, target_uid);
462 if (sender_uid != 0 && sender_uid != target_uid) {
463 _E("Not permitted user!");
464 _app2sd_server_return_method_error(invocation,
465 APP2EXT_ERROR_OPERATION_NOT_PERMITTED);
469 ret = app2sd_usr_on_demand_setup_init(pkgid, target_uid);
471 _E("error(%d)", ret);
475 param = g_variant_new("(i)", result);
476 g_dbus_method_invocation_return_value(invocation, param);
479 static void _app2sd_server_ondemand_setup_exit(GDBusConnection *connection, const gchar *sender,
480 GVariant *parameters, GDBusMethodInvocation *invocation, uid_t sender_uid)
482 GVariant *param = NULL;
483 int result = APP2EXT_SUCCESS;
485 uid_t target_uid = -1;
488 g_variant_get(parameters, "(&si)", &pkgid, &target_uid);
490 _D("pkgid(%s), sender_uid(%d), target_uid(%d)",
491 pkgid, sender_uid, target_uid);
493 if (sender_uid != 0 && sender_uid != target_uid) {
494 _E("Not permitted user!");
495 _app2sd_server_return_method_error(invocation,
496 APP2EXT_ERROR_OPERATION_NOT_PERMITTED);
500 ret = app2sd_usr_on_demand_setup_exit(pkgid, target_uid);
502 _E("error(%d)", ret);
506 param = g_variant_new("(i)", result);
507 g_dbus_method_invocation_return_value(invocation, param);
510 static void _app2sd_server_move_installed_app(GDBusConnection *connection, const gchar *sender,
511 GVariant *parameters, GDBusMethodInvocation *invocation, uid_t sender_uid)
513 GVariant *param = NULL;
514 int result = APP2EXT_SUCCESS;
521 uid_t target_uid = -1;
522 GList *dir_list = NULL;
524 app2ext_dir_details *dir_detail = NULL;
526 g_variant_get(parameters, "(&sia(si)i)", &pkgid, &move_type, &iter, &target_uid);
528 _D("pkgid(%s), move_type(%d),sender_uid(%d), target_uid(%d)",
529 pkgid, move_type, sender_uid, target_uid);
531 if (sender_uid != 0 && sender_uid != target_uid) {
532 _E("Not permitted user!");
533 g_variant_iter_free(iter);
534 _app2sd_server_return_method_error(invocation,
535 APP2EXT_ERROR_OPERATION_NOT_PERMITTED);
539 while (g_variant_iter_loop(iter, "(si)", &str, &type)) {
541 _D("str(%s), type(%d)", str, type);
543 /* generate dir_list */
544 dir_detail = (app2ext_dir_details *)calloc(1, sizeof(app2ext_dir_details));
545 if (dir_detail == NULL) {
546 _E("memory allocation failed");
547 result = APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
551 dir_detail->name = strdup((char *)str);
552 if (dir_detail->name == NULL) {
555 result = APP2EXT_ERROR_MEMORY_ALLOC_FAILED;
559 dir_detail->type = type;
560 list = g_list_append(list, dir_detail);
563 g_variant_iter_free(iter);
565 dir_list = g_list_first(list);
566 ret = app2sd_usr_move_installed_app(pkgid, dir_list, move_type, target_uid);
568 _E("usr_move error(%d)", ret);
572 param = g_variant_new("(i)", result);
573 g_dbus_method_invocation_return_value(invocation, param);
576 static void _app2sd_server_force_clean(GDBusConnection *connection, const gchar *sender,
577 GVariant *parameters, GDBusMethodInvocation *invocation, uid_t sender_uid)
579 GVariant *param = NULL;
580 int result = APP2EXT_SUCCESS;
582 uid_t target_uid = -1;
585 g_variant_get(parameters, "(&si)", &pkgid, &target_uid);
587 _D("pkgid(%s), sender_uid(%d), target_uid(%d)",
588 pkgid, sender_uid, target_uid);
590 if (sender_uid != 0 && sender_uid != target_uid) {
591 _E("Not permitted user!");
592 _app2sd_server_return_method_error(invocation,
593 APP2EXT_ERROR_OPERATION_NOT_PERMITTED);
597 ret = app2sd_usr_force_clean(pkgid, target_uid);
599 _E("error(%d)", ret);
603 param = g_variant_new("(i)", result);
604 g_dbus_method_invocation_return_value(invocation, param);
607 static void _app2sd_server_enable_full_pkg(GDBusConnection *connection, const gchar *sender,
608 GVariant *parameters, GDBusMethodInvocation *invocation, uid_t sender_uid)
610 GVariant *param = NULL;
611 int result = APP2EXT_SUCCESS;
614 _D("sender_uid(%d)", sender_uid);
616 if (sender_uid >= REGULAR_USER) {
617 _E("Not permitted user!");
618 _app2sd_server_return_method_error(invocation,
619 APP2EXT_ERROR_OPERATION_NOT_PERMITTED);
623 ret = app2sd_enable_full_pkg();
625 _E("error(%d)", ret);
629 param = g_variant_new("(i)", result);
630 g_dbus_method_invocation_return_value(invocation, param);
633 static void _app2sd_server_disable_full_pkg(GDBusConnection *connection, const gchar *sender,
634 GVariant *parameters, GDBusMethodInvocation *invocation, uid_t sender_uid)
636 GVariant *param = NULL;
637 int result = APP2EXT_SUCCESS;
640 _D("sender_uid(%d)", sender_uid);
642 if (sender_uid >= REGULAR_USER) {
643 _E("Not permitted user!");
644 _app2sd_server_return_method_error(invocation,
645 APP2EXT_ERROR_OPERATION_NOT_PERMITTED);
649 ret = app2sd_disable_full_pkg();
651 _E("error(%d)", ret);
655 param = g_variant_new("(i)", result);
656 g_dbus_method_invocation_return_value(invocation, param);
659 static void handle_method_call(GDBusConnection *connection,
660 const gchar *sender, const gchar *object_path,
661 const gchar *interface_name, const gchar *method_name,
662 GVariant *parameters, GDBusMethodInvocation *invocation,
665 uid_t sender_uid = -1;
667 sender_uid = (uid_t)__app2sd_get_sender_uid(connection, sender);
669 if (g_strcmp0(method_name, "PreAppInstall") == 0) {
670 _app2sd_server_pre_app_install(connection, sender,
671 parameters, invocation, sender_uid);
672 } else if (g_strcmp0(method_name, "PostAppInstall") == 0) {
673 _app2sd_server_post_app_install(connection, sender,
674 parameters, invocation, sender_uid);
675 } else if (g_strcmp0(method_name, "PreAppUpgrade") == 0) {
676 _app2sd_server_pre_app_upgrade(connection, sender,
677 parameters, invocation, sender_uid);
678 } else if (g_strcmp0(method_name, "PostAppUpgrade") == 0) {
679 _app2sd_server_post_app_upgrade(connection, sender,
680 parameters, invocation, sender_uid);
681 } else if (g_strcmp0(method_name, "PreAppUninstall") == 0) {
682 _app2sd_server_pre_app_uninstall(connection, sender,
683 parameters, invocation, sender_uid);
684 } else if (g_strcmp0(method_name, "PostAppUninstall") == 0) {
685 _app2sd_server_post_app_uninstall(connection, sender,
686 parameters, invocation, sender_uid);
687 } else if (g_strcmp0(method_name, "OndemandSetupInit") == 0) {
688 _app2sd_server_ondemand_setup_init(connection, sender,
689 parameters, invocation, sender_uid);
690 } else if (g_strcmp0(method_name, "OndemandSetupExit") == 0) {
691 _app2sd_server_ondemand_setup_exit(connection, sender,
692 parameters, invocation, sender_uid);
693 } else if (g_strcmp0(method_name, "MoveInstalledApp") == 0) {
694 _app2sd_server_move_installed_app(connection, sender,
695 parameters, invocation, sender_uid);
696 } else if (g_strcmp0(method_name, "ForceClean") == 0) {
697 _app2sd_server_force_clean(connection, sender,
698 parameters, invocation, sender_uid);
699 } else if (g_strcmp0(method_name, "EnableFullPkg") == 0) {
700 _app2sd_server_enable_full_pkg(connection, sender,
701 parameters, invocation, sender_uid);
702 } else if (g_strcmp0(method_name, "DisableFullPkg") == 0) {
703 _app2sd_server_disable_full_pkg(connection, sender,
704 parameters, invocation, sender_uid);
707 g_timeout_add_seconds(5, __exit_app2sd_server, NULL);
710 static const GDBusInterfaceVTable interface_vtable = {
716 static void __app2sd_on_bus_acquired(GDBusConnection *connection,
717 const gchar *name, gpointer user_data)
719 _I("bus acquired(%s)", name);
722 GError *error = NULL;
724 reg_id = g_dbus_connection_register_object(connection,
726 introspection_data->interfaces[0],
730 _E("g_dbus_connection_register_object error(%s)", error->message);
735 static void __app2sd_on_name_acquired(GDBusConnection *connection,
736 const gchar *name, gpointer user_data)
738 _I("name acquired(%s)", name);
741 static void __app2sd_on_name_lost(GDBusConnection *connection,
742 const gchar *name, gpointer user_data)
744 _E("name lost(%s)", name);
745 g_main_loop_quit(app2sd_mainloop);
748 static int __app2sd_server_init()
750 GError *error = NULL;
753 /* gdbus setup for method call */
754 introspection_data = g_dbus_node_info_new_for_xml(introspection_xml, &error);
755 if (!introspection_data) {
756 _E("g_dbus_node_info_new_for_xml error(%s)", error->message);
761 owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
763 G_BUS_NAME_OWNER_FLAGS_NONE,
764 __app2sd_on_bus_acquired,
765 __app2sd_on_name_acquired,
766 __app2sd_on_name_lost,
769 _E("g_bus_own_name error");
770 g_dbus_node_info_unref(introspection_data);
779 static void __app2sd_finalize(void)
781 _D("app2sd finalize");
783 if (introspection_data)
784 g_dbus_node_info_unref(introspection_data);
786 _D("app2sd finalize end");
789 int main(int argc, char *argv[])
793 _I("app2sd_server : start");
795 ret = __app2sd_server_init();
797 _E("app2sd_server init failed(%d)", ret);
801 app2sd_mainloop = g_main_loop_new(NULL, FALSE);
802 if (!app2sd_mainloop) {
803 _E("g_main_loop_new failed");
807 g_main_loop_run(app2sd_mainloop);
811 _I("app2sd_server : end");