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