4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Jayoun Lee <airjany@samsung.com>, Sewook Park <sewook7.park@samsung.com>, Jaeho Lee <jaeho81.lee@samsung.com>
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
31 #include <sys/smack.h>
33 #include <tzplatform_config.h>
34 #include "ail_private.h"
37 #define GLOBAL_USER tzplatform_getuid(TZ_SYS_GLOBALAPP_USER)
39 #define QUERY_ATTACH "attach database '%s' as Global"
40 #define QUERY_CREATE_VIEW_APP "CREATE temp VIEW app_info as select distinct * from (select * from main.app_info m union select * from Global.app_info g)"
42 #define QUERY_CREATE_VIEW_LOCAL "CREATE temp VIEW localname as select distinct * from (select * from main.localname m union select * from Global.localname g)"
44 #define SET_SMACK_LABEL(x, uid) \
46 if (smack_setlabel((x), (((uid) == GLOBAL_USER) ? "*" : "User"), SMACK_LABEL_ACCESS)) \
47 _E("failed chsmack -a \"User/*\" %s", x); \
49 _D("chsmack -a \"User/*\" %s", x); \
52 #define retv_with_dbmsg_if(expr, val) \
55 _E("db_info.dbUserro: %s", sqlite3_errmsg(db_info.dbUserro)); \
56 _E("db_info.dbGlobalro: %s", sqlite3_errmsg(db_info.dbGlobalro)); \
57 _E("db_info.dbUserrw: %s", sqlite3_errmsg(db_info.dbUserrw)); \
58 _E("db_info.dbGlobalrw: %s", sqlite3_errmsg(db_info.dbGlobalrw)); \
59 _E("db_info.dbUserro errcode: %d", sqlite3_extended_errcode(db_info.dbUserro)); \
60 _E("db_info.dbGlobalro errcode: %d", sqlite3_extended_errcode(db_info.dbGlobalro)); \
61 _E("db_info.dbUserrw errcode: %d", sqlite3_extended_errcode(db_info.dbUserrw)); \
62 _E("db_info.dbGlobalrw errcode: %d", sqlite3_extended_errcode(db_info.dbGlobalrw)); \
67 #define tryvm_with_dbmsg_if(expr, val) \
70 _E("db_info.dbUserro: %s", sqlite3_errmsg(db_info.dbUserro)); \
71 _E("db_info.dbGlobalro: %s", sqlite3_errmsg(db_info.dbGlobalro)); \
72 _E("db_info.dbUserrw: %s", sqlite3_errmsg(db_info.dbUserrw)); \
73 _E("db_info.dbGlobalrw: %s", sqlite3_errmsg(db_info.dbGlobalrw)); \
74 _E("db_info.dbUserro errcode: %d", sqlite3_extended_errcode(db_info.dbUserro)); \
75 _E("db_info.dbGlobalro errcode: %d", sqlite3_extended_errcode(db_info.dbGlobalro)); \
76 _E("db_info.dbUserrw errcode: %d", sqlite3_extended_errcode(db_info.dbUserrw)); \
77 _E("db_info.dbGlobalrw errcode: %d", sqlite3_extended_errcode(db_info.dbGlobalrw)); \
82 static __thread struct {
94 static __thread sqlite3 *dbInit = NULL;
96 static int ail_db_change_perm(const char *db_file, uid_t uid)
98 char journal_file[BUFSIZE];
103 struct passwd *userinfo = NULL;
104 char *pwd_buf = NULL;
107 files[0] = (char *)db_file;
108 files[1] = journal_file;
111 retv_if(!db_file, AIL_ERROR_FAIL);
112 if (getuid() != OWNER_ROOT) /* At this time we should be root to apply this */
115 pwd_bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
116 if (pwd_bufsize <= 0)
119 pwd_buf = (char *)malloc(pwd_bufsize);
120 if (pwd_buf == NULL) {
122 return AIL_ERROR_OUT_OF_MEMORY;
125 if (getpwuid_r(uid, &pwd, pwd_buf, pwd_bufsize, &userinfo) != 0) {
126 _E("FAIL: user %d doesn't exist", uid);
128 return AIL_ERROR_FAIL;
130 snprintf(journal_file, sizeof(journal_file), "%s%s", db_file, "-journal");
132 for (i = 0; files[i]; i++) {
133 /* Compare git_t type and not group name */
134 ret = chown(files[i], uid, userinfo->pw_gid);
135 SET_SMACK_LABEL(files[i], uid);
137 _E("FAIL : chown %s %d.%d, because %d", db_file, uid, userinfo->pw_gid, errno);
139 return AIL_ERROR_FAIL;
142 ret = chmod(files[i], S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
144 _E("FAIL : chmod %s 0664, because %d", db_file, errno);
146 return AIL_ERROR_FAIL;
155 char *ail_get_icon_path(uid_t uid)
159 struct group *grpinfo = NULL;
161 struct passwd *userinfo = NULL;
167 _E("FAIL : Root is not allowed user! please fix it replacing with DEFAULT_USER");
171 if (uid != GLOBAL_USER) {
172 buflen = sysconf(_SC_GETPW_R_SIZE_MAX);
176 pwd_buf = (char *)malloc(buflen);
177 if (pwd_buf == NULL) {
182 if (getpwuid_r(uid, &pwd, pwd_buf, buflen, &userinfo) != 0) {
183 _E("getpwuid(%d) returns NULL !", uid);
188 buflen = sysconf(_SC_GETGR_R_SIZE_MAX);
192 buf = (char *)malloc(buflen);
199 if (getgrnam_r("users", &grpbuf, buf, buflen, &grpinfo) != 0) {
200 _E("getgrnam_r(users) returns NULL !");
206 /* Compare git_t type and not group name */
207 if (grpinfo->gr_gid != userinfo->pw_gid) {
208 _E("UID [%d] does not belong to 'users' group!", uid);
214 if (asprintf(&result, "%s/.applications/icons/", userinfo->pw_dir) == -1)
215 _E("out of memory: asprintf() is failed.");
219 result = strdup(tzplatform_mkpath(TZ_SYS_RW_ICONS, "/"));
220 if (result == NULL) {
226 int ret = mkdir(result, S_IRWXU | S_IRGRP | S_IXGRP | S_IXOTH);
227 if (ret == -1 && errno != EEXIST) {
228 _E("FAIL : to create directory %s %d", result, errno);
229 } else if (getuid() == OWNER_ROOT) {
230 ret = chown(result, uid, grpinfo ? grpinfo->gr_gid : 0);
231 SET_SMACK_LABEL(result, uid);
233 _E("FAIL : chown %s %d.%d, because %d", result, uid,
234 grpinfo ? grpinfo->gr_gid : 0, errno);
243 char *ail_get_app_DB_journal(uid_t uid)
245 char *app_path = ail_get_app_DB(uid);
248 if (asprintf(&result, "%s-journal", app_path) == -1)
249 _E("out of memory: asprintf() is failed.");
256 char *ail_get_app_DB(uid_t uid)
260 struct group *grpinfo = NULL;
264 struct passwd *userinfo;
270 _E("FAIL : Root is not allowed! switch to DEFAULT_USER");
274 if (uid != GLOBAL_USER) {
275 buflen = sysconf(_SC_GETPW_R_SIZE_MAX);
279 pwd_buf = (char *)malloc(buflen);
280 if (pwd_buf == NULL) {
285 if (getpwuid_r(uid, &pwd, pwd_buf, buflen, &userinfo) != 0) {
286 _E("getpwuid(%d) returns NULL !", uid);
291 buflen = sysconf(_SC_GETGR_R_SIZE_MAX);
295 buf = (char *)malloc(buflen);
302 if (getgrnam_r("users", &grpbuf, buf, buflen, &grpinfo) != 0) {
303 _E("getgrnam(users) returns NULL !");
309 /* Compare git_t type and not group name */
310 if (grpinfo->gr_gid != userinfo->pw_gid) {
311 _E("UID [%d] does not belong to 'users' group!", uid);
317 if (asprintf(&result, "%s/.applications/dbspace/.app_info.db", userinfo->pw_dir) == -1)
318 _E("out of memory: asprintf() is failed.");
322 result = strdup(APP_INFO_DB_FILE);
323 if (result == NULL) {
329 temp = strdup(result);
335 dir = strrchr(temp, '/');
343 int ret = mkdir(temp, S_IRWXU | S_IRGRP | S_IXGRP | S_IXOTH);
344 if (ret == -1 && errno != EEXIST) {
345 _E("FAIL : to create directory %s %d", temp, errno);
346 } else if (getuid() == OWNER_ROOT) {
347 ret = chown(temp, uid, grpinfo ? grpinfo->gr_gid : 0);
348 SET_SMACK_LABEL(temp, uid);
350 _E("FAIL : chown %s %d.%d, because %d", temp, uid,
351 grpinfo ? grpinfo->gr_gid : 0, errno);
361 char *ail_get_desktop_path(uid_t uid)
365 struct group *grpinfo = NULL;
367 struct passwd *userinfo = NULL;
373 _E("FAIL : Root is not allowed user! please fix it replacing with DEFAULT_USER");
377 if (uid != GLOBAL_USER) {
378 buflen = sysconf(_SC_GETPW_R_SIZE_MAX);
382 pwd_buf = (char *)malloc(buflen);
383 if (pwd_buf == NULL) {
388 if (getpwuid_r(uid, &pwd, pwd_buf, buflen, &userinfo) != 0) {
389 _E("getpwuid(%d) returns NULL !", uid);
394 buflen = sysconf(_SC_GETGR_R_SIZE_MAX);
398 buf = (char *)malloc(buflen);
405 if (getgrnam_r("users", &grpbuf, buf, buflen, &grpinfo) != 0) {
406 _E("getgrnam(users) returns NULL !");
412 /* Compare git_t type and not group name */
413 if (grpinfo->gr_gid != userinfo->pw_gid) {
414 _E("UID [%d] does not belong to 'users' group!", uid);
420 if (asprintf(&result, "%s/.applications/desktop/", userinfo->pw_dir) == -1)
421 _E("out of memory: asprintf() is failed.");
425 result = strdup(tzplatform_mkpath(TZ_SYS_RW_DESKTOP_APP, "/"));
426 if (result == NULL) {
432 int ret = mkdir(result, S_IRWXU | S_IRGRP | S_IXGRP | S_IXOTH);
433 if (ret == -1 && errno != EEXIST) {
434 _E("FAIL : to create directory %s %d", result, errno);
435 } else if (getuid() == OWNER_ROOT) {
436 ret = chown(result, uid, grpinfo ? grpinfo->gr_gid : 0);
437 SET_SMACK_LABEL(result, uid);
439 _E("FAIL : chown %s %d.%d, because %d", result, uid,
440 grpinfo ? grpinfo->gr_gid : 0, errno);
450 static ail_error_e db_do_prepare(sqlite3 *db, const char *query, sqlite3_stmt **stmt)
454 retv_if(!query, AIL_ERROR_INVALID_PARAMETER);
455 retv_if(!stmt, AIL_ERROR_INVALID_PARAMETER);
456 retv_if(!db, AIL_ERROR_DB_FAILED);
458 ret = sqlite3_prepare_v2(db, query, strlen(query), stmt, NULL);
459 if (ret != SQLITE_OK) {
460 _E("%s\n", sqlite3_errmsg(db));
461 return AIL_ERROR_DB_FAILED;
466 ail_error_e db_open(db_open_mode mode, uid_t uid)
472 const char *tbls[3] = {
473 "CREATE TABLE app_info "
474 "(package TEXT PRIMARY KEY, "
475 "exec TEXT DEFAULT 'No Exec', "
476 "name TEXT DEFAULT 'No Name', "
477 "type TEXT DEFAULT 'Application', "
478 "icon TEXT DEFAULT 'No Icon', "
482 "x_slp_service TEXT, "
483 "x_slp_packagetype TEXT, "
484 "x_slp_packagecategories TEXT, "
485 "x_slp_packageid TEXT, "
488 "x_slp_exe_path TEXT, "
491 "x_slp_domain TEXT, "
492 "x_slp_submodemainid TEXT, "
493 "x_slp_installedstorage TEXT, "
494 "x_slp_baselayoutwidth INTEGER DEFAULT 0, "
495 "x_slp_installedtime INTEGER DEFAULT 0, "
496 "nodisplay INTEGER DEFAULT 0, "
497 "x_slp_taskmanage INTEGER DEFAULT 1, "
498 "x_slp_multiple INTEGER DEFAULT 0, "
499 "x_slp_removable INTEGER DEFAULT 1, "
500 "x_slp_ishorizontalscale INTEGER DEFAULT 0, "
501 "x_slp_enabled INTEGER DEFAULT 1, "
502 "x_slp_submode INTEGER DEFAULT 0, "
503 "desktop TEXT UNIQUE NOT NULL);",
504 "CREATE TABLE localname (package TEXT NOT NULL, "
505 "locale TEXT NOT NULL, "
506 "name TEXT NOT NULL, "
507 "x_slp_pkgid TEXT NOT NULL, PRIMARY KEY (package, locale));",
512 db = ail_get_app_DB(uid);
514 _E("Failed to get app DB");
515 return AIL_ERROR_DB_FAILED;
518 global_db = ail_get_app_DB(GLOBAL_USER);
519 if (global_db == NULL) {
520 _E("Failed to get global app DB");
522 return AIL_ERROR_DB_FAILED;
525 if (access(db, F_OK)) {
526 if (AIL_ERROR_OK == db_util_open_with_options(db,
527 &dbInit, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL)) {
528 for (i = 0; tbls[i] != NULL; i++) {
529 ret = do_db_exec(tbls[i], dbInit);
530 if (ret != AIL_ERROR_OK)
533 if (getuid() == OWNER_ROOT && AIL_ERROR_OK != ail_db_change_perm(db, uid))
534 _E("Failed to change permission\n");
537 _E("Failed to create table %s\n", db);
542 ret = sqlite3_close(dbInit);
543 tryvm_with_dbmsg_if(ret != SQLITE_OK, AIL_ERROR_DB_FAILED);
546 if (mode & DB_OPEN_RO) {
547 if (uid != GLOBAL_USER) {
548 if (!db_info.dbUserro) {
549 db_util_open_with_options(db, &db_info.dbUserro, SQLITE_OPEN_READONLY, NULL);
550 char query_attach[AIL_SQL_QUERY_MAX_LEN];
551 char query_view_app[AIL_SQL_QUERY_MAX_LEN];
552 char query_view_local[AIL_SQL_QUERY_MAX_LEN];
553 snprintf(query_attach, AIL_SQL_QUERY_MAX_LEN, QUERY_ATTACH, global_db);
554 if (db_exec_usr_ro(query_attach) < 0) {
555 _D("executing query_attach : %s", query_attach);
558 snprintf(query_view_app, AIL_SQL_QUERY_MAX_LEN, QUERY_CREATE_VIEW_APP);
559 if (db_exec_usr_ro(query_view_app) < 0) {
560 _D("executing query_attach : %s", query_view_app);
564 snprintf(query_view_local, AIL_SQL_QUERY_MAX_LEN, QUERY_CREATE_VIEW_LOCAL);
565 if (db_exec_usr_ro(query_view_local) < 0) {
566 _D("executing query_attach : %s", query_view_local);
571 if (!db_info.dbGlobalro) {
572 ret = db_util_open_with_options(global_db, &db_info.dbGlobalro, SQLITE_OPEN_READONLY, NULL);
573 tryvm_with_dbmsg_if(ret != SQLITE_OK, AIL_ERROR_DB_FAILED);
578 if (mode & DB_OPEN_RW) {
579 if (uid != GLOBAL_USER) {
580 if (!db_info.dbUserrw) {
581 ret = db_util_open(db, &db_info.dbUserrw, 0);
582 tryvm_with_dbmsg_if(ret != SQLITE_OK, AIL_ERROR_DB_FAILED);
585 if (!db_info.dbGlobalrw) {
586 ret = db_util_open(global_db, &db_info.dbGlobalrw, 0);
587 tryvm_with_dbmsg_if(ret != SQLITE_OK, AIL_ERROR_DB_FAILED);
601 return AIL_ERROR_DB_FAILED;
604 ail_error_e db_prepare(const char *query, sqlite3_stmt **stmt)
606 return db_do_prepare(db_info.dbUserro, query, stmt);
609 ail_error_e db_prepare_globalro(const char *query, sqlite3_stmt **stmt)
611 return db_do_prepare(db_info.dbGlobalro, query, stmt);
614 ail_error_e db_prepare_rw(const char *query, sqlite3_stmt **stmt)
616 return db_do_prepare(db_info.dbUserrw, query, stmt);
619 ail_error_e db_prepare_globalrw(const char *query, sqlite3_stmt **stmt)
621 return db_do_prepare(db_info.dbGlobalrw, query, stmt);
624 ail_error_e db_bind_bool(sqlite3_stmt *stmt, int idx, bool value)
628 retv_if(!stmt, AIL_ERROR_INVALID_PARAMETER);
630 ret = sqlite3_bind_int(stmt, idx, (int) value);
631 retv_with_dbmsg_if(ret != SQLITE_OK, AIL_ERROR_DB_FAILED);
636 ail_error_e db_bind_int(sqlite3_stmt *stmt, int idx, int value)
640 retv_if(!stmt, AIL_ERROR_INVALID_PARAMETER);
642 ret = sqlite3_bind_int(stmt, idx, value);
643 retv_with_dbmsg_if(ret != SQLITE_OK, AIL_ERROR_DB_FAILED);
648 ail_error_e db_bind_text(sqlite3_stmt *stmt, int idx, const char* value)
652 retv_if(!stmt, AIL_ERROR_INVALID_PARAMETER);
654 ret = sqlite3_bind_text(stmt, idx, value, strlen(value), 0);
655 retv_with_dbmsg_if(ret != SQLITE_OK, AIL_ERROR_DB_FAILED);
660 ail_error_e db_step(sqlite3_stmt *stmt)
664 retv_if(!stmt, AIL_ERROR_INVALID_PARAMETER);
666 ret = sqlite3_step(stmt);
669 return AIL_ERROR_NO_DATA;
674 retv_with_dbmsg_if(1, AIL_ERROR_DB_FAILED);
677 ail_error_e db_column_bool(sqlite3_stmt *stmt, int index, bool *value)
681 retv_if(!stmt, AIL_ERROR_INVALID_PARAMETER);
682 retv_if(!value, AIL_ERROR_INVALID_PARAMETER);
684 out_val = sqlite3_column_int(stmt, index);
685 *value = (out_val == 1) ? true : false;
690 ail_error_e db_column_int(sqlite3_stmt *stmt, int index, int *value)
692 retv_if(!stmt, AIL_ERROR_INVALID_PARAMETER);
693 retv_if(!value, AIL_ERROR_INVALID_PARAMETER);
695 *value = sqlite3_column_int(stmt, index);
700 ail_error_e db_column_str(sqlite3_stmt *stmt, int index, char **str)
702 retv_if(!stmt, AIL_ERROR_INVALID_PARAMETER);
703 retv_if(!str, AIL_ERROR_INVALID_PARAMETER);
705 *str = (char *)sqlite3_column_text(stmt, index);
710 ail_error_e db_reset(sqlite3_stmt *stmt)
714 retv_if(!stmt, AIL_ERROR_INVALID_PARAMETER);
716 sqlite3_clear_bindings(stmt);
718 ret = sqlite3_reset(stmt);
719 retv_with_dbmsg_if(ret != SQLITE_OK, AIL_ERROR_DB_FAILED);
724 ail_error_e db_finalize(sqlite3_stmt *stmt)
728 retv_if(!stmt, AIL_ERROR_INVALID_PARAMETER);
730 ret = sqlite3_finalize(stmt);
731 retv_with_dbmsg_if(ret != SQLITE_OK, AIL_ERROR_DB_FAILED);
736 ail_error_e do_db_exec(const char *query, sqlite3 * fileSQL)
741 retv_if(!query, AIL_ERROR_INVALID_PARAMETER);
742 retv_if(!fileSQL, AIL_ERROR_DB_FAILED);
744 ret = sqlite3_exec(fileSQL, query, NULL, NULL, &errmsg);
745 if (ret != SQLITE_OK) {
746 _E("Cannot execute this query - %s. because %s",
747 query, errmsg ? errmsg : "uncatched error");
749 sqlite3_free(errmsg);
750 return AIL_ERROR_DB_FAILED;
756 ail_error_e db_exec_usr_rw(const char *query)
758 return do_db_exec(query, db_info.dbUserrw);
761 ail_error_e db_exec_usr_ro(const char *query)
763 return do_db_exec(query, db_info.dbUserro);
766 ail_error_e db_exec_glo_ro(const char *query)
768 return do_db_exec(query, db_info.dbGlobalro);
771 ail_error_e db_exec_glo_rw(const char *query)
773 return do_db_exec(query, db_info.dbGlobalrw);
776 ail_error_e db_close(void)
780 if (db_info.dbUserro) {
781 ret = sqlite3_close(db_info.dbUserro);
782 retv_with_dbmsg_if(ret != SQLITE_OK, AIL_ERROR_DB_FAILED);
783 db_info.dbUserro = NULL;
786 if (db_info.dbGlobalrw) {
787 ret = sqlite3_close(db_info.dbGlobalrw);
788 retv_with_dbmsg_if(ret != SQLITE_OK, AIL_ERROR_DB_FAILED);
789 db_info.dbGlobalrw = NULL;
792 if (db_info.dbUserrw) {
793 ret = sqlite3_close(db_info.dbUserrw);
794 retv_with_dbmsg_if(ret != SQLITE_OK, AIL_ERROR_DB_FAILED);
795 db_info.dbUserrw = NULL;
801 EXPORT_API ail_error_e ail_db_close(void)
806 int db_exec_sqlite_query(char *query, sqlite_query_callback callback, void *data)
808 char *error_message = NULL;
809 if (db_info.dbGlobalro) {
811 sqlite3_exec(db_info.dbGlobalro, query, callback, data, &error_message)) {
812 _E("Don't execute query = %s error message = %s\n", query,
814 sqlite3_free(error_message);
818 if (db_info.dbUserro) {
820 sqlite3_exec(db_info.dbUserro, query, callback, data, &error_message)) {
821 _E("Don't execute query = %s error message = %s\n", query,
823 sqlite3_free(error_message);
827 sqlite3_free(error_message);