Fix wrong parameter
[platform/core/appfw/pkgmgr-info.git] / src / server / 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 "db_handle_provider.hh"
18
19 #include <fcntl.h>
20 #include <sys/types.h>
21
22 #include <tzplatform_config.h>
23
24 #include <algorithm>
25 #include <string>
26 #include <vector>
27
28 #include "utils/logging.hh"
29
30 #include "pkgmgrinfo_debug.h"
31 #include "pkgmgr-info.h"
32
33 #ifdef LOG_TAG
34 #undef LOG_TAG
35 #endif
36 #define LOG_TAG "PKGMGR_INFO"
37
38 namespace {
39
40 constexpr uid_t REGULAR_USER = 5000;
41
42 uid_t globaluser_uid = -1;
43
44 uid_t GetGlobalUID() {
45   if (globaluser_uid == (uid_t)-1)
46     globaluser_uid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
47
48   return globaluser_uid;
49 }
50
51 uid_t ConvertUID(uid_t uid) {
52   if (uid < REGULAR_USER)
53     return GetGlobalUID();
54   else
55     return uid;
56 }
57
58 static const std::string global_parser_memory_db_path =
59     "file:parserdb?mode=memory&cache=shared";
60
61 static const std::string cert_memory_db_path =
62     "file:certdb?mode=memory&cache=shared";
63
64 }  // namespace
65
66 namespace pkgmgr_server {
67 namespace database {
68
69 std::unordered_map<uid_t, std::unique_ptr<DBHandleProvider>>
70     DBHandleProvider::provider_;
71 bool DBHandleProvider::is_memory_global_ = false;
72 std::unique_ptr<sqlite3, decltype(sqlite3_close_v2)*>
73     DBHandleProvider::global_parser_memory_db_handle_(
74         nullptr, sqlite3_close_v2);
75 std::unique_ptr<sqlite3, decltype(sqlite3_close_v2)*>
76     DBHandleProvider::cert_memory_db_handle_(nullptr, sqlite3_close_v2);
77 std::string DBHandleProvider::global_parser_file_db_path_;
78 std::string DBHandleProvider::cert_file_db_path_;
79 std::unordered_set<pid_t> DBHandleProvider::pid_list_;
80 std::recursive_mutex DBHandleProvider::lock_;
81
82 DBHandleProvider::DBHandleProvider(uid_t uid) : uid_(uid),
83     is_memory_(false), parser_memory_db_handle_(nullptr, sqlite3_close_v2) {
84   char* tmp_path;
85
86   if (global_parser_file_db_path_.empty()) {
87     tmp_path = getUserPkgParserDBPathUID(GetGlobalUID());
88     global_parser_file_db_path_ = tmp_path;
89     free(tmp_path);
90
91     tmp_path = getUserPkgCertDBPath();
92     cert_file_db_path_ = tmp_path;
93     free(tmp_path);
94   }
95
96   tmp_path = getUserPkgParserDBPathUID(uid_);
97   parser_file_db_path_ = tmp_path;
98   free(tmp_path);
99
100   parser_memory_db_path_ = "file:parserdb" +
101       std::to_string(static_cast<int>(uid_)) + "?mode=memory&cache=shared";
102 }
103
104 DBHandleProvider& DBHandleProvider::GetInst(uid_t uid) {
105   static std::mutex singleton_lock;
106   std::unique_lock<std::mutex> u(singleton_lock);
107
108   uid = ConvertUID(uid);
109   auto& prov = provider_[uid];
110   if (prov == nullptr)
111     prov.reset(new DBHandleProvider(uid));
112
113   return *prov;
114 }
115
116 bool DBHandleProvider::IsCrashedWriteRequest() {
117   std::unique_lock<std::recursive_mutex> u(lock_);
118
119   if (pid_list_.empty())
120     return false;
121
122   bool ret = true;
123   LOG(DEBUG) << "Check process count : " << pid_list_.size();
124   std::vector<pid_t> remove_pids;
125   for (pid_t pid : pid_list_) {
126     std::string status_path = "/proc/" + std::to_string(pid) + "/status";
127
128     int fd = open(status_path.c_str(), O_RDONLY);
129     if (fd < 0) {
130       LOG(ERROR) << "Process is crashed : " << pid;
131       remove_pids.push_back(pid);
132     } else {
133       ret = false;
134       close(fd);
135     }
136   }
137
138   for (pid_t pid : remove_pids)
139     pid_list_.erase(pid);
140
141   return ret;
142 }
143
144 std::vector<std::pair<std::string, uid_t>> DBHandleProvider::GetParserDBPath(
145     pid_t pid, bool write) {
146   std::unique_lock<std::recursive_mutex> u(lock_);
147   std::vector<std::pair<std::string, uid_t>> db_path_list;
148
149   if (is_memory_ != is_memory_global_)
150     is_memory_global_ ? SetMemoryMode(pid) : UnsetMemoryMode(pid);
151
152   if (IsMemoryDBActive(pid, write)) {
153     if (uid_ > REGULAR_USER)
154       db_path_list.emplace_back(std::make_pair(parser_memory_db_path_, uid_));
155     db_path_list.emplace_back(
156         std::make_pair(global_parser_memory_db_path, GetGlobalUID()));
157   } else {
158     if (uid_ > REGULAR_USER)
159       db_path_list.emplace_back(std::make_pair(parser_file_db_path_, uid_));
160     db_path_list.emplace_back(
161         std::make_pair(global_parser_file_db_path_, GetGlobalUID()));
162   }
163
164   if (db_path_list.size() == 1) {
165     LOG(DEBUG) << "global db path : " << db_path_list[0].first;
166   } else {
167     LOG(DEBUG) << "local db path : " << db_path_list[0].first;
168     LOG(DEBUG) << "global db path : " << db_path_list[1].first;
169   }
170
171   return db_path_list;
172 }
173
174 std::string DBHandleProvider::GetCertDBPath(pid_t pid, bool write) {
175   std::unique_lock<std::recursive_mutex> u(lock_);
176   if (is_memory_ != is_memory_global_)
177     is_memory_global_ ? SetMemoryMode(pid) : UnsetMemoryMode(pid);
178
179   if (IsMemoryDBActive(pid, write))
180     return cert_memory_db_path;
181   else
182     return cert_file_db_path_;
183 }
184
185 sqlite3* DBHandleProvider::GetMemoryDBHandle(const std::string& filedb_path,
186     const std::string& memorydb_path) {
187   sqlite3* memorydb = nullptr;
188   sqlite3* filedb = nullptr;
189   int ret = sqlite3_open_v2(memorydb_path.c_str(), &memorydb,
190       SQLITE_OPEN_READONLY | SQLITE_OPEN_URI, nullptr);
191   if (ret != SQLITE_OK) {
192     LOG(ERROR) << "Failed to open memory DB " << ret << ": " << memorydb_path;
193     return nullptr;
194   }
195
196   ret = sqlite3_open_v2(filedb_path.c_str(), &filedb,
197       SQLITE_OPEN_READONLY, nullptr);
198   if (ret != SQLITE_OK) {
199     LOG(ERROR) << "Failed to open file DB " << ret << ": " << filedb_path;
200     sqlite3_close_v2(memorydb);
201     return nullptr;
202   }
203
204   sqlite3_backup* backup = sqlite3_backup_init(memorydb, "main",
205       filedb, "main");
206   if (backup == nullptr) {
207     LOG(ERROR) << "Failed to backup for memory DB";
208     sqlite3_close_v2(memorydb);
209     sqlite3_close_v2(filedb);
210     return nullptr;
211   }
212
213   sqlite3_backup_step(backup, -1);
214   sqlite3_backup_finish(backup);
215   sqlite3_close_v2(filedb);
216   return memorydb;
217 }
218
219 void DBHandleProvider::SetMemoryMode(pid_t pid) {
220   std::unique_lock<std::recursive_mutex> u(lock_);
221   if (is_memory_global_ && is_memory_)
222     return;
223
224   sqlite3* parser_db = GetMemoryDBHandle(parser_file_db_path_,
225       parser_memory_db_path_);
226   if (parser_db != nullptr)
227     parser_memory_db_handle_.reset(parser_db);
228
229   if (is_memory_ == is_memory_global_) {  /* first call */
230     sqlite3* global_parser_file_db = GetMemoryDBHandle(
231         global_parser_file_db_path_, global_parser_memory_db_path);
232     if (global_parser_file_db)
233       global_parser_memory_db_handle_.reset(global_parser_file_db);
234     sqlite3* cert_db = GetMemoryDBHandle(cert_file_db_path_,
235         cert_memory_db_path);
236     if (cert_db != nullptr)
237       cert_memory_db_handle_.reset(cert_db);
238
239     if (pid_list_.find(pid) == pid_list_.end())
240       pid_list_.insert(pid);
241   }
242
243   is_memory_ = true;
244   is_memory_global_ = true;
245   LOG(DEBUG) << "Set Memory mode : Memory";
246 }
247
248 void DBHandleProvider::UnsetMemoryMode(pid_t pid) {
249   std::unique_lock<std::recursive_mutex> u(lock_);
250   if (!is_memory_global_ && !is_memory_)
251     return;
252
253   parser_memory_db_handle_.reset(nullptr);
254   cert_memory_db_handle_.reset(nullptr);
255   global_parser_memory_db_handle_.reset(nullptr);
256
257   auto it = pid_list_.find(pid);
258   if (it != pid_list_.end())
259     pid_list_.erase(it);
260   else
261     LOG(ERROR) << "Given pid is not exists in pid list : " << pid;
262
263   is_memory_ = false;
264   is_memory_global_ = false;
265   LOG(DEBUG) << "Set Memory mode : File";
266 }
267
268 bool DBHandleProvider::IsMemoryDBActive(pid_t pid, bool write) {
269   return (is_memory_ && pid_list_.find(pid) == pid_list_.end() && !write);
270 }
271
272 }  // namespace database
273 }  // namespace pkgmgr_server