Change logic of delivering db path and handle
[platform/core/appfw/pkgmgr-info.git] / src / common / database / db_handle_provider.cc
1 /*
2  * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 #include <sys/types.h>
18
19 #include <tzplatform_config.h>
20
21 #include "db_handle_provider.hh"
22 #include "pkgmgr-info.h"
23 #include "pkgmgrinfo_debug.h"
24
25 #include <algorithm>
26 #include <vector>
27
28 #ifdef LOG_TAG
29 #undef LOG_TAG
30 #endif
31 #define LOG_TAG "PKGMGR_INFO"
32
33 namespace {
34
35 constexpr uid_t REGULAR_USER = 5000;
36
37 uid_t GetGlobalUID() {
38   return tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
39 }
40
41 uid_t ConvertUID(uid_t uid) {
42   if (uid < REGULAR_USER)
43     return tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
44   else
45     return uid;
46 }
47
48 }  // namespace
49
50 namespace pkgmgr_common {
51
52 std::unordered_map<uid_t, std::unique_ptr<DBHandleProvider>>
53     DBHandleProvider::provider_;
54 bool DBHandleProvider::is_memory_global_ = false;
55 std::unique_ptr<sqlite3, decltype(sqlite3_close_v2)*>
56     DBHandleProvider::global_parser_memory_db_handle_(nullptr, sqlite3_close_v2);
57 std::unique_ptr<sqlite3, decltype(sqlite3_close_v2)*>
58     DBHandleProvider::cert_memory_db_handle_(nullptr, sqlite3_close_v2);
59 std::string DBHandleProvider::global_parser_memory_db_path_ =
60     "file:parserdb?mode=memory&cache=shared";
61 std::string DBHandleProvider::global_parser_file_db_path_;
62 std::string DBHandleProvider::cert_memory_db_path_ =
63     "file:certdb?mode=memory&cache=shared";
64 std::string DBHandleProvider::cert_file_db_path_;
65 std::unordered_set<pid_t> DBHandleProvider::pid_list_;
66 std::recursive_mutex DBHandleProvider::global_lock_;
67
68 DBHandleProvider::DBHandleProvider(uid_t uid) : uid_(uid),
69     is_memory_(false), parser_memory_db_handle_(nullptr, sqlite3_close_v2) {
70   char* tmp_path = nullptr;
71   if (global_parser_file_db_path_.empty()) {
72     tmp_path = getUserPkgParserDBPathUID(GetGlobalUID());
73     global_parser_file_db_path_ = tmp_path;
74     free(tmp_path);
75
76     tmp_path = getUserPkgCertDBPath();
77     cert_file_db_path_ = tmp_path;
78     free(tmp_path);
79   }
80
81   tmp_path = getUserPkgParserDBPathUID(uid_);
82   parser_file_db_path_ = tmp_path;
83   free(tmp_path);
84
85   parser_memory_db_path_ = "file:parserdb" +
86       std::to_string(static_cast<int>(uid_)) + "?mode=memory&cache=shared";
87 }
88
89 DBHandleProvider& DBHandleProvider::GetInst(uid_t uid) {
90   static std::mutex singleton_lock;
91   std::unique_lock<std::mutex> u(singleton_lock);
92   uid = ConvertUID(uid);
93   auto& prov = provider_[uid];
94   if (prov == nullptr) {
95     prov.reset(new DBHandleProvider(uid));
96   }
97
98   return *prov;
99 }
100
101 std::vector<std::pair<std::string, uid_t>> DBHandleProvider::GetParserDBPath(pid_t pid) {
102   std::unique_lock<std::recursive_mutex> u(lock_);
103   std::unique_lock<std::recursive_mutex> gu(global_lock_);
104   std::vector<std::pair<std::string, uid_t>> db_path_list;
105   if (is_memory_ != is_memory_global_)
106     SetMemoryMode(pid, is_memory_global_);
107
108   if (is_memory_ && pid_list_.find(pid) == pid_list_.end()) {
109     if (uid_ > REGULAR_USER)
110       db_path_list.emplace_back(std::make_pair(parser_memory_db_path_, uid_));
111     db_path_list.emplace_back(std::make_pair(global_parser_memory_db_path_, GetGlobalUID()));
112   } else {
113     if (uid_ > REGULAR_USER)
114       db_path_list.emplace_back(std::make_pair(parser_file_db_path_, uid_));
115     db_path_list.emplace_back(std::make_pair(global_parser_file_db_path_, GetGlobalUID()));
116   }
117
118   if (db_path_list.size() == 1) {
119     LOGD("global db path : %s", db_path_list[0].first.c_str());
120   } else {
121     LOGD("local db path : %s", db_path_list[0].first.c_str());
122     LOGD("global db path : %s", db_path_list[1].first.c_str());
123   }
124
125   return db_path_list;
126 }
127
128 std::string DBHandleProvider::GetCertDBPath(pid_t pid) {
129   std::unique_lock<std::recursive_mutex> u(lock_);
130   std::unique_lock<std::recursive_mutex> gu(global_lock_);
131   if (is_memory_ != is_memory_global_)
132     SetMemoryMode(pid, is_memory_global_);
133
134   if (is_memory_ && pid_list_.find(pid) == pid_list_.end()) {
135      return cert_memory_db_path_;
136   } else {
137      return cert_file_db_path_;
138   }
139 }
140
141 sqlite3* DBHandleProvider::GetMemoryDBHandle(const std::string& filedb_path,
142     const std::string& memorydb_path) {
143   sqlite3* memorydb = nullptr;
144   sqlite3* filedb = nullptr;
145   int ret = sqlite3_open_v2(memorydb_path.c_str(), &memorydb,
146       SQLITE_OPEN_READONLY | SQLITE_OPEN_URI, nullptr);
147   if (ret != SQLITE_OK) {
148     LOGE("Failed to open memory DB %d(%s)", ret, memorydb_path.c_str());
149     return nullptr;
150   }
151
152   ret = sqlite3_open_v2(filedb_path.c_str(), &filedb,
153       SQLITE_OPEN_READONLY, nullptr);
154   if (ret != SQLITE_OK) {
155     LOGE("Failed to open file DB %d(%s)", ret, filedb_path.c_str());
156     sqlite3_close_v2(memorydb);
157     return nullptr;
158   }
159   sqlite3_backup* backup = sqlite3_backup_init(memorydb, "main",
160       filedb, "main");
161   if (backup == nullptr) {
162     LOGE("Failed to backup for memory DB");
163     sqlite3_close_v2(memorydb);
164     sqlite3_close_v2(filedb);
165     return nullptr;
166   }
167
168   sqlite3_backup_step(backup, -1);
169   sqlite3_backup_finish(backup);
170   LOGD("Set memory DB(%s)", memorydb_path.c_str());
171   sqlite3_close_v2(filedb);
172   return memorydb;
173 }
174
175 void DBHandleProvider::SetMemoryMode(pid_t pid, bool flag) {
176   std::unique_lock<std::recursive_mutex> u(lock_);
177   std::unique_lock<std::recursive_mutex> gu(global_lock_);
178   if (flag == is_memory_global_ && flag == is_memory_)
179     return;
180
181   if (flag == true) {
182     sqlite3* parser_db = GetMemoryDBHandle(parser_file_db_path_,
183         parser_memory_db_path_);
184     if (parser_db != nullptr)
185       parser_memory_db_handle_.reset(parser_db);
186
187     if (is_memory_ == is_memory_global_) {  /* first call */
188       sqlite3* global_parser_file_db = GetMemoryDBHandle(global_parser_file_db_path_,
189           global_parser_memory_db_path_);
190       if (global_parser_file_db)
191         global_parser_memory_db_handle_.reset(global_parser_file_db);
192       sqlite3* cert_db = GetMemoryDBHandle(cert_file_db_path_,
193           cert_memory_db_path_);
194       if (cert_db != nullptr)
195         cert_memory_db_handle_.reset(cert_db);
196
197       if (pid_list_.find(pid) == pid_list_.end())
198         pid_list_.insert(pid);
199     }
200   } else {
201     parser_memory_db_handle_.reset(nullptr);
202     cert_memory_db_handle_.reset(nullptr);
203     global_parser_memory_db_handle_.reset(nullptr);
204
205     auto it = pid_list_.find(pid);
206     if (it != pid_list_.end())
207       pid_list_.erase(it);
208     else
209       LOGE("Given pid is not exists in pid list : %d", pid);
210   }
211   is_memory_ = flag;
212   is_memory_global_ = flag;
213   LOGD("Set Memory mode : %s", flag ? "Memory" : "File");
214 }
215
216 }  // namespace pkgmgr_common