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"
21 #include <sys/types.h>
23 #include <tzplatform_config.h>
29 #include "cache_flag.hh"
30 #include "utils/logging.hh"
32 #include "pkgmgr-info.h"
33 #include "pkgmgrinfo_debug.h"
34 #include "pkgmgrinfo_internal.h"
35 #include "pkgmgrinfo_internal.hh"
36 #include "pkgmgrinfo_private.h"
41 #define LOG_TAG "PKGMGR_INFO"
45 uid_t globaluser_uid = -1;
47 uid_t GetGlobalUID() {
48 if (globaluser_uid == (uid_t)-1)
49 globaluser_uid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
51 return globaluser_uid;
54 uid_t ConvertUID(uid_t uid) {
55 if (uid < REGULAR_USER)
56 return GetGlobalUID();
61 static const std::string global_parser_memdb_path =
62 "file:parserdb?mode=memory&cache=shared";
64 static const std::string cert_memdb_path =
65 "file:certdb?mode=memory&cache=shared";
69 namespace pkgmgr_server {
72 std::unordered_map<uid_t, std::unique_ptr<DBHandleProvider>>
73 DBHandleProvider::provider_map_;
74 bool DBHandleProvider::is_global_memdb_set_ = false;
75 std::unique_ptr<sqlite3, decltype(sqlite3_close_v2)*>
76 DBHandleProvider::global_parser_memdb_handle_(nullptr,
78 std::unique_ptr<sqlite3, decltype(sqlite3_close_v2)*>
79 DBHandleProvider::cert_memdb_handle_(nullptr, sqlite3_close_v2);
80 std::string DBHandleProvider::global_parser_filedb_path_;
81 std::string DBHandleProvider::cert_filedb_path_;
82 std::unordered_set<pid_t> DBHandleProvider::writer_pid_list_;
83 std::recursive_mutex DBHandleProvider::lock_;
84 std::mutex DBHandleProvider::pid_list_lock_;
86 DBHandleProvider::DBHandleProvider(uid_t uid)
88 is_user_memdb_set_(false),
89 parser_memdb_handle_(nullptr, sqlite3_close_v2) {
92 if (global_parser_filedb_path_.empty()) {
93 tmp_path = getUserPkgParserDBPathUID(GetGlobalUID());
94 global_parser_filedb_path_ = tmp_path;
98 if (cert_filedb_path_.empty()) {
99 tmp_path = getUserPkgCertDBPath();
100 cert_filedb_path_ = tmp_path;
104 tmp_path = getUserPkgParserDBPathUID(uid_);
105 user_parser_filedb_path_ = tmp_path;
108 user_parser_memdb_path_ = "file:parserdb" +
109 std::to_string(static_cast<int>(uid_)) +
110 "?mode=memory&cache=shared";
113 DBHandleProvider& DBHandleProvider::GetInst(uid_t uid) {
114 static std::mutex singleton_lock_;
115 std::unique_lock<std::mutex> u(singleton_lock_);
117 uid = ConvertUID(uid);
118 auto& prov = provider_map_[uid];
120 prov.reset(new DBHandleProvider(uid));
125 bool DBHandleProvider::IsCrashedWriteRequest() {
126 std::unique_lock<std::mutex> u(pid_list_lock_);
128 if (writer_pid_list_.empty())
132 LOG(DEBUG) << "Check process count : " << writer_pid_list_.size();
133 std::vector<pid_t> remove_pids;
134 for (pid_t pid : writer_pid_list_) {
135 std::string status_path = "/proc/" + std::to_string(pid) + "/status";
137 int fd = open(status_path.c_str(), O_RDONLY);
139 LOG(ERROR) << "Process is crashed : " << pid;
140 remove_pids.push_back(pid);
147 for (pid_t pid : remove_pids)
148 writer_pid_list_.erase(pid);
153 std::vector<std::pair<std::string, uid_t>> DBHandleProvider::GetParserDBPath(
154 pid_t pid, bool write) {
155 std::unique_lock<std::recursive_mutex> u(lock_);
156 std::vector<std::pair<std::string, uid_t>> db_path_list;
158 if (is_user_memdb_set_ != is_global_memdb_set_)
159 is_global_memdb_set_ ? SetMemoryMode(pid) : UnsetMemoryMode(pid);
161 if (IsMemoryDBActive(pid, write)) {
162 if (uid_ > REGULAR_USER)
163 db_path_list.emplace_back(std::make_pair(user_parser_memdb_path_, uid_));
165 db_path_list.emplace_back(
166 std::make_pair(global_parser_memdb_path, GetGlobalUID()));
168 if (uid_ > REGULAR_USER)
169 db_path_list.emplace_back(std::make_pair(user_parser_filedb_path_, uid_));
171 db_path_list.emplace_back(
172 std::make_pair(global_parser_filedb_path_, GetGlobalUID()));
175 if (db_path_list.size() == 1) {
176 LOG(DEBUG) << "global db path : " << db_path_list[0].first;
178 LOG(DEBUG) << "local db path : " << db_path_list[0].first;
179 LOG(DEBUG) << "global db path : " << db_path_list[1].first;
185 std::string DBHandleProvider::GetCertDBPath(pid_t pid, bool write) {
186 std::unique_lock<std::recursive_mutex> u(lock_);
187 if (is_user_memdb_set_ != is_global_memdb_set_)
188 is_global_memdb_set_ ? SetMemoryMode(pid) : UnsetMemoryMode(pid);
190 if (IsMemoryDBActive(pid, write))
191 return cert_memdb_path;
193 return cert_filedb_path_;
196 sqlite3* DBHandleProvider::CreateMemoryDBHandle(const std::string& filedb_path,
197 const std::string& memorydb_path) {
198 sqlite3* memorydb = nullptr;
199 sqlite3* filedb = nullptr;
200 int ret = sqlite3_open_v2(memorydb_path.c_str(), &memorydb,
201 SQLITE_OPEN_READONLY | SQLITE_OPEN_URI, nullptr);
202 if (ret != SQLITE_OK) {
203 LOG(ERROR) << "Failed to open memory DB " << ret << ": " << memorydb_path;
207 ret = sqlite3_open_v2(filedb_path.c_str(), &filedb, SQLITE_OPEN_READONLY,
209 if (ret != SQLITE_OK) {
210 LOG(ERROR) << "Failed to open file DB " << ret << ": " << filedb_path;
211 sqlite3_close_v2(memorydb);
215 sqlite3_backup* backup =
216 sqlite3_backup_init(memorydb, "main", filedb, "main");
217 if (backup == nullptr) {
218 LOG(ERROR) << "Failed to backup for memory DB";
219 sqlite3_close_v2(memorydb);
220 sqlite3_close_v2(filedb);
224 sqlite3_backup_step(backup, -1);
225 sqlite3_backup_finish(backup);
226 sqlite3_close_v2(filedb);
230 void DBHandleProvider::SetMemoryMode(pid_t pid) {
231 std::unique_lock<std::recursive_mutex> u(lock_);
232 if (is_global_memdb_set_ && is_user_memdb_set_)
236 CreateMemoryDBHandle(user_parser_filedb_path_, user_parser_memdb_path_);
237 if (parser_db != nullptr)
238 parser_memdb_handle_.reset(parser_db);
240 if (is_user_memdb_set_ == is_global_memdb_set_) {
241 sqlite3* global_parser_file_db = CreateMemoryDBHandle(
242 global_parser_filedb_path_, global_parser_memdb_path);
243 if (global_parser_file_db)
244 global_parser_memdb_handle_.reset(global_parser_file_db);
247 CreateMemoryDBHandle(cert_filedb_path_, cert_memdb_path);
248 if (cert_db != nullptr)
249 cert_memdb_handle_.reset(cert_db);
254 is_user_memdb_set_ = true;
255 is_global_memdb_set_ = true;
256 LOG(DEBUG) << "Set Memory mode : Memory";
259 void DBHandleProvider::UnsetMemoryMode(pid_t pid) {
260 std::unique_lock<std::recursive_mutex> u(lock_);
261 if (!is_global_memdb_set_ && !is_user_memdb_set_)
264 parser_memdb_handle_.reset(nullptr);
265 cert_memdb_handle_.reset(nullptr);
266 global_parser_memdb_handle_.reset(nullptr);
269 LOG(ERROR) << "Given pid is not exists in pid list : " << pid;
271 is_user_memdb_set_ = false;
272 is_global_memdb_set_ = false;
274 auto lock = CacheFlag::GetWriterLock();
275 CacheFlag::SetStatus(CacheFlag::Status::PREPARING);
279 CacheFlag::SetStatus(CacheFlag::Status::UNPREPARED);
280 LOG(DEBUG) << "Set Memory mode : File";
283 bool DBHandleProvider::IsMemoryDBActive(pid_t pid, bool write) {
284 std::unique_lock<std::mutex> u(pid_list_lock_);
285 if (!is_user_memdb_set_)
291 if (writer_pid_list_.find(pid) != writer_pid_list_.end())
297 void DBHandleProvider::TrimCache() {
298 std::unique_lock<std::recursive_mutex> u(lock_);
303 void DBHandleProvider::ReleaseCache() {
304 auto lock = CacheFlag::GetWriterLock();
305 CacheFlag::SetStatus(CacheFlag::Status::PREPARING);
309 CacheFlag::SetStatus(CacheFlag::Status::UNPREPARED);
314 bool DBHandleProvider::IsWriter(pid_t pid) {
315 std::unique_lock<std::mutex> u(pid_list_lock_);
316 return writer_pid_list_.find(pid) != writer_pid_list_.end();
319 int DBHandleProvider::UpdateCache(sqlite3* db, pid_t pid, uid_t uid, bool write,
320 const std::string& locale) {
324 GHashTable* list = g_hash_table_new(g_str_hash, g_str_equal);
325 if (list == nullptr) {
326 LOG(ERROR) << "Out of memory";
327 return PMINFO_R_ERROR;
330 auto tmp_filter = reinterpret_cast<pkgmgrinfo_filter_x*>(
331 calloc(1, sizeof(pkgmgrinfo_filter_x)));
332 if (tmp_filter == nullptr) {
333 LOG(ERROR) << "Out of memory";
334 g_hash_table_destroy(list);
335 return PMINFO_R_ERROR;
338 int ret = pkginfo_internal_filter_get_list(db, tmp_filter, uid_,
339 locale.c_str(), list);
340 if (ret == PMINFO_R_OK) {
343 g_hash_table_iter_init(&iter, list);
344 while (g_hash_table_iter_next(&iter, nullptr, &value)) {
345 auto* pkg = reinterpret_cast<package_x*>(value);
346 std::string pkgid = pkg->package;
347 AddPackage(std::move(pkgid), pkg);
351 g_hash_table_destroy(list);
352 if (ret == PMINFO_R_ERROR) {
357 std::vector<std::shared_ptr<application_x>> app_list;
358 ret = pkgmgr_server::internal::appinfo_internal_filter_get_list(db,
359 tmp_filter, uid_, uid, locale.c_str(), app_list);
361 if (ret == PMINFO_R_OK) {
362 for (auto& app : app_list) {
363 app->privileges = pkg_map_[app->package].front()->privileges;
364 std::string appid = app->appid;
365 AddApplication(std::move(appid), std::move(app));
373 std::vector<std::shared_ptr<package_x>> DBHandleProvider::GetPackages(
374 pid_t pid, bool write, pkgmgrinfo_filter_x* filter,
375 const std::string& package) {
376 std::vector<std::shared_ptr<package_x>> ret;
377 for (auto& info : pkg_map_[package]) {
379 for (auto* it = filter->list; it != nullptr; it = g_slist_next(it)) {
380 auto node = reinterpret_cast<pkgmgrinfo_node_x*>(it->data);
381 auto* checker = FilterCheckerProvider::GetInst().
382 GetPkgFilterChecker(node->prop);
383 if (!checker->CheckFilter(node, info.get())) {
395 void DBHandleProvider::AddPackage(std::string package, package_x* info) {
396 auto ptr = std::shared_ptr<package_x>(info, pkgmgrinfo_basic_free_package);
397 pkg_map_[package].push_back(ptr);
398 pkg_map_[""].push_back(std::move(ptr));
401 std::vector<std::shared_ptr<application_x>> DBHandleProvider::GetApplications(
402 pid_t pid, bool write, pkgmgrinfo_filter_x* filter,
403 const std::string& app) {
404 /* make metadata filter map */
405 std::unordered_map<std::string, std::string> metadata_map;
406 for (auto* it = filter->list_metadata; it != nullptr; it = g_slist_next(it)) {
407 auto node = reinterpret_cast<pkgmgrinfo_metadata_node_x*>(it->data);
408 if (node->key == nullptr)
411 metadata_map[node->key] = (node->value ? node->value : "");
414 std::vector<std::shared_ptr<application_x>> ret;
415 for (auto& info : app_map_[app]) {
417 for (auto* it = filter->list; it != nullptr; it = g_slist_next(it)) {
418 auto node = reinterpret_cast<pkgmgrinfo_node_x*>(it->data);
419 auto* checker = FilterCheckerProvider::GetInst().
420 GetAppFilterChecker(node->prop);
421 if (!checker->CheckFilter(node, info.get())) {
429 if (!metadata_map.empty()) {
431 for (auto* it = info->metadata; it != nullptr; it = g_list_next(it)) {
432 auto* node = reinterpret_cast<metadata_x*>(it->data);
433 if (node->key != nullptr) {
434 auto metadata = metadata_map.find(node->key);
435 if (metadata == metadata_map.end())
438 if (metadata->second.empty() ||
439 strcmp(node->value ? node->value : "",
440 metadata->second.c_str()) == 0) {
454 void DBHandleProvider::AddApplication(std::string app, std::shared_ptr<application_x> info) {
455 app_map_[app].push_back(info);
456 app_map_[""].push_back(std::move(info));
459 void DBHandleProvider::InsertPID(pid_t pid) {
460 std::unique_lock<std::mutex> u(pid_list_lock_);
462 writer_pid_list_.insert(pid);
465 bool DBHandleProvider::ErasePID(pid_t pid) {
466 std::unique_lock<std::mutex> u(pid_list_lock_);
468 return writer_pid_list_.erase(pid) == 1;
471 } // namespace database
472 } // namespace pkgmgr_server