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