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