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