Fix queue_job
[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_GLOBAL_APP_ENABLE_FOR_UID,
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_GLOBAL_APP_ENABLE_FOR_UID,
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_GLOBAL_APP_DISABLE_FOR_UID,
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_GLOBAL_APP_DISABLE_FOR_UID,
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 %s", backend_cmd, job->pkgid);
1168         argv = __generate_argv(args);
1169         pid = __fork_and_exec_with_args(argv, job->target_uid);
1170
1171         g_strfreev(argv);
1172         return pid;
1173 }
1174
1175 static int __process_clearcache(struct backend_job *job)
1176 {
1177         static const char *backend_cmd = "/usr/bin/pkg_cleardata";
1178         char **argv;
1179         char args[MAX_PKG_ARGS_LEN];
1180         int pid;
1181
1182         if ((int)job->target_uid < REGULAR_USER)
1183                 return -1;
1184
1185         snprintf(args, sizeof(args), "%s -c %s", backend_cmd, job->pkgid);
1186         argv = __generate_argv(args);
1187         pid = __fork_and_exec_with_args(argv, job->target_uid);
1188
1189         g_strfreev(argv);
1190         return pid;
1191 }
1192
1193 static int __process_kill(struct backend_job *job)
1194 {
1195         int ret;
1196         pkgmgrinfo_pkginfo_h handle;
1197         pkgcmd_data *pdata;
1198
1199         ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(job->pkgid, job->target_uid,
1200                         &handle);
1201         if (ret < 0) {
1202                 ERR("Failed to get handle");
1203                 _return_value_to_caller(job->req_id,
1204                                 g_variant_new("(ii)", PKGMGR_R_ERROR, 0));
1205                 return -1;
1206         }
1207
1208         pdata = calloc(1, sizeof(pkgcmd_data));
1209         if (pdata == NULL) {
1210                 ERR("memory alloc failed");
1211                 _return_value_to_caller(job->req_id,
1212                                 g_variant_new("(ii)", PKGMGR_R_ENOMEM, 0));
1213                 return -1;
1214         }
1215         pdata->cmd = strdup("kill");
1216         if (pdata->cmd == NULL) {
1217                 ERR("out of memory");
1218                 _return_value_to_caller(job->req_id,
1219                                 g_variant_new("(ii)", PKGMGR_R_ENOMEM, 0));
1220                 free(pdata);
1221                 return -1;
1222         }
1223         pdata->uid = job->target_uid;
1224         ret = pkgmgrinfo_appinfo_get_usr_list(handle, PMINFO_ALL_APP,
1225                         __pkgcmd_app_cb, pdata, job->target_uid);
1226
1227         _return_value_to_caller(job->req_id,
1228                         g_variant_new("(ii)", PKGMGR_R_OK, pdata->pid));
1229
1230         free(pdata->cmd);
1231         free(pdata);
1232         pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
1233         if (ret < 0) {
1234                 ERR("pkgmgrinfo_appinfo_get_list() failed");
1235                 return -1;
1236         }
1237
1238         return 0;
1239 }
1240
1241 static int __process_check(struct backend_job *job)
1242 {
1243         int ret;
1244         pkgmgrinfo_pkginfo_h handle;
1245         pkgcmd_data *pdata;
1246
1247         ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(job->pkgid, job->target_uid,
1248                         &handle);
1249         if (ret < 0) {
1250                 ERR("Failed to get handle");
1251                 _return_value_to_caller(job->req_id,
1252                                 g_variant_new("(ii)", PKGMGR_R_ERROR, 0));
1253                 return -1;
1254         }
1255
1256         pdata = calloc(1, sizeof(pkgcmd_data));
1257         if (pdata == NULL) {
1258                 ERR("memory alloc failed");
1259                 _return_value_to_caller(job->req_id,
1260                                 g_variant_new("(ii)", PKGMGR_R_ENOMEM, 0));
1261                 return -1;
1262         }
1263         pdata->cmd = strdup("check");
1264         if (pdata->cmd == NULL) {
1265                 ERR("out of memory");
1266                 _return_value_to_caller(job->req_id,
1267                                 g_variant_new("(ii)", PKGMGR_R_ENOMEM, 0));
1268                 free(pdata);
1269                 return -1;
1270         }
1271         pdata->uid = job->target_uid;
1272         ret = pkgmgrinfo_appinfo_get_usr_list(handle, PMINFO_ALL_APP,
1273                         __pkgcmd_app_cb, pdata, job->target_uid);
1274
1275         _return_value_to_caller(job->req_id,
1276                         g_variant_new("(ii)", PKGMGR_R_OK, pdata->pid));
1277
1278         free(pdata->cmd);
1279         free(pdata);
1280         pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
1281         if (ret < 0) {
1282                 ERR("pkgmgrinfo_appinfo_get_list() failed");
1283                 return -1;
1284         }
1285
1286         return 0;
1287 }
1288
1289 static int __process_generate_license_request(struct backend_job *job)
1290 {
1291         int ret;
1292         char *resp_data;
1293         char req_data[MAX_PKG_ARGS_LEN];
1294         unsigned int req_data_len;
1295         char license_url[MAX_PKG_ARGS_LEN];
1296         unsigned int license_url_len;
1297
1298         resp_data = job->args;
1299         req_data_len = sizeof(req_data);
1300         license_url_len = sizeof(license_url);
1301
1302         ret = drm_tizen_generate_license_request(resp_data, strlen(resp_data),
1303                         req_data, &req_data_len, license_url, &license_url_len);
1304         if (ret != TADC_SUCCESS) {
1305                 ERR("drm_tizen_generate_license_request failed: %d", ret);
1306                 _return_value_to_caller(job->req_id, g_variant_new("(iss)",
1307                                         PKGMGR_R_ESYSTEM, "", ""));
1308                 return -1;
1309         }
1310
1311         _return_value_to_caller(job->req_id,
1312                         g_variant_new("(iss)", PKGMGR_R_OK, req_data,
1313                                 license_url));
1314
1315         return 0;
1316 }
1317
1318 static int __process_register_license(struct backend_job *job)
1319 {
1320         int ret;
1321         char *resp_data;
1322
1323         resp_data = job->args;
1324
1325         ret = drm_tizen_register_license(resp_data, strlen(resp_data));
1326         if (ret != TADC_SUCCESS) {
1327                 ERR("drm_tizen_register_license failed: %d", ret);
1328                 _return_value_to_caller(job->req_id,
1329                                 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
1330                 return -1;
1331         }
1332
1333         _return_value_to_caller(job->req_id,
1334                         g_variant_new("(i)", PKGMGR_R_OK));
1335
1336         return 0;
1337 }
1338
1339 static int __process_decrypt_package(struct backend_job *job)
1340 {
1341         int ret;
1342         char *drm_file_path;
1343         char *decrypted_file_path;
1344
1345         drm_file_path = job->pkgid;
1346         decrypted_file_path = job->args;
1347
1348         /* TODO: check ownership of decrypted file */
1349         ret = drm_tizen_decrypt_package(drm_file_path, strlen(drm_file_path),
1350                         decrypted_file_path, strlen(decrypted_file_path));
1351         if (ret != TADC_SUCCESS) {
1352                 ERR("drm_tizen_register_license failed: %d", ret);
1353                 _return_value_to_caller(job->req_id,
1354                                 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
1355                 return -1;
1356         }
1357
1358         _return_value_to_caller(job->req_id,
1359                         g_variant_new("(i)", PKGMGR_R_OK));
1360
1361         return 0;
1362 }
1363
1364 static int __process_update_app_splash_screen(struct backend_job *job, int flag)
1365 {
1366         int ret;
1367         bool is_global = false;
1368         const char *val;
1369
1370         ret = __change_job_info(job, job->target_uid, &is_global);
1371         if (ret != PMINFO_R_OK || strlen(job->appid) == 0)
1372                 return -1;
1373
1374         val = flag ? PKGMGR_INSTALLER_APP_ENABLE_SPLASH_SCREEN_EVENT_STR :
1375                 PKGMGR_INSTALLER_APP_DISABLE_SPLASH_SCREEN_EVENT_STR;
1376         _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1377                         PKGMGR_INSTALLER_START_KEY_STR, val, job->req_type);
1378
1379         if (is_global)
1380                 ret = pkgmgr_parser_update_global_app_splash_screen_display_info_in_usr_db(job->appid, job->target_uid, flag);
1381         else
1382                 ret = pkgmgr_parser_update_app_splash_screen_display_info_in_usr_db(
1383                         job->appid, job->target_uid, flag);
1384         if (ret != PMINFO_R_OK)
1385                 _send_app_signal(job->target_uid, job->req_id, job->pkgid,
1386                                 job->appid, PKGMGR_INSTALLER_END_KEY_STR,
1387                                 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1388                                 job->req_type);
1389         else
1390                 _send_app_signal(job->target_uid, job->req_id, job->pkgid,
1391                                 job->appid, PKGMGR_INSTALLER_END_KEY_STR,
1392                                 PKGMGR_INSTALLER_OK_EVENT_STR,
1393                                 job->req_type);
1394
1395         return ret;
1396 }
1397
1398 static int __process_set_restriction_mode(struct backend_job *job)
1399 {
1400         int ret;
1401         int mode;
1402
1403         mode = atoi(job->args);
1404         ret = _set_restriction_mode(job->target_uid, job->pkgid, mode);
1405
1406         _return_value_to_caller(job->req_id,
1407                         g_variant_new("(i)", ret));
1408
1409         return ret;
1410 }
1411
1412 static int __process_unset_restriction_mode(struct backend_job *job)
1413 {
1414         int ret;
1415         int mode;
1416
1417         mode = atoi(job->args);
1418         ret = _unset_restriction_mode(job->target_uid, job->pkgid, mode);
1419
1420         _return_value_to_caller(job->req_id,
1421                         g_variant_new("(i)", ret));
1422
1423         return ret;
1424 }
1425
1426 static int __process_get_restriction_mode(struct backend_job *job)
1427 {
1428         int ret;
1429         int mode = -1;
1430
1431         ret = _get_restriction_mode(job->target_uid, job->pkgid, &mode);
1432
1433         _return_value_to_caller(job->req_id,
1434                         g_variant_new("(ii)", mode, ret));
1435
1436         return ret;
1437 }
1438
1439 static int __process_set_app_label(struct backend_job *job)
1440 {
1441         int ret;
1442
1443         ret = pkgmgr_parser_update_app_label_info_in_usr_db(job->pkgid,
1444                         job->target_uid, job->args);
1445         _return_value_to_caller(job->req_id, g_variant_new("(i)", ret));
1446
1447         return ret;
1448 }
1449
1450 static int __post_process(int ret, int x, struct backend_job *job)
1451 {
1452         if (ret < 0) {
1453                 __set_backend_free(x);
1454                 _free_backend_job(job);
1455         } else {
1456                 g_hash_table_insert(backend_info_table, (gpointer)ret,
1457                                 (gpointer)job);
1458         }
1459         return 0;
1460 }
1461
1462 gboolean queue_job(void *data)
1463 {
1464         struct backend_job *job = NULL;
1465         int x;
1466         int ret;
1467
1468         /* Pop a job from queue */
1469         for (x = 0; x < num_of_backends; x++) {
1470                 if (__is_backend_busy(x))
1471                         continue;
1472
1473                 job = _pop_queue(x);
1474                 if (job)
1475                         break;
1476         }
1477
1478         /* all backend messages queue are empty or busy */
1479         if (x == num_of_backends || job == NULL) {
1480                 DBG("no job available");
1481                 return FALSE;
1482         }
1483
1484         /* set current backend job */
1485         DBG("handle request type [%d]", job->req_type);
1486
1487 #ifdef TIZEN_FEATURE_CSR
1488         if (job->req_type == REQUEST_TYPE_INSTALL ||
1489                         job->req_type == REQUEST_TYPE_MOUNT_INSTALL ||
1490                         job->req_type == REQUEST_TYPE_REINSTALL) {
1491                 ret = __check_csr(job->pkgid);
1492                 if (ret != 0) {
1493                         ret = -1;
1494                         _send_fail_signal(job);
1495                         _free_backend_job(job);
1496                         return TRUE;
1497                 }
1498         }
1499 #endif
1500
1501         switch (job->req_type) {
1502         case REQUEST_TYPE_INSTALL:
1503                 __set_backend_busy(x);
1504                 ret = __process_install(job);
1505                 __post_process(ret, x, job);
1506                 break;
1507         case REQUEST_TYPE_MOUNT_INSTALL:
1508                 __set_backend_busy(x);
1509                 ret = __process_mount_install(job);
1510                 __post_process(ret, x, job);
1511                 break;
1512         case REQUEST_TYPE_REINSTALL:
1513                 __set_backend_busy(x);
1514                 ret = __process_reinstall(job);
1515                 __post_process(ret, x, job);
1516                 break;
1517         case REQUEST_TYPE_UNINSTALL:
1518                 __set_backend_busy(x);
1519                 ret = __process_uninstall(job);
1520                 __post_process(ret, x, job);
1521                 break;
1522         case REQUEST_TYPE_MOVE:
1523                 __set_backend_busy(x);
1524                 ret = __process_move(job);
1525                 __post_process(ret, x, job);
1526                 break;
1527         case REQUEST_TYPE_ENABLE_PKG:
1528                 __set_backend_busy(x);
1529                 ret = __process_enable_pkg(job);
1530                 if (ret < 0)
1531                         _send_fail_signal(job);
1532                 __post_process(ret, x, job);
1533                 break;
1534         case REQUEST_TYPE_DISABLE_PKG:
1535                 __set_backend_busy(x);
1536                 ret = __process_disable_pkg(job);
1537                 if (ret < 0)
1538                         _send_fail_signal(job);
1539                 __post_process(ret, x, job);
1540                 break;
1541         case REQUEST_TYPE_ENABLE_APP:
1542                 ret = __process_enable_app(job);
1543                 _free_backend_job(job);
1544                 break;
1545         case REQUEST_TYPE_DISABLE_APP:
1546                 ret = __process_disable_app(job);
1547                 _free_backend_job(job);
1548                 break;
1549         case REQUEST_TYPE_GETSIZE:
1550                 __set_backend_busy(x);
1551                 ret = __process_getsize(job);
1552                 __post_process(ret, x, job);
1553                 break;
1554         case REQUEST_TYPE_GETSIZE_SYNC:
1555                 __set_backend_busy(x);
1556                 ret = __process_getsize_sync(job);
1557                 if (ret < 0)
1558                         __free_extra_info(job);
1559                 __post_process(ret, x, job);
1560                 break;
1561         case REQUEST_TYPE_CLEARDATA:
1562                 __set_backend_busy(x);
1563                 ret = __process_cleardata(job);
1564                 __post_process(ret, x, job);
1565                 break;
1566         case REQUEST_TYPE_CLEARCACHE:
1567                 __set_backend_busy(x);
1568                 ret = __process_clearcache(job);
1569                 __post_process(ret, x, job);
1570                 break;
1571         case REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID:
1572                 ret = __process_enable_global_app_for_uid(job);
1573                 _free_backend_job(job);
1574                 break;
1575         case REQUEST_TYPE_DISABLE_GLOBAL_APP_FOR_UID:
1576                 ret = __process_disable_global_app_for_uid(job);
1577                 _free_backend_job(job);
1578                 break;
1579         case REQUEST_TYPE_KILL:
1580                 ret = __process_kill(job);
1581                 _free_backend_job(job);
1582                 break;
1583         case REQUEST_TYPE_CHECK:
1584                 ret = __process_check(job);
1585                 _free_backend_job(job);
1586                 break;
1587         case REQUEST_TYPE_GENERATE_LICENSE_REQUEST:
1588                 ret = __process_generate_license_request(job);
1589                 _free_backend_job(job);
1590                 break;
1591         case REQUEST_TYPE_REGISTER_LICENSE:
1592                 ret = __process_register_license(job);
1593                 _free_backend_job(job);
1594                 break;
1595         case REQUEST_TYPE_DECRYPT_PACKAGE:
1596                 ret = __process_decrypt_package(job);
1597                 _free_backend_job(job);
1598                 break;
1599         case REQUEST_TYPE_ENABLE_APP_SPLASH_SCREEN:
1600                 ret = __process_update_app_splash_screen(job, 1);
1601                 _free_backend_job(job);
1602                 break;
1603         case REQUEST_TYPE_DISABLE_APP_SPLASH_SCREEN:
1604                 ret = __process_update_app_splash_screen(job, 0);
1605                 _free_backend_job(job);
1606                 break;
1607         case REQUEST_TYPE_SET_RESTRICTION_MODE:
1608                 ret = __process_set_restriction_mode(job);
1609                 _free_backend_job(job);
1610                 break;
1611         case REQUEST_TYPE_UNSET_RESTRICTION_MODE:
1612                 ret = __process_unset_restriction_mode(job);
1613                 _free_backend_job(job);
1614                 break;
1615         case REQUEST_TYPE_GET_RESTRICTION_MODE:
1616                 ret = __process_get_restriction_mode(job);
1617                 _free_backend_job(job);
1618                 break;
1619         case REQUEST_TYPE_SET_APP_LABEL:
1620                 ret = __process_set_app_label(job);
1621                 _free_backend_job(job);
1622                 break;
1623         default:
1624                 ret = -1;
1625                 break;
1626         }
1627
1628         return TRUE;
1629 }
1630
1631 int main(int argc, char *argv[])
1632 {
1633         int r;
1634
1635         DBG("server start");
1636
1637         r = _init_backend_queue();
1638         if (r) {
1639                 DBG("Queue Initialization Failed");
1640                 return -1;
1641         }
1642
1643         r = __init_backend_info();
1644         if (r) {
1645                 DBG("backend info init failed");
1646                 return -1;
1647         }
1648
1649         r = _init_request_handler();
1650         if (r) {
1651                 ERR("dbus init failed");
1652                 return -1;
1653         }
1654
1655         if (__register_signal_handler()) {
1656                 ERR("failed to register signal handler");
1657                 return -1;
1658         }
1659
1660 #if !GLIB_CHECK_VERSION(2, 35, 0)
1661         g_type_init();
1662 #endif
1663         mainloop = g_main_loop_new(NULL, FALSE);
1664         if (!mainloop) {
1665                 ERR("g_main_loop_new failed");
1666                 return -1;
1667         }
1668
1669         DBG("Main loop is created.");
1670
1671         g_main_loop_run(mainloop);
1672
1673         DBG("Quit main loop.");
1674         _fini_request_handler();
1675         __fini_backend_info();
1676         _fini_backend_queue();
1677
1678         DBG("package manager server terminated.");
1679
1680         return 0;
1681 }