/* * Copyright (c) 2000 - 2017 Samsung Electronics Co., Ltd. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "badge_log.h" #include "badge_error.h" #include "badge_internal.h" #include "badge_ipc.h" #include "badge_db.h" #include "badge_private.h" #include "badge_setting_service.h" #define BADGE_PKGNAME_LEN 512 #define BADGE_CHANGED_NOTI "badge_changed" struct _badge_h { char *pkgname; char *writable_pkgs; }; struct _badge_cb_data { badge_change_cb callback; void *data; }; static GHashTable *_badge_cb_hash = NULL; static inline long _get_max_len(void) { long max = 0; long path_max_len = 4096; #ifdef _PC_PATH_MAX max = (pathconf("/", _PC_PATH_MAX) < 1 ? path_max_len : pathconf("/", _PC_PATH_MAX)); #else /* _PC_PATH_MAX */ max = path_max_len; #endif /* _PC_PATH_MAX */ return max; } char *_badge_get_pkgname_by_pid(void) { char *pkgname = NULL; int pid = 0; int ret = AUL_R_OK; int fd = 0; long max = 0; pid = getpid(); max = _get_max_len(); pkgname = malloc(max); if (!pkgname) { /* LCOV_EXCL_START */ ERR("Failed to alloc memory"); return NULL; /* LCOV_EXCL_STOP */ } memset(pkgname, 0x00, max); ret = aul_app_get_pkgname_bypid(pid, pkgname, max); if (ret != AUL_R_OK) { fd = open("/proc/self/cmdline", O_RDONLY); if (fd < 0) { /* LCOV_EXCL_START */ free(pkgname); return NULL; /* LCOV_EXCL_STOP */ } ret = read(fd, pkgname, max - 1); if (ret <= 0) { /* LCOV_EXCL_START */ close(fd); free(pkgname); return NULL; /* LCOV_EXCL_STOP */ } close(fd); } if (pkgname[0] == '\0') { /* LCOV_EXCL_START */ free(pkgname); return NULL; /* LCOV_EXCL_STOP */ } else { return pkgname; } } static int _badge_check_data_inserted(const char *pkgname, sqlite3 *db, uid_t uid) { sqlite3_stmt *stmt = NULL; int count = 0; int result = BADGE_ERROR_NONE; char *sqlbuf = NULL; int sqlret; if (!pkgname || !db) return BADGE_ERROR_INVALID_PARAMETER; sqlbuf = sqlite3_mprintf("SELECT count(*) FROM %q WHERE " \ "pkgname = %Q AND uid = %d", BADGE_TABLE_NAME, pkgname, uid); if (!sqlbuf) { /* LCOV_EXCL_START */ ERR("Failed to alloc query"); return BADGE_ERROR_OUT_OF_MEMORY; /* LCOV_EXCL_STOP */ } sqlret = sqlite3_prepare_v2(db, sqlbuf, -1, &stmt, NULL); if (sqlret != SQLITE_OK) { /* LCOV_EXCL_START */ ERR("sqlite3_prepare_v2 failed [%d][%s]", sqlret, sqlite3_errmsg(db)); result = BADGE_ERROR_FROM_DB; goto free_and_return; /* LCOV_EXCL_STOP */ } sqlret = sqlite3_step(stmt); if (sqlret == SQLITE_ROW) count = sqlite3_column_int(stmt, 0); else count = 0; DBG("[%s], DB search result[%d]", sqlbuf, count); if (count > 0) result = BADGE_ERROR_ALREADY_EXIST; else result = BADGE_ERROR_NOT_EXIST; free_and_return: if (sqlbuf) sqlite3_free(sqlbuf); if (stmt) sqlite3_finalize(stmt); return result; } static int _badge_check_option_inserted(const char *pkgname, sqlite3 *db, uid_t uid) { sqlite3_stmt *stmt = NULL; int count = 0; int result = BADGE_ERROR_NONE; char *sqlbuf = NULL; int sqlret; if (!pkgname || !db) return BADGE_ERROR_INVALID_PARAMETER; sqlbuf = sqlite3_mprintf("SELECT count(*) FROM %q WHERE " \ "pkgname = %Q AND uid = %d", BADGE_OPTION_TABLE_NAME, pkgname, uid); if (!sqlbuf) { /* LCOV_EXCL_START */ ERR("Failed to alloc query"); return BADGE_ERROR_OUT_OF_MEMORY; /* LCOV_EXCL_STOP */ } sqlret = sqlite3_prepare_v2(db, sqlbuf, -1, &stmt, NULL); if (sqlret != SQLITE_OK) { /* LCOV_EXCL_START */ ERR("sqlite3_prepare_v2 failed [%d][%s]", sqlret, sqlite3_errmsg(db)); result = BADGE_ERROR_FROM_DB; goto free_and_return; /* LCOV_EXCL_STOP */ } sqlret = sqlite3_step(stmt); if (sqlret == SQLITE_ROW) count = sqlite3_column_int(stmt, 0); else count = 0; DBG("[%s], DB search result[%d]", sqlbuf, count); if (count > 0) result = BADGE_ERROR_ALREADY_EXIST; else result = BADGE_ERROR_NOT_EXIST; free_and_return: if (sqlbuf) sqlite3_free(sqlbuf); if (stmt) sqlite3_finalize(stmt); return result; } static int _is_same_certinfo(const char *caller, const char *pkgname) { int ret = PACKAGE_MANAGER_ERROR_NONE; package_manager_compare_result_type_e compare_result = PACKAGE_MANAGER_COMPARE_MISMATCH; if (!caller || !pkgname) return 0; ret = package_manager_compare_package_cert_info(pkgname, caller, &compare_result); if (ret == PACKAGE_MANAGER_ERROR_NONE && compare_result == PACKAGE_MANAGER_COMPARE_MATCH) return 1; return 0; } static bool __check_label(pid_t pid) { #define SMACK_LABEL_LEN 255 #define COMPARE_LABEL_COUNT 3 bool ret = false; int i; ssize_t len; char *label = NULL; char check_label[COMPARE_LABEL_COUNT][SMACK_LABEL_LEN+1] = { "System", "System::Privileged", "User"}; len = smack_new_label_from_process(pid, &label); if (len < 0 || label == NULL) goto out; for (i = 0; i < COMPARE_LABEL_COUNT; i++) { if (g_strcmp0(label, check_label[i]) == 0) { ret = true; goto out; } } out: if (label) free(label); return ret; } static int _badge_check_writable(const char *caller, const char *pkgname, sqlite3 *db, uid_t uid, pid_t pid) { sqlite3_stmt *stmt = NULL; int count = 0; int result = BADGE_ERROR_NONE; char *sqlbuf = NULL; int sqlret; if (!db || !caller || !pkgname) return BADGE_ERROR_INVALID_PARAMETER; if (g_strcmp0(caller, pkgname) == 0) return BADGE_ERROR_NONE; if (__check_label(pid) == true) return BADGE_ERROR_NONE; /* LCOV_EXCL_START */ if (_is_same_certinfo(caller, pkgname) == 1) return BADGE_ERROR_NONE; sqlbuf = sqlite3_mprintf("SELECT COUNT(*) FROM %q WHERE " \ "pkgname = %Q AND writable_pkgs LIKE '%%%q%%'" \ "AND uid = %d", BADGE_TABLE_NAME, pkgname, caller, uid); if (!sqlbuf) { ERR("Failed to alloc query"); return BADGE_ERROR_OUT_OF_MEMORY; } sqlret = sqlite3_prepare_v2(db, sqlbuf, -1, &stmt, NULL); if (sqlret != SQLITE_OK) { ERR("sqlite3_prepare_v2 failed [%d][%s]", sqlret, sqlite3_errmsg(db)); result = BADGE_ERROR_FROM_DB; goto free_and_return; } sqlret = sqlite3_step(stmt); if (sqlret == SQLITE_ROW) count = sqlite3_column_int(stmt, 0); else count = 0; DBG("[%s], DB search result[%d]", sqlbuf, count); if (count <= 0) result = BADGE_ERROR_PERMISSION_DENIED; free_and_return: if (sqlbuf) sqlite3_free(sqlbuf); if (stmt) sqlite3_finalize(stmt); return result; /* LCOV_EXCL_STOP */ } int _badge_is_existing(const char *pkgname, bool *existing, uid_t uid) { sqlite3 *db = NULL; int sqlret; int result = BADGE_ERROR_NONE; if (!pkgname || !existing) { /* LCOV_EXCL_START */ ERR("pkgname : %s, existing : %p", pkgname, existing); return BADGE_ERROR_INVALID_PARAMETER; /* LCOV_EXCL_STOP */ } sqlret = db_util_open(BADGE_DB_PATH, &db, 0); if (sqlret != SQLITE_OK || !db) { /* LCOV_EXCL_START */ ERR("Failed to db_util_open [%d]", sqlret); if (sqlret == SQLITE_PERM) return BADGE_ERROR_PERMISSION_DENIED; return BADGE_ERROR_FROM_DB; /* LCOV_EXCL_STOP */ } result = _badge_check_data_inserted(pkgname, db, uid); if (result == BADGE_ERROR_ALREADY_EXIST) { *existing = TRUE; result = BADGE_ERROR_NONE; } else if (result == BADGE_ERROR_NOT_EXIST) { *existing = FALSE; result = BADGE_ERROR_NONE; } sqlret = db_util_close(db); if (sqlret != SQLITE_OK) WARN("Failed to db_util_close [%d]", sqlret); /* LCOV_EXCL_LINE */ return result; } int _badge_get_list(GList **badge_list, uid_t uid) { sqlite3 *db = NULL; int result = BADGE_ERROR_NONE; char *sqlbuf = NULL; sqlite3_stmt *stmt = NULL; int sqlret; const char *pkg; unsigned int badge_count; badge_info_s *badge_info; sqlret = db_util_open(BADGE_DB_PATH, &db, 0); if (sqlret != SQLITE_OK || !db) { /* LCOV_EXCL_START */ ERR("Failed to db_util_open [%d]", sqlret); return BADGE_ERROR_FROM_DB; /* LCOV_EXCL_STOP */ } sqlbuf = sqlite3_mprintf("SELECT pkgname, badge FROM %q WHERE uid = %d", BADGE_TABLE_NAME, uid); if (!sqlbuf) { /* LCOV_EXCL_START */ ERR("Failed to alloc query"); result = BADGE_ERROR_OUT_OF_MEMORY; goto free_and_return; /* LCOV_EXCL_STOP */ } sqlret = sqlite3_prepare_v2(db, sqlbuf, -1, &stmt, NULL); if (sqlret != SQLITE_OK) { /* LCOV_EXCL_START */ ERR("sqlite3_prepare_v2 failed [%d][%s]", sqlret, sqlite3_errmsg(db)); result = BADGE_ERROR_FROM_DB; goto free_and_return; /* LCOV_EXCL_STOP */ } sqlret = sqlite3_step(stmt); if (sqlret == SQLITE_DONE) { INFO("badge db has no data"); result = BADGE_ERROR_NOT_EXIST; goto free_and_return; } else if (sqlret != SQLITE_ROW) { ERR("Failed to sqlite3_step [%d]", sqlret); result = BADGE_ERROR_FROM_DB; goto free_and_return; } do { pkg = (const char *)sqlite3_column_text(stmt, 0); badge_count = (unsigned int)sqlite3_column_int(stmt, 1); if (pkg) { badge_info = (badge_info_s *)calloc(sizeof(badge_info_s), 1); if (badge_info == NULL) { /* LCOV_EXCL_START */ ERR("alloc badge_info failed"); result = BADGE_ERROR_OUT_OF_MEMORY; break; /* LCOV_EXCL_STOP */ } badge_info->pkg = strdup(pkg); badge_info->badge_count = badge_count; *badge_list = g_list_append(*badge_list, badge_info); } else { /* LCOV_EXCL_START */ ERR("db has invaild data"); result = BADGE_ERROR_FROM_DB; /* LCOV_EXCL_STOP */ } } while (sqlite3_step(stmt) == SQLITE_ROW); free_and_return: if (sqlbuf) sqlite3_free(sqlbuf); if (stmt) sqlite3_finalize(stmt); sqlret = db_util_close(db); if (sqlret != SQLITE_OK) WARN("Failed to db_util_close [%d]", sqlret); /* LCOV_EXCL_LINE */ return result; } int _badge_insert(badge_h *badge, uid_t uid) { sqlite3 *db = NULL; int sqlret; int ret = BADGE_ERROR_NONE; int result = BADGE_ERROR_NONE; char *sqlbuf = NULL; bool is_existed = false; if (!badge || !badge->pkgname || !badge->writable_pkgs) return BADGE_ERROR_INVALID_PARAMETER; ret = badge_setting_is_existed_appid(badge->pkgname, &is_existed, uid); if (ret == BADGE_ERROR_NONE && is_existed == false) { result = BADGE_ERROR_INVALID_PACKAGE; goto return_close_db; } else if (ret != BADGE_ERROR_NONE) { ERR("Failed to check existed appid [%d]", ret); result = ret; goto return_close_db; } sqlret = db_util_open(BADGE_DB_PATH, &db, 0); if (sqlret != SQLITE_OK || !db) { /* LCOV_EXCL_START */ ERR("Failed to db_util_open [%s][%d]", BADGE_DB_PATH, sqlret); return BADGE_ERROR_FROM_DB; /* LCOV_EXCL_STOP */ } /* Check pkgname & id */ ret = _badge_check_data_inserted(badge->pkgname, db, uid); if (ret != BADGE_ERROR_NOT_EXIST) { /* LCOV_EXCL_START */ result = ret; goto return_close_db; /* LCOV_EXCL_STOP */ } sqlbuf = sqlite3_mprintf("INSERT INTO %q " \ "(pkgname, writable_pkgs, uid) VALUES (%Q, %Q, %d);", BADGE_TABLE_NAME, badge->pkgname, badge->writable_pkgs, uid); if (!sqlbuf) { /* LCOV_EXCL_START */ ERR("Failed to alloc query"); result = BADGE_ERROR_OUT_OF_MEMORY; goto return_close_db; /* LCOV_EXCL_STOP */ } ret = badge_db_exec(db, sqlbuf, NULL); if (ret != BADGE_ERROR_NONE) { /* LCOV_EXCL_START */ ERR("Failed to insert badge[%s], err[%d]", badge->pkgname, ret); result = ret; goto return_close_db; /* LCOV_EXCL_STOP */ } /* inserting badge options */ ret = _badge_check_option_inserted(badge->pkgname, db, uid); if (ret != BADGE_ERROR_NOT_EXIST) { result = ret; goto return_close_db; } sqlbuf = sqlite3_mprintf("INSERT INTO %q " \ "(pkgname, uid) VALUES (%Q, %d);", BADGE_OPTION_TABLE_NAME, badge->pkgname, uid); if (!sqlbuf) { /* LCOV_EXCL_START */ ERR("Failed to alloc query"); result = BADGE_ERROR_OUT_OF_MEMORY; goto return_close_db; /* LCOV_EXCL_STOP */ } ret = badge_db_exec(db, sqlbuf, NULL); if (ret != BADGE_ERROR_NONE) { /* LCOV_EXCL_START */ ERR("Failed to insert badge option[%s], err[%d]", badge->pkgname, sqlret); result = ret; goto return_close_db; /* LCOV_EXCL_STOP */ } return_close_db: if (sqlbuf) sqlite3_free(sqlbuf); sqlret = db_util_close(db); if (sqlret != SQLITE_OK) WARN("Failed to db_util_close [%d]", sqlret); /* LCOV_EXCL_LINE */ return result; } int _badge_remove(const char *caller, const char *pkgname, uid_t uid, pid_t pid) { int ret = BADGE_ERROR_NONE; int result = BADGE_ERROR_NONE; sqlite3 *db = NULL; int sqlret; char *sqlbuf = NULL; if (!caller || !pkgname) return BADGE_ERROR_INVALID_PARAMETER; sqlret = db_util_open(BADGE_DB_PATH, &db, 0); if (sqlret != SQLITE_OK || !db) { /* LCOV_EXCL_START */ ERR("Failed to db_util_open [%d]", sqlret); return BADGE_ERROR_FROM_DB; /* LCOV_EXCL_STOP */ } ret = _badge_check_data_inserted(pkgname, db, uid); if (ret != BADGE_ERROR_ALREADY_EXIST) { result = ret; goto return_close_db; } ret = _badge_check_writable(caller, pkgname, db, uid, pid); if (ret != BADGE_ERROR_NONE) { result = ret; goto return_close_db; } sqlbuf = sqlite3_mprintf("DELETE FROM %q WHERE pkgname = %Q AND uid = %d", BADGE_TABLE_NAME, pkgname, uid); if (!sqlbuf) { /* LCOV_EXCL_START */ ERR("Failed to alloc query"); result = BADGE_ERROR_OUT_OF_MEMORY; goto return_close_db; /* LCOV_EXCL_STOP */ } ret = badge_db_exec(db, sqlbuf, NULL); if (ret != BADGE_ERROR_NONE) { ERR("Failed to remove badge[%s], err[%d]", pkgname, ret); result = ret; goto return_close_db; } /* treating option table */ ret = _badge_check_option_inserted(pkgname, db, uid); if (ret != BADGE_ERROR_ALREADY_EXIST) { result = ret; goto return_close_db; } sqlbuf = sqlite3_mprintf("DELETE FROM %q WHERE pkgname = %Q AND uid = %d", BADGE_OPTION_TABLE_NAME, pkgname, uid); if (!sqlbuf) { /* LCOV_EXCL_START */ ERR("Failed to alloc query"); result = BADGE_ERROR_OUT_OF_MEMORY; goto return_close_db; /* LCOV_EXCL_STOP */ } ret = badge_db_exec(db, sqlbuf, NULL); if (ret != BADGE_ERROR_NONE) { /* LCOV_EXCL_START */ ERR("Failed to remove badge option[%s], err[%d]", pkgname, ret); result = ret; goto return_close_db; /* LCOV_EXCL_STOP */ } return_close_db: if (sqlbuf) sqlite3_free(sqlbuf); sqlret = db_util_close(db); if (sqlret != SQLITE_OK) WARN("Failed to db_util_close [%d]", sqlret); /* LCOV_EXCL_LINE */ return result; } static int _badge_remove_by_appid(const char *appid, uid_t uid, sqlite3 *db) { int ret = BADGE_ERROR_NONE; int result = BADGE_ERROR_NONE; char *sqlbuf = NULL; ret = _badge_check_data_inserted(appid, db, uid); if (ret != BADGE_ERROR_ALREADY_EXIST) { result = ret; goto return_close_db; } sqlbuf = sqlite3_mprintf("DELETE FROM %q WHERE pkgname = %Q AND uid = %d", BADGE_TABLE_NAME, appid, uid); if (!sqlbuf) { /* LCOV_EXCL_START */ ERR("Failed to alloc query"); result = BADGE_ERROR_OUT_OF_MEMORY; goto return_close_db; /* LCOV_EXCL_STOP */ } ret = badge_db_exec(db, sqlbuf, NULL); if (ret != BADGE_ERROR_NONE) { /* LCOV_EXCL_START */ ERR("Failed to remove badge[%s], err[%d]", appid, ret); result = ret; goto return_close_db; /* LCOV_EXCL_STOP */ } /* treating option table */ ret = _badge_check_option_inserted(appid, db, uid); if (ret != BADGE_ERROR_ALREADY_EXIST) { result = ret; goto return_close_db; } sqlbuf = sqlite3_mprintf("DELETE FROM %q WHERE pkgname = %Q AND uid = %d", BADGE_OPTION_TABLE_NAME, appid, uid); if (!sqlbuf) { /* LCOV_EXCL_START */ ERR("Failed to alloc query"); result = BADGE_ERROR_OUT_OF_MEMORY; goto return_close_db; /* LCOV_EXCL_STOP */ } ret = badge_db_exec(db, sqlbuf, NULL); if (ret != BADGE_ERROR_NONE) { /* LCOV_EXCL_START */ ERR("Failed to remove badge option[%s], err[%d]", appid, ret); result = ret; goto return_close_db; /* LCOV_EXCL_STOP */ } return_close_db: if (sqlbuf) sqlite3_free(sqlbuf); return result; } static bool _get_table_field_data_string(char **table, char **buf, int ucs2, int index) { bool ret = false; int sLen = 0; char *pTemp; if (table == NULL || buf == NULL || index < 0) { /* LCOV_EXCL_START */ ERR("table[%p], buf[%p], index[%d]", table, buf, index); return false; /* LCOV_EXCL_STOP */ } pTemp = table[index]; if (pTemp == NULL) { *buf = NULL; /* LCOV_EXCL_LINE */ } else { sLen = strlen(pTemp); if (sLen) { *buf = (char *)malloc(sLen + 1); if (*buf == NULL) { ERR("malloc is failed"); /* LCOV_EXCL_LINE */ goto out; } memset(*buf, 0, sLen + 1); strncpy(*buf, pTemp, sLen); } else { *buf = NULL; /* LCOV_EXCL_LINE */ } } ret = true; out: return ret; } int _badge_remove_by_pkgname(const char *pkgname, uid_t uid) { int ret = BADGE_ERROR_NONE; int sql_ret; int row_count = 0; int col_count = 0; int col_index = 0; int index; char *sql_query = NULL; char **query_result = NULL; char *appid = NULL; sqlite3 *db = NULL; sql_ret = db_util_open(BADGE_DB_PATH, &db, 0); if (sql_ret != SQLITE_OK || db == NULL) { ERR("Failed db util open [%s][%d]", BADGE_DB_PATH, sql_ret); return BADGE_ERROR_FROM_DB; } sql_query = sqlite3_mprintf("SELECT appid FROM %s WHERE pkgname = %Q" \ "AND (uid = %d OR uid = %d) ORDER BY uid DESC;", BADGE_SETTING_DB_TABLE, pkgname, uid, tzplatform_getuid(TZ_SYS_GLOBALAPP_USER)); if (!sql_query) { /* LCOV_EXCL_START */ ERR("Failed to alloc query"); ret = BADGE_ERROR_FROM_DB; goto out; /* LCOV_EXCL_STOP */ } sql_ret = sqlite3_get_table(db, sql_query, &query_result, &row_count, &col_count, NULL); if (sql_ret != SQLITE_OK && sql_ret != -1) { /* LCOV_EXCL_START */ ERR("sqlite3_get_table failed [%d][%s]", sql_ret, sqlite3_errmsg(db)); ret = BADGE_ERROR_FROM_DB; goto out; /* LCOV_EXCL_STOP */ } if (!row_count) { DBG("No setting found for [%s]", pkgname); ret = BADGE_ERROR_NOT_EXIST; goto out; } col_index = col_count; for (index = 0; index < row_count; index++) { _get_table_field_data_string(query_result, &appid, 1, col_index++); if (appid) { _badge_remove_by_appid(appid, uid, db); free(appid); appid = NULL; } } out: if (query_result) sqlite3_free_table(query_result); if (sql_query) sqlite3_free(sql_query); if (db) { sql_ret = db_util_close(db); if (sql_ret != SQLITE_OK) WARN("Failed to db_util_close"); } return ret; } int _badge_set_count(const char *caller, const char *pkgname, unsigned int count, uid_t uid, pid_t pid) { int ret = BADGE_ERROR_NONE; int result = BADGE_ERROR_NONE; sqlite3 *db = NULL; char *sqlbuf = NULL; int sqlret; if (!caller || !pkgname) return BADGE_ERROR_INVALID_PARAMETER; sqlret = db_util_open(BADGE_DB_PATH, &db, 0); if (sqlret != SQLITE_OK || !db) { /* LCOV_EXCL_START */ ERR("Failed to db_util_open [%d]", sqlret); return BADGE_ERROR_FROM_DB; /* LCOV_EXCL_STOP */ } ret = _badge_check_data_inserted(pkgname, db, uid); if (ret != BADGE_ERROR_ALREADY_EXIST) { result = ret; goto return_close_db; } ret = _badge_check_writable(caller, pkgname, db, uid, pid); if (ret != BADGE_ERROR_NONE) { result = ret; goto return_close_db; } sqlbuf = sqlite3_mprintf("UPDATE %q SET badge = %d " \ "WHERE pkgname = %Q AND uid = %d", BADGE_TABLE_NAME, count, pkgname, uid); if (!sqlbuf) { /* LCOV_EXCL_START */ ERR("Failed to alloc query"); result = BADGE_ERROR_OUT_OF_MEMORY; goto return_close_db; /* LCOV_EXCL_STOP */ } ret = badge_db_exec(db, sqlbuf, NULL); if (ret != BADGE_ERROR_NONE) { /* LCOV_EXCL_START */ ERR("Failed to set badge[%s] count[%d], err[%d]", pkgname, count, ret); result = ret; goto return_close_db; /* LCOV_EXCL_STOP */ } return_close_db: if (sqlbuf) sqlite3_free(sqlbuf); sqlret = db_util_close(db); if (sqlret != SQLITE_OK) WARN("Failed to db_util_close [%d]", sqlret); /* LCOV_EXCL_LINE */ return result; } int _badge_get_count(const char *pkgname, unsigned int *count, uid_t uid) { int ret = BADGE_ERROR_NONE; int result = BADGE_ERROR_NONE; sqlite3 *db = NULL; char *sqlbuf = NULL; sqlite3_stmt *stmt = NULL; int sqlret; if (!pkgname || !count) return BADGE_ERROR_INVALID_PARAMETER; sqlret = db_util_open(BADGE_DB_PATH, &db, 0); if (sqlret != SQLITE_OK || !db) { /* LCOV_EXCL_START */ ERR("Failed to db_util_open [%d]", sqlret); if (sqlret == SQLITE_PERM) return BADGE_ERROR_PERMISSION_DENIED; else return BADGE_ERROR_FROM_DB; /* LCOV_EXCL_STOP */ } ret = _badge_check_data_inserted(pkgname, db, uid); if (ret != BADGE_ERROR_ALREADY_EXIST) { result = ret; goto return_close_db; } sqlbuf = sqlite3_mprintf("SELECT badge FROM %q " \ "WHERE pkgname = %Q AND uid = %d", BADGE_TABLE_NAME, pkgname, uid); if (!sqlbuf) { /* LCOV_EXCL_START */ ERR("Failed to alloc query"); result = BADGE_ERROR_OUT_OF_MEMORY; goto return_close_db; /* LCOV_EXCL_STOP */ } sqlret = sqlite3_prepare_v2(db, sqlbuf, -1, &stmt, NULL); if (sqlret != SQLITE_OK) { /* LCOV_EXCL_START */ ERR("sqlite3_prepare_v2 failed [%d][%s]", sqlret, sqlite3_errmsg(db)); result = BADGE_ERROR_FROM_DB; goto return_close_db; /* LCOV_EXCL_STOP */ } sqlret = sqlite3_step(stmt); if (sqlret == SQLITE_ROW) *count = (unsigned int)sqlite3_column_int(stmt, 0); else *count = (unsigned int)0; return_close_db: if (sqlbuf) sqlite3_free(sqlbuf); if (stmt) sqlite3_finalize(stmt); sqlret = db_util_close(db); if (sqlret != SQLITE_OK) WARN("Failed to db_util_close [%d]", sqlret); /* LCOV_EXCL_LINE */ return result; } int _badge_set_display(const char *pkgname, unsigned int is_display, uid_t uid) { int ret = BADGE_ERROR_NONE; int result = BADGE_ERROR_NONE; sqlite3 *db = NULL; char *sqlbuf = NULL; int sqlret; if (!pkgname) return BADGE_ERROR_INVALID_PARAMETER; if (is_display != 0 && is_display != 1) return BADGE_ERROR_INVALID_PARAMETER; sqlret = db_util_open(BADGE_DB_PATH, &db, 0); if (sqlret != SQLITE_OK || !db) { /* LCOV_EXCL_START */ ERR("Failed to db_util_open [%d]", sqlret); return BADGE_ERROR_FROM_DB; /* LCOV_EXCL_STOP */ } ret = _badge_check_data_inserted(pkgname, db, uid); if (ret != BADGE_ERROR_ALREADY_EXIST) { result = ret; goto return_close_db; } ret = _badge_check_option_inserted(pkgname, db, uid); if (ret == BADGE_ERROR_ALREADY_EXIST) { sqlbuf = sqlite3_mprintf("UPDATE %q SET display = %d " \ "WHERE pkgname = %Q AND uid = %d", BADGE_OPTION_TABLE_NAME, is_display, pkgname, uid); if (!sqlbuf) { /* LCOV_EXCL_START */ ERR("Failed to alloc query"); result = BADGE_ERROR_OUT_OF_MEMORY; goto return_close_db; /* LCOV_EXCL_STOP */ } ret = badge_db_exec(db, sqlbuf, NULL); if (ret != BADGE_ERROR_NONE) { /* LCOV_EXCL_START */ ERR("Failed to set badge[%s] option[%d], err[%d]", pkgname, is_display, ret); result = ret; goto return_close_db; /* LCOV_EXCL_STOP */ } } else if (ret == BADGE_ERROR_NOT_EXIST) { sqlbuf = sqlite3_mprintf("INSERT INTO %q " \ "(pkgname, display, uid) VALUES (%Q, %d, %d);", BADGE_OPTION_TABLE_NAME, pkgname, is_display, uid); if (!sqlbuf) { /* LCOV_EXCL_START */ ERR("Failed to alloc query"); result = BADGE_ERROR_OUT_OF_MEMORY; goto return_close_db; /* LCOV_EXCL_STOP */ } ret = badge_db_exec(db, sqlbuf, NULL); if (ret != BADGE_ERROR_NONE) { /* LCOV_EXCL_START */ ERR("Failed to set badge[%s] option[%d], err[%d]", pkgname, is_display, ret); result = ret; goto return_close_db; /* LCOV_EXCL_STOP */ } } else { result = ret; goto return_close_db; } return_close_db: if (sqlbuf) sqlite3_free(sqlbuf); sqlret = db_util_close(db); if (sqlret != SQLITE_OK) WARN("Failed to db_util_close [%d]", sqlret); /* LCOV_EXCL_LINE */ return result; } int _badge_get_display(const char *pkgname, unsigned int *is_display, uid_t uid) { int ret = BADGE_ERROR_NONE; int result = BADGE_ERROR_NONE; sqlite3 *db = NULL; char *sqlbuf = NULL; sqlite3_stmt *stmt = NULL; int sqlret; if (!pkgname || !is_display) return BADGE_ERROR_INVALID_PARAMETER; sqlret = db_util_open(BADGE_DB_PATH, &db, 0); if (sqlret != SQLITE_OK || !db) { /* LCOV_EXCL_START */ ERR("Failed to db_util_open [%d]", sqlret); if (sqlret == SQLITE_PERM) return BADGE_ERROR_PERMISSION_DENIED; else return BADGE_ERROR_FROM_DB; /* LCOV_EXCL_STOP */ } ret = _badge_check_option_inserted(pkgname, db, uid); if (ret != BADGE_ERROR_ALREADY_EXIST) { if (ret == BADGE_ERROR_NOT_EXIST) *is_display = 1; result = ret; goto return_close_db; } sqlbuf = sqlite3_mprintf("SELECT display FROM %q " \ "WHERE pkgname = %Q AND uid = %d", BADGE_OPTION_TABLE_NAME, pkgname, uid); if (!sqlbuf) { /* LCOV_EXCL_START */ ERR("Failed to alloc query"); result = BADGE_ERROR_OUT_OF_MEMORY; goto return_close_db; /* LCOV_EXCL_STOP */ } sqlret = sqlite3_prepare_v2(db, sqlbuf, -1, &stmt, NULL); if (sqlret != SQLITE_OK) { /* LCOV_EXCL_START */ ERR("Failed to prepare [%d][%s]", sqlret, sqlite3_errmsg(db)); result = BADGE_ERROR_FROM_DB; goto return_close_db; /* LCOV_EXCL_STOP */ } sqlret = sqlite3_step(stmt); if (sqlret == SQLITE_ROW) *is_display = (unsigned int)sqlite3_column_int(stmt, 0); else *is_display = (unsigned int)1; return_close_db: if (sqlbuf) sqlite3_free(sqlbuf); if (stmt) sqlite3_finalize(stmt); sqlret = db_util_close(db); if (sqlret != SQLITE_OK) WARN("Failed to db_util_close [%d]", sqlret); /* LCOV_EXCL_LINE */ return result; } void badge_changed_cb_call(unsigned int action, const char *pkgname, unsigned int count, uid_t uid) { GList *badge_cb_list = NULL; struct _badge_cb_data *bd = NULL; DBG("call badge_change_cb"); if (_badge_cb_hash == NULL) return; badge_cb_list = (GList *)g_hash_table_lookup(_badge_cb_hash, GUINT_TO_POINTER(uid)); if (badge_cb_list == NULL) { ERR("invalid data"); return; } badge_cb_list = g_list_first(badge_cb_list); for (; badge_cb_list != NULL; badge_cb_list = badge_cb_list->next) { bd = badge_cb_list->data; if (bd != NULL && bd->callback != NULL) { DBG("call badge_change_cb : action %d, pkgname %s, count %d", action, pkgname, count); bd->callback(action, pkgname, count, bd->data); } } } static int _badge_changed_monitor_init(uid_t uid) { return badge_ipc_monitor_init(uid); } static void _badge_chanaged_monitor_fini(void) { badge_ipc_monitor_fini(); } static gint _badge_data_compare(gconstpointer a, gconstpointer b) { const struct _badge_cb_data *bd = NULL; if (!a) return -1; bd = (struct _badge_cb_data *)a; if (bd->callback == b) return 0; return 1; } static struct _badge_cb_data *__malloc_badge_cb_data(badge_change_cb callback, void *data) { struct _badge_cb_data *bd = NULL; bd = (struct _badge_cb_data *)malloc(sizeof(struct _badge_cb_data)); if (bd == NULL) { /* LCOV_EXCL_START */ ERR("Failed malloc badge_cb_data"); return NULL; /* LCOV_EXCL_STOP */ } bd->callback = callback; bd->data = data; return bd; } int _badge_free(badge_h *badge) { if (!badge) return BADGE_ERROR_INVALID_PARAMETER; if (badge->pkgname) free(badge->pkgname); if (badge->writable_pkgs) free(badge->writable_pkgs); free(badge); return BADGE_ERROR_NONE; } badge_h *_badge_new(const char *pkgname, const char *writable_pkgs, int *err) { badge_h *badge = NULL; if (!pkgname || !writable_pkgs) { ERR("Invalid parameters"); if (err) *err = BADGE_ERROR_INVALID_PARAMETER; return NULL; } badge = (badge_h *)malloc(sizeof(struct _badge_h)); if (!badge) { /* LCOV_EXCL_START */ ERR("Failed to alloc handle"); if (err) *err = BADGE_ERROR_OUT_OF_MEMORY; return NULL; /* LCOV_EXCL_STOP */ } badge->pkgname = strdup(pkgname); badge->writable_pkgs = strdup(writable_pkgs); if (err) *err = BADGE_ERROR_NONE; return badge; } char *_badge_pkgs_new(int *err, const char *pkg1, ...) { char *caller_pkgname = NULL; char *s = NULL; char *result = NULL; char *ptr = NULL; gsize length; va_list args; char *new_pkgs = NULL; if (err) *err = BADGE_ERROR_NONE; caller_pkgname = _badge_get_pkgname_by_pid(); if (!caller_pkgname) { ERR("Failed to get caller pkgname"); if (err) *err = BADGE_ERROR_PERMISSION_DENIED; return NULL; } if (!pkg1) { WARN("pkg1 is NULL"); return caller_pkgname; } length = strlen(pkg1); va_start(args, pkg1); s = va_arg(args, char *); while (s) { length += strlen(s); s = va_arg(args, char *); } va_end(args); if (length <= 0) { WARN("length is %d", length); return caller_pkgname; } result = g_new0(char, length + 1); /* 1 for null terminate */ if (!result) { /* LCOV_EXCL_START */ ERR("Failed to alloc memory"); if (err) *err = BADGE_ERROR_OUT_OF_MEMORY; free(caller_pkgname); return NULL; /* LCOV_EXCL_STOP */ } ptr = result; ptr = g_stpcpy(ptr, pkg1); va_start(args, pkg1); s = va_arg(args, char *); while (s) { ptr = g_stpcpy(ptr, s); s = va_arg(args, char *); } va_end(args); if (g_strstr_len(result, -1, caller_pkgname) == NULL) { new_pkgs = g_strdup_printf("%s%s", caller_pkgname, result); if (!new_pkgs) { ERR("Failed to alloc memory"); if (err) *err = BADGE_ERROR_OUT_OF_MEMORY; free(result); free(caller_pkgname); return NULL; } free(result); result = new_pkgs; } free(caller_pkgname); return result; } EXPORT_API int badge_create_for_uid(const char *pkgname, const char *writable_pkg, uid_t uid) { CHECK_BADGE_FEATURE(); char *caller = NULL; int err = BADGE_ERROR_NONE; caller = _badge_get_pkgname_by_pid(); if (!caller) { ERR("Failed to get caller pkgname"); return BADGE_ERROR_PERMISSION_DENIED; } err = badge_ipc_request_insert(pkgname, writable_pkg, caller, uid); free(caller); return err; } EXPORT_API int badge_new_for_uid(const char *writable_app_id, uid_t uid) { CHECK_BADGE_FEATURE(); char *caller = NULL; int err = BADGE_ERROR_NONE; caller = _badge_get_pkgname_by_pid(); if (!caller) { ERR("Failed to get caller pkgname"); return BADGE_ERROR_PERMISSION_DENIED; } err = badge_ipc_request_insert(caller, writable_app_id, caller, uid); free(caller); return err; } EXPORT_API int badge_add_for_uid(const char *badge_app_id, uid_t uid) { CHECK_BADGE_FEATURE(); char *caller = NULL; int err = BADGE_ERROR_NONE; caller = _badge_get_pkgname_by_pid(); if (!caller) { ERR("Failed to get caller pkgname"); return BADGE_ERROR_PERMISSION_DENIED; } if (badge_app_id == NULL) { badge_app_id = caller; } else { int pkgmgr_ret = PACKAGE_MANAGER_ERROR_NONE; package_manager_compare_result_type_e compare_result = PACKAGE_MANAGER_COMPARE_MISMATCH; pkgmgr_ret = package_manager_compare_app_cert_info(badge_app_id, caller, &compare_result); if (pkgmgr_ret != PACKAGE_MANAGER_ERROR_NONE || compare_result != PACKAGE_MANAGER_COMPARE_MATCH) { err = BADGE_ERROR_INVALID_PACKAGE; goto out; } } err = badge_ipc_request_insert(badge_app_id, caller, caller, uid); out: if (caller) free(caller); return err; } EXPORT_API int badge_remove_for_uid(const char *app_id, uid_t uid) { CHECK_BADGE_FEATURE(); char *caller = NULL; int result = BADGE_ERROR_NONE; caller = _badge_get_pkgname_by_pid(); if (!caller) { ERR("Failed to get caller pkgname"); result = BADGE_ERROR_PERMISSION_DENIED; goto out; } result = badge_ipc_request_delete(app_id, caller, uid); out: if (caller) free(caller); return result; } EXPORT_API int badge_is_existing_for_uid(const char *app_id, bool *existing, uid_t uid) { CHECK_BADGE_FEATURE(); return badge_ipc_request_is_existing(app_id, existing, uid); } EXPORT_API int badge_foreach_for_uid(badge_foreach_cb callback, void *user_data, uid_t uid) { CHECK_BADGE_FEATURE(); int result = BADGE_ERROR_NONE; result = badge_ipc_request_get_list(callback, user_data, uid); if (result == BADGE_ERROR_IO_ERROR) result = BADGE_ERROR_FROM_DB; return result; } EXPORT_API int badge_set_count_for_uid(const char *app_id, unsigned int count, uid_t uid) { CHECK_BADGE_FEATURE(); char *caller = NULL; int result = BADGE_ERROR_NONE; DBG("app_id %s, count %d", app_id, count); caller = _badge_get_pkgname_by_pid(); if (!caller) { ERR("Failed to get caller pkgname"); result = BADGE_ERROR_PERMISSION_DENIED; goto out; } result = badge_ipc_request_set_count(app_id, caller, count, uid); out: if (caller) free(caller); return result; } EXPORT_API int badge_get_count_for_uid(const char *app_id, unsigned int *count, uid_t uid) { CHECK_BADGE_FEATURE(); int result = BADGE_ERROR_NONE; result = badge_ipc_request_get_count(app_id, count, uid); if (result == BADGE_ERROR_IO_ERROR) result = BADGE_ERROR_FROM_DB; return result; } EXPORT_API int badge_set_display_for_uid(const char *app_id, unsigned int is_display, uid_t uid) { CHECK_BADGE_FEATURE(); char *caller = NULL; int result = BADGE_ERROR_NONE; caller = _badge_get_pkgname_by_pid(); if (!caller) { ERR("Failed to get caller pkgname"); result = BADGE_ERROR_PERMISSION_DENIED; goto out; } result = badge_ipc_request_set_display(app_id, caller, is_display, uid); out: if (caller) free(caller); return result; } EXPORT_API int badge_get_display_for_uid(const char *app_id, unsigned int *is_display, uid_t uid) { CHECK_BADGE_FEATURE(); int result = BADGE_ERROR_NONE; result = badge_ipc_request_get_display(app_id, is_display, uid); if (result == BADGE_ERROR_IO_ERROR) result = BADGE_ERROR_FROM_DB; return result; } EXPORT_API int badge_register_changed_cb_for_uid(badge_change_cb callback, void *data, uid_t uid) { CHECK_BADGE_FEATURE(); struct _badge_cb_data *bd = NULL; GList *badge_cb_list = NULL; GList *badge_found_list = NULL; int ret; if (_badge_cb_hash == NULL) _badge_cb_hash = g_hash_table_new(g_direct_hash, g_direct_equal); badge_cb_list = (GList *)g_hash_table_lookup(_badge_cb_hash, GUINT_TO_POINTER(uid)); if (badge_cb_list == NULL) { bd = __malloc_badge_cb_data(callback, data); if (!bd) return BADGE_ERROR_OUT_OF_MEMORY; badge_cb_list = g_list_append(badge_cb_list, bd); g_hash_table_insert(_badge_cb_hash, GUINT_TO_POINTER(uid), badge_cb_list); } else { badge_found_list = g_list_find_custom(g_list_first(badge_cb_list), (gconstpointer)callback, (GCompareFunc)_badge_data_compare); if (badge_found_list) { bd = g_list_nth_data(badge_found_list, 0); bd->data = data; } else { bd = __malloc_badge_cb_data(callback, data); if (!bd) return BADGE_ERROR_OUT_OF_MEMORY; badge_cb_list = g_list_append(badge_cb_list, bd); } } ret = _badge_changed_monitor_init(uid); if (ret == BADGE_ERROR_NONE) { ret = badge_ipc_init_badge(uid); if (ret != BADGE_ERROR_NONE && ret != BADGE_ERROR_NOT_EXIST) { badge_unregister_changed_cb_for_uid(callback, uid); return BADGE_ERROR_IO_ERROR; } } else { /* LCOV_EXCL_START */ ERR("badge_ipc_monitor_init err [%d]", ret); badge_unregister_changed_cb_for_uid(callback, uid); return ret; /* LCOV_EXCL_STOP */ } return BADGE_ERROR_NONE; } EXPORT_API int badge_unregister_changed_cb_for_uid(badge_change_cb callback, uid_t uid) { CHECK_BADGE_FEATURE(); GList *badge_cb_list = NULL; GList *badge_delete_list = NULL; struct _badge_cb_data *bd = NULL; if (_badge_cb_hash == NULL) return BADGE_ERROR_INVALID_PARAMETER; badge_cb_list = (GList *)g_hash_table_lookup(_badge_cb_hash, GUINT_TO_POINTER(uid)); if (badge_cb_list == NULL) return BADGE_ERROR_INVALID_PARAMETER; badge_delete_list = g_list_find_custom(g_list_first(badge_cb_list), (gconstpointer)callback, (GCompareFunc)_badge_data_compare); if (badge_delete_list) { bd = g_list_nth_data(badge_delete_list, 0); badge_cb_list = g_list_delete_link(badge_cb_list, badge_delete_list); free(bd); } else { return BADGE_ERROR_INVALID_PARAMETER; } if (badge_cb_list == NULL) g_hash_table_steal(_badge_cb_hash, GUINT_TO_POINTER(uid)); else g_hash_table_replace(_badge_cb_hash, GUINT_TO_POINTER(uid), badge_cb_list); if (g_hash_table_size(_badge_cb_hash) == 0) _badge_chanaged_monitor_fini(); return BADGE_ERROR_NONE; } EXPORT_API int badge_is_service_ready(void) { CHECK_BADGE_FEATURE(); return badge_ipc_is_master_ready(); } EXPORT_API int badge_add_deferred_task( void (*badge_add_deferred_task)(void *data), void *user_data) { CHECK_BADGE_FEATURE(); return badge_ipc_add_deferred_task(badge_add_deferred_task, user_data); } EXPORT_API int badge_del_deferred_task( void (*badge_add_deferred_task)(void *data)) { CHECK_BADGE_FEATURE(); return badge_ipc_del_deferred_task(badge_add_deferred_task); } EXPORT_API int badge_is_existing(const char *app_id, bool *existing) { CHECK_BADGE_FEATURE(); if (app_id == NULL || existing == NULL) return BADGE_ERROR_INVALID_PARAMETER; return badge_is_existing_for_uid(app_id, existing, getuid()); } EXPORT_API int badge_create(const char *pkgname, const char *writable_pkg) { CHECK_BADGE_FEATURE(); if (pkgname == NULL) return BADGE_ERROR_INVALID_PARAMETER; return badge_create_for_uid(pkgname, writable_pkg, getuid()); }