e7559f731fd7016ca060192c341fbd67fa41454a
[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         job->extra_data = extra_getsize_info;
1369         extra_getsize_info->getsize_fifo = strdup(fifo_path);
1370         if (!extra_getsize_info->getsize_fifo) {
1371                 ERR("out of memory");
1372                 goto error;
1373         }
1374
1375         if (mkfifo(extra_getsize_info->getsize_fifo, 0600) < 0) {
1376                 ERR("failed to mkfifo");
1377                 goto error;
1378         }
1379
1380         snprintf(args, sizeof(args), "%s %s %s %d -k %s -u %d --sync",
1381                         backend_cmd, job->pkgid, job->args, job->caller_uid,
1382                         job->req_id, job->target_uid);
1383         argv = __generate_argv(args);
1384         pid = __fork_and_exec_with_args(argv, APPFW_UID);
1385
1386         g_strfreev(argv);
1387
1388         if (pid < 0) {
1389                 ERR("failed to execute backend");
1390                 goto error;
1391         }
1392         if (__setup_size_info_io(job) < 0) {
1393                 ERR("failed to setup io handler");
1394                 goto error;
1395         }
1396
1397         return pid;
1398
1399 error:
1400         _return_value_to_caller(job->req_id,
1401                 g_variant_new("(ix)", PKGMGR_R_ERROR, -1));
1402         return -1;
1403 }
1404
1405 static int __process_cleardata(struct backend_job *job)
1406 {
1407         static const char *backend_cmd = "/usr/bin/pkg_cleardata";
1408         char **argv;
1409         char args[MAX_PKG_ARGS_LEN];
1410         int pid;
1411
1412         if ((int)job->target_uid < REGULAR_USER)
1413                 return -1;
1414
1415         snprintf(args, sizeof(args), "%s -d -n %s -u %d",
1416                         backend_cmd, job->pkgid, job->target_uid);
1417         argv = __generate_argv(args);
1418         pid = __fork_and_exec_with_args(argv, APPFW_UID);
1419
1420         g_strfreev(argv);
1421         return pid;
1422 }
1423
1424 static int __process_clearcache(struct backend_job *job)
1425 {
1426         static const char *backend_cmd = "/usr/bin/pkg_cleardata";
1427         char **argv;
1428         char args[MAX_PKG_ARGS_LEN];
1429         int pid;
1430
1431         if ((int)job->target_uid < REGULAR_USER)
1432                 return -1;
1433
1434         snprintf(args, sizeof(args), "%s -c -n %s -u %d",
1435                         backend_cmd, job->pkgid, job->target_uid);
1436         argv = __generate_argv(args);
1437         pid = __fork_and_exec_with_args(argv, APPFW_UID);
1438
1439         g_strfreev(argv);
1440         return pid;
1441 }
1442
1443 static int __process_kill(struct backend_job *job)
1444 {
1445         int ret;
1446         pkgmgrinfo_pkginfo_h handle;
1447         pkgcmd_data *pdata;
1448
1449         ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(job->pkgid, job->target_uid,
1450                         &handle);
1451         if (ret < 0) {
1452                 ERR("Failed to get handle");
1453                 _return_value_to_caller(job->req_id,
1454                                 g_variant_new("(ii)", PKGMGR_R_ERROR, 0));
1455                 return -1;
1456         }
1457
1458         pdata = calloc(1, sizeof(pkgcmd_data));
1459         if (pdata == NULL) {
1460                 ERR("memory alloc failed");
1461                 _return_value_to_caller(job->req_id,
1462                                 g_variant_new("(ii)", PKGMGR_R_ENOMEM, 0));
1463                 return -1;
1464         }
1465         pdata->cmd = strdup("kill");
1466         if (pdata->cmd == NULL) {
1467                 ERR("out of memory");
1468                 _return_value_to_caller(job->req_id,
1469                                 g_variant_new("(ii)", PKGMGR_R_ENOMEM, 0));
1470                 free(pdata);
1471                 return -1;
1472         }
1473         pdata->uid = job->target_uid;
1474         ret = pkgmgrinfo_appinfo_get_usr_list(handle, PMINFO_ALL_APP,
1475                         __pkgcmd_app_cb, pdata, job->target_uid);
1476
1477         _return_value_to_caller(job->req_id,
1478                         g_variant_new("(ii)", PKGMGR_R_OK, pdata->pid));
1479
1480         free(pdata->cmd);
1481         free(pdata);
1482         pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
1483         if (ret < 0) {
1484                 ERR("pkgmgrinfo_appinfo_get_list() failed");
1485                 return -1;
1486         }
1487
1488         return 0;
1489 }
1490
1491 static int __process_check(struct backend_job *job)
1492 {
1493         int ret;
1494         pkgmgrinfo_pkginfo_h handle;
1495         pkgcmd_data *pdata;
1496
1497         ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(job->pkgid, job->target_uid,
1498                         &handle);
1499         if (ret < 0) {
1500                 ERR("Failed to get handle");
1501                 _return_value_to_caller(job->req_id,
1502                                 g_variant_new("(ii)", PKGMGR_R_ERROR, 0));
1503                 return -1;
1504         }
1505
1506         pdata = calloc(1, sizeof(pkgcmd_data));
1507         if (pdata == NULL) {
1508                 ERR("memory alloc failed");
1509                 _return_value_to_caller(job->req_id,
1510                                 g_variant_new("(ii)", PKGMGR_R_ENOMEM, 0));
1511                 return -1;
1512         }
1513         pdata->cmd = strdup("check");
1514         if (pdata->cmd == NULL) {
1515                 ERR("out of memory");
1516                 _return_value_to_caller(job->req_id,
1517                                 g_variant_new("(ii)", PKGMGR_R_ENOMEM, 0));
1518                 free(pdata);
1519                 return -1;
1520         }
1521         pdata->uid = job->target_uid;
1522         ret = pkgmgrinfo_appinfo_get_usr_list(handle, PMINFO_ALL_APP,
1523                         __pkgcmd_app_cb, pdata, job->target_uid);
1524
1525         _return_value_to_caller(job->req_id,
1526                         g_variant_new("(ii)", PKGMGR_R_OK, pdata->pid));
1527
1528         free(pdata->cmd);
1529         free(pdata);
1530         pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
1531         if (ret < 0) {
1532                 ERR("pkgmgrinfo_appinfo_get_list() failed");
1533                 return -1;
1534         }
1535
1536         return 0;
1537 }
1538
1539 static int __load_drm_library(void)
1540 {
1541         if (drm_lib_handle)
1542                 return 0;
1543
1544         drm_lib_handle = dlopen(PATH_LIBDRM_SVC_CORE, RTLD_LAZY);
1545         if (!drm_lib_handle) {
1546                 DBG("Unable to open %s", PATH_LIBDRM_SVC_CORE);
1547                 return -1;
1548         }
1549
1550         _drm_tizen_generate_license_request =
1551                         dlsym(drm_lib_handle, "drm_tizen_generate_license_request");
1552         if (_drm_tizen_generate_license_request == NULL) {
1553                 ERR("_drm_tizen_generate_license_request() failed");
1554                 goto catch;
1555         }
1556
1557         _drm_tizen_register_license =
1558                                 dlsym(drm_lib_handle, "drm_tizen_register_license");
1559         if (_drm_tizen_register_license == NULL) {
1560                 ERR("_register_license() failed");
1561                 goto catch;
1562         }
1563
1564         _drm_tizen_decrypt_package =
1565                         dlsym(drm_lib_handle, "drm_tizen_decrypt_package");
1566         if (_drm_tizen_decrypt_package == NULL) {
1567                 ERR("_drm_tizen_decrypt_package() failed");
1568                 goto catch;
1569         }
1570
1571         return 0;
1572 catch:
1573         if (drm_lib_handle) {
1574                 dlclose(drm_lib_handle);
1575                 drm_lib_handle = NULL;
1576         }
1577         return -1;
1578 }
1579
1580 static void __unload_drm_library(void)
1581 {
1582         if (drm_lib_handle) {
1583                 dlclose(drm_lib_handle);
1584                 drm_lib_handle = NULL;
1585         }
1586 }
1587
1588 static int __process_generate_license_request(struct backend_job *job)
1589 {
1590         char *resp_data;
1591         char req_data[MAX_PKG_ARGS_LEN];
1592         unsigned int req_data_len;
1593         char license_url[MAX_PKG_ARGS_LEN];
1594         unsigned int license_url_len;
1595         int ret;
1596
1597         resp_data = job->args;
1598         req_data_len = sizeof(req_data);
1599         license_url_len = sizeof(license_url);
1600
1601         if (__load_drm_library() != 0) {
1602                 ERR("Failed to load library");
1603                 goto catch;
1604         }
1605
1606         ret = _drm_tizen_generate_license_request(resp_data, strlen(resp_data),
1607                         req_data, &req_data_len,
1608                         license_url, &license_url_len);
1609         if (ret != 1) {
1610                 ERR("drm_tizen_generate_license_request failed");
1611                 goto catch;
1612         }
1613         _return_value_to_caller(job->req_id,
1614                         g_variant_new("(iss)", PKGMGR_R_OK, req_data,
1615                                 license_url));
1616         is_drm_busy = true;
1617         return 0;
1618
1619 catch:
1620         _return_value_to_caller(job->req_id, g_variant_new("(iss)",
1621                                 PKGMGR_R_ESYSTEM, "", ""));
1622         is_drm_busy = false;
1623         __unload_drm_library();
1624         return -1;
1625 }
1626
1627 static int __process_register_license(struct backend_job *job)
1628 {
1629         char *resp_data;
1630         int ret;
1631
1632         resp_data = job->args;
1633         if (!_drm_tizen_register_license) {
1634                 ERR("_drm_tizen_register_license is not loaded");
1635                 goto catch;
1636         }
1637         ret = _drm_tizen_register_license(resp_data, strlen(resp_data));
1638         if (ret != 1) {
1639                 ERR("drm_tizen_register_license failed: %d", ret);
1640                 goto catch;
1641         }
1642         _return_value_to_caller(job->req_id,
1643                         g_variant_new("(i)", PKGMGR_R_OK));
1644         return 0;
1645
1646 catch:
1647         _return_value_to_caller(job->req_id,
1648                         g_variant_new("(i)", PKGMGR_R_ESYSTEM));
1649         is_drm_busy = false;
1650         __unload_drm_library();
1651
1652         return -1;
1653 }
1654
1655 static int __process_decrypt_package(struct backend_job *job)
1656 {
1657         int ret;
1658         char *drm_file_path;
1659         char *decrypted_file_path;
1660
1661         drm_file_path = job->pkgid;
1662         decrypted_file_path = job->args;
1663
1664         /* TODO: check ownership of decrypted file */
1665         if (!_drm_tizen_decrypt_package) {
1666                 ERR("drm_tizen_decrypt_package is not loaded");
1667
1668                 goto catch;
1669         }
1670         ret = _drm_tizen_decrypt_package(drm_file_path, strlen(drm_file_path),
1671                         decrypted_file_path, strlen(decrypted_file_path));
1672         if (ret != 1) {
1673                 ERR("drm_tizen_decrypt_package failed: %d", ret);
1674                 goto catch;
1675         }
1676         _return_value_to_caller(job->req_id,
1677                         g_variant_new("(i)", PKGMGR_R_OK));
1678         return 0;
1679
1680 catch:
1681         _return_value_to_caller(job->req_id,
1682                 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
1683         is_drm_busy = false;
1684         __unload_drm_library();
1685
1686         return -1;
1687 }
1688
1689 static int __process_update_app_splash_screen(struct backend_job *job, int flag)
1690 {
1691         int ret;
1692         bool is_global = false;
1693         const char *val;
1694
1695         ret = __change_job_info(job, job->target_uid, &is_global);
1696         if (ret != PMINFO_R_OK || strlen(job->appid) == 0)
1697                 return -1;
1698
1699         val = flag ? PKGMGR_INSTALLER_APP_ENABLE_SPLASH_SCREEN_EVENT_STR :
1700                 PKGMGR_INSTALLER_APP_DISABLE_SPLASH_SCREEN_EVENT_STR;
1701         _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1702                         PKGMGR_INSTALLER_START_KEY_STR, val, job->req_type);
1703
1704         if (is_global)
1705                 ret = pkgmgr_parser_update_global_app_splash_screen_display_info_in_usr_db(job->appid, job->target_uid, flag);
1706         else
1707                 ret = pkgmgr_parser_update_app_splash_screen_display_info_in_usr_db(
1708                         job->appid, job->target_uid, flag);
1709         if (ret != PMINFO_R_OK)
1710                 _send_app_signal(job->target_uid, job->req_id, job->pkgid,
1711                                 job->appid, PKGMGR_INSTALLER_END_KEY_STR,
1712                                 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1713                                 job->req_type);
1714         else
1715                 _send_app_signal(job->target_uid, job->req_id, job->pkgid,
1716                                 job->appid, PKGMGR_INSTALLER_END_KEY_STR,
1717                                 PKGMGR_INSTALLER_OK_EVENT_STR,
1718                                 job->req_type);
1719
1720         return ret;
1721 }
1722
1723 static int __process_set_restriction_mode(struct backend_job *job)
1724 {
1725         int ret;
1726         int mode;
1727
1728         mode = atoi(job->args);
1729         ret = _set_restriction_mode(job->target_uid, job->pkgid, mode);
1730
1731         _return_value_to_caller(job->req_id,
1732                         g_variant_new("(i)", ret));
1733
1734         return ret;
1735 }
1736
1737 static int __process_unset_restriction_mode(struct backend_job *job)
1738 {
1739         int ret;
1740         int mode;
1741
1742         mode = atoi(job->args);
1743         ret = _unset_restriction_mode(job->target_uid, job->pkgid, mode);
1744
1745         _return_value_to_caller(job->req_id,
1746                         g_variant_new("(i)", ret));
1747
1748         return ret;
1749 }
1750
1751 static int __process_get_restriction_mode(struct backend_job *job)
1752 {
1753         int ret;
1754         int mode = -1;
1755
1756         ret = _get_restriction_mode(job->target_uid, job->pkgid, &mode);
1757
1758         _return_value_to_caller(job->req_id,
1759                         g_variant_new("(ii)", mode, ret));
1760
1761         return ret;
1762 }
1763
1764 static int __process_set_app_label(struct backend_job *job)
1765 {
1766         int ret;
1767
1768         ret = pkgmgr_parser_update_app_label_info_in_usr_db(job->pkgid,
1769                         job->target_uid, job->args);
1770         _return_value_to_caller(job->req_id, g_variant_new("(i)", ret));
1771
1772         return ret;
1773 }
1774
1775 static int __process_set_app_icon(struct backend_job *job)
1776 {
1777         int ret;
1778         pkgmgrinfo_appinfo_h handle = NULL;
1779         char *app_root_path = NULL;
1780
1781         ret = pkgmgrinfo_appinfo_get_usr_appinfo(job->pkgid, job->target_uid, &handle);
1782         if (ret != PMINFO_R_OK) {
1783                 _return_value_to_caller(job->req_id, g_variant_new("(i)", ret));
1784                 return PKGMGR_R_ENOPKG;
1785         }
1786
1787         ret = pkgmgrinfo_appinfo_get_root_path(handle, &app_root_path);
1788         if (ret != PMINFO_R_OK || !app_root_path) {
1789                 _return_value_to_caller(job->req_id, g_variant_new("(i)", ret));
1790                 pkgmgrinfo_appinfo_destroy_appinfo(handle);
1791                 return PKGMGR_R_ESYSTEM;
1792         }
1793
1794         if (strncasecmp(job->args, app_root_path, strlen(app_root_path)) != 0 ||
1795                         strstr(job->args, "..") != NULL ||
1796                         access(job->args, F_OK) != 0) {
1797                 ERR("invalid path[%s]", job->args);
1798                 _return_value_to_caller(job->req_id, g_variant_new("(i)", ret));
1799                 pkgmgrinfo_appinfo_destroy_appinfo(handle);
1800                 return PKGMGR_R_EINVAL;
1801         }
1802
1803         pkgmgrinfo_appinfo_destroy_appinfo(handle);
1804         ret = pkgmgr_parser_update_app_icon_info_in_usr_db(job->pkgid,
1805                         job->target_uid, job->args);
1806         _return_value_to_caller(job->req_id, g_variant_new("(i)", ret));
1807
1808         return ret;
1809 }
1810
1811 static int __process_migrate_external_image(struct backend_job *job)
1812 {
1813         char *backend_cmd;
1814         char **argv;
1815         char args[MAX_PKG_ARGS_LEN];
1816         int pid;
1817
1818         backend_cmd = job->backend_path;
1819         if (backend_cmd == NULL)
1820                 return -1;
1821
1822         snprintf(args, sizeof(args), "%s -k %s --migrate-extimg %s -u %d %s",
1823                         backend_cmd, job->req_id, job->pkgid,
1824                         (int)job->target_uid, job->args);
1825
1826         argv = __generate_argv(args);
1827
1828         pid = __fork_and_exec_with_args(argv, APPFW_UID);
1829         g_strfreev(argv);
1830
1831         return pid;
1832 }
1833
1834 static int __post_process(int ret, int x, struct backend_job *job)
1835 {
1836         if (ret < 0) {
1837                 __set_backend_free(x);
1838                 _free_backend_job(job);
1839         } else {
1840                 g_hash_table_insert(backend_info_table, (gpointer)ret,
1841                                 (gpointer)job);
1842         }
1843         return 0;
1844 }
1845
1846 gboolean queue_job(void *data)
1847 {
1848         struct backend_job *job = NULL;
1849         int x;
1850         int ret;
1851
1852         /* Pop a job from queue */
1853         for (x = 0; x < num_of_backends; x++) {
1854                 if (__is_backend_busy(x))
1855                         continue;
1856
1857                 job = _pop_queue(x);
1858                 if (job)
1859                         break;
1860         }
1861
1862         /* all backend messages queue are empty or busy */
1863         if (x == num_of_backends || job == NULL) {
1864                 DBG("no job available");
1865                 return FALSE;
1866         }
1867
1868         /* set current backend job */
1869         DBG("handle request type [%d]", job->req_type);
1870
1871         if (job->req_type == REQUEST_TYPE_INSTALL ||
1872                         job->req_type == REQUEST_TYPE_MOUNT_INSTALL ||
1873                         job->req_type == REQUEST_TYPE_REINSTALL) {
1874                 ret = __check_csr(job->pkgid);
1875                 if (ret != 0) {
1876                         ret = -1;
1877                         _send_fail_signal(job);
1878                         _free_backend_job(job);
1879                         return TRUE;
1880                 }
1881         }
1882
1883         switch (job->req_type) {
1884         case REQUEST_TYPE_INSTALL:
1885                 __set_backend_busy(x);
1886                 __set_power_lock();
1887                 ret = __process_install(job);
1888                 __post_process(ret, x, job);
1889                 break;
1890         case REQUEST_TYPE_MOUNT_INSTALL:
1891                 __set_backend_busy(x);
1892                 __set_power_lock();
1893                 ret = __process_mount_install(job);
1894                 __post_process(ret, x, job);
1895                 break;
1896         case REQUEST_TYPE_REINSTALL:
1897                 __set_backend_busy(x);
1898                 __set_power_lock();
1899                 ret = __process_reinstall(job);
1900                 __post_process(ret, x, job);
1901                 break;
1902         case REQUEST_TYPE_UNINSTALL:
1903                 __set_backend_busy(x);
1904                 __set_power_lock();
1905                 ret = __process_uninstall(job);
1906                 __post_process(ret, x, job);
1907                 break;
1908         case REQUEST_TYPE_MOVE:
1909                 __set_backend_busy(x);
1910                 __set_power_lock();
1911                 ret = __process_move(job);
1912                 __post_process(ret, x, job);
1913                 break;
1914         case REQUEST_TYPE_ENABLE_PKG:
1915                 __set_backend_busy(x);
1916                 __set_power_lock();
1917                 ret = __process_enable_pkg(job);
1918                 if (ret < 0)
1919                         _send_fail_signal(job);
1920                 __post_process(ret, x, job);
1921                 break;
1922         case REQUEST_TYPE_DISABLE_PKG:
1923                 __set_backend_busy(x);
1924                 __set_power_lock();
1925                 ret = __process_disable_pkg(job);
1926                 if (ret < 0)
1927                         _send_fail_signal(job);
1928                 __post_process(ret, x, job);
1929                 break;
1930         case REQUEST_TYPE_REGISTER_PKG_UPDATE_INFO:
1931                 ret = __process_register_pkg_update_info(job);
1932                 __free_extra_info(job);
1933                 _free_backend_job(job);
1934                 break;
1935         case REQUEST_TYPE_UNREGISTER_PKG_UPDATE_INFO:
1936                 ret = __process_unregister_pkg_update_info(job);
1937                 _free_backend_job(job);
1938                 break;
1939         case REQUEST_TYPE_UNREGISTER_ALL_PKG_UPDATE_INFO:
1940                 ret = __process_unregister_all_pkg_update_info(job);
1941                 _free_backend_job(job);
1942                 break;
1943         case REQUEST_TYPE_ENABLE_APP:
1944                 ret = __process_enable_app(job);
1945                 _free_backend_job(job);
1946                 break;
1947         case REQUEST_TYPE_DISABLE_APP:
1948                 ret = __process_disable_app(job);
1949                 _free_backend_job(job);
1950                 break;
1951         case REQUEST_TYPE_GETSIZE:
1952                 __set_backend_busy(x);
1953                 ret = __process_getsize(job);
1954                 __post_process(ret, x, job);
1955                 break;
1956         case REQUEST_TYPE_GETSIZE_SYNC:
1957                 __set_backend_busy(x);
1958                 ret = __process_getsize_sync(job);
1959                 if (ret < 0)
1960                         __free_extra_info(job);
1961                 __post_process(ret, x, job);
1962                 break;
1963         case REQUEST_TYPE_CLEARDATA:
1964                 __set_backend_busy(x);
1965                 __set_power_lock();
1966                 ret = __process_cleardata(job);
1967                 __post_process(ret, x, job);
1968                 break;
1969         case REQUEST_TYPE_CLEARCACHE:
1970                 __set_backend_busy(x);
1971                 __set_power_lock();
1972                 ret = __process_clearcache(job);
1973                 __post_process(ret, x, job);
1974                 break;
1975         case REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID:
1976                 ret = __process_enable_global_app_for_uid(job);
1977                 _free_backend_job(job);
1978                 break;
1979         case REQUEST_TYPE_DISABLE_GLOBAL_APP_FOR_UID:
1980                 ret = __process_disable_global_app_for_uid(job);
1981                 _free_backend_job(job);
1982                 break;
1983         case REQUEST_TYPE_KILL:
1984                 ret = __process_kill(job);
1985                 _free_backend_job(job);
1986                 break;
1987         case REQUEST_TYPE_CHECK:
1988                 ret = __process_check(job);
1989                 _free_backend_job(job);
1990                 break;
1991         case REQUEST_TYPE_GENERATE_LICENSE_REQUEST:
1992                 ret = __process_generate_license_request(job);
1993                 _free_backend_job(job);
1994                 break;
1995         case REQUEST_TYPE_REGISTER_LICENSE:
1996                 ret = __process_register_license(job);
1997                 _free_backend_job(job);
1998                 break;
1999         case REQUEST_TYPE_DECRYPT_PACKAGE:
2000                 ret = __process_decrypt_package(job);
2001                 _free_backend_job(job);
2002                 break;
2003         case REQUEST_TYPE_ENABLE_APP_SPLASH_SCREEN:
2004                 ret = __process_update_app_splash_screen(job, 1);
2005                 _free_backend_job(job);
2006                 break;
2007         case REQUEST_TYPE_DISABLE_APP_SPLASH_SCREEN:
2008                 ret = __process_update_app_splash_screen(job, 0);
2009                 _free_backend_job(job);
2010                 break;
2011         case REQUEST_TYPE_SET_RESTRICTION_MODE:
2012                 ret = __process_set_restriction_mode(job);
2013                 _free_backend_job(job);
2014                 break;
2015         case REQUEST_TYPE_UNSET_RESTRICTION_MODE:
2016                 ret = __process_unset_restriction_mode(job);
2017                 _free_backend_job(job);
2018                 break;
2019         case REQUEST_TYPE_GET_RESTRICTION_MODE:
2020                 ret = __process_get_restriction_mode(job);
2021                 _free_backend_job(job);
2022                 break;
2023         case REQUEST_TYPE_SET_APP_LABEL:
2024                 ret = __process_set_app_label(job);
2025                 _free_backend_job(job);
2026                 break;
2027         case REQUEST_TYPE_SET_APP_ICON:
2028                 ret = __process_set_app_icon(job);
2029                 _free_backend_job(job);
2030                 break;
2031         case REQUEST_TYPE_MIGRATE_EXTERNAL_IMAGE:
2032                 __set_backend_busy(x);
2033                 __set_power_lock();
2034                 ret = __process_migrate_external_image(job);
2035                 __post_process(ret, x, job);
2036                 break;
2037         default:
2038                 ret = -1;
2039                 break;
2040         }
2041
2042         return TRUE;
2043 }
2044
2045 int main(int argc, char *argv[])
2046 {
2047         int r;
2048
2049         DBG("server start");
2050
2051         if (__register_signal_handler()) {
2052                 ERR("failed to register signal handler");
2053                 return -1;
2054         }
2055
2056         r = _init_backend_queue();
2057         if (r) {
2058                 ERR("Queue Initialization Failed");
2059                 return -1;
2060         }
2061
2062         r = __init_backend_info();
2063         if (r) {
2064                 ERR("backend info init failed");
2065                 return -1;
2066         }
2067
2068         r = _init_request_handler();
2069         if (r) {
2070                 ERR("dbus init failed");
2071                 return -1;
2072         }
2073
2074 #if !GLIB_CHECK_VERSION(2, 35, 0)
2075         g_type_init();
2076 #endif
2077         mainloop = g_main_loop_new(NULL, FALSE);
2078         if (!mainloop) {
2079                 ERR("g_main_loop_new failed");
2080                 return -1;
2081         }
2082
2083         DBG("Main loop is created.");
2084
2085         g_main_loop_run(mainloop);
2086
2087         DBG("Quit main loop.");
2088         _fini_request_handler();
2089         __fini_backend_info();
2090         _fini_backend_queue();
2091
2092         g_source_remove(swid);
2093         g_io_channel_unref(sio);
2094
2095         DBG("package manager server terminated.");
2096
2097         return 0;
2098 }