92b96c5806cc71ee1c328608ce8b64cc2b9a4555
[platform/core/appfw/pkgmgr-info.git] / src / server / database / abstract_db_handler.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 "abstract_db_handler.hh"
18
19 #include <gio/gio.h>
20 #include <stdlib.h>
21 #include <sys/stat.h>
22 #include <sys/sysmacros.h>
23 #include <sys/types.h>
24 #include <tzplatform_config.h>
25
26 #include <string>
27 #include <vector>
28
29 #include <database.hpp>
30 #include "db_handle_provider.hh"
31 #include "utils/logging.hh"
32
33 #include "pkgmgr-info.h"
34 #include "pkgmgrinfo_debug.h"
35 #include "pkgmgrinfo_private.h"
36
37 namespace {
38
39 constexpr useconds_t BUSY_WAITING_USEC = (1000000 / 10 / 2); /* 0.05 sec */
40 constexpr int BUSY_WAITING_MAX = 100; /* wait for max 5 sec */
41
42 bool ReadDbBusyHandler(int count) {
43   if (count < BUSY_WAITING_MAX) {
44     usleep(BUSY_WAITING_USEC);
45     return true;
46   } else {
47     return false;
48   }
49 }
50
51 tizen_base::Database OpenReadDb(const std::string& path) {
52   tizen_base::Database db(path.c_str(), SQLITE_OPEN_READONLY | SQLITE_OPEN_URI,
53       ReadDbBusyHandler);
54
55   return db;
56 }
57
58 constexpr const char RESOURCED_BUS_NAME[] = "org.tizen.resourced";
59 constexpr const char RESOURCED_PROC_PATH[] = "/Org/Tizen/ResourceD/Process";
60 constexpr const char RESOURCED_PROC_INTERFACE[] = "org.tizen.resourced.process";
61 constexpr const char RESOURCED_PROC_METHOD[] = "ProcExclude";
62
63 bool WriteDbBusyHandler(int count) {
64   if (count < (BUSY_WAITING_MAX / 2)) {
65     usleep(BUSY_WAITING_USEC);
66     return true;
67   } else if (count < BUSY_WAITING_MAX) {
68     usleep(BUSY_WAITING_USEC);
69     return true;
70   } else {
71     return false;
72   }
73 }
74
75 tizen_base::Database OpenWriteDb(uid_t uid, const std::string& path) {
76   tizen_base::Database db(path.c_str(), SQLITE_OPEN_READWRITE,
77       WriteDbBusyHandler);
78   db.OneStepExec({ "PRAGMA foreign_keys=ON" });
79
80   return db;
81 }
82
83 tizen_base::Database OpenCreateDb(uid_t uid, const std::string& path) {
84   tizen_base::Database db(path.c_str(), SQLITE_OPEN_READWRITE |
85       SQLITE_OPEN_CREATE, WriteDbBusyHandler);
86
87   return db;
88 }
89
90 uid_t ConvertUID(uid_t uid) {
91   static uid_t globaluser_uid = -1;
92
93   if (uid < REGULAR_USER) {
94     if (globaluser_uid == (uid_t)-1)
95       globaluser_uid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
96
97     return globaluser_uid;
98   } else {
99     return uid;
100   }
101 }
102
103 }  // namespace
104
105 namespace pkgmgr_server {
106 namespace database {
107
108 std::shared_mutex AbstractDBHandler::lock_;
109
110 AbstractDBHandler::~AbstractDBHandler() = default;
111
112 std::vector<std::pair<std::string, uid_t>> AbstractDBHandler::GetDBPath() {
113   std::vector<std::pair<std::string, uid_t>> db_path;
114   if (db_type_ == pkgmgr_common::DBType::DB_TYPE_FILE_PKGDB)
115     db_path = DBHandleProvider::GetInst(uid_).GetParserDBPath(pid_,
116         op_type_ == pkgmgr_common::DBOperationType::OPERATION_TYPE_WRITE);
117   else if (db_type_ == pkgmgr_common::DBType::DB_TYPE_FILE_CERTDB)
118     db_path.emplace_back(
119         std::make_pair(DBHandleProvider::GetInst(uid_).GetCertDBPath(pid_,
120             op_type_ == pkgmgr_common::DBOperationType::OPERATION_TYPE_WRITE),
121             uid_));
122
123   return db_path;
124 }
125
126 bool AbstractDBHandler::Connect() {
127   if (db_type_ == pkgmgr_common::DBType::DB_TYPE_NONE ||
128       op_type_ == pkgmgr_common::DBOperationType::OPERATION_TYPE_NONE) {
129     LOG(ERROR) << "Invalid parameter";
130     return false;
131   }
132
133   auto dbpath_list = GetDBPath();
134
135   try {
136     for (const auto& [path, uid] : dbpath_list) {
137       if (op_type_ == pkgmgr_common::DBOperationType::OPERATION_TYPE_READ) {
138         db_handle_list_.emplace_back(OpenReadDb(path), uid);
139       } else if (
140           op_type_ == pkgmgr_common::DBOperationType::OPERATION_TYPE_WRITE) {
141         if (ConvertUID(uid) != ConvertUID(uid_))
142           continue;
143         db_handle_list_.emplace_back(OpenWriteDb(uid_, path), uid);
144       } else {
145         if (ConvertUID(uid) != ConvertUID(uid_))
146           continue;
147
148         if (access(path.c_str(), F_OK) != -1) {
149           LOG(ERROR) << "Database for user " << uid_ << " is already exists";
150           return false;
151         }
152
153         db_handle_list_.emplace_back(OpenCreateDb(uid_, path), uid);
154       }
155     }
156   } catch (const tizen_base::DbException& e) {
157     LOG(ERROR) << e.msg();
158     return false;
159   }
160
161   return true;
162 }
163
164 void AbstractDBHandler::ClearDBHandle() {
165   db_handle_list_.clear();
166 }
167
168 const std::vector<std::pair<tizen_base::Database, uid_t>>&
169     AbstractDBHandler::GetConnection() {
170   return db_handle_list_;
171 }
172
173 void AbstractDBHandler::SetOpType(pkgmgr_common::DBOperationType type) {
174   op_type_ = type;
175 }
176
177 const std::string& AbstractDBHandler::GetLocale() {
178   return locale_;
179 }
180
181 int AbstractDBHandler::GetPID() {
182   return pid_;
183 }
184
185 uid_t AbstractDBHandler::GetUID() {
186   return uid_;
187 }
188
189 void AbstractDBHandler::SetLocale(std::string locale) {
190   locale_ = std::move(locale);
191 }
192
193 void AbstractDBHandler::SetDBType(pkgmgr_common::DBType type) {
194   db_type_ = type;
195 }
196
197 pkgmgr_common::DBOperationType AbstractDBHandler::GetOpType() {
198   return op_type_;
199 }
200
201 uid_t AbstractDBHandler::GetDefaultUser() {
202   static uid_t default_user = tzplatform_getuid(TZ_SYS_DEFAULT_USER);
203
204   return default_user;
205 }
206
207 }  // namespace database
208 }  // namespace pkgmgr_server