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 "utils/logging.hh"
31 #include "pkgmgr-info.h"
32 #include "pkgmgrinfo_debug.h"
33 #include "pkgmgrinfo_internal.h"
34 #include "pkgmgrinfo_private.h"
39 #define LOG_TAG "PKGMGR_INFO"
43 uid_t globaluser_uid = -1;
45 uid_t GetGlobalUID() {
46 if (globaluser_uid == (uid_t)-1)
47 globaluser_uid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
49 return globaluser_uid;
52 uid_t ConvertUID(uid_t uid) {
53 if (uid < REGULAR_USER)
54 return GetGlobalUID();
59 static const std::string global_parser_memory_db_path =
60 "file:parserdb?mode=memory&cache=shared";
62 static const std::string cert_memory_db_path =
63 "file:certdb?mode=memory&cache=shared";
67 namespace pkgmgr_server {
70 std::unordered_map<uid_t, std::unique_ptr<DBHandleProvider>>
71 DBHandleProvider::provider_;
72 bool DBHandleProvider::is_memory_global_ = false;
73 std::unique_ptr<sqlite3, decltype(sqlite3_close_v2)*>
74 DBHandleProvider::global_parser_memory_db_handle_(nullptr,
76 std::unique_ptr<sqlite3, decltype(sqlite3_close_v2)*>
77 DBHandleProvider::cert_memory_db_handle_(nullptr, sqlite3_close_v2);
78 std::string DBHandleProvider::global_parser_file_db_path_;
79 std::string DBHandleProvider::cert_file_db_path_;
80 std::unordered_set<pid_t> DBHandleProvider::pid_list_;
81 std::recursive_mutex DBHandleProvider::lock_;
83 DBHandleProvider::DBHandleProvider(uid_t uid)
86 parser_memory_db_handle_(nullptr, sqlite3_close_v2) {
89 if (global_parser_file_db_path_.empty()) {
90 tmp_path = getUserPkgParserDBPathUID(GetGlobalUID());
91 global_parser_file_db_path_ = tmp_path;
94 tmp_path = getUserPkgCertDBPath();
95 cert_file_db_path_ = tmp_path;
99 tmp_path = getUserPkgParserDBPathUID(uid_);
100 parser_file_db_path_ = tmp_path;
103 parser_memory_db_path_ = "file:parserdb" +
104 std::to_string(static_cast<int>(uid_)) +
105 "?mode=memory&cache=shared";
108 DBHandleProvider& DBHandleProvider::GetInst(uid_t uid) {
109 static std::mutex singleton_lock_;
110 std::unique_lock<std::mutex> u(singleton_lock_);
112 uid = ConvertUID(uid);
113 auto& prov = provider_[uid];
115 prov.reset(new DBHandleProvider(uid));
120 bool DBHandleProvider::IsCrashedWriteRequest() {
121 std::unique_lock<std::recursive_mutex> u(lock_);
123 if (pid_list_.empty())
127 LOG(DEBUG) << "Check process count : " << pid_list_.size();
128 std::vector<pid_t> remove_pids;
129 for (pid_t pid : pid_list_) {
130 std::string status_path = "/proc/" + std::to_string(pid) + "/status";
132 int fd = open(status_path.c_str(), O_RDONLY);
134 LOG(ERROR) << "Process is crashed : " << pid;
135 remove_pids.push_back(pid);
142 for (pid_t pid : remove_pids)
143 pid_list_.erase(pid);
148 std::vector<std::pair<std::string, uid_t>> DBHandleProvider::GetParserDBPath(
149 pid_t pid, bool write) {
150 std::unique_lock<std::recursive_mutex> u(lock_);
151 std::vector<std::pair<std::string, uid_t>> db_path_list;
153 if (is_memory_ != is_memory_global_)
154 is_memory_global_ ? SetMemoryMode(pid) : UnsetMemoryMode(pid);
156 if (IsMemoryDBActive(pid, write)) {
157 if (uid_ > REGULAR_USER)
158 db_path_list.emplace_back(std::make_pair(parser_memory_db_path_, uid_));
159 db_path_list.emplace_back(
160 std::make_pair(global_parser_memory_db_path, GetGlobalUID()));
162 if (uid_ > REGULAR_USER)
163 db_path_list.emplace_back(std::make_pair(parser_file_db_path_, uid_));
164 db_path_list.emplace_back(
165 std::make_pair(global_parser_file_db_path_, GetGlobalUID()));
168 if (db_path_list.size() == 1) {
169 LOG(DEBUG) << "global db path : " << db_path_list[0].first;
171 LOG(DEBUG) << "local db path : " << db_path_list[0].first;
172 LOG(DEBUG) << "global db path : " << db_path_list[1].first;
178 std::string DBHandleProvider::GetCertDBPath(pid_t pid, bool write) {
179 std::unique_lock<std::recursive_mutex> u(lock_);
180 if (is_memory_ != is_memory_global_)
181 is_memory_global_ ? SetMemoryMode(pid) : UnsetMemoryMode(pid);
183 if (IsMemoryDBActive(pid, write))
184 return cert_memory_db_path;
186 return cert_file_db_path_;
189 sqlite3* DBHandleProvider::GetMemoryDBHandle(const std::string& filedb_path,
190 const std::string& memorydb_path) {
191 sqlite3* memorydb = nullptr;
192 sqlite3* filedb = nullptr;
193 int ret = sqlite3_open_v2(memorydb_path.c_str(), &memorydb,
194 SQLITE_OPEN_READONLY | SQLITE_OPEN_URI, nullptr);
195 if (ret != SQLITE_OK) {
196 LOG(ERROR) << "Failed to open memory DB " << ret << ": " << memorydb_path;
200 ret = sqlite3_open_v2(filedb_path.c_str(), &filedb, SQLITE_OPEN_READONLY,
202 if (ret != SQLITE_OK) {
203 LOG(ERROR) << "Failed to open file DB " << ret << ": " << filedb_path;
204 sqlite3_close_v2(memorydb);
208 sqlite3_backup* backup =
209 sqlite3_backup_init(memorydb, "main", filedb, "main");
210 if (backup == nullptr) {
211 LOG(ERROR) << "Failed to backup for memory DB";
212 sqlite3_close_v2(memorydb);
213 sqlite3_close_v2(filedb);
217 sqlite3_backup_step(backup, -1);
218 sqlite3_backup_finish(backup);
219 sqlite3_close_v2(filedb);
223 void DBHandleProvider::SetMemoryMode(pid_t pid) {
224 std::unique_lock<std::recursive_mutex> u(lock_);
225 if (is_memory_global_ && is_memory_)
229 GetMemoryDBHandle(parser_file_db_path_, parser_memory_db_path_);
230 if (parser_db != nullptr)
231 parser_memory_db_handle_.reset(parser_db);
233 if (is_memory_ == is_memory_global_) {
234 sqlite3* global_parser_file_db = GetMemoryDBHandle(
235 global_parser_file_db_path_, global_parser_memory_db_path);
236 if (global_parser_file_db)
237 global_parser_memory_db_handle_.reset(global_parser_file_db);
239 GetMemoryDBHandle(cert_file_db_path_, cert_memory_db_path);
240 if (cert_db != nullptr)
241 cert_memory_db_handle_.reset(cert_db);
243 if (pid_list_.find(pid) == pid_list_.end())
244 pid_list_.insert(pid);
248 is_memory_global_ = true;
249 old_pkg_map_ = std::move(pkg_map_);
250 old_app_map_ = std::move(app_map_);
252 LOG(DEBUG) << "Set Memory mode : Memory";
255 void DBHandleProvider::UnsetMemoryMode(pid_t pid) {
256 std::unique_lock<std::recursive_mutex> u(lock_);
257 if (!is_memory_global_ && !is_memory_)
260 parser_memory_db_handle_.reset(nullptr);
261 cert_memory_db_handle_.reset(nullptr);
262 global_parser_memory_db_handle_.reset(nullptr);
264 auto it = pid_list_.find(pid);
265 if (it != pid_list_.end())
268 LOG(ERROR) << "Given pid is not exists in pid list : " << pid;
271 is_memory_global_ = false;
272 old_pkg_map_.clear();
273 old_app_map_.clear();
274 LOG(DEBUG) << "Set Memory mode : File";
277 bool DBHandleProvider::IsMemoryDBActive(pid_t pid, bool write) {
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() {
293 bool DBHandleProvider::NeedUpdate(pid_t pid, bool write,
294 const std::string& locale) {
295 std::unique_lock<std::recursive_mutex> u(lock_);
296 return (!IsMemoryDBActive(pid, write) && (locale_ != locale || released_));
299 int DBHandleProvider::UpdateCache(sqlite3* db, pid_t pid, uid_t uid, bool write,
300 const std::string& locale) {
301 if (!NeedUpdate(pid, write, locale))
304 std::unique_lock<std::recursive_mutex> u(lock_);
310 GHashTable* list = g_hash_table_new(g_str_hash, g_str_equal);
311 if (list == nullptr) {
312 LOG(ERROR) << "Out of memory";
313 return PMINFO_R_ERROR;
316 auto tmp_filter = reinterpret_cast<pkgmgrinfo_filter_x*>(
317 calloc(1, sizeof(pkgmgrinfo_filter_x)));
318 if (tmp_filter == nullptr) {
319 LOG(ERROR) << "Out of memory";
320 g_hash_table_destroy(list);
321 return PMINFO_R_ERROR;
324 int ret = pkginfo_internal_filter_get_list(db, tmp_filter, uid_,
325 locale_.c_str(), list);
326 if (ret == PMINFO_R_OK) {
329 g_hash_table_iter_init(&iter, list);
330 while (g_hash_table_iter_next(&iter, nullptr, &value)) {
331 auto* pkg = reinterpret_cast<package_x*>(value);
332 AddPackage(pkg->package, pkg);
336 g_hash_table_destroy(list);
337 if (ret == PMINFO_R_ERROR) {
342 list = g_hash_table_new(g_str_hash, g_str_equal);
343 ret = appinfo_internal_filter_get_list(db, tmp_filter, uid_, uid,
344 locale_.c_str(), list);
346 if (ret == PMINFO_R_OK) {
349 g_hash_table_iter_init(&iter, list);
350 while (g_hash_table_iter_next(&iter, nullptr, &value)) {
351 auto* app = reinterpret_cast<application_x*>(value);
352 app->privileges = pkg_map_[app->package].front()->privileges;
353 AddApplication(app->appid, app);
356 g_hash_table_destroy(list);
362 std::vector<std::shared_ptr<package_x>> DBHandleProvider::GetPackages(
363 pid_t pid, bool write, pkgmgrinfo_filter_x* filter,
364 const std::string& package) {
365 auto& pkg_map = (IsMemoryDBActive(pid, write) ? old_pkg_map_ : pkg_map_);
367 std::vector<std::shared_ptr<package_x>> ret;
368 for (auto& info : pkg_map[package]) {
370 for (auto* it = filter->list; it != nullptr; it = g_slist_next(it)) {
371 auto node = reinterpret_cast<pkgmgrinfo_node_x*>(it->data);
372 auto* checker = FilterCheckerProvider::GetInst().
373 GetPkgFilterChecker(node->prop);
374 if (!checker->CheckFilter(node, info.get())) {
386 void DBHandleProvider::AddPackage(std::string package, package_x* info) {
387 auto ptr = std::shared_ptr<package_x>(info, pkgmgrinfo_basic_free_package);
388 pkg_map_[package].push_back(ptr);
389 pkg_map_[""].push_back(std::move(ptr));
392 std::vector<std::shared_ptr<application_x>> DBHandleProvider::GetApplications(
393 pid_t pid, bool write, pkgmgrinfo_filter_x* filter,
394 const std::string& app) {
395 auto& app_map = (IsMemoryDBActive(pid, write) ? old_app_map_ : app_map_);
397 /* make metadata filter map */
398 std::unordered_map<std::string, std::string> metadata_map;
399 for (auto* it = filter->list_metadata; it != nullptr; it = g_slist_next(it)) {
400 auto node = reinterpret_cast<pkgmgrinfo_metadata_node_x*>(it->data);
401 if (node->key == nullptr)
404 metadata_map[node->key] = (node->value ? node->value : "");
407 std::vector<std::shared_ptr<application_x>> ret;
408 for (auto& info : app_map[app]) {
410 for (auto* it = filter->list; it != nullptr; it = g_slist_next(it)) {
411 auto node = reinterpret_cast<pkgmgrinfo_node_x*>(it->data);
412 auto* checker = FilterCheckerProvider::GetInst().
413 GetAppFilterChecker(node->prop);
414 if (!checker->CheckFilter(node, info.get())) {
422 if (!metadata_map.empty()) {
424 for (auto* it = info->metadata; it != nullptr; it = g_list_next(it)) {
425 auto* node = reinterpret_cast<metadata_x*>(it->data);
426 if (node->key != nullptr) {
427 auto metadata = metadata_map.find(node->key);
428 if (metadata != metadata_map.end() &&
429 strstr(node->value ? node->value : "",
430 metadata->second.c_str()) != nullptr) {
444 void DBHandleProvider::AddApplication(std::string app, application_x* info) {
446 std::shared_ptr<application_x>(info, pkgmgrinfo_basic_free_application);
447 app_map_[app].push_back(ptr);
448 app_map_[""].push_back(std::move(ptr));
451 } // namespace database
452 } // namespace pkgmgr_server