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