Change codes for CPU lock
[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 denied[%d] installation", 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(%d)", 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         pkgid = g_shell_quote(job->pkgid);
845         if (!req_id || !pkgid)
846                 return -1;
847
848         snprintf(args, sizeof(args), "%s -k %s -i %s -u %d %s", backend_cmd,
849                         req_id, pkgid, (int)job->target_uid, job->args);
850
851         argv = __generate_argv(args);
852
853         pid = __fork_and_exec_with_args(argv, APPFW_UID);
854         g_strfreev(argv);
855         g_free(req_id);
856         g_free(pkgid);
857
858         return pid;
859 }
860
861 static int __process_mount_install(struct backend_job *job)
862 {
863         char *backend_cmd;
864         char **argv;
865         char args[MAX_PKG_ARGS_LEN];
866         gchar *req_id;
867         gchar *pkgid;
868         int pid;
869
870         backend_cmd = job->backend_path;
871         if (backend_cmd == NULL)
872                 return -1;
873
874         req_id = g_shell_quote(job->req_id);
875         pkgid = g_shell_quote(job->pkgid);
876         if (!req_id || !pkgid)
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         pkgid = g_shell_quote(job->pkgid);
907         if (!req_id || !pkgid)
908                 return -1;
909
910         snprintf(args, sizeof(args), "%s -k %s -r %s -u %d", backend_cmd,
911                         req_id, pkgid, (int)job->target_uid);
912         argv = __generate_argv(args);
913
914         pid = __fork_and_exec_with_args(argv, APPFW_UID);
915
916         g_strfreev(argv);
917         g_free(req_id);
918         g_free(pkgid);
919
920         return pid;
921 }
922
923 static int __process_uninstall(struct backend_job *job)
924 {
925         char *backend_cmd;
926         char **argv;
927         char args[MAX_PKG_ARGS_LEN];
928         int pid;
929
930         backend_cmd = job->backend_path;
931         if (backend_cmd == NULL)
932                 return -1;
933
934         snprintf(args, sizeof(args), "%s -k %s -d %s -u %d", backend_cmd,
935                         job->req_id, job->pkgid, (int)job->target_uid);
936         argv = __generate_argv(args);
937
938         pid = __fork_and_exec_with_args(argv, APPFW_UID);
939
940         g_strfreev(argv);
941
942         return pid;
943 }
944
945 static int __process_move(struct backend_job *job)
946 {
947         char *backend_cmd;
948         char **argv;
949         char args[MAX_PKG_ARGS_LEN];
950         int pid;
951
952         backend_cmd = job->backend_path;
953         if (backend_cmd == NULL)
954                 return -1;
955
956         snprintf(args, sizeof(args), "%s -k %s -m %s -u %d -t %s", backend_cmd,
957                         job->req_id, job->pkgid, (int)job->target_uid, job->args);
958         argv = __generate_argv(args);
959
960         pid = __fork_and_exec_with_args(argv, APPFW_UID);
961
962         g_strfreev(argv);
963
964         return pid;
965 }
966
967 static int __process_enable_pkg(struct backend_job *job)
968 {
969         char *backend_cmd;
970         char **argv;
971         char args[MAX_PKG_ARGS_LEN];
972         pkgmgrinfo_pkginfo_h pkginfo_h;
973         bool is_readonly;
974         bool is_global;
975         int ret;
976         int pid;
977
978         backend_cmd = job->backend_path;
979         if (backend_cmd == NULL)
980                 return -1;
981
982         ret = pkgmgrinfo_pkginfo_get_usr_disabled_pkginfo(
983                         job->pkgid, job->target_uid, &pkginfo_h);
984         if (ret != PMINFO_R_OK) {
985                 ERR("Failed to get appinfo");
986                 return -1;
987         }
988
989         ret = pkgmgrinfo_pkginfo_is_global(pkginfo_h, &is_global);
990         if (ret != PMINFO_R_OK) {
991                 ERR("Failed to get global value");
992                 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
993                 return -1;
994         }
995
996         if ((is_global && job->target_uid != GLOBAL_USER) ||
997                         (!is_global && job->target_uid == GLOBAL_USER)) {
998                 ERR("Invalid attempt to enable pkg");
999                 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
1000                 return -1;
1001         }
1002
1003         ret = pkgmgrinfo_pkginfo_is_readonly(pkginfo_h, &is_readonly);
1004         if (ret != PMINFO_R_OK) {
1005                 ERR("Failed to get readonly value");
1006                 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
1007                 return -1;
1008         }
1009
1010         snprintf(args, sizeof(args), "%s -k %s -u %d -A %s %s",
1011                         backend_cmd, job->req_id, (int)job->target_uid,
1012                         job->pkgid, (is_readonly) ? "--preload" : "");
1013         argv = __generate_argv(args);
1014         pid = __fork_and_exec_with_args(argv, APPFW_UID);
1015
1016         g_strfreev(argv);
1017         pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
1018
1019         return pid;
1020 }
1021
1022 static int __process_disable_pkg(struct backend_job *job)
1023 {
1024         char *backend_cmd;
1025         char **argv;
1026         char args[MAX_PKG_ARGS_LEN];
1027         pkgmgrinfo_pkginfo_h pkginfo_h;
1028         bool is_readonly;
1029         bool is_global;
1030         int ret;
1031         int pid;
1032
1033         backend_cmd = job->backend_path;
1034         if (backend_cmd == NULL)
1035                 return -1;
1036
1037         ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(
1038                         job->pkgid, job->target_uid, &pkginfo_h);
1039         if (ret != PMINFO_R_OK) {
1040                 ERR("Failed to get appinfo");
1041                 return -1;
1042         }
1043
1044         ret = pkgmgrinfo_pkginfo_is_global(pkginfo_h, &is_global);
1045         if (ret != PMINFO_R_OK) {
1046                 ERR("Failed to get global value");
1047                 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
1048                 return -1;
1049         }
1050
1051         if ((is_global && job->target_uid != GLOBAL_USER) ||
1052                         (!is_global && job->target_uid == GLOBAL_USER)) {
1053                 ERR("Invalid attempt to disable pkg");
1054                 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
1055                 return -1;
1056         }
1057
1058         ret = pkgmgrinfo_pkginfo_is_readonly(pkginfo_h, &is_readonly);
1059         if (ret != PMINFO_R_OK) {
1060                 ERR("Failed to get readonly value");
1061                 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
1062                 return -1;
1063         }
1064
1065         snprintf(args, sizeof(args), "%s -k %s -u %d -D %s %s",
1066                         backend_cmd, job->req_id, (int)job->target_uid,
1067                         job->pkgid, (is_readonly) ? "--preload" : "");
1068         argv = __generate_argv(args);
1069
1070         pid = __fork_and_exec_with_args(argv, APPFW_UID);
1071
1072         g_strfreev(argv);
1073
1074         pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
1075         return pid;
1076 }
1077
1078 static int __process_register_pkg_update_info(struct backend_job *job)
1079 {
1080         int ret;
1081
1082         if (!job->extra_data) {
1083                 _return_value_to_caller(job->req_id,
1084                                 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
1085                 return -1;
1086         }
1087
1088         ret = pkgmgr_parser_register_pkg_update_info_in_usr_db(
1089                         (pkgmgrinfo_updateinfo_h)job->extra_data, job->target_uid);
1090         if (ret == PMINFO_R_OK)
1091                 _return_value_to_caller(job->req_id,
1092                                 g_variant_new("(i)", PKGMGR_R_OK));
1093         else
1094                 _return_value_to_caller(job->req_id,
1095                                 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
1096
1097         pkgmgrinfo_updateinfo_destroy(job->extra_data);
1098         job->extra_data = NULL;
1099
1100         return ret;
1101 }
1102
1103 static int __process_unregister_pkg_update_info(struct backend_job *job)
1104 {
1105         int ret = pkgmgr_parser_unregister_pkg_update_info_in_usr_db
1106                         (job->pkgid, job->target_uid);
1107
1108         if (ret == PMINFO_R_OK)
1109                 _return_value_to_caller(job->req_id,
1110                                 g_variant_new("(i)", PKGMGR_R_OK));
1111         else
1112                 _return_value_to_caller(job->req_id,
1113                                 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
1114         return ret;
1115 }
1116
1117 static int __process_unregister_all_pkg_update_info(struct backend_job *job)
1118 {
1119         int ret = pkgmgr_parser_unregister_all_pkg_update_info_in_usr_db(
1120                         job->target_uid);
1121
1122         if (ret != PMINFO_R_OK) {
1123                 _return_value_to_caller(job->req_id,
1124                                 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
1125                 return ret;
1126         }
1127
1128         if (__is_admin_user(job->caller_uid)) {
1129                 ret = pkgmgr_parser_unregister_all_pkg_update_info_in_usr_db(
1130                                 GLOBAL_USER);
1131                 if (ret != PMINFO_R_OK) {
1132                         _return_value_to_caller(job->req_id,
1133                                         g_variant_new("(i)", PKGMGR_R_ESYSTEM));
1134                         return ret;
1135                 }
1136         }
1137         _return_value_to_caller(job->req_id,
1138                         g_variant_new("(i)", PKGMGR_R_OK));
1139
1140         return ret;
1141 }
1142
1143 static int __process_enable_app(struct backend_job *job)
1144 {
1145         int ret = -1;
1146         bool is_global = false;
1147
1148         /* get actual pkgid and replace it to appid which is currently stored
1149          * at pkgid variable
1150          */
1151         ret = __change_job_info(job, job->target_uid, &is_global);
1152         if (ret != PMINFO_R_OK || strlen(job->appid) == 0) {
1153                 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
1154                                 PKGMGR_INSTALLER_START_KEY_STR,
1155                                 PKGMGR_INSTALLER_APP_ENABLE_EVENT_STR,
1156                                 job->req_type);
1157                 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
1158                                 PKGMGR_INSTALLER_END_KEY_STR,
1159                                 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1160                                 job->req_type);
1161                 return ret;
1162         }
1163
1164         _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1165                         PKGMGR_INSTALLER_START_KEY_STR,
1166                         PKGMGR_INSTALLER_APP_ENABLE_EVENT_STR, job->req_type);
1167
1168         ret = pkgmgr_parser_update_app_disable_info_in_usr_db(job->appid,
1169                         job->target_uid, 0);
1170         if (ret != PMINFO_R_OK)
1171                 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1172                                 PKGMGR_INSTALLER_END_KEY_STR,
1173                                 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1174                                 job->req_type);
1175         else
1176                 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1177                                 PKGMGR_INSTALLER_END_KEY_STR,
1178                                 PKGMGR_INSTALLER_OK_EVENT_STR,
1179                                 job->req_type);
1180
1181         return ret;
1182 }
1183
1184 static int __process_disable_app(struct backend_job *job)
1185 {
1186         int ret = -1;
1187         bool is_global = false;
1188
1189         /* get actual pkgid and replace it to appid which is currently stored
1190          * at pkgid variable
1191          */
1192         ret = __change_job_info(job, job->target_uid, &is_global);
1193         if (ret != PMINFO_R_OK || strlen(job->appid) == 0) {
1194                 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
1195                                 PKGMGR_INSTALLER_START_KEY_STR,
1196                                 PKGMGR_INSTALLER_APP_DISABLE_EVENT_STR,
1197                                 job->req_type);
1198                 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
1199                                 PKGMGR_INSTALLER_END_KEY_STR,
1200                                 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1201                                 job->req_type);
1202                 return ret;
1203         }
1204
1205         _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1206                         PKGMGR_INSTALLER_START_KEY_STR,
1207                         PKGMGR_INSTALLER_APP_DISABLE_EVENT_STR, job->req_type);
1208
1209         ret = __kill_app(job->appid, job->target_uid);
1210         if (ret != 0) {
1211                 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1212                                 PKGMGR_INSTALLER_END_KEY_STR,
1213                                 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1214                                 job->req_type);
1215         }
1216
1217         ret = pkgmgr_parser_update_app_disable_info_in_usr_db(job->appid,
1218                         job->target_uid, 1);
1219         if (ret != PMINFO_R_OK)
1220                 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1221                                 PKGMGR_INSTALLER_END_KEY_STR,
1222                                 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1223                                 job->req_type);
1224         else
1225                 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1226                                 PKGMGR_INSTALLER_END_KEY_STR,
1227                                 PKGMGR_INSTALLER_OK_EVENT_STR,
1228                                 job->req_type);
1229
1230         return ret;
1231 }
1232
1233 static int __process_enable_global_app_for_uid(struct backend_job *job)
1234 {
1235         int ret = -1;
1236         bool is_global = true;
1237
1238         /* get actual pkgid and replace it to appid which is currently stored
1239          * at pkgid variable
1240          */
1241         ret = __change_job_info(job, job->target_uid, &is_global);
1242         if (ret != PMINFO_R_OK || strlen(job->appid) == 0) {
1243                 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
1244                                 PKGMGR_INSTALLER_START_KEY_STR,
1245                                 PKGMGR_INSTALLER_APP_ENABLE_EVENT_STR,
1246                                 job->req_type);
1247                 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
1248                                 PKGMGR_INSTALLER_END_KEY_STR,
1249                                 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1250                                 job->req_type);
1251                 return ret;
1252         }
1253
1254         _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1255                         PKGMGR_INSTALLER_START_KEY_STR,
1256                         PKGMGR_INSTALLER_APP_ENABLE_EVENT_STR,
1257                         job->req_type);
1258
1259         ret = pkgmgr_parser_update_global_app_disable_for_uid_info_in_db(
1260                         job->appid, job->target_uid, 0);
1261         if (ret != PMINFO_R_OK)
1262                 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1263                                 PKGMGR_INSTALLER_END_KEY_STR,
1264                                 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1265                                 job->req_type);
1266         else
1267                 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1268                                 PKGMGR_INSTALLER_END_KEY_STR,
1269                                 PKGMGR_INSTALLER_OK_EVENT_STR,
1270                                 job->req_type);
1271
1272         return ret;
1273 }
1274
1275 static int __process_disable_global_app_for_uid(struct backend_job *job)
1276 {
1277         int ret = -1;
1278         bool is_global = true;
1279
1280         /* get actual pkgid and replace it to appid which is currently stored
1281          * at pkgid variable
1282          */
1283         ret = __change_job_info(job, GLOBAL_USER, &is_global);
1284         if (ret != PMINFO_R_OK || strlen(job->appid) == 0) {
1285                 _send_app_signal(job->target_uid, job->req_id,
1286                                 job->pkgid, job->pkgid,
1287                                 PKGMGR_INSTALLER_START_KEY_STR,
1288                                 PKGMGR_INSTALLER_APP_DISABLE_EVENT_STR,
1289                                 job->req_type);
1290                 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->pkgid,
1291                                 PKGMGR_INSTALLER_END_KEY_STR,
1292                                 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1293                                 job->req_type);
1294                 return ret;
1295         }
1296
1297         _send_app_signal(job->target_uid, job->req_id,
1298                         job->pkgid, job->appid,
1299                         PKGMGR_INSTALLER_START_KEY_STR,
1300                         PKGMGR_INSTALLER_APP_DISABLE_EVENT_STR,
1301                         job->req_type);
1302
1303         ret = __kill_app(job->appid, job->target_uid);
1304         ret = pkgmgr_parser_update_global_app_disable_for_uid_info_in_db(
1305                         job->appid, job->target_uid, 1);
1306
1307         if (ret != PMINFO_R_OK)
1308                 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1309                                 PKGMGR_INSTALLER_END_KEY_STR,
1310                                 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1311                                 job->req_type);
1312         else
1313                 _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1314                                 PKGMGR_INSTALLER_END_KEY_STR,
1315                                 PKGMGR_INSTALLER_OK_EVENT_STR,
1316                                 job->req_type);
1317
1318         return ret;
1319 }
1320
1321 static int __process_getsize(struct backend_job *job)
1322 {
1323         static const char backend_cmd[] = "/usr/bin/pkg_getsize";
1324         char **argv;
1325         char args[MAX_PKG_ARGS_LEN];
1326         int pid;
1327
1328         snprintf(args, sizeof(args), "%s %s %s %d -k %s -u %d",
1329                         backend_cmd, job->pkgid, job->args, job->caller_uid,
1330                         job->req_id, job->target_uid);
1331         argv = __generate_argv(args);
1332         pid = __fork_and_exec_with_args(argv, APPFW_UID);
1333
1334         g_strfreev(argv);
1335
1336         return pid;
1337 }
1338
1339 static int __process_getsize_sync(struct backend_job *job)
1340 {
1341         static const char backend_cmd[] = "/usr/bin/pkg_getsize";
1342         char **argv;
1343         char args[MAX_PKG_ARGS_LEN];
1344         char fifo_path[PATH_MAX];
1345         struct getsize_sync_extra_info *extra_getsize_info;
1346         int pid;
1347
1348         snprintf(fifo_path, sizeof(fifo_path), "/tmp/pkgmgr/%s",
1349                         job->req_id);
1350
1351         extra_getsize_info = calloc(1, sizeof(struct getsize_sync_extra_info));
1352         if (!extra_getsize_info) {
1353                 ERR("memory alloc failed");
1354                 goto error;
1355         }
1356
1357         extra_getsize_info->getsize_fifo = strdup(fifo_path);
1358         if (!extra_getsize_info->getsize_fifo) {
1359                 ERR("out of memory");
1360                 goto error;
1361         }
1362
1363         if (mkfifo(extra_getsize_info->getsize_fifo, 0600) < 0) {
1364                 ERR("failed to mkfifo");
1365                 goto error;
1366         }
1367         job->extra_data = extra_getsize_info;
1368
1369         snprintf(args, sizeof(args), "%s %s %s %d -k %s -u %d --sync",
1370                         backend_cmd, job->pkgid, job->args, job->caller_uid,
1371                         job->req_id, job->target_uid);
1372         argv = __generate_argv(args);
1373         pid = __fork_and_exec_with_args(argv, APPFW_UID);
1374
1375         g_strfreev(argv);
1376
1377         if (pid < 0) {
1378                 ERR("failed to execute backend");
1379                 goto error;
1380         }
1381         if (__setup_size_info_io(job) < 0) {
1382                 ERR("failed to setup io handler");
1383                 goto error;
1384         }
1385
1386         return pid;
1387
1388 error:
1389         _return_value_to_caller(job->req_id,
1390                 g_variant_new("(ix)", PKGMGR_R_ERROR, -1));
1391         return -1;
1392 }
1393
1394 static int __process_cleardata(struct backend_job *job)
1395 {
1396         static const char *backend_cmd = "/usr/bin/pkg_cleardata";
1397         char **argv;
1398         char args[MAX_PKG_ARGS_LEN];
1399         int pid;
1400
1401         if ((int)job->target_uid < REGULAR_USER)
1402                 return -1;
1403
1404         snprintf(args, sizeof(args), "%s -d -n %s -u %d",
1405                         backend_cmd, job->pkgid, job->target_uid);
1406         argv = __generate_argv(args);
1407         pid = __fork_and_exec_with_args(argv, APPFW_UID);
1408
1409         g_strfreev(argv);
1410         return pid;
1411 }
1412
1413 static int __process_clearcache(struct backend_job *job)
1414 {
1415         static const char *backend_cmd = "/usr/bin/pkg_cleardata";
1416         char **argv;
1417         char args[MAX_PKG_ARGS_LEN];
1418         int pid;
1419
1420         if ((int)job->target_uid < REGULAR_USER)
1421                 return -1;
1422
1423         snprintf(args, sizeof(args), "%s -c -n %s -u %d",
1424                         backend_cmd, job->pkgid, job->target_uid);
1425         argv = __generate_argv(args);
1426         pid = __fork_and_exec_with_args(argv, APPFW_UID);
1427
1428         g_strfreev(argv);
1429         return pid;
1430 }
1431
1432 static int __process_kill(struct backend_job *job)
1433 {
1434         int ret;
1435         pkgmgrinfo_pkginfo_h handle;
1436         pkgcmd_data *pdata;
1437
1438         ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(job->pkgid, job->target_uid,
1439                         &handle);
1440         if (ret < 0) {
1441                 ERR("Failed to get handle");
1442                 _return_value_to_caller(job->req_id,
1443                                 g_variant_new("(ii)", PKGMGR_R_ERROR, 0));
1444                 return -1;
1445         }
1446
1447         pdata = calloc(1, sizeof(pkgcmd_data));
1448         if (pdata == NULL) {
1449                 ERR("memory alloc failed");
1450                 _return_value_to_caller(job->req_id,
1451                                 g_variant_new("(ii)", PKGMGR_R_ENOMEM, 0));
1452                 return -1;
1453         }
1454         pdata->cmd = strdup("kill");
1455         if (pdata->cmd == NULL) {
1456                 ERR("out of memory");
1457                 _return_value_to_caller(job->req_id,
1458                                 g_variant_new("(ii)", PKGMGR_R_ENOMEM, 0));
1459                 free(pdata);
1460                 return -1;
1461         }
1462         pdata->uid = job->target_uid;
1463         ret = pkgmgrinfo_appinfo_get_usr_list(handle, PMINFO_ALL_APP,
1464                         __pkgcmd_app_cb, pdata, job->target_uid);
1465
1466         _return_value_to_caller(job->req_id,
1467                         g_variant_new("(ii)", PKGMGR_R_OK, pdata->pid));
1468
1469         free(pdata->cmd);
1470         free(pdata);
1471         pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
1472         if (ret < 0) {
1473                 ERR("pkgmgrinfo_appinfo_get_list() failed");
1474                 return -1;
1475         }
1476
1477         return 0;
1478 }
1479
1480 static int __process_check(struct backend_job *job)
1481 {
1482         int ret;
1483         pkgmgrinfo_pkginfo_h handle;
1484         pkgcmd_data *pdata;
1485
1486         ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(job->pkgid, job->target_uid,
1487                         &handle);
1488         if (ret < 0) {
1489                 ERR("Failed to get handle");
1490                 _return_value_to_caller(job->req_id,
1491                                 g_variant_new("(ii)", PKGMGR_R_ERROR, 0));
1492                 return -1;
1493         }
1494
1495         pdata = calloc(1, sizeof(pkgcmd_data));
1496         if (pdata == NULL) {
1497                 ERR("memory alloc failed");
1498                 _return_value_to_caller(job->req_id,
1499                                 g_variant_new("(ii)", PKGMGR_R_ENOMEM, 0));
1500                 return -1;
1501         }
1502         pdata->cmd = strdup("check");
1503         if (pdata->cmd == NULL) {
1504                 ERR("out of memory");
1505                 _return_value_to_caller(job->req_id,
1506                                 g_variant_new("(ii)", PKGMGR_R_ENOMEM, 0));
1507                 free(pdata);
1508                 return -1;
1509         }
1510         pdata->uid = job->target_uid;
1511         ret = pkgmgrinfo_appinfo_get_usr_list(handle, PMINFO_ALL_APP,
1512                         __pkgcmd_app_cb, pdata, job->target_uid);
1513
1514         _return_value_to_caller(job->req_id,
1515                         g_variant_new("(ii)", PKGMGR_R_OK, pdata->pid));
1516
1517         free(pdata->cmd);
1518         free(pdata);
1519         pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
1520         if (ret < 0) {
1521                 ERR("pkgmgrinfo_appinfo_get_list() failed");
1522                 return -1;
1523         }
1524
1525         return 0;
1526 }
1527
1528 static int __load_drm_library(void)
1529 {
1530         if (drm_lib_handle)
1531                 return 0;
1532
1533         drm_lib_handle = dlopen(PATH_LIBDRM_SVC_CORE, RTLD_LAZY);
1534         if (!drm_lib_handle) {
1535                 DBG("Unable to open %s", PATH_LIBDRM_SVC_CORE);
1536                 return -1;
1537         }
1538
1539         _drm_tizen_generate_license_request =
1540                         dlsym(drm_lib_handle, "drm_tizen_generate_license_request");
1541         if (_drm_tizen_generate_license_request == NULL) {
1542                 ERR("_drm_tizen_generate_license_request() failed");
1543                 goto catch;
1544         }
1545
1546         _drm_tizen_register_license =
1547                                 dlsym(drm_lib_handle, "drm_tizen_register_license");
1548         if (_drm_tizen_register_license == NULL) {
1549                 ERR("_register_license() failed");
1550                 goto catch;
1551         }
1552
1553         _drm_tizen_decrypt_package =
1554                         dlsym(drm_lib_handle, "drm_tizen_decrypt_package");
1555         if (_drm_tizen_decrypt_package == NULL) {
1556                 ERR("_drm_tizen_decrypt_package() failed");
1557                 goto catch;
1558         }
1559
1560         return 0;
1561 catch:
1562         if (drm_lib_handle) {
1563                 dlclose(drm_lib_handle);
1564                 drm_lib_handle = NULL;
1565         }
1566         return -1;
1567 }
1568
1569 static void __unload_drm_library(void)
1570 {
1571         if (drm_lib_handle) {
1572                 dlclose(drm_lib_handle);
1573                 drm_lib_handle = NULL;
1574         }
1575 }
1576
1577 static int __process_generate_license_request(struct backend_job *job)
1578 {
1579         char *resp_data;
1580         char req_data[MAX_PKG_ARGS_LEN];
1581         unsigned int req_data_len;
1582         char license_url[MAX_PKG_ARGS_LEN];
1583         unsigned int license_url_len;
1584         int ret;
1585
1586         resp_data = job->args;
1587         req_data_len = sizeof(req_data);
1588         license_url_len = sizeof(license_url);
1589
1590         if (__load_drm_library() != 0) {
1591                 ERR("Failed to load library");
1592                 goto catch;
1593         }
1594
1595         ret = _drm_tizen_generate_license_request(resp_data, strlen(resp_data),
1596                         req_data, &req_data_len,
1597                         license_url, &license_url_len);
1598         if (ret != 1) {
1599                 ERR("drm_tizen_generate_license_request failed");
1600                 goto catch;
1601         }
1602         _return_value_to_caller(job->req_id,
1603                         g_variant_new("(iss)", PKGMGR_R_OK, req_data,
1604                                 license_url));
1605         is_drm_busy = true;
1606         return 0;
1607
1608 catch:
1609         _return_value_to_caller(job->req_id, g_variant_new("(iss)",
1610                                 PKGMGR_R_ESYSTEM, "", ""));
1611         is_drm_busy = false;
1612         __unload_drm_library();
1613         return -1;
1614 }
1615
1616 static int __process_register_license(struct backend_job *job)
1617 {
1618         char *resp_data;
1619         int ret;
1620
1621         resp_data = job->args;
1622         if (!_drm_tizen_register_license) {
1623                 ERR("_drm_tizen_register_license is not loaded");
1624                 goto catch;
1625         }
1626         ret = _drm_tizen_register_license(resp_data, strlen(resp_data));
1627         if (ret != 1) {
1628                 ERR("drm_tizen_register_license failed: %d", ret);
1629                 goto catch;
1630         }
1631         _return_value_to_caller(job->req_id,
1632                         g_variant_new("(i)", PKGMGR_R_OK));
1633         return 0;
1634
1635 catch:
1636         _return_value_to_caller(job->req_id,
1637                         g_variant_new("(i)", PKGMGR_R_ESYSTEM));
1638         is_drm_busy = false;
1639         __unload_drm_library();
1640
1641         return -1;
1642 }
1643
1644 static int __process_decrypt_package(struct backend_job *job)
1645 {
1646         int ret;
1647         char *drm_file_path;
1648         char *decrypted_file_path;
1649
1650         drm_file_path = job->pkgid;
1651         decrypted_file_path = job->args;
1652
1653         /* TODO: check ownership of decrypted file */
1654         if (!_drm_tizen_decrypt_package) {
1655                 ERR("drm_tizen_decrypt_package is not loaded");
1656
1657                 goto catch;
1658         }
1659         ret = _drm_tizen_decrypt_package(drm_file_path, strlen(drm_file_path),
1660                         decrypted_file_path, strlen(decrypted_file_path));
1661         if (ret != 1) {
1662                 ERR("drm_tizen_decrypt_package failed: %d", ret);
1663                 goto catch;
1664         }
1665         _return_value_to_caller(job->req_id,
1666                         g_variant_new("(i)", PKGMGR_R_OK));
1667         return 0;
1668
1669 catch:
1670         _return_value_to_caller(job->req_id,
1671                 g_variant_new("(i)", PKGMGR_R_ESYSTEM));
1672         is_drm_busy = false;
1673         __unload_drm_library();
1674
1675         return -1;
1676 }
1677
1678 static int __process_update_app_splash_screen(struct backend_job *job, int flag)
1679 {
1680         int ret;
1681         bool is_global = false;
1682         const char *val;
1683
1684         ret = __change_job_info(job, job->target_uid, &is_global);
1685         if (ret != PMINFO_R_OK || strlen(job->appid) == 0)
1686                 return -1;
1687
1688         val = flag ? PKGMGR_INSTALLER_APP_ENABLE_SPLASH_SCREEN_EVENT_STR :
1689                 PKGMGR_INSTALLER_APP_DISABLE_SPLASH_SCREEN_EVENT_STR;
1690         _send_app_signal(job->target_uid, job->req_id, job->pkgid, job->appid,
1691                         PKGMGR_INSTALLER_START_KEY_STR, val, job->req_type);
1692
1693         if (is_global)
1694                 ret = pkgmgr_parser_update_global_app_splash_screen_display_info_in_usr_db(job->appid, job->target_uid, flag);
1695         else
1696                 ret = pkgmgr_parser_update_app_splash_screen_display_info_in_usr_db(
1697                         job->appid, job->target_uid, flag);
1698         if (ret != PMINFO_R_OK)
1699                 _send_app_signal(job->target_uid, job->req_id, job->pkgid,
1700                                 job->appid, PKGMGR_INSTALLER_END_KEY_STR,
1701                                 PKGMGR_INSTALLER_FAIL_EVENT_STR,
1702                                 job->req_type);
1703         else
1704                 _send_app_signal(job->target_uid, job->req_id, job->pkgid,
1705                                 job->appid, PKGMGR_INSTALLER_END_KEY_STR,
1706                                 PKGMGR_INSTALLER_OK_EVENT_STR,
1707                                 job->req_type);
1708
1709         return ret;
1710 }
1711
1712 static int __process_set_restriction_mode(struct backend_job *job)
1713 {
1714         int ret;
1715         int mode;
1716
1717         mode = atoi(job->args);
1718         ret = _set_restriction_mode(job->target_uid, job->pkgid, mode);
1719
1720         _return_value_to_caller(job->req_id,
1721                         g_variant_new("(i)", ret));
1722
1723         return ret;
1724 }
1725
1726 static int __process_unset_restriction_mode(struct backend_job *job)
1727 {
1728         int ret;
1729         int mode;
1730
1731         mode = atoi(job->args);
1732         ret = _unset_restriction_mode(job->target_uid, job->pkgid, mode);
1733
1734         _return_value_to_caller(job->req_id,
1735                         g_variant_new("(i)", ret));
1736
1737         return ret;
1738 }
1739
1740 static int __process_get_restriction_mode(struct backend_job *job)
1741 {
1742         int ret;
1743         int mode = -1;
1744
1745         ret = _get_restriction_mode(job->target_uid, job->pkgid, &mode);
1746
1747         _return_value_to_caller(job->req_id,
1748                         g_variant_new("(ii)", mode, ret));
1749
1750         return ret;
1751 }
1752
1753 static int __process_set_app_label(struct backend_job *job)
1754 {
1755         int ret;
1756
1757         ret = pkgmgr_parser_update_app_label_info_in_usr_db(job->pkgid,
1758                         job->target_uid, job->args);
1759         _return_value_to_caller(job->req_id, g_variant_new("(i)", ret));
1760
1761         return ret;
1762 }
1763
1764 static int __process_migrate_external_image(struct backend_job *job)
1765 {
1766         char *backend_cmd;
1767         char **argv;
1768         char args[MAX_PKG_ARGS_LEN];
1769         int pid;
1770
1771         backend_cmd = job->backend_path;
1772         if (backend_cmd == NULL)
1773                 return -1;
1774
1775         snprintf(args, sizeof(args), "%s -k %s --migrate-extimg %s -u %d %s",
1776                         backend_cmd, job->req_id, job->pkgid,
1777                         (int)job->target_uid, job->args);
1778
1779         argv = __generate_argv(args);
1780
1781         pid = __fork_and_exec_with_args(argv, APPFW_UID);
1782         g_strfreev(argv);
1783
1784         return pid;
1785 }
1786
1787 static int __post_process(int ret, int x, struct backend_job *job)
1788 {
1789         if (ret < 0) {
1790                 __set_backend_free(x);
1791                 _free_backend_job(job);
1792         } else {
1793                 g_hash_table_insert(backend_info_table, (gpointer)ret,
1794                                 (gpointer)job);
1795         }
1796         return 0;
1797 }
1798
1799 gboolean queue_job(void *data)
1800 {
1801         struct backend_job *job = NULL;
1802         int x;
1803         int ret;
1804
1805         /* Pop a job from queue */
1806         for (x = 0; x < num_of_backends; x++) {
1807                 if (__is_backend_busy(x))
1808                         continue;
1809
1810                 job = _pop_queue(x);
1811                 if (job)
1812                         break;
1813         }
1814
1815         /* all backend messages queue are empty or busy */
1816         if (x == num_of_backends || job == NULL) {
1817                 DBG("no job available");
1818                 return FALSE;
1819         }
1820
1821         /* set current backend job */
1822         DBG("handle request type [%d]", job->req_type);
1823
1824         if (job->req_type == REQUEST_TYPE_INSTALL ||
1825                         job->req_type == REQUEST_TYPE_MOUNT_INSTALL ||
1826                         job->req_type == REQUEST_TYPE_REINSTALL) {
1827                 ret = __check_csr(job->pkgid);
1828                 if (ret != 0) {
1829                         ret = -1;
1830                         _send_fail_signal(job);
1831                         _free_backend_job(job);
1832                         return TRUE;
1833                 }
1834         }
1835
1836         switch (job->req_type) {
1837         case REQUEST_TYPE_INSTALL:
1838                 __set_backend_busy(x);
1839                 __set_power_lock();
1840                 ret = __process_install(job);
1841                 __post_process(ret, x, job);
1842                 break;
1843         case REQUEST_TYPE_MOUNT_INSTALL:
1844                 __set_backend_busy(x);
1845                 __set_power_lock();
1846                 ret = __process_mount_install(job);
1847                 __post_process(ret, x, job);
1848                 break;
1849         case REQUEST_TYPE_REINSTALL:
1850                 __set_backend_busy(x);
1851                 __set_power_lock();
1852                 ret = __process_reinstall(job);
1853                 __post_process(ret, x, job);
1854                 break;
1855         case REQUEST_TYPE_UNINSTALL:
1856                 __set_backend_busy(x);
1857                 __set_power_lock();
1858                 ret = __process_uninstall(job);
1859                 __post_process(ret, x, job);
1860                 break;
1861         case REQUEST_TYPE_MOVE:
1862                 __set_backend_busy(x);
1863                 __set_power_lock();
1864                 ret = __process_move(job);
1865                 __post_process(ret, x, job);
1866                 break;
1867         case REQUEST_TYPE_ENABLE_PKG:
1868                 __set_backend_busy(x);
1869                 __set_power_lock();
1870                 ret = __process_enable_pkg(job);
1871                 if (ret < 0)
1872                         _send_fail_signal(job);
1873                 __post_process(ret, x, job);
1874                 break;
1875         case REQUEST_TYPE_DISABLE_PKG:
1876                 __set_backend_busy(x);
1877                 __set_power_lock();
1878                 ret = __process_disable_pkg(job);
1879                 if (ret < 0)
1880                         _send_fail_signal(job);
1881                 __post_process(ret, x, job);
1882                 break;
1883         case REQUEST_TYPE_REGISTER_PKG_UPDATE_INFO:
1884                 ret = __process_register_pkg_update_info(job);
1885                 __free_extra_info(job);
1886                 _free_backend_job(job);
1887                 break;
1888         case REQUEST_TYPE_UNREGISTER_PKG_UPDATE_INFO:
1889                 ret = __process_unregister_pkg_update_info(job);
1890                 _free_backend_job(job);
1891                 break;
1892         case REQUEST_TYPE_UNREGISTER_ALL_PKG_UPDATE_INFO:
1893                 ret = __process_unregister_all_pkg_update_info(job);
1894                 _free_backend_job(job);
1895                 break;
1896         case REQUEST_TYPE_ENABLE_APP:
1897                 ret = __process_enable_app(job);
1898                 _free_backend_job(job);
1899                 break;
1900         case REQUEST_TYPE_DISABLE_APP:
1901                 ret = __process_disable_app(job);
1902                 _free_backend_job(job);
1903                 break;
1904         case REQUEST_TYPE_GETSIZE:
1905                 __set_backend_busy(x);
1906                 ret = __process_getsize(job);
1907                 __post_process(ret, x, job);
1908                 break;
1909         case REQUEST_TYPE_GETSIZE_SYNC:
1910                 __set_backend_busy(x);
1911                 ret = __process_getsize_sync(job);
1912                 if (ret < 0)
1913                         __free_extra_info(job);
1914                 __post_process(ret, x, job);
1915                 break;
1916         case REQUEST_TYPE_CLEARDATA:
1917                 __set_backend_busy(x);
1918                 __set_power_lock();
1919                 ret = __process_cleardata(job);
1920                 __post_process(ret, x, job);
1921                 break;
1922         case REQUEST_TYPE_CLEARCACHE:
1923                 __set_backend_busy(x);
1924                 __set_power_lock();
1925                 ret = __process_clearcache(job);
1926                 __post_process(ret, x, job);
1927                 break;
1928         case REQUEST_TYPE_ENABLE_GLOBAL_APP_FOR_UID:
1929                 ret = __process_enable_global_app_for_uid(job);
1930                 _free_backend_job(job);
1931                 break;
1932         case REQUEST_TYPE_DISABLE_GLOBAL_APP_FOR_UID:
1933                 ret = __process_disable_global_app_for_uid(job);
1934                 _free_backend_job(job);
1935                 break;
1936         case REQUEST_TYPE_KILL:
1937                 ret = __process_kill(job);
1938                 _free_backend_job(job);
1939                 break;
1940         case REQUEST_TYPE_CHECK:
1941                 ret = __process_check(job);
1942                 _free_backend_job(job);
1943                 break;
1944         case REQUEST_TYPE_GENERATE_LICENSE_REQUEST:
1945                 ret = __process_generate_license_request(job);
1946                 _free_backend_job(job);
1947                 break;
1948         case REQUEST_TYPE_REGISTER_LICENSE:
1949                 ret = __process_register_license(job);
1950                 _free_backend_job(job);
1951                 break;
1952         case REQUEST_TYPE_DECRYPT_PACKAGE:
1953                 ret = __process_decrypt_package(job);
1954                 _free_backend_job(job);
1955                 break;
1956         case REQUEST_TYPE_ENABLE_APP_SPLASH_SCREEN:
1957                 ret = __process_update_app_splash_screen(job, 1);
1958                 _free_backend_job(job);
1959                 break;
1960         case REQUEST_TYPE_DISABLE_APP_SPLASH_SCREEN:
1961                 ret = __process_update_app_splash_screen(job, 0);
1962                 _free_backend_job(job);
1963                 break;
1964         case REQUEST_TYPE_SET_RESTRICTION_MODE:
1965                 ret = __process_set_restriction_mode(job);
1966                 _free_backend_job(job);
1967                 break;
1968         case REQUEST_TYPE_UNSET_RESTRICTION_MODE:
1969                 ret = __process_unset_restriction_mode(job);
1970                 _free_backend_job(job);
1971                 break;
1972         case REQUEST_TYPE_GET_RESTRICTION_MODE:
1973                 ret = __process_get_restriction_mode(job);
1974                 _free_backend_job(job);
1975                 break;
1976         case REQUEST_TYPE_SET_APP_LABEL:
1977                 ret = __process_set_app_label(job);
1978                 _free_backend_job(job);
1979                 break;
1980         case REQUEST_TYPE_MIGRATE_EXTERNAL_IMAGE:
1981                 __set_backend_busy(x);
1982                 __set_power_lock();
1983                 ret = __process_migrate_external_image(job);
1984                 __post_process(ret, x, job);
1985                 break;
1986         default:
1987                 ret = -1;
1988                 break;
1989         }
1990
1991         return TRUE;
1992 }
1993
1994 int main(int argc, char *argv[])
1995 {
1996         int r;
1997
1998         DBG("server start");
1999
2000         if (__register_signal_handler()) {
2001                 ERR("failed to register signal handler");
2002                 return -1;
2003         }
2004
2005         r = _init_backend_queue();
2006         if (r) {
2007                 ERR("Queue Initialization Failed");
2008                 return -1;
2009         }
2010
2011         r = __init_backend_info();
2012         if (r) {
2013                 ERR("backend info init failed");
2014                 return -1;
2015         }
2016
2017         r = _init_request_handler();
2018         if (r) {
2019                 ERR("dbus init failed");
2020                 return -1;
2021         }
2022
2023 #if !GLIB_CHECK_VERSION(2, 35, 0)
2024         g_type_init();
2025 #endif
2026         mainloop = g_main_loop_new(NULL, FALSE);
2027         if (!mainloop) {
2028                 ERR("g_main_loop_new failed");
2029                 return -1;
2030         }
2031
2032         DBG("Main loop is created.");
2033
2034         g_main_loop_run(mainloop);
2035
2036         DBG("Quit main loop.");
2037         _fini_request_handler();
2038         __fini_backend_info();
2039         _fini_backend_queue();
2040
2041         g_source_remove(swid);
2042         g_io_channel_unref(sio);
2043
2044         DBG("package manager server terminated.");
2045
2046         return 0;
2047 }