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_private.h"
40 #define LOG_TAG "PKGMGR_INFO"
44 uid_t globaluser_uid = -1;
46 uid_t GetGlobalUID() {
47 if (globaluser_uid == (uid_t)-1)
48 globaluser_uid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
50 return globaluser_uid;
53 uid_t ConvertUID(uid_t uid) {
54 if (uid < REGULAR_USER)
55 return GetGlobalUID();
60 static const std::string global_parser_memory_db_path =
61 "file:parserdb?mode=memory&cache=shared";
63 static const std::string cert_memory_db_path =
64 "file:certdb?mode=memory&cache=shared";
68 namespace pkgmgr_server {
71 std::unordered_map<uid_t, std::unique_ptr<DBHandleProvider>>
72 DBHandleProvider::provider_;
73 bool DBHandleProvider::is_memory_global_ = false;
74 std::unique_ptr<sqlite3, decltype(sqlite3_close_v2)*>
75 DBHandleProvider::global_parser_memory_db_handle_(nullptr,
77 std::unique_ptr<sqlite3, decltype(sqlite3_close_v2)*>
78 DBHandleProvider::cert_memory_db_handle_(nullptr, sqlite3_close_v2);
79 std::string DBHandleProvider::global_parser_file_db_path_;
80 std::string DBHandleProvider::cert_file_db_path_;
81 std::unordered_set<pid_t> DBHandleProvider::pid_list_;
82 std::recursive_mutex DBHandleProvider::lock_;
83 std::mutex DBHandleProvider::pid_list_lock_;
85 DBHandleProvider::DBHandleProvider(uid_t uid)
88 parser_memory_db_handle_(nullptr, sqlite3_close_v2) {
91 if (global_parser_file_db_path_.empty()) {
92 tmp_path = getUserPkgParserDBPathUID(GetGlobalUID());
93 global_parser_file_db_path_ = tmp_path;
96 tmp_path = getUserPkgCertDBPath();
97 cert_file_db_path_ = tmp_path;
101 tmp_path = getUserPkgParserDBPathUID(uid_);
102 parser_file_db_path_ = tmp_path;
105 parser_memory_db_path_ = "file:parserdb" +
106 std::to_string(static_cast<int>(uid_)) +
107 "?mode=memory&cache=shared";
110 DBHandleProvider& DBHandleProvider::GetInst(uid_t uid) {
111 static std::mutex singleton_lock_;
112 std::unique_lock<std::mutex> u(singleton_lock_);
114 uid = ConvertUID(uid);
115 auto& prov = provider_[uid];
117 prov.reset(new DBHandleProvider(uid));
122 bool DBHandleProvider::IsCrashedWriteRequest() {
123 std::unique_lock<std::mutex> u(pid_list_lock_);
125 if (pid_list_.empty())
129 LOG(DEBUG) << "Check process count : " << pid_list_.size();
130 std::vector<pid_t> remove_pids;
131 for (pid_t pid : pid_list_) {
132 std::string status_path = "/proc/" + std::to_string(pid) + "/status";
134 int fd = open(status_path.c_str(), O_RDONLY);
136 LOG(ERROR) << "Process is crashed : " << pid;
137 remove_pids.push_back(pid);
144 for (pid_t pid : remove_pids)
145 pid_list_.erase(pid);
150 std::vector<std::pair<std::string, uid_t>> DBHandleProvider::GetParserDBPath(
151 pid_t pid, bool write) {
152 std::unique_lock<std::recursive_mutex> u(lock_);
153 std::vector<std::pair<std::string, uid_t>> db_path_list;
155 if (is_memory_ != is_memory_global_)
156 is_memory_global_ ? SetMemoryMode(pid) : UnsetMemoryMode(pid);
158 if (IsMemoryDBActive(pid, write)) {
159 if (uid_ > REGULAR_USER)
160 db_path_list.emplace_back(std::make_pair(parser_memory_db_path_, uid_));
161 db_path_list.emplace_back(
162 std::make_pair(global_parser_memory_db_path, GetGlobalUID()));
164 if (uid_ > REGULAR_USER)
165 db_path_list.emplace_back(std::make_pair(parser_file_db_path_, uid_));
166 db_path_list.emplace_back(
167 std::make_pair(global_parser_file_db_path_, GetGlobalUID()));
170 if (db_path_list.size() == 1) {
171 LOG(DEBUG) << "global db path : " << db_path_list[0].first;
173 LOG(DEBUG) << "local db path : " << db_path_list[0].first;
174 LOG(DEBUG) << "global db path : " << db_path_list[1].first;
180 std::string DBHandleProvider::GetCertDBPath(pid_t pid, bool write) {
181 std::unique_lock<std::recursive_mutex> u(lock_);
182 if (is_memory_ != is_memory_global_)
183 is_memory_global_ ? SetMemoryMode(pid) : UnsetMemoryMode(pid);
185 if (IsMemoryDBActive(pid, write))
186 return cert_memory_db_path;
188 return cert_file_db_path_;
191 sqlite3* DBHandleProvider::GetMemoryDBHandle(const std::string& filedb_path,
192 const std::string& memorydb_path) {
193 sqlite3* memorydb = nullptr;
194 sqlite3* filedb = nullptr;
195 int ret = sqlite3_open_v2(memorydb_path.c_str(), &memorydb,
196 SQLITE_OPEN_READONLY | SQLITE_OPEN_URI, nullptr);
197 if (ret != SQLITE_OK) {
198 LOG(ERROR) << "Failed to open memory DB " << ret << ": " << memorydb_path;
202 ret = sqlite3_open_v2(filedb_path.c_str(), &filedb, SQLITE_OPEN_READONLY,
204 if (ret != SQLITE_OK) {
205 LOG(ERROR) << "Failed to open file DB " << ret << ": " << filedb_path;
206 sqlite3_close_v2(memorydb);
210 sqlite3_backup* backup =
211 sqlite3_backup_init(memorydb, "main", filedb, "main");
212 if (backup == nullptr) {
213 LOG(ERROR) << "Failed to backup for memory DB";
214 sqlite3_close_v2(memorydb);
215 sqlite3_close_v2(filedb);
219 sqlite3_backup_step(backup, -1);
220 sqlite3_backup_finish(backup);
221 sqlite3_close_v2(filedb);
225 void DBHandleProvider::SetMemoryMode(pid_t pid) {
226 std::unique_lock<std::recursive_mutex> u(lock_);
227 if (is_memory_global_ && is_memory_)
231 GetMemoryDBHandle(parser_file_db_path_, parser_memory_db_path_);
232 if (parser_db != nullptr)
233 parser_memory_db_handle_.reset(parser_db);
235 if (is_memory_ == is_memory_global_) {
236 sqlite3* global_parser_file_db = GetMemoryDBHandle(
237 global_parser_file_db_path_, global_parser_memory_db_path);
238 if (global_parser_file_db)
239 global_parser_memory_db_handle_.reset(global_parser_file_db);
241 GetMemoryDBHandle(cert_file_db_path_, cert_memory_db_path);
242 if (cert_db != nullptr)
243 cert_memory_db_handle_.reset(cert_db);
249 is_memory_global_ = true;
250 LOG(DEBUG) << "Set Memory mode : Memory";
253 void DBHandleProvider::UnsetMemoryMode(pid_t pid) {
254 std::unique_lock<std::recursive_mutex> u(lock_);
255 if (!is_memory_global_ && !is_memory_)
258 auto lock = CacheFlag::GetWriterLock();
259 CacheFlag::SetStatus(CacheFlag::Status::PREPARING);
261 parser_memory_db_handle_.reset(nullptr);
262 cert_memory_db_handle_.reset(nullptr);
263 global_parser_memory_db_handle_.reset(nullptr);
266 LOG(ERROR) << "Given pid is not exists in pid list : " << pid;
269 is_memory_global_ = false;
272 CacheFlag::SetStatus(CacheFlag::Status::UNPREPARED);
273 LOG(DEBUG) << "Set Memory mode : File";
276 bool DBHandleProvider::IsMemoryDBActive(pid_t pid, bool write) {
277 std::unique_lock<std::mutex> u(pid_list_lock_);
278 return (is_memory_ && pid_list_.find(pid) == pid_list_.end() && !write);
281 void DBHandleProvider::TrimCache() {
282 std::unique_lock<std::recursive_mutex> u(lock_);
287 void DBHandleProvider::ReleaseCache() {
288 auto lock = CacheFlag::GetWriterLock();
289 CacheFlag::SetStatus(CacheFlag::Status::PREPARING);
293 CacheFlag::SetStatus(CacheFlag::Status::UNPREPARED);
298 bool DBHandleProvider::IsWriter(pid_t pid) {
299 std::unique_lock<std::mutex> u(pid_list_lock_);
300 return pid_list_.find(pid) != pid_list_.end();
303 int DBHandleProvider::UpdateCache(sqlite3* db, pid_t pid, uid_t uid, bool write,
304 const std::string& locale) {
308 GHashTable* list = g_hash_table_new(g_str_hash, g_str_equal);
309 if (list == nullptr) {
310 LOG(ERROR) << "Out of memory";
311 return PMINFO_R_ERROR;
314 auto tmp_filter = reinterpret_cast<pkgmgrinfo_filter_x*>(
315 calloc(1, sizeof(pkgmgrinfo_filter_x)));
316 if (tmp_filter == nullptr) {
317 LOG(ERROR) << "Out of memory";
318 g_hash_table_destroy(list);
319 return PMINFO_R_ERROR;
322 int ret = pkginfo_internal_filter_get_list(db, tmp_filter, uid_,
323 locale.c_str(), list);
324 if (ret == PMINFO_R_OK) {
327 g_hash_table_iter_init(&iter, list);
328 while (g_hash_table_iter_next(&iter, nullptr, &value)) {
329 auto* pkg = reinterpret_cast<package_x*>(value);
330 AddPackage(pkg->package, pkg);
334 g_hash_table_destroy(list);
335 if (ret == PMINFO_R_ERROR) {
340 list = g_hash_table_new(g_str_hash, g_str_equal);
341 ret = appinfo_internal_filter_get_list(db, tmp_filter, uid_, uid,
342 locale.c_str(), list);
344 if (ret == PMINFO_R_OK) {
347 g_hash_table_iter_init(&iter, list);
348 while (g_hash_table_iter_next(&iter, nullptr, &value)) {
349 auto* app = reinterpret_cast<application_x*>(value);
350 app->privileges = pkg_map_[app->package].front()->privileges;
351 AddApplication(app->appid, app);
354 g_hash_table_destroy(list);
360 std::vector<std::shared_ptr<package_x>> DBHandleProvider::GetPackages(
361 pid_t pid, bool write, pkgmgrinfo_filter_x* filter,
362 const std::string& package) {
363 std::vector<std::shared_ptr<package_x>> ret;
364 for (auto& info : pkg_map_[package]) {
366 for (auto* it = filter->list; it != nullptr; it = g_slist_next(it)) {
367 auto node = reinterpret_cast<pkgmgrinfo_node_x*>(it->data);
368 auto* checker = FilterCheckerProvider::GetInst().
369 GetPkgFilterChecker(node->prop);
370 if (!checker->CheckFilter(node, info.get())) {
382 void DBHandleProvider::AddPackage(std::string package, package_x* info) {
383 auto ptr = std::shared_ptr<package_x>(info, pkgmgrinfo_basic_free_package);
384 pkg_map_[package].push_back(ptr);
385 pkg_map_[""].push_back(std::move(ptr));
388 std::vector<std::shared_ptr<application_x>> DBHandleProvider::GetApplications(
389 pid_t pid, bool write, pkgmgrinfo_filter_x* filter,
390 const std::string& app) {
391 /* make metadata filter map */
392 std::unordered_map<std::string, std::string> metadata_map;
393 for (auto* it = filter->list_metadata; it != nullptr; it = g_slist_next(it)) {
394 auto node = reinterpret_cast<pkgmgrinfo_metadata_node_x*>(it->data);
395 if (node->key == nullptr)
398 metadata_map[node->key] = (node->value ? node->value : "");
401 std::vector<std::shared_ptr<application_x>> ret;
402 for (auto& info : app_map_[app]) {
404 for (auto* it = filter->list; it != nullptr; it = g_slist_next(it)) {
405 auto node = reinterpret_cast<pkgmgrinfo_node_x*>(it->data);
406 auto* checker = FilterCheckerProvider::GetInst().
407 GetAppFilterChecker(node->prop);
408 if (!checker->CheckFilter(node, info.get())) {
416 if (!metadata_map.empty()) {
418 for (auto* it = info->metadata; it != nullptr; it = g_list_next(it)) {
419 auto* node = reinterpret_cast<metadata_x*>(it->data);
420 if (node->key != nullptr) {
421 auto metadata = metadata_map.find(node->key);
422 if (metadata != metadata_map.end() &&
423 strstr(node->value ? node->value : "",
424 metadata->second.c_str()) != nullptr) {
438 void DBHandleProvider::AddApplication(std::string app, application_x* info) {
440 std::shared_ptr<application_x>(info, pkgmgrinfo_basic_free_application);
441 app_map_[app].push_back(ptr);
442 app_map_[""].push_back(std::move(ptr));
445 void DBHandleProvider::InsertPID(pid_t pid) {
446 std::unique_lock<std::mutex> u(pid_list_lock_);
448 pid_list_.insert(pid);
451 bool DBHandleProvider::ErasePID(pid_t pid) {
452 std::unique_lock<std::mutex> u(pid_list_lock_);
454 return pid_list_.erase(pid) == 1;
457 } // namespace database
458 } // namespace pkgmgr_server