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