Change to add quote using g_shell_quote in some parameter
[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         gchar *req_id;
693         gchar *pkgid;
694         int pid;
695
696         backend_cmd = job->backend_path;
697         if (backend_cmd == NULL)
698                 return -1;
699
700         req_id = g_shell_quote(job->req_id);
701         pkgid = g_shell_quote(job->pkgid);
702         if (!req_id || !pkgid)
703                 return -1;
704
705         snprintf(args, sizeof(args), "%s -k %s -i %s -u %d %s", backend_cmd,
706                         req_id, pkgid, (int)job->target_uid, job->args);
707
708         argv = __generate_argv(args);
709
710         pid = __fork_and_exec_with_args(argv, APPFW_UID);
711         g_strfreev(argv);
712         g_free(req_id);
713         g_free(pkgid);
714
715         return pid;
716 }
717
718 static int __process_mount_install(struct backend_job *job)
719 {
720         char *backend_cmd;
721         char **argv;
722         char args[MAX_PKG_ARGS_LEN];
723         gchar *req_id;
724         gchar *pkgid;
725         int pid;
726
727         backend_cmd = job->backend_path;
728         if (backend_cmd == NULL)
729                 return -1;
730
731         req_id = g_shell_quote(job->req_id);
732         pkgid = g_shell_quote(job->pkgid);
733         if (!req_id || !pkgid)
734                 return -1;
735
736         snprintf(args, sizeof(args), "%s -k %s -w %s -u %d %s", backend_cmd,
737                         req_id, pkgid, (int)job->target_uid, job->args);
738
739         argv = __generate_argv(args);
740
741         pid = __fork_and_exec_with_args(argv, APPFW_UID);
742         g_strfreev(argv);
743         g_free(req_id);
744         g_free(pkgid);
745
746         return pid;
747 }
748
749 static int __process_reinstall(struct backend_job *job)
750 {
751         char *backend_cmd;
752         char **argv;
753         char args[MAX_PKG_ARGS_LEN];
754         gchar *req_id;
755         gchar *pkgid;
756         int pid;
757
758         backend_cmd = job->backend_path;
759         if (backend_cmd == NULL)
760                 return -1;
761
762         req_id = g_shell_quote(job->req_id);
763         pkgid = g_shell_quote(job->pkgid);
764         if (!req_id || !pkgid)
765                 return -1;
766
767         snprintf(args, sizeof(args), "%s -k %s -r %s -u %d", backend_cmd,
768                         req_id, pkgid, (int)job->target_uid);
769         argv = __generate_argv(args);
770
771         pid = __fork_and_exec_with_args(argv, APPFW_UID);
772
773         g_strfreev(argv);
774         g_free(req_id);
775         g_free(pkgid);
776
777         return pid;
778 }
779
780 static int __process_uninstall(struct backend_job *job)
781 {
782         char *backend_cmd;
783         char **argv;
784         char args[MAX_PKG_ARGS_LEN];
785         int pid;
786
787         backend_cmd = job->backend_path;
788         if (backend_cmd == NULL)
789                 return -1;
790
791         snprintf(args, sizeof(args), "%s -k %s -d %s -u %d", backend_cmd,
792                         job->req_id, job->pkgid, (int)job->target_uid);
793         argv = __generate_argv(args);
794
795         pid = __fork_and_exec_with_args(argv, APPFW_UID);
796
797         g_strfreev(argv);
798
799         return pid;
800 }
801
802 static int __process_move(struct backend_job *job)
803 {
804         char *backend_cmd;
805         char **argv;
806         char args[MAX_PKG_ARGS_LEN];
807         int pid;
808
809         backend_cmd = job->backend_path;
810         if (backend_cmd == NULL)
811                 return -1;
812
813         snprintf(args, sizeof(args), "%s -k %s -m %s -u %d -t %s", backend_cmd,
814                         job->req_id, job->pkgid, (int)job->target_uid, job->args);
815         argv = __generate_argv(args);
816
817         pid = __fork_and_exec_with_args(argv, APPFW_UID);
818
819         g_strfreev(argv);
820
821         return pid;
822 }
823
824 static int __process_enable_pkg(struct backend_job *job)
825 {
826         char *backend_cmd;
827         char **argv;
828         char args[MAX_PKG_ARGS_LEN];
829         pkgmgrinfo_pkginfo_h pkginfo_h;
830         bool is_readonly;
831         bool is_global;
832         int ret;
833         int pid;
834
835         backend_cmd = job->backend_path;
836         if (backend_cmd == NULL)
837                 return -1;
838
839         ret = pkgmgrinfo_pkginfo_get_usr_disabled_pkginfo(
840                         job->pkgid, job->target_uid, &pkginfo_h);
841         if (ret != PMINFO_R_OK) {
842                 ERR("Failed to get appinfo");
843                 return -1;
844         }
845
846         ret = pkgmgrinfo_pkginfo_is_global(pkginfo_h, &is_global);
847         if (ret != PMINFO_R_OK) {
848                 ERR("Failed to get global value");
849                 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
850                 return -1;
851         }
852
853         if ((is_global && job->target_uid != GLOBAL_USER) ||
854                         (!is_global && job->target_uid == GLOBAL_USER)) {
855                 ERR("Invalid attempt to enable pkg");
856                 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
857                 return -1;
858         }
859
860         ret = pkgmgrinfo_pkginfo_is_readonly(pkginfo_h, &is_readonly);
861         if (ret != PMINFO_R_OK) {
862                 ERR("Failed to get readonly value");
863                 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
864                 return -1;
865         }
866
867         snprintf(args, sizeof(args), "%s -k %s -u %d -A %s %s",
868                         backend_cmd, job->req_id, (int)job->target_uid,
869                         job->pkgid, (is_readonly) ? "--preload" : "");
870         argv = __generate_argv(args);
871         pid = __fork_and_exec_with_args(argv, APPFW_UID);
872
873         g_strfreev(argv);
874         pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
875
876         return pid;
877 }
878
879 static int __process_disable_pkg(struct backend_job *job)
880 {
881         char *backend_cmd;
882         char **argv;
883         char args[MAX_PKG_ARGS_LEN];
884         pkgmgrinfo_pkginfo_h pkginfo_h;
885         bool is_readonly;
886         bool is_global;
887         int ret;
888         int pid;
889
890         backend_cmd = job->backend_path;
891         if (backend_cmd == NULL)
892                 return -1;
893
894         ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(
895                         job->pkgid, job->target_uid, &pkginfo_h);
896         if (ret != PMINFO_R_OK) {
897                 ERR("Failed to get appinfo");
898                 return -1;
899         }
900
901         ret = pkgmgrinfo_pkginfo_is_global(pkginfo_h, &is_global);
902         if (ret != PMINFO_R_OK) {
903                 ERR("Failed to get global value");
904                 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
905                 return -1;
906         }
907
908         if ((is_global && job->target_uid != GLOBAL_USER) ||
909                         (!is_global && job->target_uid == GLOBAL_USER)) {
910                 ERR("Invalid attempt to disable pkg");
911                 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
912                 return -1;
913         }
914
915         ret = pkgmgrinfo_pkginfo_is_readonly(pkginfo_h, &is_readonly);
916         if (ret != PMINFO_R_OK) {
917                 ERR("Failed to get readonly value");
918                 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
919                 return -1;
920         }
921
922         snprintf(args, sizeof(args), "%s -k %s -u %d -D %s %s",
923                         backend_cmd, job->req_id, (int)job->target_uid,
924                         job->pkgid, (is_readonly) ? "--preload" : "");
925         argv = __generate_argv(args);
926
927         pid = __fork_and_exec_with_args(argv, APPFW_UID);
928
929         g_strfreev(argv);
930
931         pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
932         return pid;
933 }
934
935 static int __process_enable_app(struct backend_job *job)
936 {
937         int ret = -1;
938         bool is_global = false;
939
940         /* get actual pkgid and replace it to appid which is currently stored
941          * at pkgid variable
942          */
943         ret = __change_job_info(job, job->target_uid, &is_global);
944         if (ret != PMINFO_R_OK || strlen(job->appid) == 0) {
945                 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
946                                 PKGMGR_INSTALLER_START_KEY_STR,
947                                 PKGMGR_INSTALLER_APP_ENABLE_EVENT_STR,
948                                 job->req_type);
949                 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
950                                 PKGMGR_INSTALLER_END_KEY_STR,
951                                 PKGMGR_INSTALLER_FAIL_EVENT_STR,
952                                 job->req_type);
953                 return ret;
954         }
955
956         _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
957                         PKGMGR_INSTALLER_START_KEY_STR,
958                         PKGMGR_INSTALLER_APP_ENABLE_EVENT_STR, job->req_type);
959
960         ret = pkgmgr_parser_update_app_disable_info_in_usr_db(job->appid,
961                         job->target_uid, 0);
962         if (ret != PMINFO_R_OK)
963                 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
964                                 PKGMGR_INSTALLER_END_KEY_STR,
965                                 PKGMGR_INSTALLER_FAIL_EVENT_STR,
966                                 job->req_type);
967         else
968                 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
969                                 PKGMGR_INSTALLER_END_KEY_STR,
970                                 PKGMGR_INSTALLER_OK_EVENT_STR,
971                                 job->req_type);
972
973         return ret;
974 }
975
976 static int __process_disable_app(struct backend_job *job)
977 {
978         int ret = -1;
979         bool is_global = false;
980
981         /* get actual pkgid and replace it to appid which is currently stored
982          * at pkgid variable
983          */
984         ret = __change_job_info(job, job->target_uid, &is_global);
985         if (ret != PMINFO_R_OK || strlen(job->appid) == 0) {
986                 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
987                                 PKGMGR_INSTALLER_START_KEY_STR,
988                                 PKGMGR_INSTALLER_APP_DISABLE_EVENT_STR,
989                                 job->req_type);
990                 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
991                                 PKGMGR_INSTALLER_END_KEY_STR,
992                                 PKGMGR_INSTALLER_FAIL_EVENT_STR,
993                                 job->req_type);
994                 return ret;
995         }
996
997         _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
998                         PKGMGR_INSTALLER_START_KEY_STR,
999                         PKGMGR_INSTALLER_APP_DISABLE_EVENT_STR, job->req_type);
1000
1001         ret = __kill_app(job->appid, job->target_uid);
1002         if (ret != 0) {
1003                 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1004                                 PKGMGR_INSTALLER_END_KEY_STR,
1005                                 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1006                                 job->req_type);
1007         }
1008
1009         ret = pkgmgr_parser_update_app_disable_info_in_usr_db(job->appid,
1010                         job->target_uid, 1);
1011         if (ret != PMINFO_R_OK)
1012                 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1013                                 PKGMGR_INSTALLER_END_KEY_STR,
1014                                 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1015                                 job->req_type);
1016         else
1017                 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1018                                 PKGMGR_INSTALLER_END_KEY_STR,
1019                                 PKGMGR_INSTALLER_OK_EVENT_STR,
1020                                 job->req_type);
1021
1022         return ret;
1023 }
1024
1025 static int __process_enable_global_app_for_uid(struct backend_job *job)
1026 {
1027         int ret = -1;
1028         bool is_global = true;
1029
1030         /* get actual pkgid and replace it to appid which is currently stored
1031          * at pkgid variable
1032          */
1033         ret = __change_job_info(job, job->target_uid, &is_global);
1034         if (ret != PMINFO_R_OK || strlen(job->appid) == 0) {
1035                 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
1036                                 PKGMGR_INSTALLER_START_KEY_STR,
1037                                 PKGMGR_INSTALLER_APP_ENABLE_EVENT_STR,
1038                                 job->req_type);
1039                 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
1040                                 PKGMGR_INSTALLER_END_KEY_STR,
1041                                 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1042                                 job->req_type);
1043                 return ret;
1044         }
1045
1046         _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1047                         PKGMGR_INSTALLER_START_KEY_STR,
1048                         PKGMGR_INSTALLER_APP_ENABLE_EVENT_STR,
1049                         job->req_type);
1050
1051         ret = pkgmgr_parser_update_global_app_disable_for_uid_info_in_db(
1052                         job->appid, job->target_uid, 0);
1053         if (ret != PMINFO_R_OK)
1054                 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1055                                 PKGMGR_INSTALLER_END_KEY_STR,
1056                                 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1057                                 job->req_type);
1058         else
1059                 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1060                                 PKGMGR_INSTALLER_END_KEY_STR,
1061                                 PKGMGR_INSTALLER_OK_EVENT_STR,
1062                                 job->req_type);
1063
1064         return ret;
1065 }
1066
1067 static int __process_disable_global_app_for_uid(struct backend_job *job)
1068 {
1069         int ret = -1;
1070         bool is_global = true;
1071
1072         /* get actual pkgid and replace it to appid which is currently stored
1073          * at pkgid variable
1074          */
1075         ret = __change_job_info(job, GLOBAL_USER, &is_global);
1076         if (ret != PMINFO_R_OK || strlen(job->appid) == 0) {
1077                 _send_app_signal(job->target_uid, job->req_id,
1078                                 job->pkgid, job->pkgid,
1079                                 PKGMGR_INSTALLER_START_KEY_STR,
1080                                 PKGMGR_INSTALLER_APP_DISABLE_EVENT_STR,
1081                                 job->req_type);
1082                 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
1083                                 PKGMGR_INSTALLER_END_KEY_STR,
1084                                 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1085                                 job->req_type);
1086                 return ret;
1087         }
1088
1089         _send_app_signal(job->target_uid, job->req_id,
1090                         job->pkgid, job->appid,
1091                         PKGMGR_INSTALLER_START_KEY_STR,
1092                         PKGMGR_INSTALLER_APP_DISABLE_EVENT_STR,
1093                         job->req_type);
1094
1095         ret = __kill_app(job->appid, job->target_uid);
1096         ret = pkgmgr_parser_update_global_app_disable_for_uid_info_in_db(
1097                         job->appid, job->target_uid, 1);
1098
1099         if (ret != PMINFO_R_OK)
1100                 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1101                                 PKGMGR_INSTALLER_END_KEY_STR,
1102                                 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1103                                 job->req_type);
1104         else
1105                 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1106                                 PKGMGR_INSTALLER_END_KEY_STR,
1107                                 PKGMGR_INSTALLER_OK_EVENT_STR,
1108                                 job->req_type);
1109
1110         return ret;
1111 }
1112
1113 static int __process_getsize(struct backend_job *job)
1114 {
1115         static const char backend_cmd[] = "/usr/bin/pkg_getsize";
1116         char **argv;
1117         char args[MAX_PKG_ARGS_LEN];
1118         int pid;
1119
1120         snprintf(args, sizeof(args), "%s %s %s %d -k %s -u %d",
1121                         backend_cmd, job->pkgid, job->args, job->caller_uid,
1122                         job->req_id, job->target_uid);
1123         argv = __generate_argv(args);
1124         pid = __fork_and_exec_with_args(argv, APPFW_UID);
1125
1126         g_strfreev(argv);
1127
1128         return pid;
1129 }
1130
1131 static int __process_getsize_sync(struct backend_job *job)
1132 {
1133         static const char backend_cmd[] = "/usr/bin/pkg_getsize";
1134         char **argv;
1135         char args[MAX_PKG_ARGS_LEN];
1136         char fifo_path[PATH_MAX];
1137         int pid;
1138
1139         snprintf(fifo_path, sizeof(fifo_path), "/tmp/pkgmgr/%s",
1140                         job->req_id);
1141
1142         job->extra = calloc(1, sizeof(struct job_extra_info));
1143         if (!job->extra) {
1144                 ERR("memory alloc failed");
1145                 goto error;
1146         }
1147
1148         job->extra->getsize_fifo = strdup(fifo_path);
1149         if (!job->extra->getsize_fifo) {
1150                 ERR("out of memory");
1151                 goto error;
1152         }
1153
1154         if (mkfifo(job->extra->getsize_fifo, 0600) < 0) {
1155                 ERR("failed to mkfifo");
1156                 goto error;
1157         }
1158
1159         snprintf(args, sizeof(args), "%s %s %s %d -k %s -u %d --sync",
1160                         backend_cmd, job->pkgid, job->args, job->caller_uid,
1161                         job->req_id, job->target_uid);
1162         argv = __generate_argv(args);
1163         pid = __fork_and_exec_with_args(argv, APPFW_UID);
1164
1165         g_strfreev(argv);
1166
1167         if (pid < 0) {
1168                 ERR("failed to execute backend");
1169                 goto error;
1170         }
1171         if (__setup_size_info_io(job) < 0) {
1172                 ERR("failed to setup io handler");
1173                 goto error;
1174         }
1175
1176         return pid;
1177
1178 error:
1179         _return_value_to_caller(job->req_id,
1180                 g_variant_new("(ix)", PKGMGR_R_ERROR, -1));
1181         return -1;
1182 }
1183
1184 static int __process_cleardata(struct backend_job *job)
1185 {
1186         static const char *backend_cmd = "/usr/bin/pkg_cleardata";
1187         char **argv;
1188         char args[MAX_PKG_ARGS_LEN];
1189         int pid;
1190
1191         if ((int)job->target_uid < REGULAR_USER)
1192                 return -1;
1193
1194         snprintf(args, sizeof(args), "%s -d -n %s -u %d",
1195                         backend_cmd, job->pkgid, job->target_uid);
1196         argv = __generate_argv(args);
1197         pid = __fork_and_exec_with_args(argv, APPFW_UID);
1198
1199         g_strfreev(argv);
1200         return pid;
1201 }
1202
1203 static int __process_clearcache(struct backend_job *job)
1204 {
1205         static const char *backend_cmd = "/usr/bin/pkg_cleardata";
1206         char **argv;
1207         char args[MAX_PKG_ARGS_LEN];
1208         int pid;
1209
1210         if ((int)job->target_uid < REGULAR_USER)
1211                 return -1;
1212
1213         snprintf(args, sizeof(args), "%s -c -n %s -u %d",
1214                         backend_cmd, job->pkgid, job->target_uid);
1215         argv = __generate_argv(args);
1216         pid = __fork_and_exec_with_args(argv, APPFW_UID);
1217
1218         g_strfreev(argv);
1219         return pid;
1220 }
1221
1222 static int __process_kill(struct backend_job *job)
1223 {
1224         int ret;
1225         pkgmgrinfo_pkginfo_h handle;
1226         pkgcmd_data *pdata;
1227
1228         ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(job->pkgid, job->target_uid,
1229                         &handle);
1230         if (ret < 0) {
1231                 ERR("Failed to get handle");
1232                 _return_value_to_caller(job->req_id,
1233                                 g_variant_new("(ii)", PKGMGR_R_ERROR, 0));
1234                 return -1;
1235         }
1236
1237         pdata = calloc(1, sizeof(pkgcmd_data));
1238         if (pdata == NULL) {
1239                 ERR("memory alloc failed");
1240                 _return_value_to_caller(job->req_id,
1241                                 g_variant_new("(ii)", PKGMGR_R_ENOMEM, 0));
1242                 return -1;
1243         }
1244         pdata->cmd = strdup("kill");
1245         if (pdata->cmd == NULL) {
1246                 ERR("out of memory");
1247                 _return_value_to_caller(job->req_id,
1248                                 g_variant_new("(ii)", PKGMGR_R_ENOMEM, 0));
1249                 free(pdata);
1250                 return -1;
1251         }
1252         pdata->uid = job->target_uid;
1253         ret = pkgmgrinfo_appinfo_get_usr_list(handle, PMINFO_ALL_APP,
1254                         __pkgcmd_app_cb, pdata, job->target_uid);
1255
1256         _return_value_to_caller(job->req_id,
1257                         g_variant_new("(ii)", PKGMGR_R_OK, pdata->pid));
1258
1259         free(pdata->cmd);
1260         free(pdata);
1261         pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
1262         if (ret < 0) {
1263                 ERR("pkgmgrinfo_appinfo_get_list() failed");
1264                 return -1;
1265         }
1266
1267         return 0;
1268 }
1269
1270 static int __process_check(struct backend_job *job)
1271 {
1272         int ret;
1273         pkgmgrinfo_pkginfo_h handle;
1274         pkgcmd_data *pdata;
1275
1276         ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(job->pkgid, job->target_uid,
1277                         &handle);
1278         if (ret < 0) {
1279                 ERR("Failed to get handle");
1280                 _return_value_to_caller(job->req_id,
1281                                 g_variant_new("(ii)", PKGMGR_R_ERROR, 0));
1282                 return -1;
1283         }
1284
1285         pdata = calloc(1, sizeof(pkgcmd_data));
1286         if (pdata == NULL) {
1287                 ERR("memory alloc failed");
1288                 _return_value_to_caller(job->req_id,
1289                                 g_variant_new("(ii)", PKGMGR_R_ENOMEM, 0));
1290                 return -1;
1291         }
1292         pdata->cmd = strdup("check");
1293         if (pdata->cmd == NULL) {
1294                 ERR("out of memory");
1295                 _return_value_to_caller(job->req_id,
1296                                 g_variant_new("(ii)", PKGMGR_R_ENOMEM, 0));
1297                 free(pdata);
1298                 return -1;
1299         }
1300         pdata->uid = job->target_uid;
1301         ret = pkgmgrinfo_appinfo_get_usr_list(handle, PMINFO_ALL_APP,
1302                         __pkgcmd_app_cb, pdata, job->target_uid);
1303
1304         _return_value_to_caller(job->req_id,
1305                         g_variant_new("(ii)", PKGMGR_R_OK, pdata->pid));
1306
1307         free(pdata->cmd);
1308         free(pdata);
1309         pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
1310         if (ret < 0) {
1311                 ERR("pkgmgrinfo_appinfo_get_list() failed");
1312                 return -1;
1313         }
1314
1315         return 0;
1316 }
1317
1318 static int __process_generate_license_request(struct backend_job *job)
1319 {
1320         int ret;
1321         char *resp_data;
1322         char req_data[MAX_PKG_ARGS_LEN];
1323         unsigned int req_data_len;
1324         char license_url[MAX_PKG_ARGS_LEN];
1325         unsigned int license_url_len;
1326
1327         resp_data = job->args;
1328         req_data_len = sizeof(req_data);
1329         license_url_len = sizeof(license_url);
1330
1331         ret = drm_tizen_generate_license_request(resp_data, strlen(resp_data),
1332                         req_data, &req_data_len, license_url, &license_url_len);
1333         if (ret != TADC_SUCCESS) {
1334                 ERR("drm_tizen_generate_license_request failed: %d", ret);
1335                 _return_value_to_caller(job->req_id, g_variant_new("(iss)",
1336                                         PKGMGR_R_ESYSTEM, "", ""));
1337                 return -1;
1338         }
1339
1340         _return_value_to_caller(job->req_id,
1341                         g_variant_new("(iss)", PKGMGR_R_OK, req_data,
1342                                 license_url));
1343
1344         return 0;
1345 }
1346
1347 static int __process_register_license(struct backend_job *job)
1348 {
1349         int ret;
1350         char *resp_data;
1351
1352         resp_data = job->args;
1353
1354         ret = drm_tizen_register_license(resp_data, strlen(resp_data));
1355         if (ret != TADC_SUCCESS) {
1356                 ERR("drm_tizen_register_license failed: %d", ret);
1357                 _return_value_to_caller(job->req_id,
1358                                 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
1359                 return -1;
1360         }
1361
1362         _return_value_to_caller(job->req_id,
1363                         g_variant_new("(i)", PKGMGR_R_OK));
1364
1365         return 0;
1366 }
1367
1368 static int __process_decrypt_package(struct backend_job *job)
1369 {
1370         int ret;
1371         char *drm_file_path;
1372         char *decrypted_file_path;
1373
1374         drm_file_path = job->pkgid;
1375         decrypted_file_path = job->args;
1376
1377         /* TODO: check ownership of decrypted file */
1378         ret = drm_tizen_decrypt_package(drm_file_path, strlen(drm_file_path),
1379                         decrypted_file_path, strlen(decrypted_file_path));
1380         if (ret != TADC_SUCCESS) {
1381                 ERR("drm_tizen_register_license failed: %d", ret);
1382                 _return_value_to_caller(job->req_id,
1383                                 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
1384                 return -1;
1385         }
1386
1387         _return_value_to_caller(job->req_id,
1388                         g_variant_new("(i)", PKGMGR_R_OK));
1389
1390         return 0;
1391 }
1392
1393 static int __process_update_app_splash_screen(struct backend_job *job, int flag)
1394 {
1395         int ret;
1396         bool is_global = false;
1397         const char *val;
1398
1399         ret = __change_job_info(job, job->target_uid, &is_global);
1400         if (ret != PMINFO_R_OK || strlen(job->appid) == 0)
1401                 return -1;
1402
1403         val = flag ? PKGMGR_INSTALLER_APP_ENABLE_SPLASH_SCREEN_EVENT_STR :
1404                 PKGMGR_INSTALLER_APP_DISABLE_SPLASH_SCREEN_EVENT_STR;
1405         _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1406                         PKGMGR_INSTALLER_START_KEY_STR, val, job->req_type);
1407
1408         if (is_global)
1409                 ret = pkgmgr_parser_update_global_app_splash_screen_display_info_in_usr_db(job->appid, job->target_uid, flag);
1410         else
1411                 ret = pkgmgr_parser_update_app_splash_screen_display_info_in_usr_db(
1412                         job->appid, job->target_uid, flag);
1413         if (ret != PMINFO_R_OK)
1414                 _send_app_signal(job->target_uid, job->req_id, job->pkgid,
1415                                 job->appid, PKGMGR_INSTALLER_END_KEY_STR,
1416                                 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1417                                 job->req_type);
1418         else
1419                 _send_app_signal(job->target_uid, job->req_id, job->pkgid,
1420                                 job->appid, PKGMGR_INSTALLER_END_KEY_STR,
1421                                 PKGMGR_INSTALLER_OK_EVENT_STR,
1422                                 job->req_type);
1423
1424         return ret;
1425 }
1426
1427 static int __process_set_restriction_mode(struct backend_job *job)
1428 {
1429         int ret;
1430         int mode;
1431
1432         mode = atoi(job->args);
1433         ret = _set_restriction_mode(job->target_uid, job->pkgid, mode);
1434
1435         _return_value_to_caller(job->req_id,
1436                         g_variant_new("(i)", ret));
1437
1438         return ret;
1439 }
1440
1441 static int __process_unset_restriction_mode(struct backend_job *job)
1442 {
1443         int ret;
1444         int mode;
1445
1446         mode = atoi(job->args);
1447         ret = _unset_restriction_mode(job->target_uid, job->pkgid, mode);
1448
1449         _return_value_to_caller(job->req_id,
1450                         g_variant_new("(i)", ret));
1451
1452         return ret;
1453 }
1454
1455 static int __process_get_restriction_mode(struct backend_job *job)
1456 {
1457         int ret;
1458         int mode = -1;
1459
1460         ret = _get_restriction_mode(job->target_uid, job->pkgid, &mode);
1461
1462         _return_value_to_caller(job->req_id,
1463                         g_variant_new("(ii)", mode, ret));
1464
1465         return ret;
1466 }
1467
1468 static int __process_set_app_label(struct backend_job *job)
1469 {
1470         int ret;
1471
1472         ret = pkgmgr_parser_update_app_label_info_in_usr_db(job->pkgid,
1473                         job->target_uid, job->args);
1474         _return_value_to_caller(job->req_id, g_variant_new("(i)", ret));
1475
1476         return ret;
1477 }
1478
1479 static int __process_migrate_external_image(struct backend_job *job)
1480 {
1481         char *backend_cmd;
1482         char **argv;
1483         char args[MAX_PKG_ARGS_LEN];
1484         int pid;
1485
1486         backend_cmd = job->backend_path;
1487         if (backend_cmd == NULL)
1488                 return -1;
1489
1490         snprintf(args, sizeof(args), "%s -k %s --migrate-extimg %s -u %d %s",
1491                         backend_cmd, job->req_id, job->pkgid,
1492                         (int)job->target_uid, job->args);
1493
1494         argv = __generate_argv(args);
1495
1496         pid = __fork_and_exec_with_args(argv, APPFW_UID);
1497         g_strfreev(argv);
1498
1499         return pid;
1500 }
1501
1502 static int __post_process(int ret, int x, struct backend_job *job)
1503 {
1504         if (ret < 0) {
1505                 __set_backend_free(x);
1506                 _free_backend_job(job);
1507         } else {
1508                 g_hash_table_insert(backend_info_table, (gpointer)ret,
1509                                 (gpointer)job);
1510         }
1511         return 0;
1512 }
1513
1514 gboolean queue_job(void *data)
1515 {
1516         struct backend_job *job = NULL;
1517         int x;
1518         int ret;
1519
1520         /* Pop a job from queue */
1521         for (x = 0; x < num_of_backends; x++) {
1522                 if (__is_backend_busy(x))
1523                         continue;
1524
1525                 job = _pop_queue(x);
1526                 if (job)
1527                         break;
1528         }
1529
1530         /* all backend messages queue are empty or busy */
1531         if (x == num_of_backends || job == NULL) {
1532                 DBG("no job available");
1533                 return FALSE;
1534         }
1535
1536         /* set current backend job */
1537         DBG("handle request type [%d]", job->req_type);
1538
1539 #ifdef TIZEN_FEATURE_CSR
1540         if (job->req_type == REQUEST_TYPE_INSTALL ||
1541                         job->req_type == REQUEST_TYPE_MOUNT_INSTALL ||
1542                         job->req_type == REQUEST_TYPE_REINSTALL) {
1543                 ret = __check_csr(job->pkgid);
1544                 if (ret != 0) {
1545                         ret = -1;
1546                         _send_fail_signal(job);
1547                         _free_backend_job(job);
1548                         return TRUE;
1549                 }
1550         }
1551 #endif
1552
1553         switch (job->req_type) {
1554         case REQUEST_TYPE_INSTALL:
1555                 __set_backend_busy(x);
1556                 ret = __process_install(job);
1557                 __post_process(ret, x, job);
1558                 break;
1559         case REQUEST_TYPE_MOUNT_INSTALL:
1560                 __set_backend_busy(x);
1561                 ret = __process_mount_install(job);
1562                 __post_process(ret, x, job);
1563                 break;
1564         case REQUEST_TYPE_REINSTALL:
1565                 __set_backend_busy(x);
1566                 ret = __process_reinstall(job);
1567                 __post_process(ret, x, job);
1568                 break;
1569         case REQUEST_TYPE_UNINSTALL:
1570                 __set_backend_busy(x);
1571                 ret = __process_uninstall(job);
1572                 __post_process(ret, x, job);
1573                 break;
1574         case REQUEST_TYPE_MOVE:
1575                 __set_backend_busy(x);
1576                 ret = __process_move(job);
1577                 __post_process(ret, x, job);
1578                 break;
1579         case REQUEST_TYPE_ENABLE_PKG:
1580                 __set_backend_busy(x);
1581                 ret = __process_enable_pkg(job);
1582                 if (ret < 0)
1583                         _send_fail_signal(job);
1584                 __post_process(ret, x, job);
1585                 break;
1586         case REQUEST_TYPE_DISABLE_PKG:
1587                 __set_backend_busy(x);
1588                 ret = __process_disable_pkg(job);
1589                 if (ret < 0)
1590                         _send_fail_signal(job);
1591                 __post_process(ret, x, job);
1592                 break;
1593         case REQUEST_TYPE_ENABLE_APP:
1594                 ret = __process_enable_app(job);
1595                 _free_backend_job(job);
1596                 break;
1597         case REQUEST_TYPE_DISABLE_APP:
1598                 ret = __process_disable_app(job);
1599                 _free_backend_job(job);
1600                 break;
1601         case REQUEST_TYPE_GETSIZE:
1602                 __set_backend_busy(x);
1603                 ret = __process_getsize(job);
1604                 __post_process(ret, x, job);
1605                 break;
1606         case REQUEST_TYPE_GETSIZE_SYNC:
1607                 __set_backend_busy(x);
1608                 ret = __process_getsize_sync(job);
1609                 if (ret < 0)
1610                         __free_extra_info(job);
1611                 __post_process(ret, x, job);
1612                 break;
1613         case REQUEST_TYPE_CLEARDATA:
1614                 __set_backend_busy(x);
1615                 ret = __process_cleardata(job);
1616                 __post_process(ret, x, job);
1617                 break;
1618         case REQUEST_TYPE_CLEARCACHE:
1619                 __set_backend_busy(x);
1620                 ret = __process_clearcache(job);
1621                 __post_process(ret, x, job);
1622                 break;
1623         case REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID:
1624                 ret = __process_enable_global_app_for_uid(job);
1625                 _free_backend_job(job);
1626                 break;
1627         case REQUEST_TYPE_DISABLE_GLOBAL_APP_FOR_UID:
1628                 ret = __process_disable_global_app_for_uid(job);
1629                 _free_backend_job(job);
1630                 break;
1631         case REQUEST_TYPE_KILL:
1632                 ret = __process_kill(job);
1633                 _free_backend_job(job);
1634                 break;
1635         case REQUEST_TYPE_CHECK:
1636                 ret = __process_check(job);
1637                 _free_backend_job(job);
1638                 break;
1639         case REQUEST_TYPE_GENERATE_LICENSE_REQUEST:
1640                 ret = __process_generate_license_request(job);
1641                 _free_backend_job(job);
1642                 break;
1643         case REQUEST_TYPE_REGISTER_LICENSE:
1644                 ret = __process_register_license(job);
1645                 _free_backend_job(job);
1646                 break;
1647         case REQUEST_TYPE_DECRYPT_PACKAGE:
1648                 ret = __process_decrypt_package(job);
1649                 _free_backend_job(job);
1650                 break;
1651         case REQUEST_TYPE_ENABLE_APP_SPLASH_SCREEN:
1652                 ret = __process_update_app_splash_screen(job, 1);
1653                 _free_backend_job(job);
1654                 break;
1655         case REQUEST_TYPE_DISABLE_APP_SPLASH_SCREEN:
1656                 ret = __process_update_app_splash_screen(job, 0);
1657                 _free_backend_job(job);
1658                 break;
1659         case REQUEST_TYPE_SET_RESTRICTION_MODE:
1660                 ret = __process_set_restriction_mode(job);
1661                 _free_backend_job(job);
1662                 break;
1663         case REQUEST_TYPE_UNSET_RESTRICTION_MODE:
1664                 ret = __process_unset_restriction_mode(job);
1665                 _free_backend_job(job);
1666                 break;
1667         case REQUEST_TYPE_GET_RESTRICTION_MODE:
1668                 ret = __process_get_restriction_mode(job);
1669                 _free_backend_job(job);
1670                 break;
1671         case REQUEST_TYPE_SET_APP_LABEL:
1672                 ret = __process_set_app_label(job);
1673                 _free_backend_job(job);
1674                 break;
1675         case REQUEST_TYPE_MIGRATE_EXTERNAL_IMAGE:
1676                 __set_backend_busy(x);
1677                 ret = __process_migrate_external_image(job);
1678                 __post_process(ret, x, job);
1679                 break;
1680         default:
1681                 ret = -1;
1682                 break;
1683         }
1684
1685         return TRUE;
1686 }
1687
1688 int main(int argc, char *argv[])
1689 {
1690         int r;
1691
1692         DBG("server start");
1693
1694         r = _init_backend_queue();
1695         if (r) {
1696                 DBG("Queue Initialization Failed");
1697                 return -1;
1698         }
1699
1700         r = __init_backend_info();
1701         if (r) {
1702                 DBG("backend info init failed");
1703                 return -1;
1704         }
1705
1706         r = _init_request_handler();
1707         if (r) {
1708                 ERR("dbus init failed");
1709                 return -1;
1710         }
1711
1712         if (__register_signal_handler()) {
1713                 ERR("failed to register signal handler");
1714                 return -1;
1715         }
1716
1717 #if !GLIB_CHECK_VERSION(2, 35, 0)
1718         g_type_init();
1719 #endif
1720         mainloop = g_main_loop_new(NULL, FALSE);
1721         if (!mainloop) {
1722                 ERR("g_main_loop_new failed");
1723                 return -1;
1724         }
1725
1726         DBG("Main loop is created.");
1727
1728         g_main_loop_run(mainloop);
1729
1730         DBG("Quit main loop.");
1731         _fini_request_handler();
1732         __fini_backend_info();
1733         _fini_backend_queue();
1734
1735         DBG("package manager server terminated.");
1736
1737         return 0;
1738 }