Add CPU lock on pkgmgr-server
[platform/core/appfw/pkgmgr-server.git] / src / pkgmgr-server.c
1 /*
2  * slp-pkgmgr
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Jayoun Lee <airjany@samsung.com>, Sewook Park <sewook7.park@samsung.com>,
7  * Jaeho Lee <jaeho81.lee@samsung.com>, Shobhit Srivastava <shobhit.s@samsung.com>
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  * http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  */
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <ctype.h>
27 #include <unistd.h>
28 #include <pwd.h>
29 #include <sys/types.h>
30 #include <sys/wait.h>
31 #include <sys/stat.h>
32 #include <sys/types.h>
33 #include <sys/signalfd.h>
34 #include <signal.h>
35 #include <grp.h>
36 #include <fcntl.h>
37
38 #include <glib.h>
39 #include <gio/gio.h>
40
41 #include <aul.h>
42 #include <pkgmgr-info.h>
43 #include <pkgmgr/pkgmgr_parser_db.h>
44 #include <tzplatform_config.h>
45 #include <drm-tizen-apps.h>
46 #include <dd-display.h>
47 #ifdef TIZEN_FEATURE_CSR
48 #include <csr-content-screening.h>
49 #endif
50
51 #include "pkgmgr_installer.h"
52 #include "pkgmgr-server.h"
53 #include "queue.h"
54 #include "package-manager.h"
55
56 #define OWNER_ROOT 0
57 #define GLOBAL_USER tzplatform_getuid(TZ_SYS_GLOBALAPP_USER)
58 #define APPFW_UID 301
59
60
61 #define EXT_STORAGE_GROUP 10001
62 #define EXT_STORAGE_APPDATA_GROUP 10002
63 #define MEDIA_STORAGE_GROUP 10502
64 #define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
65 #define MAX_LONGLONG_LENGTH 32
66
67 typedef struct  {
68         char **env;
69         uid_t uid;
70         gid_t gid;
71 } user_ctx;
72
73 typedef struct {
74         uid_t uid;
75         char *cmd;
76         int pid;
77 } pkgcmd_data;
78
79 /*
80 8 bit value to represent maximum 8 backends.
81 Each bit position corresponds to a queue slot which
82 is dynamically determined.
83 */
84 static char backend_busy = 0;
85 extern int num_of_backends;
86 bool is_drm_busy = false;
87 static bool is_lock_set = false;
88
89 static GIOChannel *sio;
90 static guint swid;
91 static GHashTable *backend_info_table;
92 static GMainLoop *mainloop;
93
94 static int __check_backend_status_for_exit(void);
95 static int __check_queue_status_for_exit(void);
96 static int __is_backend_busy(int position);
97 static void __set_backend_busy(int position);
98 static void __set_backend_free(int position);
99
100 gboolean exit_server(void *data);
101
102 /* To check whether a particular backend is free/busy */
103 static int __is_backend_busy(int position)
104 {
105         return backend_busy & (1 << position);
106 }
107 /* To set a particular backend as busy */
108 static void __set_backend_busy(int position)
109 {
110         backend_busy = backend_busy | (1 << position);
111 }
112 /* To set a particular backend as free */
113 static void __set_backend_free(int position)
114 {
115         backend_busy = backend_busy & ~(1 << position);
116 }
117
118 static void __set_power_lock(void)
119 {
120         if (is_lock_set)
121                 return;
122
123         if (display_lock_state(LCD_OFF, STAY_CUR_STATE, 0) == 0)
124                 is_lock_set = true;
125 }
126
127 static void __release_power_lock(void)
128 {
129         if (!is_lock_set)
130                 return;
131
132         if (display_unlock_state(LCD_OFF, PM_SLEEP_MARGIN) == 0)
133                 is_lock_set = false;
134 }
135
136 static gboolean getsize_io_handler(GIOChannel *io, GIOCondition cond,
137                 gpointer data)
138 {
139         GError *err = NULL;
140         GIOStatus s;
141         gsize len;
142         char buf[MAX_LONGLONG_LENGTH];
143         long long result = 0;
144         struct backend_job *job = (struct backend_job *)data;
145         struct getsize_sync_extra_info *extra_getsize_info =
146                         (struct getsize_sync_extra_info *)job->extra_data;
147
148         s = g_io_channel_read_chars(io, (gchar *)buf, sizeof(buf), &len, &err);
149         if (s != G_IO_STATUS_NORMAL) {
150                 ERR("getsize fd read failed: %s", err->message);
151                 g_error_free(err);
152                 result = -1;
153         } else {
154                 if (strlen(buf) == 0) {
155                         ERR("empty result");
156                         result = -1;
157                 } else {
158                         result = atoll(buf);
159                 }
160         }
161
162         _return_value_to_caller(job->req_id, g_variant_new("(ix)",
163                 (result < 0) ? PKGMGR_R_ERROR : PKGMGR_R_OK, result));
164
165         unlink(extra_getsize_info->getsize_fifo);
166         free(extra_getsize_info->getsize_fifo);
167         extra_getsize_info->getsize_fifo = NULL;
168
169         return FALSE;
170 }
171
172 static int __setup_size_info_io(struct backend_job *job)
173 {
174         guint getsize_wid;
175         struct getsize_sync_extra_info *extra_getsize_info =
176                         (struct getsize_sync_extra_info *)job->extra_data;
177
178         extra_getsize_info->getsize_fd = open(extra_getsize_info->getsize_fifo,
179                 O_RDONLY | O_NONBLOCK);
180         if (extra_getsize_info->getsize_fd < 0) {
181                 ERR("failed to open the fifo(%s), errno(%d)",
182                                 extra_getsize_info->getsize_fifo, errno);
183                 return -1;
184         }
185
186         extra_getsize_info->getsize_io =
187                         g_io_channel_unix_new(extra_getsize_info->getsize_fd);
188         if (!extra_getsize_info->getsize_io)
189                 return -1;
190         g_io_channel_set_encoding(extra_getsize_info->getsize_io, NULL, NULL);
191         g_io_channel_set_buffered(extra_getsize_info->getsize_io, FALSE);
192         getsize_wid = g_io_add_watch_full(extra_getsize_info->getsize_io,
193                 G_PRIORITY_HIGH, G_IO_IN, getsize_io_handler, job, NULL);
194         if (!getsize_wid) {
195                 ERR("failed to add io watch");
196                 return -1;
197         }
198
199         return 0;
200 }
201
202 static gboolean __signal_handler(GIOChannel *io, GIOCondition cond,
203                 gpointer data)
204 {
205         GError *err = NULL;
206         GIOStatus s;
207         gsize len;
208         struct signalfd_siginfo fdsi;
209         struct backend_job *job;
210         struct getsize_sync_extra_info *extra_getsize_info;
211         pid_t pid;
212         int status;
213
214         s = g_io_channel_read_chars(io, (gchar *)&fdsi,
215                         sizeof(struct signalfd_siginfo), &len, &err);
216         if (s != G_IO_STATUS_NORMAL || len != sizeof(struct signalfd_siginfo)) {
217                 ERR("Signal read failed");
218                 g_error_free(err);
219                 return TRUE;
220         }
221
222         while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
223                 job = (struct backend_job *)g_hash_table_lookup(
224                         backend_info_table, (gconstpointer)pid);
225                 if (job == NULL) {
226                         ERR("Unknown child exit");
227                         continue;
228                 }
229
230                 __set_backend_free(job->backend_slot);
231                 if (WIFSIGNALED(status)) {
232                         _send_fail_signal(job);
233                         INFO("backend[%s][%d] exit with signal[%d]",
234                                 job->backend_type, pid, WTERMSIG(status));
235                 } else if (WEXITSTATUS(status)) {
236                         INFO("backend[%s][%d] exit with error",
237                                 job->backend_type, pid);
238                 } else {
239                         INFO("backend[%s][%d] exit", job->backend_type, pid);
240                 }
241
242                 if (job->req_type == REQUEST_TYPE_GETSIZE_SYNC &&
243                                 job->extra_data) {
244                         extra_getsize_info =
245                                         (struct getsize_sync_extra_info *)job->extra_data;
246                         if (extra_getsize_info->getsize_fifo) {
247                                 ERR("invalid backend close");
248                                 _return_value_to_caller(job->req_id,
249                                         g_variant_new("(ix)",
250                                                         PKGMGR_R_ERROR, -1));
251                         }
252                 }
253                 g_hash_table_remove(backend_info_table, (gconstpointer)pid);
254         }
255         g_idle_add(queue_job, NULL);
256
257         return TRUE;
258 }
259
260 static int __init_backend_info(void)
261 {
262         backend_info_table = g_hash_table_new_full(g_direct_hash,
263                         g_direct_equal, NULL,
264                         (GDestroyNotify)_free_backend_job);
265
266         return 0;
267 }
268
269 static void __fini_backend_info(void)
270 {
271         /*Free backend info */
272         g_hash_table_destroy(backend_info_table);
273 }
274
275 static int __register_signal_handler(void)
276 {
277         sigset_t mask;
278         int sfd;
279
280         sigemptyset(&mask);
281         sigaddset(&mask, SIGCHLD);
282
283         if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) {
284                 ERR("sigprocmask failed");
285                 return -1;
286         }
287
288         sfd = signalfd(-1, &mask, SFD_NONBLOCK);
289         if (sfd == -1) {
290                 ERR("signalfd failed");
291                 return -1;
292         }
293
294         sio = g_io_channel_unix_new(sfd);
295         g_io_channel_set_close_on_unref(sio, TRUE);
296         g_io_channel_set_encoding(sio, NULL, NULL);
297         g_io_channel_set_buffered(sio, FALSE);
298         swid = g_io_add_watch(sio, G_IO_IN, __signal_handler, NULL);
299
300         g_timeout_add_seconds_full(G_PRIORITY_LOW, 2, exit_server, NULL, NULL);
301
302         return 0;
303 }
304
305 static int __check_backend_status_for_exit(void)
306 {
307         int i;
308         for (i = 0; i < num_of_backends; i++) {
309                 if (__is_backend_busy(i))
310                         return 0;
311         }
312         return 1;
313 }
314
315 static int __check_queue_status_for_exit(void)
316 {
317         int i;
318         for (i = 0; i < num_of_backends; i++) {
319                 if (_is_queue_empty(i) == 0)
320                         return 0;
321         }
322         return 1;
323 }
324
325 gboolean exit_server(void *data)
326 {
327         DBG("exit_server Start");
328         if (__check_backend_status_for_exit() &&
329                         __check_queue_status_for_exit() && !is_drm_busy) {
330                 g_main_loop_quit(mainloop);
331                 if (is_lock_set)
332                         __release_power_lock();
333                 return FALSE;
334         }
335         return TRUE;
336 }
337
338 #ifdef TIZEN_FEATURE_CSR
339 static int __check_csr(const char *path)
340 {
341         csr_cs_context_h context = NULL;
342         csr_cs_malware_h detected = NULL;
343         int ret = -1;
344
345         ret = csr_cs_context_create(&context);
346         if (ret != CSR_ERROR_NONE) {
347                 ERR("Failed to create csr context");
348                 return -1;
349         }
350
351         if (context) {
352                 ret = csr_cs_scan_file(context, path, &detected);
353                 DBG("CSR result[%d]", ret);
354
355                 csr_cs_context_destroy(context);
356                 if (detected != NULL) {
357                         ERR("CSR Denied[%s] Installation", path);
358                         return -1;
359                 }
360         }
361
362         return 0;
363 }
364 #endif
365
366 static int __kill_app(char *appid, uid_t uid)
367 {
368         int ret;
369         int pid;
370         int is_running;
371
372         is_running = aul_app_is_running_for_uid(appid, uid);
373         /* app is not running */
374         if (!is_running)
375                 return 0;
376
377         pid = aul_app_get_pid_for_uid(appid, uid);
378         if (pid == -1)
379                 return -1;
380
381         ret = aul_terminate_pid_for_uid(pid, uid);
382         if (ret != AUL_R_OK) {
383                 ERR("failed to terminate app(%d)", appid);
384                 return -1;
385         }
386
387         return 0;
388 }
389
390 static int __check_app(char *appid, uid_t uid)
391 {
392         int pid;
393         int is_running;
394
395         is_running = aul_app_is_running_for_uid(appid, uid);
396         if (!is_running)
397                 return 0;
398
399         pid = aul_app_get_pid_for_uid(appid, uid);
400
401         return pid;
402 }
403
404 static int __pkgcmd_app_cb(const pkgmgrinfo_appinfo_h handle, void *user_data)
405 {
406         char *pkgid;
407         char *appid;
408         char *exec;
409         int ret;
410         pkgcmd_data *pdata = (pkgcmd_data *)user_data;
411
412         if (handle == NULL) {
413                 perror("appinfo handle is NULL\n");
414                 exit(1);
415         }
416         ret = pkgmgrinfo_appinfo_get_exec(handle, &exec);
417         if (ret) {
418                 perror("Failed to get app exec path\n");
419                 exit(1);
420         }
421         ret = pkgmgrinfo_appinfo_get_appid(handle, &appid);
422         if (ret) {
423                 perror("Failed to get appid\n");
424                 exit(1);
425         }
426         ret = pkgmgrinfo_appinfo_get_pkgid(handle, &pkgid);
427         if (ret) {
428                 perror("Failed to get pkgid\n");
429                 exit(1);
430         }
431
432         if (strcmp(pdata->cmd, "kill") == 0) {
433                 pdata->pid = __check_app(appid, pdata->uid);
434                 if (pdata->pid > 0)
435                         ret = __kill_app(appid, pdata->uid);
436         } else if (strcmp(pdata->cmd, "check") == 0) {
437                 pdata->pid = __check_app(appid, pdata->uid);
438         }
439
440         return 0;
441 }
442
443 void free_user_context(user_ctx *ctx)
444 {
445         char **env = NULL;
446         int i = 0;
447         if (!ctx)
448                 return;
449         env = ctx->env;
450         /* env variable ends by NULL element */
451         while (env[i]) {
452                 free(env[i]);
453                 i++;
454         }
455         free(env);
456         env = NULL;
457         free(ctx);
458 }
459
460 int set_environement(user_ctx *ctx)
461 {
462         int i = 0;
463         int res = 0;
464         char **env = NULL;
465         int n;
466         gid_t *groups;
467
468         if (!ctx)
469                 return -1;
470
471         if (ctx->uid != APPFW_UID) {
472                 if (setuid(ctx->uid)) {
473                         ERR("setuid failed: %d", errno);
474                         return -1;
475                 }
476
477                 if (setgid(ctx->gid)) {
478                         ERR("setgid failed: %d", errno);
479                         return -1;
480                 }
481         }
482
483         n = getgroups(0, NULL);
484         if (n < 0) {
485                 ERR("Failed to get the number of supplementary group IDs");
486                 return -1;
487         }
488
489         groups = (gid_t *)calloc(1, sizeof(gid_t) * (n + 3));
490         if (groups == NULL) {
491                 ERR("out of memory");
492                 return -1;
493         }
494
495         n = getgroups(n, groups);
496         if (n < 0) {
497                 ERR("Failed to get list of supplementary group IDs");
498                 free(groups);
499                 return -1;
500         }
501
502         groups[n++] = EXT_STORAGE_GROUP;
503         groups[n++] = EXT_STORAGE_APPDATA_GROUP;
504         groups[n++] = MEDIA_STORAGE_GROUP;
505
506         if (setgroups(n, groups) < 0) {
507                 ERR("setgroups failed: %d", errno);
508                 free(groups);
509                 return -1;
510         }
511         free(groups);
512
513         env = ctx->env;
514         /* env variable ends by NULL element */
515         while (env[i]) {
516                 if (putenv(env[i]) != 0)
517                         res = -1;
518                 i++;
519         }
520         return res;
521 }
522
523 user_ctx *get_user_context(uid_t uid)
524 {
525         /* we can use getpwnam because this is used only after a
526          * fork and just before an execv
527          * No concurrencial call can corrupt the data
528          * returned by getpwuid
529          */
530         user_ctx *context_res;
531         char **env = NULL;
532         char buf[1024] = {0, };
533         struct passwd pwd, *result;
534         int len;
535         int ret = 0;
536         int i;
537
538         ret = getpwuid_r(uid, &pwd, buf, sizeof(buf), &result);
539         if (ret != 0 || result == NULL)
540                 return NULL;
541
542         do {
543                 context_res = (user_ctx *)malloc(sizeof(user_ctx));
544                 if (!context_res) {
545                         ret = -1;
546                         break;
547                 }
548                 env = (char **)malloc(3 * sizeof(char *));
549                 if (!env) {
550                         ret = -1;
551                         break;
552                 }
553                 /* Build environment context */
554                 len = snprintf(NULL, 0, "HOME=%s", pwd.pw_dir);
555                 env[0] = (char *)malloc((len + 1) * sizeof(char));
556                 if (env[0] == NULL) {
557                         ret = -1;
558                         break;
559                 }
560                 snprintf(env[0], len + 1, "HOME=%s", pwd.pw_dir);
561                 len = snprintf(NULL, 0, "USER=%s", pwd.pw_name);
562                 env[1] = (char *)malloc((len + 1) * sizeof(char));
563                 if (env[1] == NULL) {
564                         ret = -1;
565                         break;
566                 }
567                 snprintf(env[1], len + 1, "USER=%s", pwd.pw_name);
568                 env[2] = NULL;
569         } while (0);
570
571         if (ret == -1) {
572                 free(context_res);
573                 context_res = NULL;
574                 i = 0;
575                 /* env variable ends by NULL element */
576                 while (env && env[i]) {
577                         free(env[i]);
578                         i++;
579                 }
580                 free(env);
581                 env = NULL;
582         } else {
583                 context_res->env = env;
584                 context_res->uid = uid;
585                 context_res->gid = pwd.pw_gid;
586         }
587         return context_res;
588 }
589
590 static char **__generate_argv(const char *args)
591 {
592         /* Create args vector
593          * req_id + pkgid + args
594          *
595          * vector size = # of args +
596          *(req_id + pkgid + NULL termination = 3)
597          * Last value must be NULL for execv.
598          */
599         gboolean ret_parse;
600         gint argcp;
601         gchar **argvp;
602         GError *gerr = NULL;
603         int i;
604
605         ret_parse = g_shell_parse_argv(args, &argcp, &argvp, &gerr);
606         if (FALSE == ret_parse) {
607                 ERR("Failed to split args: %s", args);
608                 ERR("messsage: %s", gerr->message);
609                 exit(1);
610         }
611
612         /* dbg */
613         for (i = 0; i < argcp; i++)
614                 DBG(">>>>>> argsv[%d]=%s", i, argvp[i]);
615
616         return argvp;
617 }
618
619 void __set_environment(gpointer user_data)
620 {
621         user_ctx *ctx = (user_ctx *)user_data;
622
623         if (set_environement(ctx))
624                 ERR("Failed to set env for the user : %d", ctx->uid);
625 }
626
627 static int __fork_and_exec_with_args(char **argv, uid_t uid)
628 {
629         user_ctx *user_context;
630         GError *error = NULL;
631         gboolean ret;
632         int pid;
633
634         user_context = get_user_context(uid);
635         if (!user_context) {
636                 ERR("Failed to getenv");
637                 return -1;
638         }
639
640         ret = g_spawn_async(NULL, argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD,
641                         __set_environment, (gpointer)user_context, &pid,
642                         &error);
643         if (ret != TRUE) {
644                 ERR("Failed to excute backend: %s", error->message);
645                 g_error_free(error);
646                 free_user_context(user_context);
647                 return -1;
648         }
649
650         free_user_context(user_context);
651
652         return pid;
653 }
654
655 static int __change_job_info(struct backend_job *job, uid_t uid,
656                 bool *is_global)
657 {
658         int ret = 0;
659         char *pkgid = NULL;
660         pkgmgrinfo_appinfo_h handle = NULL;
661         if (job->req_type != REQUEST_TYPE_DISABLE_APP &&
662                         job->req_type != REQUEST_TYPE_DISABLE_GLOBAL_APP_FOR_UID &&
663                         job->req_type != REQUEST_TYPE_ENABLE_APP_SPLASH_SCREEN &&
664                         job->req_type != REQUEST_TYPE_DISABLE_APP_SPLASH_SCREEN &&
665                         job->req_type != REQUEST_TYPE_ENABLE_APP &&
666                         job->req_type != REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID)
667                 return PMINFO_R_ERROR;
668
669         ret = pkgmgrinfo_appinfo_get_usr_all_appinfo(job->pkgid, uid, &handle);
670         if (ret != PMINFO_R_OK)
671                 return PMINFO_R_ERROR;
672
673         ret = pkgmgrinfo_appinfo_is_global(handle, is_global);
674         if (ret != PMINFO_R_OK)
675                 goto catch;
676
677         if ((job->req_type == REQUEST_TYPE_DISABLE_GLOBAL_APP_FOR_UID ||
678                         job->req_type ==
679                         REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID) &&
680                         !*is_global) {
681                 ret = PMINFO_R_ERROR;
682                 goto catch;
683         }
684
685         ret = pkgmgrinfo_appinfo_get_pkgid(handle, &pkgid);
686         if (ret != PMINFO_R_OK)
687                 goto catch;
688
689         free(job->appid);
690         job->appid = strdup(job->pkgid);
691         free(job->pkgid);
692         job->pkgid = strdup(pkgid);
693
694 catch:
695         pkgmgrinfo_appinfo_destroy_appinfo(handle);
696
697         return ret;
698 }
699
700 static int __process_install(struct backend_job *job)
701 {
702         char *backend_cmd;
703         char **argv;
704         char args[MAX_PKG_ARGS_LEN];
705         gchar *req_id;
706         gchar *pkgid;
707         int pid;
708
709         backend_cmd = job->backend_path;
710         if (backend_cmd == NULL)
711                 return -1;
712
713         req_id = g_shell_quote(job->req_id);
714         pkgid = g_shell_quote(job->pkgid);
715         if (!req_id || !pkgid)
716                 return -1;
717
718         snprintf(args, sizeof(args), "%s -k %s -i %s -u %d %s", backend_cmd,
719                         req_id, pkgid, (int)job->target_uid, job->args);
720
721         argv = __generate_argv(args);
722
723         pid = __fork_and_exec_with_args(argv, APPFW_UID);
724         g_strfreev(argv);
725         g_free(req_id);
726         g_free(pkgid);
727
728         return pid;
729 }
730
731 static int __process_mount_install(struct backend_job *job)
732 {
733         char *backend_cmd;
734         char **argv;
735         char args[MAX_PKG_ARGS_LEN];
736         gchar *req_id;
737         gchar *pkgid;
738         int pid;
739
740         backend_cmd = job->backend_path;
741         if (backend_cmd == NULL)
742                 return -1;
743
744         req_id = g_shell_quote(job->req_id);
745         pkgid = g_shell_quote(job->pkgid);
746         if (!req_id || !pkgid)
747                 return -1;
748
749         snprintf(args, sizeof(args), "%s -k %s -w %s -u %d %s", backend_cmd,
750                         req_id, pkgid, (int)job->target_uid, job->args);
751
752         argv = __generate_argv(args);
753
754         pid = __fork_and_exec_with_args(argv, APPFW_UID);
755         g_strfreev(argv);
756         g_free(req_id);
757         g_free(pkgid);
758
759         return pid;
760 }
761
762 static int __process_reinstall(struct backend_job *job)
763 {
764         char *backend_cmd;
765         char **argv;
766         char args[MAX_PKG_ARGS_LEN];
767         gchar *req_id;
768         gchar *pkgid;
769         int pid;
770
771         backend_cmd = job->backend_path;
772         if (backend_cmd == NULL)
773                 return -1;
774
775         req_id = g_shell_quote(job->req_id);
776         pkgid = g_shell_quote(job->pkgid);
777         if (!req_id || !pkgid)
778                 return -1;
779
780         snprintf(args, sizeof(args), "%s -k %s -r %s -u %d", backend_cmd,
781                         req_id, pkgid, (int)job->target_uid);
782         argv = __generate_argv(args);
783
784         pid = __fork_and_exec_with_args(argv, APPFW_UID);
785
786         g_strfreev(argv);
787         g_free(req_id);
788         g_free(pkgid);
789
790         return pid;
791 }
792
793 static int __process_uninstall(struct backend_job *job)
794 {
795         char *backend_cmd;
796         char **argv;
797         char args[MAX_PKG_ARGS_LEN];
798         int pid;
799
800         backend_cmd = job->backend_path;
801         if (backend_cmd == NULL)
802                 return -1;
803
804         snprintf(args, sizeof(args), "%s -k %s -d %s -u %d", backend_cmd,
805                         job->req_id, job->pkgid, (int)job->target_uid);
806         argv = __generate_argv(args);
807
808         pid = __fork_and_exec_with_args(argv, APPFW_UID);
809
810         g_strfreev(argv);
811
812         return pid;
813 }
814
815 static int __process_move(struct backend_job *job)
816 {
817         char *backend_cmd;
818         char **argv;
819         char args[MAX_PKG_ARGS_LEN];
820         int pid;
821
822         backend_cmd = job->backend_path;
823         if (backend_cmd == NULL)
824                 return -1;
825
826         snprintf(args, sizeof(args), "%s -k %s -m %s -u %d -t %s", backend_cmd,
827                         job->req_id, job->pkgid, (int)job->target_uid, job->args);
828         argv = __generate_argv(args);
829
830         pid = __fork_and_exec_with_args(argv, APPFW_UID);
831
832         g_strfreev(argv);
833
834         return pid;
835 }
836
837 static int __process_enable_pkg(struct backend_job *job)
838 {
839         char *backend_cmd;
840         char **argv;
841         char args[MAX_PKG_ARGS_LEN];
842         pkgmgrinfo_pkginfo_h pkginfo_h;
843         bool is_readonly;
844         bool is_global;
845         int ret;
846         int pid;
847
848         backend_cmd = job->backend_path;
849         if (backend_cmd == NULL)
850                 return -1;
851
852         ret = pkgmgrinfo_pkginfo_get_usr_disabled_pkginfo(
853                         job->pkgid, job->target_uid, &pkginfo_h);
854         if (ret != PMINFO_R_OK) {
855                 ERR("Failed to get appinfo");
856                 return -1;
857         }
858
859         ret = pkgmgrinfo_pkginfo_is_global(pkginfo_h, &is_global);
860         if (ret != PMINFO_R_OK) {
861                 ERR("Failed to get global value");
862                 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
863                 return -1;
864         }
865
866         if ((is_global && job->target_uid != GLOBAL_USER) ||
867                         (!is_global && job->target_uid == GLOBAL_USER)) {
868                 ERR("Invalid attempt to enable pkg");
869                 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
870                 return -1;
871         }
872
873         ret = pkgmgrinfo_pkginfo_is_readonly(pkginfo_h, &is_readonly);
874         if (ret != PMINFO_R_OK) {
875                 ERR("Failed to get readonly value");
876                 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
877                 return -1;
878         }
879
880         snprintf(args, sizeof(args), "%s -k %s -u %d -A %s %s",
881                         backend_cmd, job->req_id, (int)job->target_uid,
882                         job->pkgid, (is_readonly) ? "--preload" : "");
883         argv = __generate_argv(args);
884         pid = __fork_and_exec_with_args(argv, APPFW_UID);
885
886         g_strfreev(argv);
887         pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
888
889         return pid;
890 }
891
892 static int __process_disable_pkg(struct backend_job *job)
893 {
894         char *backend_cmd;
895         char **argv;
896         char args[MAX_PKG_ARGS_LEN];
897         pkgmgrinfo_pkginfo_h pkginfo_h;
898         bool is_readonly;
899         bool is_global;
900         int ret;
901         int pid;
902
903         backend_cmd = job->backend_path;
904         if (backend_cmd == NULL)
905                 return -1;
906
907         ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(
908                         job->pkgid, job->target_uid, &pkginfo_h);
909         if (ret != PMINFO_R_OK) {
910                 ERR("Failed to get appinfo");
911                 return -1;
912         }
913
914         ret = pkgmgrinfo_pkginfo_is_global(pkginfo_h, &is_global);
915         if (ret != PMINFO_R_OK) {
916                 ERR("Failed to get global value");
917                 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
918                 return -1;
919         }
920
921         if ((is_global && job->target_uid != GLOBAL_USER) ||
922                         (!is_global && job->target_uid == GLOBAL_USER)) {
923                 ERR("Invalid attempt to disable pkg");
924                 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
925                 return -1;
926         }
927
928         ret = pkgmgrinfo_pkginfo_is_readonly(pkginfo_h, &is_readonly);
929         if (ret != PMINFO_R_OK) {
930                 ERR("Failed to get readonly value");
931                 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
932                 return -1;
933         }
934
935         snprintf(args, sizeof(args), "%s -k %s -u %d -D %s %s",
936                         backend_cmd, job->req_id, (int)job->target_uid,
937                         job->pkgid, (is_readonly) ? "--preload" : "");
938         argv = __generate_argv(args);
939
940         pid = __fork_and_exec_with_args(argv, APPFW_UID);
941
942         g_strfreev(argv);
943
944         pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
945         return pid;
946 }
947
948 static int __process_register_pkg_update_info(struct backend_job *job)
949 {
950         int ret;
951
952         if (!job->extra_data) {
953                 _return_value_to_caller(job->req_id,
954                                 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
955                 return -1;
956         }
957
958         ret = pkgmgr_parser_register_pkg_update_info_in_usr_db(
959                         (pkgmgrinfo_updateinfo_h)job->extra_data, job->target_uid);
960         if (ret == PMINFO_R_OK)
961                 _return_value_to_caller(job->req_id,
962                                 g_variant_new("(i)", PKGMGR_R_OK));
963         else
964                 _return_value_to_caller(job->req_id,
965                                 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
966
967         pkgmgrinfo_updateinfo_destroy(job->extra_data);
968         job->extra_data = NULL;
969
970         return ret;
971 }
972
973 static int __process_unregister_pkg_update_info(struct backend_job *job)
974 {
975         int ret = pkgmgr_parser_unregister_pkg_update_info_in_usr_db
976                         (job->pkgid, job->target_uid);
977
978         if (ret == PMINFO_R_OK)
979                 _return_value_to_caller(job->req_id,
980                                 g_variant_new("(i)", PKGMGR_R_OK));
981         else
982                 _return_value_to_caller(job->req_id,
983                                 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
984         return ret;
985 }
986
987 static int __process_unregister_all_pkg_update_info(struct backend_job *job)
988 {
989         int ret = pkgmgr_parser_unregister_all_pkg_update_info_in_usr_db(
990                         job->target_uid);
991
992         if (ret != PMINFO_R_OK) {
993                 _return_value_to_caller(job->req_id,
994                                 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
995                 return ret;
996         }
997
998         if (__is_admin_user(job->caller_uid)) {
999                 ret = pkgmgr_parser_unregister_all_pkg_update_info_in_usr_db(
1000                                 GLOBAL_USER);
1001                 if (ret != PMINFO_R_OK) {
1002                         _return_value_to_caller(job->req_id,
1003                                         g_variant_new("(i)", PKGMGR_R_ESYSTEM));
1004                         return ret;
1005                 }
1006         }
1007         _return_value_to_caller(job->req_id,
1008                         g_variant_new("(i)", PKGMGR_R_OK));
1009
1010         return ret;
1011 }
1012
1013 static int __process_enable_app(struct backend_job *job)
1014 {
1015         int ret = -1;
1016         bool is_global = false;
1017
1018         /* get actual pkgid and replace it to appid which is currently stored
1019          * at pkgid variable
1020          */
1021         ret = __change_job_info(job, job->target_uid, &is_global);
1022         if (ret != PMINFO_R_OK || strlen(job->appid) == 0) {
1023                 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
1024                                 PKGMGR_INSTALLER_START_KEY_STR,
1025                                 PKGMGR_INSTALLER_APP_ENABLE_EVENT_STR,
1026                                 job->req_type);
1027                 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
1028                                 PKGMGR_INSTALLER_END_KEY_STR,
1029                                 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1030                                 job->req_type);
1031                 return ret;
1032         }
1033
1034         _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1035                         PKGMGR_INSTALLER_START_KEY_STR,
1036                         PKGMGR_INSTALLER_APP_ENABLE_EVENT_STR, job->req_type);
1037
1038         ret = pkgmgr_parser_update_app_disable_info_in_usr_db(job->appid,
1039                         job->target_uid, 0);
1040         if (ret != PMINFO_R_OK)
1041                 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1042                                 PKGMGR_INSTALLER_END_KEY_STR,
1043                                 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1044                                 job->req_type);
1045         else
1046                 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1047                                 PKGMGR_INSTALLER_END_KEY_STR,
1048                                 PKGMGR_INSTALLER_OK_EVENT_STR,
1049                                 job->req_type);
1050
1051         return ret;
1052 }
1053
1054 static int __process_disable_app(struct backend_job *job)
1055 {
1056         int ret = -1;
1057         bool is_global = false;
1058
1059         /* get actual pkgid and replace it to appid which is currently stored
1060          * at pkgid variable
1061          */
1062         ret = __change_job_info(job, job->target_uid, &is_global);
1063         if (ret != PMINFO_R_OK || strlen(job->appid) == 0) {
1064                 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
1065                                 PKGMGR_INSTALLER_START_KEY_STR,
1066                                 PKGMGR_INSTALLER_APP_DISABLE_EVENT_STR,
1067                                 job->req_type);
1068                 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
1069                                 PKGMGR_INSTALLER_END_KEY_STR,
1070                                 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1071                                 job->req_type);
1072                 return ret;
1073         }
1074
1075         _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1076                         PKGMGR_INSTALLER_START_KEY_STR,
1077                         PKGMGR_INSTALLER_APP_DISABLE_EVENT_STR, job->req_type);
1078
1079         ret = __kill_app(job->appid, job->target_uid);
1080         if (ret != 0) {
1081                 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1082                                 PKGMGR_INSTALLER_END_KEY_STR,
1083                                 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1084                                 job->req_type);
1085         }
1086
1087         ret = pkgmgr_parser_update_app_disable_info_in_usr_db(job->appid,
1088                         job->target_uid, 1);
1089         if (ret != PMINFO_R_OK)
1090                 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1091                                 PKGMGR_INSTALLER_END_KEY_STR,
1092                                 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1093                                 job->req_type);
1094         else
1095                 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1096                                 PKGMGR_INSTALLER_END_KEY_STR,
1097                                 PKGMGR_INSTALLER_OK_EVENT_STR,
1098                                 job->req_type);
1099
1100         return ret;
1101 }
1102
1103 static int __process_enable_global_app_for_uid(struct backend_job *job)
1104 {
1105         int ret = -1;
1106         bool is_global = true;
1107
1108         /* get actual pkgid and replace it to appid which is currently stored
1109          * at pkgid variable
1110          */
1111         ret = __change_job_info(job, job->target_uid, &is_global);
1112         if (ret != PMINFO_R_OK || strlen(job->appid) == 0) {
1113                 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
1114                                 PKGMGR_INSTALLER_START_KEY_STR,
1115                                 PKGMGR_INSTALLER_APP_ENABLE_EVENT_STR,
1116                                 job->req_type);
1117                 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
1118                                 PKGMGR_INSTALLER_END_KEY_STR,
1119                                 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1120                                 job->req_type);
1121                 return ret;
1122         }
1123
1124         _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1125                         PKGMGR_INSTALLER_START_KEY_STR,
1126                         PKGMGR_INSTALLER_APP_ENABLE_EVENT_STR,
1127                         job->req_type);
1128
1129         ret = pkgmgr_parser_update_global_app_disable_for_uid_info_in_db(
1130                         job->appid, job->target_uid, 0);
1131         if (ret != PMINFO_R_OK)
1132                 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1133                                 PKGMGR_INSTALLER_END_KEY_STR,
1134                                 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1135                                 job->req_type);
1136         else
1137                 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1138                                 PKGMGR_INSTALLER_END_KEY_STR,
1139                                 PKGMGR_INSTALLER_OK_EVENT_STR,
1140                                 job->req_type);
1141
1142         return ret;
1143 }
1144
1145 static int __process_disable_global_app_for_uid(struct backend_job *job)
1146 {
1147         int ret = -1;
1148         bool is_global = true;
1149
1150         /* get actual pkgid and replace it to appid which is currently stored
1151          * at pkgid variable
1152          */
1153         ret = __change_job_info(job, GLOBAL_USER, &is_global);
1154         if (ret != PMINFO_R_OK || strlen(job->appid) == 0) {
1155                 _send_app_signal(job->target_uid, job->req_id,
1156                                 job->pkgid, job->pkgid,
1157                                 PKGMGR_INSTALLER_START_KEY_STR,
1158                                 PKGMGR_INSTALLER_APP_DISABLE_EVENT_STR,
1159                                 job->req_type);
1160                 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
1161                                 PKGMGR_INSTALLER_END_KEY_STR,
1162                                 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1163                                 job->req_type);
1164                 return ret;
1165         }
1166
1167         _send_app_signal(job->target_uid, job->req_id,
1168                         job->pkgid, job->appid,
1169                         PKGMGR_INSTALLER_START_KEY_STR,
1170                         PKGMGR_INSTALLER_APP_DISABLE_EVENT_STR,
1171                         job->req_type);
1172
1173         ret = __kill_app(job->appid, job->target_uid);
1174         ret = pkgmgr_parser_update_global_app_disable_for_uid_info_in_db(
1175                         job->appid, job->target_uid, 1);
1176
1177         if (ret != PMINFO_R_OK)
1178                 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1179                                 PKGMGR_INSTALLER_END_KEY_STR,
1180                                 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1181                                 job->req_type);
1182         else
1183                 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1184                                 PKGMGR_INSTALLER_END_KEY_STR,
1185                                 PKGMGR_INSTALLER_OK_EVENT_STR,
1186                                 job->req_type);
1187
1188         return ret;
1189 }
1190
1191 static int __process_getsize(struct backend_job *job)
1192 {
1193         static const char backend_cmd[] = "/usr/bin/pkg_getsize";
1194         char **argv;
1195         char args[MAX_PKG_ARGS_LEN];
1196         int pid;
1197
1198         snprintf(args, sizeof(args), "%s %s %s %d -k %s -u %d",
1199                         backend_cmd, job->pkgid, job->args, job->caller_uid,
1200                         job->req_id, job->target_uid);
1201         argv = __generate_argv(args);
1202         pid = __fork_and_exec_with_args(argv, APPFW_UID);
1203
1204         g_strfreev(argv);
1205
1206         return pid;
1207 }
1208
1209 static int __process_getsize_sync(struct backend_job *job)
1210 {
1211         static const char backend_cmd[] = "/usr/bin/pkg_getsize";
1212         char **argv;
1213         char args[MAX_PKG_ARGS_LEN];
1214         char fifo_path[PATH_MAX];
1215         struct getsize_sync_extra_info *extra_getsize_info;
1216         int pid;
1217
1218         snprintf(fifo_path, sizeof(fifo_path), "/tmp/pkgmgr/%s",
1219                         job->req_id);
1220
1221         extra_getsize_info = calloc(1, sizeof(struct getsize_sync_extra_info));
1222         if (!extra_getsize_info) {
1223                 ERR("memory alloc failed");
1224                 goto error;
1225         }
1226
1227         extra_getsize_info->getsize_fifo = strdup(fifo_path);
1228         if (!extra_getsize_info->getsize_fifo) {
1229                 ERR("out of memory");
1230                 goto error;
1231         }
1232
1233         if (mkfifo(extra_getsize_info->getsize_fifo, 0600) < 0) {
1234                 ERR("failed to mkfifo");
1235                 goto error;
1236         }
1237         job->extra_data = extra_getsize_info;
1238
1239         snprintf(args, sizeof(args), "%s %s %s %d -k %s -u %d --sync",
1240                         backend_cmd, job->pkgid, job->args, job->caller_uid,
1241                         job->req_id, job->target_uid);
1242         argv = __generate_argv(args);
1243         pid = __fork_and_exec_with_args(argv, APPFW_UID);
1244
1245         g_strfreev(argv);
1246
1247         if (pid < 0) {
1248                 ERR("failed to execute backend");
1249                 goto error;
1250         }
1251         if (__setup_size_info_io(job) < 0) {
1252                 ERR("failed to setup io handler");
1253                 goto error;
1254         }
1255
1256         return pid;
1257
1258 error:
1259         _return_value_to_caller(job->req_id,
1260                 g_variant_new("(ix)", PKGMGR_R_ERROR, -1));
1261         return -1;
1262 }
1263
1264 static int __process_cleardata(struct backend_job *job)
1265 {
1266         static const char *backend_cmd = "/usr/bin/pkg_cleardata";
1267         char **argv;
1268         char args[MAX_PKG_ARGS_LEN];
1269         int pid;
1270
1271         if ((int)job->target_uid < REGULAR_USER)
1272                 return -1;
1273
1274         snprintf(args, sizeof(args), "%s -d -n %s -u %d",
1275                         backend_cmd, job->pkgid, job->target_uid);
1276         argv = __generate_argv(args);
1277         pid = __fork_and_exec_with_args(argv, APPFW_UID);
1278
1279         g_strfreev(argv);
1280         return pid;
1281 }
1282
1283 static int __process_clearcache(struct backend_job *job)
1284 {
1285         static const char *backend_cmd = "/usr/bin/pkg_cleardata";
1286         char **argv;
1287         char args[MAX_PKG_ARGS_LEN];
1288         int pid;
1289
1290         if ((int)job->target_uid < REGULAR_USER)
1291                 return -1;
1292
1293         snprintf(args, sizeof(args), "%s -c -n %s -u %d",
1294                         backend_cmd, job->pkgid, job->target_uid);
1295         argv = __generate_argv(args);
1296         pid = __fork_and_exec_with_args(argv, APPFW_UID);
1297
1298         g_strfreev(argv);
1299         return pid;
1300 }
1301
1302 static int __process_kill(struct backend_job *job)
1303 {
1304         int ret;
1305         pkgmgrinfo_pkginfo_h handle;
1306         pkgcmd_data *pdata;
1307
1308         ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(job->pkgid, job->target_uid,
1309                         &handle);
1310         if (ret < 0) {
1311                 ERR("Failed to get handle");
1312                 _return_value_to_caller(job->req_id,
1313                                 g_variant_new("(ii)", PKGMGR_R_ERROR, 0));
1314                 return -1;
1315         }
1316
1317         pdata = calloc(1, sizeof(pkgcmd_data));
1318         if (pdata == NULL) {
1319                 ERR("memory alloc failed");
1320                 _return_value_to_caller(job->req_id,
1321                                 g_variant_new("(ii)", PKGMGR_R_ENOMEM, 0));
1322                 return -1;
1323         }
1324         pdata->cmd = strdup("kill");
1325         if (pdata->cmd == NULL) {
1326                 ERR("out of memory");
1327                 _return_value_to_caller(job->req_id,
1328                                 g_variant_new("(ii)", PKGMGR_R_ENOMEM, 0));
1329                 free(pdata);
1330                 return -1;
1331         }
1332         pdata->uid = job->target_uid;
1333         ret = pkgmgrinfo_appinfo_get_usr_list(handle, PMINFO_ALL_APP,
1334                         __pkgcmd_app_cb, pdata, job->target_uid);
1335
1336         _return_value_to_caller(job->req_id,
1337                         g_variant_new("(ii)", PKGMGR_R_OK, pdata->pid));
1338
1339         free(pdata->cmd);
1340         free(pdata);
1341         pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
1342         if (ret < 0) {
1343                 ERR("pkgmgrinfo_appinfo_get_list() failed");
1344                 return -1;
1345         }
1346
1347         return 0;
1348 }
1349
1350 static int __process_check(struct backend_job *job)
1351 {
1352         int ret;
1353         pkgmgrinfo_pkginfo_h handle;
1354         pkgcmd_data *pdata;
1355
1356         ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(job->pkgid, job->target_uid,
1357                         &handle);
1358         if (ret < 0) {
1359                 ERR("Failed to get handle");
1360                 _return_value_to_caller(job->req_id,
1361                                 g_variant_new("(ii)", PKGMGR_R_ERROR, 0));
1362                 return -1;
1363         }
1364
1365         pdata = calloc(1, sizeof(pkgcmd_data));
1366         if (pdata == NULL) {
1367                 ERR("memory alloc failed");
1368                 _return_value_to_caller(job->req_id,
1369                                 g_variant_new("(ii)", PKGMGR_R_ENOMEM, 0));
1370                 return -1;
1371         }
1372         pdata->cmd = strdup("check");
1373         if (pdata->cmd == NULL) {
1374                 ERR("out of memory");
1375                 _return_value_to_caller(job->req_id,
1376                                 g_variant_new("(ii)", PKGMGR_R_ENOMEM, 0));
1377                 free(pdata);
1378                 return -1;
1379         }
1380         pdata->uid = job->target_uid;
1381         ret = pkgmgrinfo_appinfo_get_usr_list(handle, PMINFO_ALL_APP,
1382                         __pkgcmd_app_cb, pdata, job->target_uid);
1383
1384         _return_value_to_caller(job->req_id,
1385                         g_variant_new("(ii)", PKGMGR_R_OK, pdata->pid));
1386
1387         free(pdata->cmd);
1388         free(pdata);
1389         pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
1390         if (ret < 0) {
1391                 ERR("pkgmgrinfo_appinfo_get_list() failed");
1392                 return -1;
1393         }
1394
1395         return 0;
1396 }
1397
1398 static int __process_generate_license_request(struct backend_job *job)
1399 {
1400         int ret;
1401         char *resp_data;
1402         char req_data[MAX_PKG_ARGS_LEN];
1403         unsigned int req_data_len;
1404         char license_url[MAX_PKG_ARGS_LEN];
1405         unsigned int license_url_len;
1406
1407         resp_data = job->args;
1408         req_data_len = sizeof(req_data);
1409         license_url_len = sizeof(license_url);
1410
1411         ret = drm_tizen_generate_license_request(resp_data, strlen(resp_data),
1412                         req_data, &req_data_len, license_url, &license_url_len);
1413         if (ret != TADC_SUCCESS) {
1414                 ERR("drm_tizen_generate_license_request failed: %d", ret);
1415                 _return_value_to_caller(job->req_id, g_variant_new("(iss)",
1416                                         PKGMGR_R_ESYSTEM, "", ""));
1417                 is_drm_busy = false;
1418                 return -1;
1419         }
1420
1421         _return_value_to_caller(job->req_id,
1422                         g_variant_new("(iss)", PKGMGR_R_OK, req_data,
1423                                 license_url));
1424         is_drm_busy = true;
1425         return 0;
1426 }
1427
1428 static int __process_register_license(struct backend_job *job)
1429 {
1430         int ret;
1431         char *resp_data;
1432
1433         resp_data = job->args;
1434
1435         ret = drm_tizen_register_license(resp_data, strlen(resp_data));
1436         if (ret != TADC_SUCCESS) {
1437                 ERR("drm_tizen_register_license failed: %d", ret);
1438                 _return_value_to_caller(job->req_id,
1439                                 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
1440                 is_drm_busy = false;
1441                 return -1;
1442         }
1443
1444         _return_value_to_caller(job->req_id,
1445                         g_variant_new("(i)", PKGMGR_R_OK));
1446
1447         return 0;
1448 }
1449
1450 static int __process_decrypt_package(struct backend_job *job)
1451 {
1452         int ret;
1453         char *drm_file_path;
1454         char *decrypted_file_path;
1455
1456         drm_file_path = job->pkgid;
1457         decrypted_file_path = job->args;
1458
1459         /* TODO: check ownership of decrypted file */
1460         ret = drm_tizen_decrypt_package(drm_file_path, strlen(drm_file_path),
1461                         decrypted_file_path, strlen(decrypted_file_path));
1462         if (ret != TADC_SUCCESS) {
1463                 ERR("drm_tizen_register_license failed: %d", ret);
1464                 _return_value_to_caller(job->req_id,
1465                                 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
1466                 is_drm_busy = false;
1467                 return -1;
1468         }
1469
1470         _return_value_to_caller(job->req_id,
1471                         g_variant_new("(i)", PKGMGR_R_OK));
1472         is_drm_busy = false;
1473
1474         return 0;
1475 }
1476
1477 static int __process_update_app_splash_screen(struct backend_job *job, int flag)
1478 {
1479         int ret;
1480         bool is_global = false;
1481         const char *val;
1482
1483         ret = __change_job_info(job, job->target_uid, &is_global);
1484         if (ret != PMINFO_R_OK || strlen(job->appid) == 0)
1485                 return -1;
1486
1487         val = flag ? PKGMGR_INSTALLER_APP_ENABLE_SPLASH_SCREEN_EVENT_STR :
1488                 PKGMGR_INSTALLER_APP_DISABLE_SPLASH_SCREEN_EVENT_STR;
1489         _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1490                         PKGMGR_INSTALLER_START_KEY_STR, val, job->req_type);
1491
1492         if (is_global)
1493                 ret = pkgmgr_parser_update_global_app_splash_screen_display_info_in_usr_db(job->appid, job->target_uid, flag);
1494         else
1495                 ret = pkgmgr_parser_update_app_splash_screen_display_info_in_usr_db(
1496                         job->appid, job->target_uid, flag);
1497         if (ret != PMINFO_R_OK)
1498                 _send_app_signal(job->target_uid, job->req_id, job->pkgid,
1499                                 job->appid, PKGMGR_INSTALLER_END_KEY_STR,
1500                                 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1501                                 job->req_type);
1502         else
1503                 _send_app_signal(job->target_uid, job->req_id, job->pkgid,
1504                                 job->appid, PKGMGR_INSTALLER_END_KEY_STR,
1505                                 PKGMGR_INSTALLER_OK_EVENT_STR,
1506                                 job->req_type);
1507
1508         return ret;
1509 }
1510
1511 static int __process_set_restriction_mode(struct backend_job *job)
1512 {
1513         int ret;
1514         int mode;
1515
1516         mode = atoi(job->args);
1517         ret = _set_restriction_mode(job->target_uid, job->pkgid, mode);
1518
1519         _return_value_to_caller(job->req_id,
1520                         g_variant_new("(i)", ret));
1521
1522         return ret;
1523 }
1524
1525 static int __process_unset_restriction_mode(struct backend_job *job)
1526 {
1527         int ret;
1528         int mode;
1529
1530         mode = atoi(job->args);
1531         ret = _unset_restriction_mode(job->target_uid, job->pkgid, mode);
1532
1533         _return_value_to_caller(job->req_id,
1534                         g_variant_new("(i)", ret));
1535
1536         return ret;
1537 }
1538
1539 static int __process_get_restriction_mode(struct backend_job *job)
1540 {
1541         int ret;
1542         int mode = -1;
1543
1544         ret = _get_restriction_mode(job->target_uid, job->pkgid, &mode);
1545
1546         _return_value_to_caller(job->req_id,
1547                         g_variant_new("(ii)", mode, ret));
1548
1549         return ret;
1550 }
1551
1552 static int __process_set_app_label(struct backend_job *job)
1553 {
1554         int ret;
1555
1556         ret = pkgmgr_parser_update_app_label_info_in_usr_db(job->pkgid,
1557                         job->target_uid, job->args);
1558         _return_value_to_caller(job->req_id, g_variant_new("(i)", ret));
1559
1560         return ret;
1561 }
1562
1563 static int __process_migrate_external_image(struct backend_job *job)
1564 {
1565         char *backend_cmd;
1566         char **argv;
1567         char args[MAX_PKG_ARGS_LEN];
1568         int pid;
1569
1570         backend_cmd = job->backend_path;
1571         if (backend_cmd == NULL)
1572                 return -1;
1573
1574         snprintf(args, sizeof(args), "%s -k %s --migrate-extimg %s -u %d %s",
1575                         backend_cmd, job->req_id, job->pkgid,
1576                         (int)job->target_uid, job->args);
1577
1578         argv = __generate_argv(args);
1579
1580         pid = __fork_and_exec_with_args(argv, APPFW_UID);
1581         g_strfreev(argv);
1582
1583         return pid;
1584 }
1585
1586 static int __post_process(int ret, int x, struct backend_job *job)
1587 {
1588         if (ret < 0) {
1589                 __set_backend_free(x);
1590                 _free_backend_job(job);
1591         } else {
1592                 g_hash_table_insert(backend_info_table, (gpointer)ret,
1593                                 (gpointer)job);
1594         }
1595         return 0;
1596 }
1597
1598 gboolean queue_job(void *data)
1599 {
1600         struct backend_job *job = NULL;
1601         int x;
1602         int ret;
1603
1604         /* Pop a job from queue */
1605         for (x = 0; x < num_of_backends; x++) {
1606                 if (__is_backend_busy(x))
1607                         continue;
1608
1609                 job = _pop_queue(x);
1610                 if (job)
1611                         break;
1612         }
1613
1614         /* all backend messages queue are empty or busy */
1615         if (x == num_of_backends || job == NULL) {
1616                 DBG("no job available");
1617                 return FALSE;
1618         }
1619
1620         /* set current backend job */
1621         DBG("handle request type [%d]", job->req_type);
1622
1623 #ifdef TIZEN_FEATURE_CSR
1624         if (job->req_type == REQUEST_TYPE_INSTALL ||
1625                         job->req_type == REQUEST_TYPE_MOUNT_INSTALL ||
1626                         job->req_type == REQUEST_TYPE_REINSTALL) {
1627                 ret = __check_csr(job->pkgid);
1628                 if (ret != 0) {
1629                         ret = -1;
1630                         _send_fail_signal(job);
1631                         _free_backend_job(job);
1632                         return TRUE;
1633                 }
1634         }
1635 #endif
1636
1637         switch (job->req_type) {
1638         case REQUEST_TYPE_INSTALL:
1639                 __set_backend_busy(x);
1640                 __set_power_lock();
1641                 ret = __process_install(job);
1642                 __post_process(ret, x, job);
1643                 break;
1644         case REQUEST_TYPE_MOUNT_INSTALL:
1645                 __set_backend_busy(x);
1646                 __set_power_lock();
1647                 ret = __process_mount_install(job);
1648                 __post_process(ret, x, job);
1649                 break;
1650         case REQUEST_TYPE_REINSTALL:
1651                 __set_backend_busy(x);
1652                 __set_power_lock();
1653                 ret = __process_reinstall(job);
1654                 __post_process(ret, x, job);
1655                 break;
1656         case REQUEST_TYPE_UNINSTALL:
1657                 __set_backend_busy(x);
1658                 __set_power_lock();
1659                 ret = __process_uninstall(job);
1660                 __post_process(ret, x, job);
1661                 break;
1662         case REQUEST_TYPE_MOVE:
1663                 __set_backend_busy(x);
1664                 __set_power_lock();
1665                 ret = __process_move(job);
1666                 __post_process(ret, x, job);
1667                 break;
1668         case REQUEST_TYPE_ENABLE_PKG:
1669                 __set_backend_busy(x);
1670                 __set_power_lock();
1671                 ret = __process_enable_pkg(job);
1672                 if (ret < 0)
1673                         _send_fail_signal(job);
1674                 __post_process(ret, x, job);
1675                 break;
1676         case REQUEST_TYPE_DISABLE_PKG:
1677                 __set_backend_busy(x);
1678                 __set_power_lock();
1679                 ret = __process_disable_pkg(job);
1680                 if (ret < 0)
1681                         _send_fail_signal(job);
1682                 __post_process(ret, x, job);
1683                 break;
1684         case REQUEST_TYPE_REGISTER_PKG_UPDATE_INFO:
1685                 ret = __process_register_pkg_update_info(job);
1686                 __free_extra_info(job);
1687                 _free_backend_job(job);
1688                 break;
1689         case REQUEST_TYPE_UNREGISTER_PKG_UPDATE_INFO:
1690                 ret = __process_unregister_pkg_update_info(job);
1691                 _free_backend_job(job);
1692                 break;
1693         case REQUEST_TYPE_UNREGISTER_ALL_PKG_UPDATE_INFO:
1694                 ret = __process_unregister_all_pkg_update_info(job);
1695                 _free_backend_job(job);
1696                 break;
1697         case REQUEST_TYPE_ENABLE_APP:
1698                 ret = __process_enable_app(job);
1699                 _free_backend_job(job);
1700                 break;
1701         case REQUEST_TYPE_DISABLE_APP:
1702                 ret = __process_disable_app(job);
1703                 _free_backend_job(job);
1704                 break;
1705         case REQUEST_TYPE_GETSIZE:
1706                 __set_backend_busy(x);
1707                 ret = __process_getsize(job);
1708                 __post_process(ret, x, job);
1709                 break;
1710         case REQUEST_TYPE_GETSIZE_SYNC:
1711                 __set_backend_busy(x);
1712                 ret = __process_getsize_sync(job);
1713                 if (ret < 0)
1714                         __free_extra_info(job);
1715                 __post_process(ret, x, job);
1716                 break;
1717         case REQUEST_TYPE_CLEARDATA:
1718                 __set_backend_busy(x);
1719                 __set_power_lock();
1720                 ret = __process_cleardata(job);
1721                 __post_process(ret, x, job);
1722                 break;
1723         case REQUEST_TYPE_CLEARCACHE:
1724                 __set_backend_busy(x);
1725                 __set_power_lock();
1726                 ret = __process_clearcache(job);
1727                 __post_process(ret, x, job);
1728                 break;
1729         case REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID:
1730                 ret = __process_enable_global_app_for_uid(job);
1731                 _free_backend_job(job);
1732                 break;
1733         case REQUEST_TYPE_DISABLE_GLOBAL_APP_FOR_UID:
1734                 ret = __process_disable_global_app_for_uid(job);
1735                 _free_backend_job(job);
1736                 break;
1737         case REQUEST_TYPE_KILL:
1738                 ret = __process_kill(job);
1739                 _free_backend_job(job);
1740                 break;
1741         case REQUEST_TYPE_CHECK:
1742                 ret = __process_check(job);
1743                 _free_backend_job(job);
1744                 break;
1745         case REQUEST_TYPE_GENERATE_LICENSE_REQUEST:
1746                 ret = __process_generate_license_request(job);
1747                 _free_backend_job(job);
1748                 break;
1749         case REQUEST_TYPE_REGISTER_LICENSE:
1750                 ret = __process_register_license(job);
1751                 _free_backend_job(job);
1752                 break;
1753         case REQUEST_TYPE_DECRYPT_PACKAGE:
1754                 ret = __process_decrypt_package(job);
1755                 _free_backend_job(job);
1756                 break;
1757         case REQUEST_TYPE_ENABLE_APP_SPLASH_SCREEN:
1758                 ret = __process_update_app_splash_screen(job, 1);
1759                 _free_backend_job(job);
1760                 break;
1761         case REQUEST_TYPE_DISABLE_APP_SPLASH_SCREEN:
1762                 ret = __process_update_app_splash_screen(job, 0);
1763                 _free_backend_job(job);
1764                 break;
1765         case REQUEST_TYPE_SET_RESTRICTION_MODE:
1766                 ret = __process_set_restriction_mode(job);
1767                 _free_backend_job(job);
1768                 break;
1769         case REQUEST_TYPE_UNSET_RESTRICTION_MODE:
1770                 ret = __process_unset_restriction_mode(job);
1771                 _free_backend_job(job);
1772                 break;
1773         case REQUEST_TYPE_GET_RESTRICTION_MODE:
1774                 ret = __process_get_restriction_mode(job);
1775                 _free_backend_job(job);
1776                 break;
1777         case REQUEST_TYPE_SET_APP_LABEL:
1778                 ret = __process_set_app_label(job);
1779                 _free_backend_job(job);
1780                 break;
1781         case REQUEST_TYPE_MIGRATE_EXTERNAL_IMAGE:
1782                 __set_backend_busy(x);
1783                 __set_power_lock();
1784                 ret = __process_migrate_external_image(job);
1785                 __post_process(ret, x, job);
1786                 break;
1787         default:
1788                 ret = -1;
1789                 break;
1790         }
1791
1792         return TRUE;
1793 }
1794
1795 int main(int argc, char *argv[])
1796 {
1797         int r;
1798
1799         DBG("server start");
1800
1801         if (__register_signal_handler()) {
1802                 ERR("failed to register signal handler");
1803                 return -1;
1804         }
1805
1806         r = _init_backend_queue();
1807         if (r) {
1808                 ERR("Queue Initialization Failed");
1809                 return -1;
1810         }
1811
1812         r = __init_backend_info();
1813         if (r) {
1814                 ERR("backend info init failed");
1815                 return -1;
1816         }
1817
1818         r = _init_request_handler();
1819         if (r) {
1820                 ERR("dbus init failed");
1821                 return -1;
1822         }
1823
1824 #if !GLIB_CHECK_VERSION(2, 35, 0)
1825         g_type_init();
1826 #endif
1827         mainloop = g_main_loop_new(NULL, FALSE);
1828         if (!mainloop) {
1829                 ERR("g_main_loop_new failed");
1830                 return -1;
1831         }
1832
1833         DBG("Main loop is created.");
1834
1835         g_main_loop_run(mainloop);
1836
1837         DBG("Quit main loop.");
1838         _fini_request_handler();
1839         __fini_backend_info();
1840         _fini_backend_queue();
1841
1842         g_source_remove(swid);
1843         g_io_channel_unref(sio);
1844
1845         DBG("package manager server terminated.");
1846
1847         return 0;
1848 }