2 * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include "db_handle_provider.hh"
22 #include <sys/types.h>
24 #include <tzplatform_config.h>
30 #include "cache_flag.hh"
31 #include "utils/logging.hh"
33 #include "pkgmgr-info.h"
34 #include "pkgmgrinfo_debug.h"
35 #include "pkgmgrinfo_internal.h"
36 #include "pkgmgrinfo_internal.hh"
37 #include "pkgmgrinfo_private.h"
42 #define LOG_TAG "PKGMGR_INFO"
46 uid_t globaluser_uid = -1;
48 uid_t GetGlobalUID() {
49 if (globaluser_uid == (uid_t)-1)
50 globaluser_uid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
52 return globaluser_uid;
55 uid_t ConvertUID(uid_t uid) {
56 if (uid < REGULAR_USER)
57 return GetGlobalUID();
62 bool GetModifiedTime(const char* dbpath, timespec* t) {
63 if (dbpath == nullptr || t == nullptr) {
64 LOG(ERROR) << "Invalid argument";
69 if (stat(dbpath, &attr)) {
70 LOG(ERROR) << "Fail to get status from file "
71 << dbpath << " errno : " << errno;
80 static const std::string global_parser_memdb_path =
81 "file:parserdb?mode=memory&cache=shared";
83 static const std::string cert_memdb_path =
84 "file:certdb?mode=memory&cache=shared";
88 namespace pkgmgr_server {
91 std::unordered_map<uid_t, std::unique_ptr<DBHandleProvider>>
92 DBHandleProvider::provider_map_;
93 bool DBHandleProvider::is_global_memdb_set_ = false;
94 std::unique_ptr<sqlite3, decltype(sqlite3_close_v2)*>
95 DBHandleProvider::global_parser_memdb_handle_(nullptr,
97 std::unique_ptr<sqlite3, decltype(sqlite3_close_v2)*>
98 DBHandleProvider::cert_memdb_handle_(nullptr, sqlite3_close_v2);
99 std::string DBHandleProvider::global_parser_filedb_path_;
100 std::string DBHandleProvider::cert_filedb_path_;
101 std::unordered_set<pid_t> DBHandleProvider::writer_pid_list_;
102 std::recursive_mutex DBHandleProvider::lock_;
103 std::shared_mutex DBHandleProvider::pid_list_lock_;
105 DBHandleProvider::DBHandleProvider(uid_t uid)
107 is_user_memdb_set_(false),
108 parser_memdb_handle_(nullptr, sqlite3_close_v2) {
111 if (global_parser_filedb_path_.empty()) {
112 tmp_path = getUserPkgParserDBPathUID(GetGlobalUID());
113 global_parser_filedb_path_ = tmp_path;
117 if (cert_filedb_path_.empty()) {
118 tmp_path = getUserPkgCertDBPath();
119 cert_filedb_path_ = tmp_path;
123 tmp_path = getUserPkgParserDBPathUID(uid_);
124 user_parser_filedb_path_ = tmp_path;
127 user_parser_memdb_path_ = "file:parserdb" +
128 std::to_string(static_cast<int>(uid_)) +
129 "?mode=memory&cache=shared";
132 DBHandleProvider& DBHandleProvider::GetInst(uid_t uid) {
133 static std::shared_mutex singleton_lock_;
134 std::shared_lock<std::shared_mutex> s(singleton_lock_);
136 uid = ConvertUID(uid);
137 auto it = provider_map_.find(uid);
138 if (it != provider_map_.end())
139 return *(it->second);
142 std::unique_lock<std::shared_mutex> u(singleton_lock_);
143 auto& prov = provider_map_[uid];
145 prov.reset(new DBHandleProvider(uid));
150 bool DBHandleProvider::IsCrashedWriteRequest() {
151 std::unique_lock<std::shared_mutex> u(pid_list_lock_);
153 if (writer_pid_list_.empty())
157 LOG(DEBUG) << "Check process count : " << writer_pid_list_.size();
158 std::vector<pid_t> remove_pids;
159 for (pid_t pid : writer_pid_list_) {
160 std::string status_path = "/proc/" + std::to_string(pid) + "/status";
162 int fd = open(status_path.c_str(), O_RDONLY);
164 LOG(ERROR) << "Process is crashed : " << pid;
165 remove_pids.push_back(pid);
172 for (pid_t pid : remove_pids)
173 writer_pid_list_.erase(pid);
178 std::vector<std::pair<std::string, uid_t>> DBHandleProvider::GetParserDBPath(
179 pid_t pid, bool write) {
180 std::unique_lock<std::recursive_mutex> u(lock_);
181 std::vector<std::pair<std::string, uid_t>> db_path_list;
183 if (is_user_memdb_set_ != is_global_memdb_set_)
184 is_global_memdb_set_ ? SetMemoryMode(pid) : UnsetMemoryMode(pid);
186 if (IsMemoryDBActive(pid, write)) {
187 if (uid_ > REGULAR_USER)
188 db_path_list.emplace_back(std::make_pair(user_parser_memdb_path_, uid_));
190 db_path_list.emplace_back(
191 std::make_pair(global_parser_memdb_path, GetGlobalUID()));
193 if (uid_ > REGULAR_USER)
194 db_path_list.emplace_back(std::make_pair(user_parser_filedb_path_, uid_));
196 db_path_list.emplace_back(
197 std::make_pair(global_parser_filedb_path_, GetGlobalUID()));
200 if (db_path_list.size() == 1) {
201 LOG(DEBUG) << "global db path : " << db_path_list[0].first;
203 LOG(DEBUG) << "local db path : " << db_path_list[0].first;
204 LOG(DEBUG) << "global db path : " << db_path_list[1].first;
210 std::string DBHandleProvider::GetCertDBPath(pid_t pid, bool write) {
211 std::unique_lock<std::recursive_mutex> u(lock_);
212 if (is_user_memdb_set_ != is_global_memdb_set_)
213 is_global_memdb_set_ ? SetMemoryMode(pid) : UnsetMemoryMode(pid);
215 if (IsMemoryDBActive(pid, write))
216 return cert_memdb_path;
218 return cert_filedb_path_;
221 sqlite3* DBHandleProvider::CreateMemoryDBHandle(const std::string& filedb_path,
222 const std::string& memorydb_path) {
223 sqlite3* memorydb = nullptr;
224 sqlite3* filedb = nullptr;
225 int ret = sqlite3_open_v2(memorydb_path.c_str(), &memorydb,
226 SQLITE_OPEN_READONLY | SQLITE_OPEN_URI, nullptr);
227 if (ret != SQLITE_OK) {
228 LOG(ERROR) << "Failed to open memory DB " << ret << ": " << memorydb_path;
232 ret = sqlite3_open_v2(filedb_path.c_str(), &filedb, SQLITE_OPEN_READONLY,
234 if (ret != SQLITE_OK) {
235 LOG(ERROR) << "Failed to open file DB " << ret << ": " << filedb_path;
236 sqlite3_close_v2(memorydb);
240 sqlite3_backup* backup =
241 sqlite3_backup_init(memorydb, "main", filedb, "main");
242 if (backup == nullptr) {
243 LOG(ERROR) << "Failed to backup for memory DB";
244 sqlite3_close_v2(memorydb);
245 sqlite3_close_v2(filedb);
249 sqlite3_backup_step(backup, -1);
250 sqlite3_backup_finish(backup);
251 sqlite3_close_v2(filedb);
255 void DBHandleProvider::SetMemoryMode(pid_t pid) {
256 std::unique_lock<std::recursive_mutex> u(lock_);
257 if (is_global_memdb_set_ && is_user_memdb_set_)
261 CreateMemoryDBHandle(user_parser_filedb_path_, user_parser_memdb_path_);
262 if (parser_db != nullptr)
263 parser_memdb_handle_.reset(parser_db);
265 if (is_user_memdb_set_ == is_global_memdb_set_) {
266 sqlite3* global_parser_file_db = CreateMemoryDBHandle(
267 global_parser_filedb_path_, global_parser_memdb_path);
268 if (global_parser_file_db)
269 global_parser_memdb_handle_.reset(global_parser_file_db);
272 CreateMemoryDBHandle(cert_filedb_path_, cert_memdb_path);
273 if (cert_db != nullptr)
274 cert_memdb_handle_.reset(cert_db);
279 is_user_memdb_set_ = true;
280 is_global_memdb_set_ = true;
281 LOG(DEBUG) << "Set Memory mode : Memory";
284 void DBHandleProvider::UnsetMemoryMode(pid_t pid) {
285 std::unique_lock<std::recursive_mutex> u(lock_);
286 if (!is_global_memdb_set_ && !is_user_memdb_set_)
289 parser_memdb_handle_.reset(nullptr);
290 cert_memdb_handle_.reset(nullptr);
291 global_parser_memdb_handle_.reset(nullptr);
294 LOG(ERROR) << "Given pid is not exists in pid list : " << pid;
296 is_user_memdb_set_ = false;
297 is_global_memdb_set_ = false;
299 LOG(DEBUG) << "Set Memory mode : File";
302 bool DBHandleProvider::IsMemoryDBActive(pid_t pid, bool write) {
303 std::unique_lock<std::shared_mutex> u(pid_list_lock_);
304 if (!is_user_memdb_set_)
310 if (writer_pid_list_.find(pid) != writer_pid_list_.end())
316 void DBHandleProvider::TrimCache() {
317 std::unique_lock<std::recursive_mutex> u(lock_);
322 void DBHandleProvider::ReleaseCache() {
323 auto lock = CacheFlag::GetWriterLock();
324 CacheFlag::SetStatus(CacheFlag::Status::PREPARING);
328 pending_pkg_.clear();
329 pkg_app_map_.clear();
330 CacheFlag::SetStatus(CacheFlag::Status::UNPREPARED);
335 bool DBHandleProvider::IsWriter(pid_t pid) {
336 std::unique_lock<std::shared_mutex> s(pid_list_lock_);
337 return writer_pid_list_.find(pid) != writer_pid_list_.end();
340 int DBHandleProvider::UpdateCache(sqlite3* db, pid_t pid, uid_t uid, bool write,
341 const std::string& locale) {
344 pending_pkg_.clear();
345 pkg_app_map_.clear();
347 const char* dbpath = sqlite3_db_filename(db, "main");
348 bool is_inmemory_db = false;
349 if (dbpath == nullptr || strlen(dbpath) == 0) {
350 LOG(INFO) << "database is inmemory db";
351 is_inmemory_db = true;
354 timespec start_time = { 0, };
355 timespec end_time = { 0, };
356 if (!is_inmemory_db && !GetModifiedTime(dbpath, &start_time))
357 return PMINFO_R_ERROR;
359 GHashTable* list = g_hash_table_new(g_str_hash, g_str_equal);
360 if (list == nullptr) {
361 LOG(ERROR) << "Out of memory";
362 return PMINFO_R_ERROR;
365 pkgmgrinfo_filter_x tmp_filter = { 0, };
366 tmp_filter.cache_flag = true;
367 int ret = pkginfo_internal_filter_get_list(db, &tmp_filter, uid_,
368 locale.c_str(), list);
369 if (ret == PMINFO_R_OK) {
372 g_hash_table_iter_init(&iter, list);
373 while (g_hash_table_iter_next(&iter, nullptr, &value)) {
374 auto* pkg = reinterpret_cast<package_x*>(value);
375 std::string pkgid = pkg->package;
376 AddPackage(std::move(pkgid), pkg);
380 g_hash_table_destroy(list);
381 if (ret == PMINFO_R_ERROR)
384 if (!is_inmemory_db && !GetModifiedTime(dbpath, &end_time))
385 return PMINFO_R_ERROR;
387 if (start_time.tv_sec != end_time.tv_sec ||
388 start_time.tv_nsec != end_time.tv_nsec) {
389 LOG(ERROR) << "Database(" << dbpath << ") modification was detected";
390 return PMINFO_R_ERROR;
393 std::vector<std::shared_ptr<application_x>> app_list;
394 ret = pkgmgr_server::internal::appinfo_internal_filter_get_list(db,
395 &tmp_filter, uid_, uid, locale.c_str(), app_list);
397 if (!is_inmemory_db && !GetModifiedTime(dbpath, &end_time))
398 return PMINFO_R_ERROR;
400 if (start_time.tv_sec != end_time.tv_sec ||
401 start_time.tv_nsec != end_time.tv_nsec) {
402 LOG(ERROR) << "Database(" << dbpath << ") modification was detected";
403 return PMINFO_R_ERROR;
406 if (ret == PMINFO_R_OK) {
407 for (auto& app : app_list) {
408 auto it = pkg_map_.find(app->package);
409 if (it == pkg_map_.end()) {
410 LOG(ERROR) << "Can not find package from pkg_map";
411 return PMINFO_R_ERROR;
414 app->privileges = it->second->privileges;
415 std::string appid = app->appid;
416 AddApplication(std::move(appid), std::move(app));
425 inline bool CheckPkgFilters(pkgmgrinfo_filter_x* filter,
426 const std::shared_ptr<package_x>& info) {
427 for (auto* it = filter->list; it != nullptr; it = g_slist_next(it)) {
428 auto node = reinterpret_cast<pkgmgrinfo_node_x*>(it->data);
429 auto* checker = FilterCheckerProvider::GetInst().
430 GetPkgFilterChecker(node->prop);
431 if (!checker->CheckFilter(node, info.get()))
438 std::vector<std::shared_ptr<package_x>> DBHandleProvider::GetPackages(
439 pid_t pid, pkgmgrinfo_filter_x* filter,
440 const std::string& package) {
441 std::vector<std::shared_ptr<package_x>> ret;
443 if (__check_package_storage_status(filter)) {
444 if (pkgmgrinfo_pkginfo_filter_add_bool(filter,
445 PMINFO_PKGINFO_PROP_PACKAGE_CHECK_STORAGE, true) != PMINFO_R_OK) {
446 LOG(ERROR) << "Fail to add check storage value to filter";
450 if (package.empty()) {
451 for (auto& info : pkg_map_) {
452 if (CheckPkgFilters(filter, info.second))
453 ret.push_back(info.second);
456 auto map_it = pkg_map_.find(package);
457 if (map_it != pkg_map_.end() && CheckPkgFilters(filter, map_it->second))
458 ret.push_back(map_it->second);
464 void DBHandleProvider::AddPackage(std::string package, package_x* info) {
465 auto ptr = std::shared_ptr<package_x>(info, pkgmgrinfo_basic_free_package);
466 pkg_map_[package] = std::move(ptr);
469 inline bool CheckAppFilters(pkgmgrinfo_filter_x* filter,
470 const std::shared_ptr<application_x>& info,
471 const std::unordered_map<std::string, std::string>& metadata_map) {
472 for (auto* it = filter->list; it != nullptr; it = g_slist_next(it)) {
473 auto node = reinterpret_cast<pkgmgrinfo_node_x*>(it->data);
474 auto* checker = FilterCheckerProvider::GetInst().
475 GetAppFilterChecker(node->prop);
476 if (!checker->CheckFilter(node, info.get()))
481 if (!metadata_map.empty()) {
483 for (auto* it = info->metadata; it != nullptr; it = g_list_next(it)) {
484 auto* node = reinterpret_cast<metadata_x*>(it->data);
485 if (node->key != nullptr) {
486 auto metadata = metadata_map.find(node->key);
487 if (metadata == metadata_map.end())
490 if (metadata->second.empty() ||
491 strcmp(node->value ? node->value : "",
492 metadata->second.c_str()) == 0)
501 std::vector<std::shared_ptr<application_x>> DBHandleProvider::GetApplications(
502 pid_t pid, pkgmgrinfo_filter_x* filter,
503 const std::string& app) {
504 /* make metadata filter map */
505 std::unordered_map<std::string, std::string> metadata_map;
506 for (auto* it = filter->list_metadata; it != nullptr; it = g_slist_next(it)) {
507 auto node = reinterpret_cast<pkgmgrinfo_metadata_node_x*>(it->data);
508 if (node->key == nullptr)
511 metadata_map[node->key] = (node->value ? node->value : "");
514 std::vector<std::shared_ptr<application_x>> ret;
515 if (pkgmgr_server::internal::check_app_storage_status(filter)) {
516 if (pkgmgrinfo_appinfo_filter_add_bool(filter,
517 PMINFO_APPINFO_PROP_APP_CHECK_STORAGE, true) != PMINFO_R_OK) {
518 LOG(ERROR) << "Fail to add check storage value to filter";
524 for (auto& info : app_map_) {
525 if (CheckAppFilters(filter, info.second, metadata_map))
526 ret.push_back(info.second);
529 auto map_it = app_map_.find(app);
530 if (map_it != app_map_.end() &&
531 CheckAppFilters(filter, map_it->second, metadata_map))
532 ret.push_back(map_it->second);
538 void DBHandleProvider::AddApplication(std::string app,
539 std::shared_ptr<application_x> info) {
540 pkg_app_map_[info->package].emplace(app);
541 app_map_[app] = std::move(info);
544 void DBHandleProvider::InsertPID(pid_t pid) {
545 std::unique_lock<std::shared_mutex> u(pid_list_lock_);
547 writer_pid_list_.insert(pid);
550 bool DBHandleProvider::ErasePID(pid_t pid) {
551 std::unique_lock<std::shared_mutex> u(pid_list_lock_);
553 return writer_pid_list_.erase(pid) == 1;
556 void DBHandleProvider::RegisterPendingPackageInfo(package_x* info) {
557 if (!info || !info->package)
560 pending_pkg_.emplace(info->package);
563 bool DBHandleProvider::UpdatePendingPackageInfo(sqlite3* db,
564 pid_t pid, uid_t uid, const std::string& locale) {
565 GHashTable* list = g_hash_table_new(g_str_hash, g_str_equal);
566 if (list == nullptr) {
567 LOG(ERROR) << "Out of memory";
571 pkgmgrinfo_filter_x tmp_filter = { 0, };
572 pkgmgrinfo_node_x node = {
573 .prop = E_PMINFO_PKGINFO_PROP_PACKAGE_ID
575 tmp_filter.cache_flag = true;
576 tmp_filter.list = g_slist_append(tmp_filter.list, (gpointer)&node);
577 for (const auto& pkg : pending_pkg_) {
579 for (auto& appid : pkg_app_map_[pkg]) {
580 app_map_.erase(appid);
583 pkg_app_map_.erase(pkg);
584 node.value = const_cast<char*>(pkg.c_str());
585 pkginfo_internal_filter_get_list(db, &tmp_filter,
586 uid_, locale.c_str(), list);
591 g_hash_table_iter_init(&iter, list);
592 while (g_hash_table_iter_next(&iter, nullptr, &value)) {
593 auto* pkg = reinterpret_cast<package_x*>(value);
594 std::string pkgid = pkg->package;
595 AddPackage(std::move(pkgid), pkg);
598 g_hash_table_iter_init(&iter, list);
599 node.prop = E_PMINFO_APPINFO_PROP_APP_PACKAGE;
600 while (g_hash_table_iter_next(&iter, nullptr, &value)) {
601 auto* pkg = reinterpret_cast<package_x*>(value);
602 node.value = pkg->package;
603 std::vector<std::shared_ptr<application_x>> app_list;
604 pkgmgr_server::internal::appinfo_internal_filter_get_list(
605 db, &tmp_filter, uid_, uid, locale.c_str(), app_list);
607 for (auto& app : app_list) {
608 app->privileges = pkg->privileges;
609 std::string appid = app->appid;
610 AddApplication(std::move(appid), std::move(app));
614 g_hash_table_destroy(list);
615 g_slist_free(tmp_filter.list);
616 pending_pkg_.clear();
620 bool DBHandleProvider::UpdateCachePkg(sqlite3* db, uid_t uid,
621 const std::string& pkgid, const std::string& locale) {
622 GHashTable* list = g_hash_table_new(g_str_hash, g_str_equal);
623 if (list == nullptr) {
624 LOG(ERROR) << "Out of memory";
628 pkgmgrinfo_filter_x tmp_filter = { 0, };
629 pkgmgrinfo_node_x node = {
630 .prop = E_PMINFO_PKGINFO_PROP_PACKAGE_ID,
631 .value = const_cast<char*>(pkgid.c_str())
633 tmp_filter.cache_flag = true;
634 tmp_filter.list = g_slist_append(tmp_filter.list, (gpointer)&node);
635 pkginfo_internal_filter_get_list(db, &tmp_filter,
636 uid_, locale.c_str(), list);
640 g_hash_table_iter_init(&iter, list);
641 while (g_hash_table_iter_next(&iter, nullptr, &value)) {
642 auto* pkg = reinterpret_cast<package_x*>(value);
643 std::string pkgid = pkg->package;
644 AddPackage(pkgid, pkg);
646 for (auto& appid : pkg_app_map_[pkgid]) {
647 app_map_.erase(appid);
650 pkg_app_map_.erase(pkgid);
652 std::vector<std::shared_ptr<application_x>> app_list;
653 node.prop = E_PMINFO_APPINFO_PROP_APP_PACKAGE;
654 node.value = const_cast<char*>(pkgid.c_str());
656 pkgmgr_server::internal::appinfo_internal_filter_get_list(
657 db, &tmp_filter, uid_, uid, locale.c_str(), app_list);
659 for (auto& app : app_list) {
660 app->privileges = pkg->privileges;
661 std::string appid = app->appid;
662 AddApplication(std::move(appid), std::move(app));
666 g_hash_table_destroy(list);
667 g_slist_free(tmp_filter.list);
671 bool DBHandleProvider::UpdateCacheApp(sqlite3* db, uid_t uid,
672 const std::string& appid, const std::string& locale) {
673 pkgmgrinfo_filter_x tmp_filter = { 0, };
674 pkgmgrinfo_node_x node = {
675 .prop = E_PMINFO_APPINFO_PROP_APP_ID,
676 .value = const_cast<char*>(appid.c_str())
678 tmp_filter.cache_flag = true;
679 tmp_filter.list = g_slist_append(tmp_filter.list, (gpointer)&node);
681 std::vector<std::shared_ptr<application_x>> app_list;
682 app_map_.erase(appid);
683 pkgmgr_server::internal::appinfo_internal_filter_get_list(db,
684 &tmp_filter, uid_, uid, locale.c_str(), app_list);
685 g_slist_free(tmp_filter.list);
687 for (auto& app : app_list) {
688 auto it = pkg_map_.find(app->package);
689 if (it == pkg_map_.end()) {
690 LOG(ERROR) << "Can not find package from pkg_map";
694 pkg_app_map_[app->package].erase(app->appid);
695 app->privileges = it->second->privileges;
696 std::string appid = app->appid;
697 AddApplication(std::move(appid), std::move(app));
703 bool DBHandleProvider::UpdateCacheAppByPkgid(sqlite3* db, uid_t uid,
704 const std::string& pkgid, const std::string& locale) {
705 auto it = pkg_map_.find(pkgid);
706 if (it == pkg_map_.end()) {
707 LOG(ERROR) << "Can not find package from pkg_map";
711 auto& pkg = it->second;
712 pkgmgrinfo_filter_x tmp_filter = { 0, };
713 pkgmgrinfo_node_x node = {
714 .prop = E_PMINFO_APPINFO_PROP_APP_PACKAGE,
715 .value = pkg->package
718 tmp_filter.cache_flag = true;
719 tmp_filter.list = g_slist_append(tmp_filter.list, (gpointer)&node);
721 std::vector<std::shared_ptr<application_x>> app_list;
722 pkgmgr_server::internal::appinfo_internal_filter_get_list(
723 db, &tmp_filter, uid_, uid, locale.c_str(), app_list);
725 for (auto& appid : pkg_app_map_[pkgid]) {
726 app_map_.erase(appid);
728 pkg_app_map_.erase(pkgid);
730 for (auto& app : app_list) {
731 app->privileges = pkg->privileges;
732 std::string appid = app->appid;
733 AddApplication(std::move(appid), std::move(app));
736 g_slist_free(tmp_filter.list);
740 } // namespace database
741 } // namespace pkgmgr_server