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