Fix fd 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 = NULL;
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                 dlclose(lib_handle);
460                 return -1;
461         }
462
463         ret = _csr_cs_context_create(&context);
464         if (ret != 0) {
465                 ERR("Failed to create context");
466                 dlclose(lib_handle);
467                 return -1;
468         }
469
470         ret = _csr_cs_scan_file(context, path, &malware);
471         /* the csr engine may not exist */
472         if (ret != 0)
473                 DBG("CSR result[%d]", ret);
474
475         ret = _csr_cs_context_destroy(context);
476         if (ret != 0)
477                 ERR("Failed to destroy context");
478
479         dlclose(lib_handle);
480
481         if (malware != NULL) {
482                 ERR("CSR detected malware from [%s]", path);
483                 return -1;
484         } else {
485                 return 0;
486         }
487 }
488
489 static int __kill_app(char *appid, uid_t uid)
490 {
491         int ret;
492         int pid;
493         int is_running;
494
495         is_running = aul_app_is_running_for_uid(appid, uid);
496         /* app is not running */
497         if (!is_running)
498                 return 0;
499
500         pid = aul_app_get_pid_for_uid(appid, uid);
501         if (pid == -1)
502                 return -1;
503
504         ret = aul_terminate_pid_for_uid(pid, uid);
505         if (ret != AUL_R_OK) {
506                 ERR("failed to terminate app(%s)", appid);
507                 return -1;
508         }
509
510         return 0;
511 }
512
513 static int __check_app(char *appid, uid_t uid)
514 {
515         int pid;
516         int is_running;
517
518         is_running = aul_app_is_running_for_uid(appid, uid);
519         if (!is_running)
520                 return 0;
521
522         pid = aul_app_get_pid_for_uid(appid, uid);
523
524         return pid;
525 }
526
527 static int __pkgcmd_app_cb(const pkgmgrinfo_appinfo_h handle, void *user_data)
528 {
529         char *pkgid;
530         char *appid;
531         char *exec;
532         int ret;
533         pkgcmd_data *pdata = (pkgcmd_data *)user_data;
534
535         if (handle == NULL) {
536                 perror("appinfo handle is NULL\n");
537                 exit(1);
538         }
539         ret = pkgmgrinfo_appinfo_get_exec(handle, &exec);
540         if (ret) {
541                 perror("Failed to get app exec path\n");
542                 exit(1);
543         }
544         ret = pkgmgrinfo_appinfo_get_appid(handle, &appid);
545         if (ret) {
546                 perror("Failed to get appid\n");
547                 exit(1);
548         }
549         ret = pkgmgrinfo_appinfo_get_pkgid(handle, &pkgid);
550         if (ret) {
551                 perror("Failed to get pkgid\n");
552                 exit(1);
553         }
554
555         if (strcmp(pdata->cmd, "kill") == 0) {
556                 pdata->pid = __check_app(appid, pdata->uid);
557                 if (pdata->pid > 0)
558                         ret = __kill_app(appid, pdata->uid);
559         } else if (strcmp(pdata->cmd, "check") == 0) {
560                 pdata->pid = __check_app(appid, pdata->uid);
561         }
562
563         return 0;
564 }
565
566 void free_user_context(user_ctx *ctx)
567 {
568         char **env = NULL;
569         int i = 0;
570         if (!ctx)
571                 return;
572         env = ctx->env;
573         /* env variable ends by NULL element */
574         while (env[i]) {
575                 free(env[i]);
576                 i++;
577         }
578         free(env);
579         env = NULL;
580         free(ctx);
581 }
582
583 int set_environement(user_ctx *ctx)
584 {
585         int i = 0;
586         int res = 0;
587         char **env = NULL;
588         int n;
589         gid_t *groups;
590
591         if (!ctx)
592                 return -1;
593
594         if (ctx->uid != APPFW_UID) {
595                 if (setuid(ctx->uid)) {
596                         ERR("setuid failed: %d", errno);
597                         return -1;
598                 }
599
600                 if (setgid(ctx->gid)) {
601                         ERR("setgid failed: %d", errno);
602                         return -1;
603                 }
604         }
605
606         n = getgroups(0, NULL);
607         if (n < 0) {
608                 ERR("Failed to get the number of supplementary group IDs");
609                 return -1;
610         }
611
612         groups = (gid_t *)calloc(1, sizeof(gid_t) * (n + 3));
613         if (groups == NULL) {
614                 ERR("out of memory");
615                 return -1;
616         }
617
618         n = getgroups(n, groups);
619         if (n < 0) {
620                 ERR("Failed to get list of supplementary group IDs");
621                 free(groups);
622                 return -1;
623         }
624
625         groups[n++] = EXT_STORAGE_GROUP;
626         groups[n++] = EXT_STORAGE_APPDATA_GROUP;
627         groups[n++] = MEDIA_STORAGE_GROUP;
628
629         if (setgroups(n, groups) < 0) {
630                 ERR("setgroups failed: %d", errno);
631                 free(groups);
632                 return -1;
633         }
634         free(groups);
635
636         env = ctx->env;
637         /* env variable ends by NULL element */
638         while (env[i]) {
639                 if (putenv(env[i]) != 0)
640                         res = -1;
641                 i++;
642         }
643         return res;
644 }
645
646 user_ctx *get_user_context(uid_t uid)
647 {
648         /* we can use getpwnam because this is used only after a
649          * fork and just before an execv
650          * No concurrencial call can corrupt the data
651          * returned by getpwuid
652          */
653         user_ctx *context_res;
654         char **env = NULL;
655         char buf[1024] = {0, };
656         struct passwd pwd, *result;
657         int len;
658         int ret = 0;
659         int i;
660
661         ret = getpwuid_r(uid, &pwd, buf, sizeof(buf), &result);
662         if (ret != 0 || result == NULL)
663                 return NULL;
664
665         do {
666                 context_res = (user_ctx *)malloc(sizeof(user_ctx));
667                 if (!context_res) {
668                         ret = -1;
669                         break;
670                 }
671                 env = (char **)malloc(3 * sizeof(char *));
672                 if (!env) {
673                         ret = -1;
674                         break;
675                 }
676                 /* Build environment context */
677                 len = snprintf(NULL, 0, "HOME=%s", pwd.pw_dir);
678                 env[0] = (char *)malloc((len + 1) * sizeof(char));
679                 if (env[0] == NULL) {
680                         ret = -1;
681                         break;
682                 }
683                 snprintf(env[0], len + 1, "HOME=%s", pwd.pw_dir);
684                 len = snprintf(NULL, 0, "USER=%s", pwd.pw_name);
685                 env[1] = (char *)malloc((len + 1) * sizeof(char));
686                 if (env[1] == NULL) {
687                         ret = -1;
688                         break;
689                 }
690                 snprintf(env[1], len + 1, "USER=%s", pwd.pw_name);
691                 env[2] = NULL;
692         } while (0);
693
694         if (ret == -1) {
695                 free(context_res);
696                 context_res = NULL;
697                 i = 0;
698                 /* env variable ends by NULL element */
699                 while (env && env[i]) {
700                         free(env[i]);
701                         i++;
702                 }
703                 free(env);
704                 env = NULL;
705         } else {
706                 context_res->env = env;
707                 context_res->uid = uid;
708                 context_res->gid = pwd.pw_gid;
709         }
710         return context_res;
711 }
712
713 static char **__generate_argv(const char *args)
714 {
715         /* Create args vector
716          * req_id + pkgid + args
717          *
718          * vector size = # of args +
719          *(req_id + pkgid + NULL termination = 3)
720          * Last value must be NULL for execv.
721          */
722         gboolean ret_parse;
723         gint argcp;
724         gchar **argvp;
725         GError *gerr = NULL;
726         int i;
727
728         ret_parse = g_shell_parse_argv(args, &argcp, &argvp, &gerr);
729         if (FALSE == ret_parse) {
730                 ERR("Failed to split args: %s", args);
731                 ERR("messsage: %s", gerr->message);
732                 exit(1);
733         }
734
735         /* dbg */
736         for (i = 0; i < argcp; i++)
737                 DBG(">>>>>> argsv[%d]=%s", i, argvp[i]);
738
739         return argvp;
740 }
741
742 void __set_environment(gpointer user_data)
743 {
744         user_ctx *ctx = (user_ctx *)user_data;
745
746         if (set_environement(ctx))
747                 ERR("Failed to set env for the user : %d", ctx->uid);
748 }
749
750 static int __fork_and_exec_with_args(char **argv, uid_t uid)
751 {
752         user_ctx *user_context;
753         GError *error = NULL;
754         gboolean ret;
755         int pid;
756
757         user_context = get_user_context(uid);
758         if (!user_context) {
759                 ERR("Failed to getenv");
760                 return -1;
761         }
762
763         ret = g_spawn_async(NULL, argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD,
764                         __set_environment, (gpointer)user_context, &pid,
765                         &error);
766         if (ret != TRUE) {
767                 ERR("Failed to excute backend: %s", error->message);
768                 g_error_free(error);
769                 free_user_context(user_context);
770                 return -1;
771         }
772
773         free_user_context(user_context);
774
775         return pid;
776 }
777
778 static int __change_job_info(struct backend_job *job, uid_t uid,
779                 bool *is_global)
780 {
781         int ret = 0;
782         char *pkgid = NULL;
783         pkgmgrinfo_appinfo_h handle = NULL;
784         if (job->req_type != REQUEST_TYPE_DISABLE_APP &&
785                         job->req_type != REQUEST_TYPE_DISABLE_GLOBAL_APP_FOR_UID &&
786                         job->req_type != REQUEST_TYPE_ENABLE_APP_SPLASH_SCREEN &&
787                         job->req_type != REQUEST_TYPE_DISABLE_APP_SPLASH_SCREEN &&
788                         job->req_type != REQUEST_TYPE_ENABLE_APP &&
789                         job->req_type != REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID)
790                 return PMINFO_R_ERROR;
791
792         ret = pkgmgrinfo_appinfo_get_usr_all_appinfo(job->pkgid, uid, &handle);
793         if (ret != PMINFO_R_OK)
794                 return PMINFO_R_ERROR;
795
796         ret = pkgmgrinfo_appinfo_is_global(handle, is_global);
797         if (ret != PMINFO_R_OK)
798                 goto catch;
799
800         if ((job->req_type == REQUEST_TYPE_DISABLE_GLOBAL_APP_FOR_UID ||
801                         job->req_type ==
802                         REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID) &&
803                         !*is_global) {
804                 ret = PMINFO_R_ERROR;
805                 goto catch;
806         }
807
808         ret = pkgmgrinfo_appinfo_get_pkgid(handle, &pkgid);
809         if (ret != PMINFO_R_OK)
810                 goto catch;
811
812         free(job->appid);
813         job->appid = strdup(job->pkgid);
814         free(job->pkgid);
815         job->pkgid = strdup(pkgid);
816
817 catch:
818         pkgmgrinfo_appinfo_destroy_appinfo(handle);
819
820         return ret;
821 }
822
823 static int __process_install(struct backend_job *job)
824 {
825         char *backend_cmd;
826         char **argv;
827         char args[MAX_PKG_ARGS_LEN];
828         gchar *req_id;
829         gchar *pkgid;
830         int pid;
831
832         backend_cmd = job->backend_path;
833         if (backend_cmd == NULL)
834                 return -1;
835
836         req_id = g_shell_quote(job->req_id);
837         if (!req_id)
838                 return -1;
839         pkgid = g_shell_quote(job->pkgid);
840         if (!pkgid) {
841                 g_free(req_id);
842                 return -1;
843         }
844
845         snprintf(args, sizeof(args), "%s -k %s -i %s -u %d %s", backend_cmd,
846                         req_id, pkgid, (int)job->target_uid, job->args);
847
848         argv = __generate_argv(args);
849
850         pid = __fork_and_exec_with_args(argv, APPFW_UID);
851         g_strfreev(argv);
852         g_free(req_id);
853         g_free(pkgid);
854
855         return pid;
856 }
857
858 static int __process_mount_install(struct backend_job *job)
859 {
860         char *backend_cmd;
861         char **argv;
862         char args[MAX_PKG_ARGS_LEN];
863         gchar *req_id;
864         gchar *pkgid;
865         int pid;
866
867         backend_cmd = job->backend_path;
868         if (backend_cmd == NULL)
869                 return -1;
870
871         req_id = g_shell_quote(job->req_id);
872         if (!req_id)
873                 return -1;
874         pkgid = g_shell_quote(job->pkgid);
875         if (!pkgid) {
876                 g_free(req_id);
877                 return -1;
878         }
879         snprintf(args, sizeof(args), "%s -k %s -w %s -u %d %s", backend_cmd,
880                         req_id, pkgid, (int)job->target_uid, job->args);
881
882         argv = __generate_argv(args);
883
884         pid = __fork_and_exec_with_args(argv, APPFW_UID);
885         g_strfreev(argv);
886         g_free(req_id);
887         g_free(pkgid);
888
889         return pid;
890 }
891
892 static int __process_reinstall(struct backend_job *job)
893 {
894         char *backend_cmd;
895         char **argv;
896         char args[MAX_PKG_ARGS_LEN];
897         gchar *req_id;
898         gchar *pkgid;
899         int pid;
900
901         backend_cmd = job->backend_path;
902         if (backend_cmd == NULL)
903                 return -1;
904
905         req_id = g_shell_quote(job->req_id);
906         if (!req_id)
907                 return -1;
908         pkgid = g_shell_quote(job->pkgid);
909         if (!pkgid) {
910                 g_free(req_id);
911                 return -1;
912         }
913
914         snprintf(args, sizeof(args), "%s -k %s -r %s -u %d", backend_cmd,
915                         req_id, pkgid, (int)job->target_uid);
916         argv = __generate_argv(args);
917
918         pid = __fork_and_exec_with_args(argv, APPFW_UID);
919
920         g_strfreev(argv);
921         g_free(req_id);
922         g_free(pkgid);
923
924         return pid;
925 }
926
927 static int __process_uninstall(struct backend_job *job)
928 {
929         char *backend_cmd;
930         char **argv;
931         char args[MAX_PKG_ARGS_LEN];
932         int pid;
933
934         backend_cmd = job->backend_path;
935         if (backend_cmd == NULL)
936                 return -1;
937
938         snprintf(args, sizeof(args), "%s -k %s -d %s -u %d", backend_cmd,
939                         job->req_id, job->pkgid, (int)job->target_uid);
940         argv = __generate_argv(args);
941
942         pid = __fork_and_exec_with_args(argv, APPFW_UID);
943
944         g_strfreev(argv);
945
946         return pid;
947 }
948
949 static int __process_move(struct backend_job *job)
950 {
951         char *backend_cmd;
952         char **argv;
953         char args[MAX_PKG_ARGS_LEN];
954         int pid;
955
956         backend_cmd = job->backend_path;
957         if (backend_cmd == NULL)
958                 return -1;
959
960         snprintf(args, sizeof(args), "%s -k %s -m %s -u %d -t %s", backend_cmd,
961                         job->req_id, job->pkgid, (int)job->target_uid, job->args);
962         argv = __generate_argv(args);
963
964         pid = __fork_and_exec_with_args(argv, APPFW_UID);
965
966         g_strfreev(argv);
967
968         return pid;
969 }
970
971 static int __process_enable_pkg(struct backend_job *job)
972 {
973         char *backend_cmd;
974         char **argv;
975         char args[MAX_PKG_ARGS_LEN];
976         pkgmgrinfo_pkginfo_h pkginfo_h;
977         bool is_readonly;
978         bool is_global;
979         int ret;
980         int pid;
981
982         backend_cmd = job->backend_path;
983         if (backend_cmd == NULL)
984                 return -1;
985
986         ret = pkgmgrinfo_pkginfo_get_usr_disabled_pkginfo(
987                         job->pkgid, job->target_uid, &pkginfo_h);
988         if (ret != PMINFO_R_OK) {
989                 ERR("Failed to get appinfo");
990                 return -1;
991         }
992
993         ret = pkgmgrinfo_pkginfo_is_global(pkginfo_h, &is_global);
994         if (ret != PMINFO_R_OK) {
995                 ERR("Failed to get global value");
996                 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
997                 return -1;
998         }
999
1000         if ((is_global && job->target_uid != GLOBAL_USER) ||
1001                         (!is_global && job->target_uid == GLOBAL_USER)) {
1002                 ERR("Invalid attempt to enable pkg");
1003                 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
1004                 return -1;
1005         }
1006
1007         ret = pkgmgrinfo_pkginfo_is_readonly(pkginfo_h, &is_readonly);
1008         if (ret != PMINFO_R_OK) {
1009                 ERR("Failed to get readonly value");
1010                 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
1011                 return -1;
1012         }
1013
1014         snprintf(args, sizeof(args), "%s -k %s -u %d -A %s %s",
1015                         backend_cmd, job->req_id, (int)job->target_uid,
1016                         job->pkgid, (is_readonly) ? "--preload" : "");
1017         argv = __generate_argv(args);
1018         pid = __fork_and_exec_with_args(argv, APPFW_UID);
1019
1020         g_strfreev(argv);
1021         pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
1022
1023         return pid;
1024 }
1025
1026 static int __process_disable_pkg(struct backend_job *job)
1027 {
1028         char *backend_cmd;
1029         char **argv;
1030         char args[MAX_PKG_ARGS_LEN];
1031         pkgmgrinfo_pkginfo_h pkginfo_h;
1032         bool is_readonly;
1033         bool is_global;
1034         int ret;
1035         int pid;
1036
1037         backend_cmd = job->backend_path;
1038         if (backend_cmd == NULL)
1039                 return -1;
1040
1041         ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(
1042                         job->pkgid, job->target_uid, &pkginfo_h);
1043         if (ret != PMINFO_R_OK) {
1044                 ERR("Failed to get appinfo");
1045                 return -1;
1046         }
1047
1048         ret = pkgmgrinfo_pkginfo_is_global(pkginfo_h, &is_global);
1049         if (ret != PMINFO_R_OK) {
1050                 ERR("Failed to get global value");
1051                 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
1052                 return -1;
1053         }
1054
1055         if ((is_global && job->target_uid != GLOBAL_USER) ||
1056                         (!is_global && job->target_uid == GLOBAL_USER)) {
1057                 ERR("Invalid attempt to disable pkg");
1058                 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
1059                 return -1;
1060         }
1061
1062         ret = pkgmgrinfo_pkginfo_is_readonly(pkginfo_h, &is_readonly);
1063         if (ret != PMINFO_R_OK) {
1064                 ERR("Failed to get readonly value");
1065                 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
1066                 return -1;
1067         }
1068
1069         snprintf(args, sizeof(args), "%s -k %s -u %d -D %s %s",
1070                         backend_cmd, job->req_id, (int)job->target_uid,
1071                         job->pkgid, (is_readonly) ? "--preload" : "");
1072         argv = __generate_argv(args);
1073
1074         pid = __fork_and_exec_with_args(argv, APPFW_UID);
1075
1076         g_strfreev(argv);
1077
1078         pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
1079         return pid;
1080 }
1081
1082 static int __process_register_pkg_update_info(struct backend_job *job)
1083 {
1084         int ret;
1085
1086         if (!job->extra_data) {
1087                 _return_value_to_caller(job->req_id,
1088                                 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
1089                 return -1;
1090         }
1091
1092         ret = pkgmgr_parser_register_pkg_update_info_in_usr_db(
1093                         (pkgmgrinfo_updateinfo_h)job->extra_data, job->target_uid);
1094         if (ret == PMINFO_R_OK)
1095                 _return_value_to_caller(job->req_id,
1096                                 g_variant_new("(i)", PKGMGR_R_OK));
1097         else
1098                 _return_value_to_caller(job->req_id,
1099                                 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
1100
1101         pkgmgrinfo_updateinfo_destroy(job->extra_data);
1102         job->extra_data = NULL;
1103
1104         return ret;
1105 }
1106
1107 static int __process_unregister_pkg_update_info(struct backend_job *job)
1108 {
1109         int ret = pkgmgr_parser_unregister_pkg_update_info_in_usr_db
1110                         (job->pkgid, job->target_uid);
1111
1112         if (ret == PMINFO_R_OK)
1113                 _return_value_to_caller(job->req_id,
1114                                 g_variant_new("(i)", PKGMGR_R_OK));
1115         else
1116                 _return_value_to_caller(job->req_id,
1117                                 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
1118         return ret;
1119 }
1120
1121 static int __process_unregister_all_pkg_update_info(struct backend_job *job)
1122 {
1123         int ret = pkgmgr_parser_unregister_all_pkg_update_info_in_usr_db(
1124                         job->target_uid);
1125
1126         if (ret != PMINFO_R_OK) {
1127                 _return_value_to_caller(job->req_id,
1128                                 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
1129                 return ret;
1130         }
1131
1132         if (__is_admin_user(job->caller_uid)) {
1133                 ret = pkgmgr_parser_unregister_all_pkg_update_info_in_usr_db(
1134                                 GLOBAL_USER);
1135                 if (ret != PMINFO_R_OK) {
1136                         _return_value_to_caller(job->req_id,
1137                                         g_variant_new("(i)", PKGMGR_R_ESYSTEM));
1138                         return ret;
1139                 }
1140         }
1141         _return_value_to_caller(job->req_id,
1142                         g_variant_new("(i)", PKGMGR_R_OK));
1143
1144         return ret;
1145 }
1146
1147 static int __process_enable_app(struct backend_job *job)
1148 {
1149         int ret = -1;
1150         bool is_global = false;
1151
1152         /* get actual pkgid and replace it to appid which is currently stored
1153          * at pkgid variable
1154          */
1155         ret = __change_job_info(job, job->target_uid, &is_global);
1156         if (ret != PMINFO_R_OK || strlen(job->appid) == 0) {
1157                 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
1158                                 PKGMGR_INSTALLER_START_KEY_STR,
1159                                 PKGMGR_INSTALLER_APP_ENABLE_EVENT_STR,
1160                                 job->req_type);
1161                 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
1162                                 PKGMGR_INSTALLER_END_KEY_STR,
1163                                 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1164                                 job->req_type);
1165                 return ret;
1166         }
1167
1168         _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1169                         PKGMGR_INSTALLER_START_KEY_STR,
1170                         PKGMGR_INSTALLER_APP_ENABLE_EVENT_STR, job->req_type);
1171
1172         ret = pkgmgr_parser_update_app_disable_info_in_usr_db(job->appid,
1173                         job->target_uid, 0);
1174         if (ret != PMINFO_R_OK)
1175                 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1176                                 PKGMGR_INSTALLER_END_KEY_STR,
1177                                 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1178                                 job->req_type);
1179         else
1180                 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1181                                 PKGMGR_INSTALLER_END_KEY_STR,
1182                                 PKGMGR_INSTALLER_OK_EVENT_STR,
1183                                 job->req_type);
1184
1185         return ret;
1186 }
1187
1188 static int __process_disable_app(struct backend_job *job)
1189 {
1190         int ret = -1;
1191         bool is_global = false;
1192
1193         /* get actual pkgid and replace it to appid which is currently stored
1194          * at pkgid variable
1195          */
1196         ret = __change_job_info(job, job->target_uid, &is_global);
1197         if (ret != PMINFO_R_OK || strlen(job->appid) == 0) {
1198                 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
1199                                 PKGMGR_INSTALLER_START_KEY_STR,
1200                                 PKGMGR_INSTALLER_APP_DISABLE_EVENT_STR,
1201                                 job->req_type);
1202                 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
1203                                 PKGMGR_INSTALLER_END_KEY_STR,
1204                                 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1205                                 job->req_type);
1206                 return ret;
1207         }
1208
1209         _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1210                         PKGMGR_INSTALLER_START_KEY_STR,
1211                         PKGMGR_INSTALLER_APP_DISABLE_EVENT_STR, job->req_type);
1212
1213         ret = __kill_app(job->appid, job->target_uid);
1214         if (ret != 0) {
1215                 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1216                                 PKGMGR_INSTALLER_END_KEY_STR,
1217                                 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1218                                 job->req_type);
1219         }
1220
1221         ret = pkgmgr_parser_update_app_disable_info_in_usr_db(job->appid,
1222                         job->target_uid, 1);
1223         if (ret != PMINFO_R_OK)
1224                 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1225                                 PKGMGR_INSTALLER_END_KEY_STR,
1226                                 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1227                                 job->req_type);
1228         else
1229                 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1230                                 PKGMGR_INSTALLER_END_KEY_STR,
1231                                 PKGMGR_INSTALLER_OK_EVENT_STR,
1232                                 job->req_type);
1233
1234         return ret;
1235 }
1236
1237 static int __process_enable_global_app_for_uid(struct backend_job *job)
1238 {
1239         int ret = -1;
1240         bool is_global = true;
1241
1242         /* get actual pkgid and replace it to appid which is currently stored
1243          * at pkgid variable
1244          */
1245         ret = __change_job_info(job, job->target_uid, &is_global);
1246         if (ret != PMINFO_R_OK || strlen(job->appid) == 0) {
1247                 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
1248                                 PKGMGR_INSTALLER_START_KEY_STR,
1249                                 PKGMGR_INSTALLER_APP_ENABLE_EVENT_STR,
1250                                 job->req_type);
1251                 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
1252                                 PKGMGR_INSTALLER_END_KEY_STR,
1253                                 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1254                                 job->req_type);
1255                 return ret;
1256         }
1257
1258         _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1259                         PKGMGR_INSTALLER_START_KEY_STR,
1260                         PKGMGR_INSTALLER_APP_ENABLE_EVENT_STR,
1261                         job->req_type);
1262
1263         ret = pkgmgr_parser_update_global_app_disable_for_uid_info_in_db(
1264                         job->appid, job->target_uid, 0);
1265         if (ret != PMINFO_R_OK)
1266                 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1267                                 PKGMGR_INSTALLER_END_KEY_STR,
1268                                 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1269                                 job->req_type);
1270         else
1271                 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1272                                 PKGMGR_INSTALLER_END_KEY_STR,
1273                                 PKGMGR_INSTALLER_OK_EVENT_STR,
1274                                 job->req_type);
1275
1276         return ret;
1277 }
1278
1279 static int __process_disable_global_app_for_uid(struct backend_job *job)
1280 {
1281         int ret = -1;
1282         bool is_global = true;
1283
1284         /* get actual pkgid and replace it to appid which is currently stored
1285          * at pkgid variable
1286          */
1287         ret = __change_job_info(job, GLOBAL_USER, &is_global);
1288         if (ret != PMINFO_R_OK || strlen(job->appid) == 0) {
1289                 _send_app_signal(job->target_uid, job->req_id,
1290                                 job->pkgid, job->pkgid,
1291                                 PKGMGR_INSTALLER_START_KEY_STR,
1292                                 PKGMGR_INSTALLER_APP_DISABLE_EVENT_STR,
1293                                 job->req_type);
1294                 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
1295                                 PKGMGR_INSTALLER_END_KEY_STR,
1296                                 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1297                                 job->req_type);
1298                 return ret;
1299         }
1300
1301         _send_app_signal(job->target_uid, job->req_id,
1302                         job->pkgid, job->appid,
1303                         PKGMGR_INSTALLER_START_KEY_STR,
1304                         PKGMGR_INSTALLER_APP_DISABLE_EVENT_STR,
1305                         job->req_type);
1306
1307         ret = __kill_app(job->appid, job->target_uid);
1308         ret = pkgmgr_parser_update_global_app_disable_for_uid_info_in_db(
1309                         job->appid, job->target_uid, 1);
1310
1311         if (ret != PMINFO_R_OK)
1312                 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1313                                 PKGMGR_INSTALLER_END_KEY_STR,
1314                                 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1315                                 job->req_type);
1316         else
1317                 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1318                                 PKGMGR_INSTALLER_END_KEY_STR,
1319                                 PKGMGR_INSTALLER_OK_EVENT_STR,
1320                                 job->req_type);
1321
1322         return ret;
1323 }
1324
1325 static int __process_getsize(struct backend_job *job)
1326 {
1327         static const char backend_cmd[] = "/usr/bin/pkg_getsize";
1328         char **argv;
1329         char args[MAX_PKG_ARGS_LEN];
1330         int pid;
1331
1332         snprintf(args, sizeof(args), "%s %s %s %d -k %s -u %d",
1333                         backend_cmd, job->pkgid, job->args, job->caller_uid,
1334                         job->req_id, job->target_uid);
1335         argv = __generate_argv(args);
1336         pid = __fork_and_exec_with_args(argv, APPFW_UID);
1337
1338         g_strfreev(argv);
1339
1340         return pid;
1341 }
1342
1343 static int __process_getsize_sync(struct backend_job *job)
1344 {
1345         static const char backend_cmd[] = "/usr/bin/pkg_getsize";
1346         char **argv;
1347         char args[MAX_PKG_ARGS_LEN];
1348         char fifo_path[PATH_MAX];
1349         struct getsize_sync_extra_info *extra_getsize_info;
1350         int pid;
1351
1352         snprintf(fifo_path, sizeof(fifo_path), "/tmp/pkgmgr/%s",
1353                         job->req_id);
1354
1355         extra_getsize_info = calloc(1, sizeof(struct getsize_sync_extra_info));
1356         if (!extra_getsize_info) {
1357                 ERR("memory alloc failed");
1358                 goto error;
1359         }
1360
1361         job->extra_data = extra_getsize_info;
1362         extra_getsize_info->getsize_fifo = strdup(fifo_path);
1363         if (!extra_getsize_info->getsize_fifo) {
1364                 ERR("out of memory");
1365                 goto error;
1366         }
1367
1368         if (mkfifo(extra_getsize_info->getsize_fifo, 0600) < 0) {
1369                 ERR("failed to mkfifo");
1370                 goto error;
1371         }
1372
1373         snprintf(args, sizeof(args), "%s %s %s %d -k %s -u %d --sync",
1374                         backend_cmd, job->pkgid, job->args, job->caller_uid,
1375                         job->req_id, job->target_uid);
1376         argv = __generate_argv(args);
1377         pid = __fork_and_exec_with_args(argv, APPFW_UID);
1378
1379         g_strfreev(argv);
1380
1381         if (pid < 0) {
1382                 ERR("failed to execute backend");
1383                 goto error;
1384         }
1385         if (__setup_size_info_io(job) < 0) {
1386                 ERR("failed to setup io handler");
1387                 goto error;
1388         }
1389
1390         return pid;
1391
1392 error:
1393         _return_value_to_caller(job->req_id,
1394                 g_variant_new("(ix)", PKGMGR_R_ERROR, -1));
1395         return -1;
1396 }
1397
1398 static int __process_cleardata(struct backend_job *job)
1399 {
1400         static const char *backend_cmd = "/usr/bin/pkg_cleardata";
1401         char **argv;
1402         char args[MAX_PKG_ARGS_LEN];
1403         int pid;
1404
1405         if ((int)job->target_uid < REGULAR_USER)
1406                 return -1;
1407
1408         snprintf(args, sizeof(args), "%s -d -n %s -u %d",
1409                         backend_cmd, job->pkgid, job->target_uid);
1410         argv = __generate_argv(args);
1411         pid = __fork_and_exec_with_args(argv, APPFW_UID);
1412
1413         g_strfreev(argv);
1414         return pid;
1415 }
1416
1417 static int __process_clearcache(struct backend_job *job)
1418 {
1419         static const char *backend_cmd = "/usr/bin/pkg_cleardata";
1420         char **argv;
1421         char args[MAX_PKG_ARGS_LEN];
1422         int pid;
1423
1424         if ((int)job->target_uid < REGULAR_USER)
1425                 return -1;
1426
1427         snprintf(args, sizeof(args), "%s -c -n %s -u %d",
1428                         backend_cmd, job->pkgid, job->target_uid);
1429         argv = __generate_argv(args);
1430         pid = __fork_and_exec_with_args(argv, APPFW_UID);
1431
1432         g_strfreev(argv);
1433         return pid;
1434 }
1435
1436 static int __process_kill(struct backend_job *job)
1437 {
1438         int ret;
1439         pkgmgrinfo_pkginfo_h handle;
1440         pkgcmd_data *pdata;
1441
1442         ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(job->pkgid, job->target_uid,
1443                         &handle);
1444         if (ret < 0) {
1445                 ERR("Failed to get handle");
1446                 _return_value_to_caller(job->req_id,
1447                                 g_variant_new("(ii)", PKGMGR_R_ERROR, 0));
1448                 return -1;
1449         }
1450
1451         pdata = calloc(1, sizeof(pkgcmd_data));
1452         if (pdata == NULL) {
1453                 ERR("memory alloc failed");
1454                 _return_value_to_caller(job->req_id,
1455                                 g_variant_new("(ii)", PKGMGR_R_ENOMEM, 0));
1456                 return -1;
1457         }
1458         pdata->cmd = strdup("kill");
1459         if (pdata->cmd == NULL) {
1460                 ERR("out of memory");
1461                 _return_value_to_caller(job->req_id,
1462                                 g_variant_new("(ii)", PKGMGR_R_ENOMEM, 0));
1463                 free(pdata);
1464                 return -1;
1465         }
1466         pdata->uid = job->target_uid;
1467         ret = pkgmgrinfo_appinfo_get_usr_list(handle, PMINFO_ALL_APP,
1468                         __pkgcmd_app_cb, pdata, job->target_uid);
1469
1470         _return_value_to_caller(job->req_id,
1471                         g_variant_new("(ii)", PKGMGR_R_OK, pdata->pid));
1472
1473         free(pdata->cmd);
1474         free(pdata);
1475         pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
1476         if (ret < 0) {
1477                 ERR("pkgmgrinfo_appinfo_get_list() failed");
1478                 return -1;
1479         }
1480
1481         return 0;
1482 }
1483
1484 static int __process_check(struct backend_job *job)
1485 {
1486         int ret;
1487         pkgmgrinfo_pkginfo_h handle;
1488         pkgcmd_data *pdata;
1489
1490         ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(job->pkgid, job->target_uid,
1491                         &handle);
1492         if (ret < 0) {
1493                 ERR("Failed to get handle");
1494                 _return_value_to_caller(job->req_id,
1495                                 g_variant_new("(ii)", PKGMGR_R_ERROR, 0));
1496                 return -1;
1497         }
1498
1499         pdata = calloc(1, sizeof(pkgcmd_data));
1500         if (pdata == NULL) {
1501                 ERR("memory alloc failed");
1502                 _return_value_to_caller(job->req_id,
1503                                 g_variant_new("(ii)", PKGMGR_R_ENOMEM, 0));
1504                 return -1;
1505         }
1506         pdata->cmd = strdup("check");
1507         if (pdata->cmd == NULL) {
1508                 ERR("out of memory");
1509                 _return_value_to_caller(job->req_id,
1510                                 g_variant_new("(ii)", PKGMGR_R_ENOMEM, 0));
1511                 free(pdata);
1512                 return -1;
1513         }
1514         pdata->uid = job->target_uid;
1515         ret = pkgmgrinfo_appinfo_get_usr_list(handle, PMINFO_ALL_APP,
1516                         __pkgcmd_app_cb, pdata, job->target_uid);
1517
1518         _return_value_to_caller(job->req_id,
1519                         g_variant_new("(ii)", PKGMGR_R_OK, pdata->pid));
1520
1521         free(pdata->cmd);
1522         free(pdata);
1523         pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
1524         if (ret < 0) {
1525                 ERR("pkgmgrinfo_appinfo_get_list() failed");
1526                 return -1;
1527         }
1528
1529         return 0;
1530 }
1531
1532 static int __load_drm_library(void)
1533 {
1534         if (drm_lib_handle)
1535                 return 0;
1536
1537         drm_lib_handle = dlopen(PATH_LIBDRM_SVC_CORE, RTLD_LAZY);
1538         if (!drm_lib_handle) {
1539                 DBG("Unable to open %s", PATH_LIBDRM_SVC_CORE);
1540                 return -1;
1541         }
1542
1543         _drm_tizen_generate_license_request =
1544                         dlsym(drm_lib_handle, "drm_tizen_generate_license_request");
1545         if (_drm_tizen_generate_license_request == NULL) {
1546                 ERR("_drm_tizen_generate_license_request() failed");
1547                 goto catch;
1548         }
1549
1550         _drm_tizen_register_license =
1551                                 dlsym(drm_lib_handle, "drm_tizen_register_license");
1552         if (_drm_tizen_register_license == NULL) {
1553                 ERR("_register_license() failed");
1554                 goto catch;
1555         }
1556
1557         _drm_tizen_decrypt_package =
1558                         dlsym(drm_lib_handle, "drm_tizen_decrypt_package");
1559         if (_drm_tizen_decrypt_package == NULL) {
1560                 ERR("_drm_tizen_decrypt_package() failed");
1561                 goto catch;
1562         }
1563
1564         return 0;
1565 catch:
1566         if (drm_lib_handle) {
1567                 dlclose(drm_lib_handle);
1568                 drm_lib_handle = NULL;
1569         }
1570         return -1;
1571 }
1572
1573 static void __unload_drm_library(void)
1574 {
1575         if (drm_lib_handle) {
1576                 dlclose(drm_lib_handle);
1577                 drm_lib_handle = NULL;
1578         }
1579 }
1580
1581 static int __process_generate_license_request(struct backend_job *job)
1582 {
1583         char *resp_data;
1584         char req_data[MAX_PKG_ARGS_LEN];
1585         unsigned int req_data_len;
1586         char license_url[MAX_PKG_ARGS_LEN];
1587         unsigned int license_url_len;
1588         int ret;
1589
1590         resp_data = job->args;
1591         req_data_len = sizeof(req_data);
1592         license_url_len = sizeof(license_url);
1593
1594         if (__load_drm_library() != 0) {
1595                 ERR("Failed to load library");
1596                 goto catch;
1597         }
1598
1599         ret = _drm_tizen_generate_license_request(resp_data, strlen(resp_data),
1600                         req_data, &req_data_len,
1601                         license_url, &license_url_len);
1602         if (ret != 1) {
1603                 ERR("drm_tizen_generate_license_request failed");
1604                 goto catch;
1605         }
1606         _return_value_to_caller(job->req_id,
1607                         g_variant_new("(iss)", PKGMGR_R_OK, req_data,
1608                                 license_url));
1609         is_drm_busy = true;
1610         return 0;
1611
1612 catch:
1613         _return_value_to_caller(job->req_id, g_variant_new("(iss)",
1614                                 PKGMGR_R_ESYSTEM, "", ""));
1615         is_drm_busy = false;
1616         __unload_drm_library();
1617         return -1;
1618 }
1619
1620 static int __process_register_license(struct backend_job *job)
1621 {
1622         char *resp_data;
1623         int ret;
1624
1625         resp_data = job->args;
1626         if (!_drm_tizen_register_license) {
1627                 ERR("_drm_tizen_register_license is not loaded");
1628                 goto catch;
1629         }
1630         ret = _drm_tizen_register_license(resp_data, strlen(resp_data));
1631         if (ret != 1) {
1632                 ERR("drm_tizen_register_license failed: %d", ret);
1633                 goto catch;
1634         }
1635         _return_value_to_caller(job->req_id,
1636                         g_variant_new("(i)", PKGMGR_R_OK));
1637         return 0;
1638
1639 catch:
1640         _return_value_to_caller(job->req_id,
1641                         g_variant_new("(i)", PKGMGR_R_ESYSTEM));
1642         is_drm_busy = false;
1643         __unload_drm_library();
1644
1645         return -1;
1646 }
1647
1648 static int __process_decrypt_package(struct backend_job *job)
1649 {
1650         int ret;
1651         char *drm_file_path;
1652         char *decrypted_file_path;
1653
1654         drm_file_path = job->pkgid;
1655         decrypted_file_path = job->args;
1656
1657         /* TODO: check ownership of decrypted file */
1658         if (!_drm_tizen_decrypt_package) {
1659                 ERR("drm_tizen_decrypt_package is not loaded");
1660
1661                 goto catch;
1662         }
1663         ret = _drm_tizen_decrypt_package(drm_file_path, strlen(drm_file_path),
1664                         decrypted_file_path, strlen(decrypted_file_path));
1665         if (ret != 1) {
1666                 ERR("drm_tizen_decrypt_package failed: %d", ret);
1667                 goto catch;
1668         }
1669         _return_value_to_caller(job->req_id,
1670                         g_variant_new("(i)", PKGMGR_R_OK));
1671         return 0;
1672
1673 catch:
1674         _return_value_to_caller(job->req_id,
1675                 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
1676         is_drm_busy = false;
1677         __unload_drm_library();
1678
1679         return -1;
1680 }
1681
1682 static int __process_update_app_splash_screen(struct backend_job *job, int flag)
1683 {
1684         int ret;
1685         bool is_global = false;
1686         const char *val;
1687
1688         ret = __change_job_info(job, job->target_uid, &is_global);
1689         if (ret != PMINFO_R_OK || strlen(job->appid) == 0)
1690                 return -1;
1691
1692         val = flag ? PKGMGR_INSTALLER_APP_ENABLE_SPLASH_SCREEN_EVENT_STR :
1693                 PKGMGR_INSTALLER_APP_DISABLE_SPLASH_SCREEN_EVENT_STR;
1694         _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1695                         PKGMGR_INSTALLER_START_KEY_STR, val, job->req_type);
1696
1697         if (is_global)
1698                 ret = pkgmgr_parser_update_global_app_splash_screen_display_info_in_usr_db(job->appid, job->target_uid, flag);
1699         else
1700                 ret = pkgmgr_parser_update_app_splash_screen_display_info_in_usr_db(
1701                         job->appid, job->target_uid, flag);
1702         if (ret != PMINFO_R_OK)
1703                 _send_app_signal(job->target_uid, job->req_id, job->pkgid,
1704                                 job->appid, PKGMGR_INSTALLER_END_KEY_STR,
1705                                 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1706                                 job->req_type);
1707         else
1708                 _send_app_signal(job->target_uid, job->req_id, job->pkgid,
1709                                 job->appid, PKGMGR_INSTALLER_END_KEY_STR,
1710                                 PKGMGR_INSTALLER_OK_EVENT_STR,
1711                                 job->req_type);
1712
1713         return ret;
1714 }
1715
1716 static int __process_set_restriction_mode(struct backend_job *job)
1717 {
1718         int ret;
1719         int mode;
1720
1721         mode = atoi(job->args);
1722         ret = _set_restriction_mode(job->target_uid, job->pkgid, mode);
1723
1724         _return_value_to_caller(job->req_id,
1725                         g_variant_new("(i)", ret));
1726
1727         return ret;
1728 }
1729
1730 static int __process_unset_restriction_mode(struct backend_job *job)
1731 {
1732         int ret;
1733         int mode;
1734
1735         mode = atoi(job->args);
1736         ret = _unset_restriction_mode(job->target_uid, job->pkgid, mode);
1737
1738         _return_value_to_caller(job->req_id,
1739                         g_variant_new("(i)", ret));
1740
1741         return ret;
1742 }
1743
1744 static int __process_get_restriction_mode(struct backend_job *job)
1745 {
1746         int ret;
1747         int mode = -1;
1748
1749         ret = _get_restriction_mode(job->target_uid, job->pkgid, &mode);
1750
1751         _return_value_to_caller(job->req_id,
1752                         g_variant_new("(ii)", mode, ret));
1753
1754         return ret;
1755 }
1756
1757 static int __process_set_app_label(struct backend_job *job)
1758 {
1759         int ret;
1760
1761         ret = pkgmgr_parser_update_app_label_info_in_usr_db(job->pkgid,
1762                         job->target_uid, job->args);
1763         _return_value_to_caller(job->req_id, g_variant_new("(i)", ret));
1764
1765         return ret;
1766 }
1767
1768 static int __process_set_app_icon(struct backend_job *job)
1769 {
1770         int ret;
1771         pkgmgrinfo_appinfo_h handle = NULL;
1772         char *app_root_path = NULL;
1773
1774         ret = pkgmgrinfo_appinfo_get_usr_appinfo(job->pkgid, job->target_uid, &handle);
1775         if (ret != PMINFO_R_OK) {
1776                 _return_value_to_caller(job->req_id, g_variant_new("(i)", ret));
1777                 return PKGMGR_R_ENOPKG;
1778         }
1779
1780         ret = pkgmgrinfo_appinfo_get_root_path(handle, &app_root_path);
1781         if (ret != PMINFO_R_OK || !app_root_path) {
1782                 _return_value_to_caller(job->req_id, g_variant_new("(i)", ret));
1783                 pkgmgrinfo_appinfo_destroy_appinfo(handle);
1784                 return PKGMGR_R_ESYSTEM;
1785         }
1786
1787         if (strncasecmp(job->args, app_root_path, strlen(app_root_path)) != 0 ||
1788                         strstr(job->args, "..") != NULL ||
1789                         access(job->args, F_OK) != 0) {
1790                 ERR("invalid path[%s]", job->args);
1791                 _return_value_to_caller(job->req_id, g_variant_new("(i)", ret));
1792                 pkgmgrinfo_appinfo_destroy_appinfo(handle);
1793                 return PKGMGR_R_EINVAL;
1794         }
1795
1796         pkgmgrinfo_appinfo_destroy_appinfo(handle);
1797         ret = pkgmgr_parser_update_app_icon_info_in_usr_db(job->pkgid,
1798                         job->target_uid, job->args);
1799         _return_value_to_caller(job->req_id, g_variant_new("(i)", ret));
1800
1801         return ret;
1802 }
1803
1804 static int __process_migrate_external_image(struct backend_job *job)
1805 {
1806         char *backend_cmd;
1807         char **argv;
1808         char args[MAX_PKG_ARGS_LEN];
1809         int pid;
1810
1811         backend_cmd = job->backend_path;
1812         if (backend_cmd == NULL)
1813                 return -1;
1814
1815         snprintf(args, sizeof(args), "%s -k %s --migrate-extimg %s -u %d %s",
1816                         backend_cmd, job->req_id, job->pkgid,
1817                         (int)job->target_uid, job->args);
1818
1819         argv = __generate_argv(args);
1820
1821         pid = __fork_and_exec_with_args(argv, APPFW_UID);
1822         g_strfreev(argv);
1823
1824         return pid;
1825 }
1826
1827 static int __post_process(int ret, int x, struct backend_job *job)
1828 {
1829         if (ret < 0) {
1830                 __set_backend_free(x);
1831                 _free_backend_job(job);
1832         } else {
1833                 g_hash_table_insert(backend_info_table, (gpointer)ret,
1834                                 (gpointer)job);
1835         }
1836         return 0;
1837 }
1838
1839 gboolean queue_job(void *data)
1840 {
1841         struct backend_job *job = NULL;
1842         int x;
1843         int ret;
1844
1845         /* Pop a job from queue */
1846         for (x = 0; x < num_of_backends; x++) {
1847                 if (__is_backend_busy(x))
1848                         continue;
1849
1850                 job = _pop_queue(x);
1851                 if (job)
1852                         break;
1853         }
1854
1855         /* all backend messages queue are empty or busy */
1856         if (x == num_of_backends || job == NULL) {
1857                 DBG("no job available");
1858                 return FALSE;
1859         }
1860
1861         /* set current backend job */
1862         DBG("handle request type [%d]", job->req_type);
1863
1864         if (job->req_type == REQUEST_TYPE_INSTALL ||
1865                         job->req_type == REQUEST_TYPE_MOUNT_INSTALL ||
1866                         job->req_type == REQUEST_TYPE_REINSTALL) {
1867                 ret = __check_csr(job->pkgid);
1868                 if (ret != 0) {
1869                         ret = -1;
1870                         _send_fail_signal(job);
1871                         _free_backend_job(job);
1872                         return TRUE;
1873                 }
1874         }
1875
1876         switch (job->req_type) {
1877         case REQUEST_TYPE_INSTALL:
1878                 __set_backend_busy(x);
1879                 __set_power_lock();
1880                 ret = __process_install(job);
1881                 __post_process(ret, x, job);
1882                 break;
1883         case REQUEST_TYPE_MOUNT_INSTALL:
1884                 __set_backend_busy(x);
1885                 __set_power_lock();
1886                 ret = __process_mount_install(job);
1887                 __post_process(ret, x, job);
1888                 break;
1889         case REQUEST_TYPE_REINSTALL:
1890                 __set_backend_busy(x);
1891                 __set_power_lock();
1892                 ret = __process_reinstall(job);
1893                 __post_process(ret, x, job);
1894                 break;
1895         case REQUEST_TYPE_UNINSTALL:
1896                 __set_backend_busy(x);
1897                 __set_power_lock();
1898                 ret = __process_uninstall(job);
1899                 __post_process(ret, x, job);
1900                 break;
1901         case REQUEST_TYPE_MOVE:
1902                 __set_backend_busy(x);
1903                 __set_power_lock();
1904                 ret = __process_move(job);
1905                 __post_process(ret, x, job);
1906                 break;
1907         case REQUEST_TYPE_ENABLE_PKG:
1908                 __set_backend_busy(x);
1909                 __set_power_lock();
1910                 ret = __process_enable_pkg(job);
1911                 if (ret < 0)
1912                         _send_fail_signal(job);
1913                 __post_process(ret, x, job);
1914                 break;
1915         case REQUEST_TYPE_DISABLE_PKG:
1916                 __set_backend_busy(x);
1917                 __set_power_lock();
1918                 ret = __process_disable_pkg(job);
1919                 if (ret < 0)
1920                         _send_fail_signal(job);
1921                 __post_process(ret, x, job);
1922                 break;
1923         case REQUEST_TYPE_REGISTER_PKG_UPDATE_INFO:
1924                 ret = __process_register_pkg_update_info(job);
1925                 __free_extra_info(job);
1926                 _free_backend_job(job);
1927                 break;
1928         case REQUEST_TYPE_UNREGISTER_PKG_UPDATE_INFO:
1929                 ret = __process_unregister_pkg_update_info(job);
1930                 _free_backend_job(job);
1931                 break;
1932         case REQUEST_TYPE_UNREGISTER_ALL_PKG_UPDATE_INFO:
1933                 ret = __process_unregister_all_pkg_update_info(job);
1934                 _free_backend_job(job);
1935                 break;
1936         case REQUEST_TYPE_ENABLE_APP:
1937                 ret = __process_enable_app(job);
1938                 _free_backend_job(job);
1939                 break;
1940         case REQUEST_TYPE_DISABLE_APP:
1941                 ret = __process_disable_app(job);
1942                 _free_backend_job(job);
1943                 break;
1944         case REQUEST_TYPE_GETSIZE:
1945                 __set_backend_busy(x);
1946                 ret = __process_getsize(job);
1947                 __post_process(ret, x, job);
1948                 break;
1949         case REQUEST_TYPE_GETSIZE_SYNC:
1950                 __set_backend_busy(x);
1951                 ret = __process_getsize_sync(job);
1952                 if (ret < 0)
1953                         __free_extra_info(job);
1954                 __post_process(ret, x, job);
1955                 break;
1956         case REQUEST_TYPE_CLEARDATA:
1957                 __set_backend_busy(x);
1958                 __set_power_lock();
1959                 ret = __process_cleardata(job);
1960                 __post_process(ret, x, job);
1961                 break;
1962         case REQUEST_TYPE_CLEARCACHE:
1963                 __set_backend_busy(x);
1964                 __set_power_lock();
1965                 ret = __process_clearcache(job);
1966                 __post_process(ret, x, job);
1967                 break;
1968         case REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID:
1969                 ret = __process_enable_global_app_for_uid(job);
1970                 _free_backend_job(job);
1971                 break;
1972         case REQUEST_TYPE_DISABLE_GLOBAL_APP_FOR_UID:
1973                 ret = __process_disable_global_app_for_uid(job);
1974                 _free_backend_job(job);
1975                 break;
1976         case REQUEST_TYPE_KILL:
1977                 ret = __process_kill(job);
1978                 _free_backend_job(job);
1979                 break;
1980         case REQUEST_TYPE_CHECK:
1981                 ret = __process_check(job);
1982                 _free_backend_job(job);
1983                 break;
1984         case REQUEST_TYPE_GENERATE_LICENSE_REQUEST:
1985                 ret = __process_generate_license_request(job);
1986                 _free_backend_job(job);
1987                 break;
1988         case REQUEST_TYPE_REGISTER_LICENSE:
1989                 ret = __process_register_license(job);
1990                 _free_backend_job(job);
1991                 break;
1992         case REQUEST_TYPE_DECRYPT_PACKAGE:
1993                 ret = __process_decrypt_package(job);
1994                 _free_backend_job(job);
1995                 break;
1996         case REQUEST_TYPE_ENABLE_APP_SPLASH_SCREEN:
1997                 ret = __process_update_app_splash_screen(job, 1);
1998                 _free_backend_job(job);
1999                 break;
2000         case REQUEST_TYPE_DISABLE_APP_SPLASH_SCREEN:
2001                 ret = __process_update_app_splash_screen(job, 0);
2002                 _free_backend_job(job);
2003                 break;
2004         case REQUEST_TYPE_SET_RESTRICTION_MODE:
2005                 ret = __process_set_restriction_mode(job);
2006                 _free_backend_job(job);
2007                 break;
2008         case REQUEST_TYPE_UNSET_RESTRICTION_MODE:
2009                 ret = __process_unset_restriction_mode(job);
2010                 _free_backend_job(job);
2011                 break;
2012         case REQUEST_TYPE_GET_RESTRICTION_MODE:
2013                 ret = __process_get_restriction_mode(job);
2014                 _free_backend_job(job);
2015                 break;
2016         case REQUEST_TYPE_SET_APP_LABEL:
2017                 ret = __process_set_app_label(job);
2018                 _free_backend_job(job);
2019                 break;
2020         case REQUEST_TYPE_SET_APP_ICON:
2021                 ret = __process_set_app_icon(job);
2022                 _free_backend_job(job);
2023                 break;
2024         case REQUEST_TYPE_MIGRATE_EXTERNAL_IMAGE:
2025                 __set_backend_busy(x);
2026                 __set_power_lock();
2027                 ret = __process_migrate_external_image(job);
2028                 __post_process(ret, x, job);
2029                 break;
2030         default:
2031                 ret = -1;
2032                 break;
2033         }
2034
2035         return TRUE;
2036 }
2037
2038 int main(int argc, char *argv[])
2039 {
2040         int r;
2041
2042         DBG("server start");
2043
2044         if (__register_signal_handler()) {
2045                 ERR("failed to register signal handler");
2046                 return -1;
2047         }
2048
2049         r = _init_backend_queue();
2050         if (r) {
2051                 ERR("Queue Initialization Failed");
2052                 return -1;
2053         }
2054
2055         r = __init_backend_info();
2056         if (r) {
2057                 ERR("backend info init failed");
2058                 return -1;
2059         }
2060
2061         r = _init_request_handler();
2062         if (r) {
2063                 ERR("dbus init failed");
2064                 return -1;
2065         }
2066
2067 #if !GLIB_CHECK_VERSION(2, 35, 0)
2068         g_type_init();
2069 #endif
2070         mainloop = g_main_loop_new(NULL, FALSE);
2071         if (!mainloop) {
2072                 ERR("g_main_loop_new failed");
2073                 return -1;
2074         }
2075
2076         DBG("Main loop is created.");
2077
2078         g_main_loop_run(mainloop);
2079
2080         DBG("Quit main loop.");
2081         _fini_request_handler();
2082         __fini_backend_info();
2083         _fini_backend_queue();
2084
2085         g_source_remove(swid);
2086         g_io_channel_unref(sio);
2087
2088         DBG("package manager server terminated.");
2089
2090         return 0;
2091 }