### Get required CFLAGS, LDFLAGS from pkg-config
include(FindPkgConfig)
-pkg_check_modules(parser_pkgs REQUIRED dlog libxml-2.0 glib-2.0 gio-2.0 sqlite3 vconf bundle capi-system-info libsmack)
+pkg_check_modules(parser_pkgs REQUIRED dlog libxml-2.0 glib-2.0 gio-2.0 vconf bundle capi-system-info libsmack)
foreach(flag ${parser_pkgs_CFLAGS})
set(parser_pkgs_CFLAGS_str "${parser_pkgs_CFLAGS_str} ${flag}")
int pkgmgr_parser_unregister_pkg_plugin_info_in_usr_db(const char *pkgid, uid_t uid);
int pkgmgr_parser_create_and_initialize_db(uid_t uid);
-int pkgmgr_parser_initialize_parser_db(uid_t uid);
-int pkgmgr_parser_initialize_cert_db(void);
int pkgmgr_parser_clear_cache_memory_db(void);
int pkgmgr_parser_clear_cache_usr_memory_db(uid_t uid);
#include <glib.h>
#include <gio/gio.h>
-#include <sqlite3.h>
#include <tzplatform_config.h>
#include <system_info.h>
return uid;
}
-#define __BEGIN_TRANSACTION(db) \
-do { \
- if (sqlite3_exec(db, "BEGIN DEFERRED", NULL, NULL, NULL) != \
- SQLITE_OK) { \
- _LOGE("begin transaction failed: %s", sqlite3_errmsg(db)); \
- return PM_PARSER_R_ERROR; \
- } \
-} while (0) \
-
-#define __DO_TRANSACTION(db, func) \
-do { \
- if (func) { \
- _LOGE("transaction failed: %s, rollback", sqlite3_errmsg(db)); \
- if (sqlite3_exec(db, "ROLLBACK", NULL, NULL, NULL) != \
- SQLITE_OK) \
- _LOGE("roll back transaction failed: %s", \
- sqlite3_errmsg(db)); \
- return PM_PARSER_R_ERROR; \
- } \
-} while (0) \
-
-#define __END_TRANSACTION(db) \
-do { \
- if (sqlite3_exec(db, "COMMIT", NULL, NULL, NULL) != \
- SQLITE_OK) { \
- _LOGE("commit failed: %s, rollback", sqlite3_errmsg(db)); \
- if (sqlite3_exec(db, "ROLLBACK", NULL, NULL, NULL) != \
- SQLITE_OK) \
- _LOGE("roll back transaction failed: %s", \
- sqlite3_errmsg(db)); \
- return PM_PARSER_R_ERROR; \
- } \
-} while (0) \
-
-static const char *__get_parser_db_path(uid_t uid)
-{
- char buf[PATH_MAX];
- const char *path;
-
- if (uid == GLOBAL_USER || uid == OWNER_ROOT) {
- path = tzplatform_mkpath(TZ_SYS_DB, ".pkgmgr_parser.db");
- } else {
- snprintf(buf, sizeof(buf), "user/%d/.pkgmgr_parser.db", uid);
- path = tzplatform_mkpath(TZ_SYS_DB, buf);
- }
-
- return path;
-}
-
-static const char *__get_cert_db_path(void)
-{
- return tzplatform_mkpath(TZ_SYS_DB, ".pkgmgr_cert.db");
-}
-
-#define DB_VERSION_PATH SYSCONFDIR "/package-manager/pkg_db_version.txt"
-static int __set_db_version(sqlite3 *db)
-{
- int ret;
- FILE *fp = NULL;
- char version[PKG_STRING_LEN_MAX] = { 0 };
- char *query = NULL;
-
- fp = fopen(DB_VERSION_PATH, "r");
- retvm_if(fp == NULL, -1, "Failed to open db version file");
- if (fgets(version, sizeof(version), fp) == NULL) {
- _LOGE("Failed to get version information");
- fclose(fp);
- return -1;
- }
- fclose(fp);
-
- query = sqlite3_mprintf("PRAGMA user_version=%Q", version);
- if (!query) {
- _LOGE("Out of memory");
- return -1;
- }
-
- ret = sqlite3_exec(db, query, NULL, NULL, NULL);
- if (ret != SQLITE_OK) {
- _LOGE("exec failed: %s", sqlite3_errmsg(db));
- sqlite3_free(query);
- return -1;
- }
- sqlite3_free(query);
-
- return 0;
-}
-
-/* TODO: Do not labeling directly */
-#define DB_LABEL "User::Home"
-#define SET_SMACK_LABEL(x) \
-do { \
- if (smack_setlabel((x), DB_LABEL, SMACK_LABEL_ACCESS)) \
- _LOGE("failed chsmack -a %s %s", DB_LABEL, x); \
- else \
- _LOGD("chsmack -a %s %s", DB_LABEL, x); \
-} while (0)
-
-static int __set_db_permission(const char *path, uid_t uid)
-{
- int fd;
- const char *files[2];
- char journal_file[BUFSIZE];
- struct stat sb;
- mode_t mode;
- struct passwd pwd;
- struct passwd *result;
- char buf[BUFSIZE];
- int ret;
- int i;
-
- if (getuid() != OWNER_ROOT)
- return 0;
-
- if (uid == OWNER_ROOT || uid == GLOBAL_USER) {
- ret = getpwnam_r(APPFW_USER, &pwd, buf, sizeof(buf), &result);
- if (result == NULL) {
- if (ret == 0)
- _LOGE("no such user: %d", uid);
- else
- _LOGE("getpwuid_r failed: %d", errno);
- return -1;
- }
- uid = pwd.pw_uid;
- }
-
- snprintf(journal_file, sizeof(journal_file), "%s-journal", path);
- files[0] = path;
- files[1] = journal_file;
-
- ret = getpwuid_r(uid, &pwd, buf, sizeof(buf), &result);
- if (result == NULL) {
- if (ret == 0)
- _LOGE("no such user: %d", uid);
- else
- _LOGE("getpwuid_r failed: %d", errno);
- return -1;
- }
-
- for (i = 0; i < 2; i++) {
- fd = open(files[i], O_RDONLY);
- if (fd == -1) {
- _LOGE("open %s failed: %d", files[i], errno);
- return -1;
- }
- ret = fstat(fd, &sb);
- if (ret == -1) {
- _LOGE("stat %s failed: %d", files[i], errno);
- close(fd);
- return -1;
- }
- if (S_ISLNK(sb.st_mode)) {
- _LOGE("%s is symlink!", files[i]);
- close(fd);
- return -1;
- }
- ret = fchown(fd, uid, pwd.pw_gid);
- if (ret == -1) {
- _LOGE("fchown %s failed: %d", files[i], errno);
- close(fd);
- return -1;
- }
-
- mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH;
- if (!strcmp(path, __get_cert_db_path()))
- mode |= S_IWOTH;
- ret = fchmod(fd, mode);
- if (ret == -1) {
- _LOGD("fchmod %s failed: %d", files[i], errno);
- close(fd);
- return -1;
- }
- close(fd);
- SET_SMACK_LABEL(files[i]);
- }
-
- return 0;
-}
-
-static int __create_tables(sqlite3 *db, const char **queries)
-{
- int ret;
- int i;
- for (i = 0; queries[i] != NULL; i++) {
- ret = sqlite3_exec(db, queries[i], NULL, NULL, NULL);
- if (ret != SQLITE_OK) {
- _LOGE("exec failed: %s", sqlite3_errmsg(db));
- return -1;
- }
- }
- return 0;
-}
-
-static int __initialize_db(sqlite3 *db, const char *dbpath, uid_t uid)
-{
- const char **queries;
-
- if (__set_db_version(db))
- return -1;
-
- if (strstr(dbpath, ".pkgmgr_parser.db")) {
- queries = PARSER_INIT_QUERIES;
- } else if (strstr(dbpath, ".pkgmgr_cert.db")) {
- queries = CERT_INIT_QUERIES;
- } else {
- _LOGE("unexpected dbpath: %s", dbpath);
- return -1;
- }
-
- __BEGIN_TRANSACTION(db);
- __DO_TRANSACTION(db, __create_tables(db, queries));
- __END_TRANSACTION(db);
-
- if (__set_db_permission(dbpath, uid))
- _LOGE("failed to set db permission");
-
- return 0;
-}
-
-#define RESOURCED_BUS_NAME "org.tizen.resourced"
-#define RESOURCED_PROC_PATH "/Org/Tizen/ResourceD/Process"
-#define RESOURCED_PROC_INTERFACE "org.tizen.resourced.process"
-#define RESOURCED_PROC_METHOD "ProcExclude"
-// This should be removed when the client server structure is complete
-static void __send_wakeup_signal_to_resourced(pid_t pid)
-{
- GError *error = NULL;
- GDBusConnection *conn;
- GDBusProxy *proxy;
- GVariant *reply;
-
- conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
- if (conn == NULL) {
- _LOGE("Failed to connect to dbus: %s", error->message);
- g_error_free(error);
- return;
- }
-
- proxy = g_dbus_proxy_new_sync(conn,
- G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
- NULL, RESOURCED_BUS_NAME,
- RESOURCED_PROC_PATH, RESOURCED_PROC_INTERFACE,
- NULL, &error);
- if (proxy == NULL) {
- _LOGE("failed to get proxy object: %s", error->message);
- g_error_free(error);
- g_object_unref(conn);
- return;
- }
-
- reply = g_dbus_proxy_call_sync(proxy, RESOURCED_PROC_METHOD,
- g_variant_new("(si)", "wakeup", pid),
- G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
- if (reply == NULL)
- _LOGE("failed to get reply from resourced");
- if (error) {
- _LOGE("failed to send request: %s", error->message);
- g_error_free(error);
- }
-
- g_object_unref(proxy);
- g_object_unref(conn);
-}
-
-// This should be removed when the client server structure is complete
-static void __check_db_lock(const char *dbpath)
-{
- FILE *fp;
- FILE *fp_cmdline;
- struct stat sb;
- char type[BUFSIZE];
- int pid;
- unsigned int maj;
- unsigned int min;
- unsigned long long ino;
- char cmdline[BUFSIZE];
- char name[BUFSIZE];
- size_t len;
-
- if (stat(dbpath, &sb) == -1) {
- _LOGE("get db file(%s) status failed: %d", dbpath, errno);
- return;
- }
-
- fp = fopen("/proc/locks", "r");
- if (fp == NULL) {
- _LOGE("Failed to open lock info: %d", errno);
- return;
- }
-
- while (fscanf(fp, "%*s %*s %*s %5s %d %x:%x:%llu %*s %*s",
- type, &pid, &maj, &min, &ino) != EOF) {
- if (maj != major(sb.st_dev) || min != minor(sb.st_dev) ||
- ino != sb.st_ino || pid == getpid() ||
- strcasecmp(type, "WRITE"))
- continue;
-
- snprintf(cmdline, sizeof(cmdline), "/proc/%d/cmdline", pid);
- fp_cmdline = fopen(cmdline, "r");
- name[0] = '\0';
- if (fp_cmdline != NULL) {
- len = fread(name, sizeof(char), sizeof(name) - 1,
- fp_cmdline);
- if (len > 0) {
- if (name[len - 1] == '\n')
- name[len - 1] = '\0';
- else
- name[len] = '\0';
- }
- fclose(fp_cmdline);
- }
-
- _LOGE("%s (%d) has lock on pkgmgr db(%s)!", name, pid, dbpath);
- __send_wakeup_signal_to_resourced(pid);
- }
-
- fclose(fp);
-}
-
-#define BUSY_WAITING_USEC (1000000 / 10 / 2) /* 0.05 sec */
-#define BUSY_WAITING_MAX 100 /* wait for max 5 sec */
-
-// This should be removed when the client server structure is complete
-static int __db_busy_handler(void *data, int count)
-{
- if (count < (BUSY_WAITING_MAX / 2)) {
- usleep(BUSY_WAITING_USEC);
- return 1;
- } else if (count == (BUSY_WAITING_MAX / 2)) {
- __check_db_lock((const char *)data);
- usleep(BUSY_WAITING_USEC);
- return 1;
- } else if (count < BUSY_WAITING_MAX) {
- usleep(BUSY_WAITING_USEC);
- return 1;
- } else {
- /* sqlite3_prepare_v2 will return SQLITE_BUSY */
- return 0;
- }
-}
-
-API int pkgmgr_parser_initialize_parser_db(uid_t uid)
-{
- int ret;
- const char *dbpath;
- sqlite3 *db;
-
- dbpath = __get_parser_db_path(uid);
- if (access(dbpath, F_OK) != -1) {
- _LOGE("Manifest db for user %d is already exists", uid);
- return PM_PARSER_R_ERROR;
- }
-
- ret = sqlite3_open_v2(dbpath, &db,
- SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
- if (ret != SQLITE_OK) {
- _LOGE("open db failed: %d", ret);
- sqlite3_close_v2(db);
- return PM_PARSER_R_ERROR;
- }
-
- ret = sqlite3_busy_handler(db, __db_busy_handler, NULL);
- if (ret != SQLITE_OK) {
- _LOGE("failed to register busy handler: %s",
- sqlite3_errmsg(db));
- sqlite3_close_v2(db);
- return ret;
- }
-
- if (__initialize_db(db, dbpath, uid)) {
- sqlite3_close_v2(db);
- return PM_PARSER_R_ERROR;
- }
- sqlite3_close_v2(db);
-
- return PM_PARSER_R_OK;
-}
-
-API int pkgmgr_parser_initialize_cert_db(void)
-{
- int ret;
- const char *dbpath;
- sqlite3 *db;
-
- dbpath = __get_cert_db_path();
- if (access(dbpath, F_OK) != -1) {
- _LOGE("Cert db is already exists");
- return PM_PARSER_R_ERROR;
- }
-
- ret = sqlite3_open_v2(dbpath, &db,
- SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
- if (ret != SQLITE_OK) {
- _LOGE("open db failed: %d", ret);
- sqlite3_close_v2(db);
- return PM_PARSER_R_ERROR;
- }
-
- ret = sqlite3_busy_handler(db, __db_busy_handler, NULL);
- if (ret != SQLITE_OK) {
- _LOGE("failed to register busy handler: %s",
- sqlite3_errmsg(db));
- sqlite3_close_v2(db);
- return ret;
- }
-
- if (__initialize_db(db, dbpath, GLOBAL_USER)) {
- sqlite3_close_v2(db);
- return PM_PARSER_R_ERROR;
- }
- sqlite3_close_v2(db);
-
- return PM_PARSER_R_OK;
-}
-
API int pkgmgr_parser_create_and_initialize_db(uid_t uid)
{
int ret;
return PM_PARSER_R_EINVAL;
}
- if (pkgmgr_parser_initialize_parser_db(uid))
+ if (_parser_create_and_initialize_db(uid))
return PM_PARSER_R_ERROR;
- if (uid == OWNER_ROOT || uid == GLOBAL_USER)
- if (pkgmgr_parser_initialize_cert_db())
- return PM_PARSER_R_ERROR;
-
return PM_PARSER_R_OK;
}
LOGE("Socket is not ready");
return false;
}
+
+ // CREATE_DB request type need to be executed directly by the caller
+ if (req_type_ == pkgmgr_common::ReqType::CREATE_DB) {
+ is_offline_ = true;
+ return RequestHandlerDirectAccess();
+ }
+
if (!socket_->Connect()) {
LOGE("Failed to connect client socket, try to direct access");
socket_->Disconnect();
enum class DBOperationType {
OPERATION_TYPE_NONE,
OPERATION_TYPE_READ,
- OPERATION_TYPE_WRITE
+ OPERATION_TYPE_WRITE,
+ OPERATION_TYPE_CREATE
};
} // namespace pkgmgr_common
DepInfo,
Query,
Result,
- Command
+ Command,
+ CreateDB
};
class EXPORT_API AbstractParcelable : public tizen_base::Parcelable {
--- /dev/null
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License) {
+ * }
+ *
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "create_db_parcelable.hh"
+
+#include <vector>
+
+namespace pkgmgr_common {
+namespace parcel {
+
+CreateDBParcelable::CreateDBParcelable(uid_t uid)
+ : AbstractParcelable(uid, ParcelableType::CreateDB) {}
+
+void CreateDBParcelable::WriteToParcel(tizen_base::Parcel* parcel) const {
+ AbstractParcelable::WriteToParcel(parcel);
+}
+
+void CreateDBParcelable::ReadFromParcel(tizen_base::Parcel* parcel) {
+ AbstractParcelable::ReadFromParcel(parcel);
+}
+
+} // namespace parcel
+} // namespace pkgmgr_common
--- /dev/null
+#ifndef CREATE_DB_PARCELABLE_HH_
+#define CREATE_DB_PARCELABLE_HH_
+
+#include "abstract_parcelable.hh"
+
+#include <string>
+#include <vector>
+
+#include "db_type.hh"
+
+namespace pkgmgr_common {
+namespace parcel {
+
+#ifndef EXPORT_API
+#define EXPORT_API __attribute__((visibility("default")))
+#endif
+
+class EXPORT_API CreateDBParcelable : public AbstractParcelable {
+ public:
+ CreateDBParcelable(uid_t uid = 0);
+ void WriteToParcel(tizen_base::Parcel* parcel) const override;
+ void ReadFromParcel(tizen_base::Parcel* parcel) override;
+};
+
+} // namespace parcel
+} // namespace pkgmgr_common
+
+#endif // CREATE_DB_PARCELABLE_HH_
#include "certinfo_parcelable.hh"
#include "depinfo_parcelable.hh"
#include "filter_parcelable.hh"
+#include "create_db_parcelable.hh"
#include "pkginfo_parcelable.hh"
#include "query_parcelable.hh"
#include "result_parcelable.hh"
res = std::make_unique<CommandParcelable>();
parcel.ReadParcelable(res.get());
break;
+ case ParcelableType::CreateDB:
+ res = std::make_unique<CreateDBParcelable>();
+ parcel.ReadParcelable(res.get());
+ break;
case ParcelableType::Unknown:
res = std::make_unique<AbstractParcelable>();
parcel.ReadParcelable(res.get());
"GET_PKG_DEP_INFO",
"QUERY",
"COMMAND",
+ "CREATE_DB",
"ERROR_REQ_TYPE"
};
if (type <= ReqType::REQ_TYPE_NONE
GET_PKG_DEP_INFO,
QUERY,
COMMAND,
+ CREATE_DB,
MAX
};
#include "common/parcel/appinfo_parcelable.hh"
#include "common/parcel/certinfo_parcelable.hh"
#include "common/parcel/command_parcelable.hh"
+#include "common/parcel/create_db_parcelable.hh"
#include "common/parcel/depinfo_parcelable.hh"
#include "common/parcel/filter_parcelable.hh"
#include "common/parcel/parcelable_factory.hh"
return PMINFO_R_OK;
}
+
+static int __create_and_initialize_db(uid_t uid) {
+ std::shared_ptr<pcp::AbstractParcelable> parcelable(
+ new pcp::CreateDBParcelable(uid));
+
+ pkgmgr_client::PkgInfoClient client(parcelable, _getuid(),
+ pkgmgr_common::ReqType::CREATE_DB);
+
+ if (!client.SendRequest())
+ return -1;
+
+ auto ptr = client.GetResultParcel();
+ if (ptr == nullptr) {
+ LOG(ERROR) << "Fail to get return parcelable";
+ return -1;
+ }
+
+ if (ptr->GetRequestResult() != PMINFO_R_OK) {
+ LOG(ERROR) << "Request fail";
+ return -1;
+ }
+
+ if (ptr->GetType() != pcp::ParcelableType::Result) {
+ LOG(ERROR) << "Invalid parcelable type";
+ return -1;
+ }
+
+ return 0;
+}
+
+extern "C" EXPORT_API int _parser_create_and_initialize_db(uid_t uid) {
+ if (__create_and_initialize_db(uid) < 0) {
+ LOG(ERROR) << "Fail to initialize db";
+ return -1;
+ }
+
+ return 0;
+}
int _parser_clear_cache_memory_db(uid_t uid);
+int _parser_create_and_initialize_db(uid_t uid);
+
#ifdef __cplusplus
}
#endif
${REQUEST_HANDLER_SRCS}
)
+ADD_DEFINITIONS("-DSYSCONFDIR=\"${SYSCONFDIR}\"")
+
SET_TARGET_PROPERTIES(pkgmgr-info-server PROPERTIES SOVERSION ${MAJORVER})
SET_TARGET_PROPERTIES(pkgmgr-info-server PROPERTIES VERSION ${FULLVER})
TARGET_LINK_LIBRARIES(pkgmgr-info-server pkgmgr-info ${libpkgs_server_LDFLAGS})
return ret;
}
+int __open_create_db(uid_t uid, const char* path,
+ sqlite3** db, int flags) {
+ int ret;
+
+ ret = sqlite3_open_v2(path, db, flags, NULL);
+ if (ret != SQLITE_OK) {
+ sqlite3_close_v2(*db);
+ return ret;
+ }
+
+ ret = sqlite3_busy_handler(*db, __writedb_busy_handler,
+ reinterpret_cast<void*>(const_cast<char*>(path)));
+ if (ret != SQLITE_OK) {
+ _LOGE("failed to register busy handler: %s",
+ sqlite3_errmsg(*db));
+ sqlite3_close_v2(*db);
+ return ret;
+ }
+
+ return ret;
+}
+
uid_t ConvertUID(uid_t uid) {
if (uid < REGULAR_USER)
return tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
AbstractDBHandler::~AbstractDBHandler() {
for (auto db_handle : db_handle_list_)
- sqlite3_close(db_handle.first);
+ sqlite3_close_v2(db_handle.first);
}
std::vector<std::pair<std::string, uid_t>> AbstractDBHandler::GetDBPath() {
if (op_type_ == pkgmgr_common::DBOperationType::OPERATION_TYPE_READ) {
ret = __open_read_db(dbpath.first.c_str(), &db, SQLITE_OPEN_READONLY |
SQLITE_OPEN_URI);
- } else {
+ } else if (op_type_ == pkgmgr_common::DBOperationType::OPERATION_TYPE_WRITE) {
if (ConvertUID(dbpath.second) != ConvertUID(uid_))
continue;
ret = __open_write_db(uid_, dbpath.first.c_str(), &db,
+ SQLITE_OPEN_READWRITE);
+ } else {
+ if (ConvertUID(dbpath.second) != ConvertUID(uid_))
+ continue;
+
+ if (access(dbpath.first.c_str(), F_OK) != -1) {
+ _LOGE("Database for user %d is already exists", uid_);
+ return false;
+ }
+ ret = __open_create_db(uid_, dbpath.first.c_str(), &db,
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
}
return true;
}
+void AbstractDBHandler::ClearDBHandle() {
+ for (auto db_handle : db_handle_list_)
+ sqlite3_close_v2(db_handle.first);
+
+ db_handle_list_.clear();
+}
+
std::vector<std::pair<sqlite3*, uid_t>> AbstractDBHandler::GetConnection() {
return db_handle_list_;
}
int AbstractDBHandler::GetPID() { return pid_; }
+uid_t AbstractDBHandler::GetUID() { return uid_; }
+
void AbstractDBHandler::SetLocale(const std::string& locale) {
locale_ = locale;
}
protected:
bool Connect();
int GetPID();
+ uid_t GetUID();
std::vector<std::pair<sqlite3*, uid_t>> GetConnection();
+ void ClearDBHandle();
std::string GetLocale();
static std::shared_timed_mutex lock_;
private:
--- /dev/null
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "create_db_handler.hh"
+
+#include <vector>
+
+#include "db_handle_provider.hh"
+
+#include "pkgmgrinfo_debug.h"
+#include "pkgmgrinfo_internal.h"
+
+#ifndef OWNER_ROOT
+#define OWNER_ROOT 0
+#endif
+#ifndef GLOBAL_USER
+#define GLOBAL_USER tzplatform_getuid(TZ_SYS_GLOBALAPP_USER)
+#endif
+
+namespace pkgmgr_server {
+namespace database {
+
+CreateDBHandler::CreateDBHandler(uid_t uid, int pid)
+ : AbstractDBHandler(uid, pid) {}
+
+CreateDBHandler::~CreateDBHandler() {}
+
+std::vector<std::vector<std::string>> CreateDBHandler::GetResult() {
+ return std::move(result_);
+}
+
+int CreateDBHandler::Execute() {
+ std::unique_lock<std::shared_timed_mutex> u(lock_);
+
+ if (CreateParserDB() < 0) {
+ LOGE("Failed to create parser db for uid [%d]", GetUID());
+ return PMINFO_R_ERROR;
+ }
+
+ if (GetUID() == GLOBAL_USER || GetUID() == OWNER_ROOT) {
+ if (CreateCertDB() < 0) {
+ LOGE("Failed to create cert db for uid [%d]", GetUID());
+ return PMINFO_R_ERROR;
+ }
+ }
+
+ return PMINFO_R_OK;
+}
+
+int CreateDBHandler::CreateParserDB() {
+ SetDBType(pkgmgr_common::DBType::DB_TYPE_FILE_PKGDB);
+ ClearDBHandle();
+
+ if (!Connect())
+ return PMINFO_R_ERROR;
+
+ std::vector<std::pair<sqlite3*, uid_t>> conn_list = GetConnection();
+ sqlite3* conn = conn_list.front().first;
+ uid_t uid = conn_list.front().second;
+
+ return pkgmgr_parser_internal_initialize_db(conn, uid);
+}
+
+int CreateDBHandler::CreateCertDB() {
+ SetDBType(pkgmgr_common::DBType::DB_TYPE_FILE_CERTDB);
+ ClearDBHandle();
+
+ if (!Connect())
+ return PMINFO_R_ERROR;
+
+ std::vector<std::pair<sqlite3*, uid_t>> conn_list = GetConnection();
+ sqlite3* conn = conn_list.front().first;
+ uid_t uid = conn_list.front().second;
+
+ return pkgmgr_parser_internal_initialize_db(conn, uid);
+}
+
+} // namespace database
+} // namespace pkgmgr_server
--- /dev/null
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CREATE_DB_HANDLER_HH_
+#define CREATE_DB_HANDLER_HH_
+
+#include <string>
+#include <list>
+#include <vector>
+
+#include <sys/types.h>
+
+#include "abstract_db_handler.hh"
+#include "db_type.hh"
+#include "pkgmgrinfo_basic.h"
+#include "pkgmgrinfo_private.h"
+
+namespace pkgmgr_server {
+namespace database {
+
+#ifndef EXPORT_API
+#define EXPORT_API __attribute__((visibility("default")))
+#endif
+
+class EXPORT_API CreateDBHandler : public AbstractDBHandler {
+ public:
+ CreateDBHandler(uid_t uid, int pid);
+ ~CreateDBHandler();
+ int Execute() override;
+ std::vector<std::vector<std::string>> GetResult();
+ int CreateParserDB();
+ int CreateCertDB();
+
+ private:
+ std::vector<std::vector<std::string>> result_;
+};
+
+} // namespace database
+} // namespace pkgmgr_server
+
+#endif // CREATE_DB_HANDLER_HH_
+
--- /dev/null
+/*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define _GNU_SOURCE
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/smack.h>
+#include <pwd.h>
+
+#include <gio/gio.h>
+#include <sqlite3.h>
+
+#include <pkgmgr_parser_db_queries.h>
+#include <system_info.h>
+
+#include "pkgmgrinfo_internal.h"
+#include "pkgmgrinfo_private.h"
+#include "pkgmgrinfo_debug.h"
+
+
+#ifndef OWNER_ROOT
+#define OWNER_ROOT 0
+#endif
+#ifndef APPFW_USER
+#define APPFW_USER "app_fw"
+#endif
+
+/* TODO: Do not labeling directly */
+#define DB_LABEL "User::Home"
+#define SET_SMACK_LABEL(x) \
+do { \
+ if (smack_setlabel((x), DB_LABEL, SMACK_LABEL_ACCESS)) \
+ _LOGE("failed chsmack -a %s %s", DB_LABEL, x); \
+ else \
+ _LOGD("chsmack -a %s %s", DB_LABEL, x); \
+} while (0)
+
+#define DB_VERSION_PATH SYSCONFDIR "/package-manager/pkg_db_version.txt"
+
+static const char *__get_cert_db_path(void)
+{
+ return tzplatform_mkpath(TZ_SYS_DB, ".pkgmgr_cert.db");
+}
+
+static int __set_db_permission(const char *path, uid_t uid)
+{
+ int fd;
+ const char *files[2];
+ char journal_file[BUFSIZE];
+ struct stat sb;
+ mode_t mode;
+ struct passwd pwd;
+ struct passwd *result;
+ char buf[BUFSIZE];
+ int ret;
+ int i;
+
+ if (getuid() != OWNER_ROOT)
+ return 0;
+
+ if (uid == OWNER_ROOT || uid == GLOBAL_USER) {
+ ret = getpwnam_r(APPFW_USER, &pwd, buf, sizeof(buf), &result);
+ if (result == NULL) {
+ if (ret == 0)
+ _LOGE("no such user: %d", uid);
+ else
+ _LOGE("getpwuid_r failed: %d", errno);
+ return -1;
+ }
+ uid = pwd.pw_uid;
+ }
+
+ snprintf(journal_file, sizeof(journal_file), "%s-journal", path);
+ files[0] = path;
+ files[1] = journal_file;
+
+ ret = getpwuid_r(uid, &pwd, buf, sizeof(buf), &result);
+ if (result == NULL) {
+ if (ret == 0)
+ _LOGE("no such user: %d", uid);
+ else
+ _LOGE("getpwuid_r failed: %d", errno);
+ return -1;
+ }
+
+ for (i = 0; i < 2; i++) {
+ fd = open(files[i], O_RDONLY);
+ if (fd == -1) {
+ _LOGE("open %s failed: %d", files[i], errno);
+ return -1;
+ }
+ ret = fstat(fd, &sb);
+ if (ret == -1) {
+ _LOGE("stat %s failed: %d", files[i], errno);
+ close(fd);
+ return -1;
+ }
+ if (S_ISLNK(sb.st_mode)) {
+ _LOGE("%s is symlink!", files[i]);
+ close(fd);
+ return -1;
+ }
+ ret = fchown(fd, uid, pwd.pw_gid);
+ if (ret == -1) {
+ _LOGE("fchown %s failed: %d", files[i], errno);
+ close(fd);
+ return -1;
+ }
+
+ mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH;
+ if (!strcmp(path, __get_cert_db_path()))
+ mode |= S_IWOTH;
+ ret = fchmod(fd, mode);
+ if (ret == -1) {
+ _LOGD("fchmod %s failed: %d", files[i], errno);
+ close(fd);
+ return -1;
+ }
+ close(fd);
+ SET_SMACK_LABEL(files[i]);
+ }
+
+ return 0;
+}
+
+static int __set_db_version(sqlite3 *db) {
+ static const char query_raw[] = "PRAGMA user_version=%Q";
+ int ret;
+ FILE *fp = NULL;
+ char version[PKG_STRING_LEN_MAX] = { 0 };
+ char *query = NULL;
+
+ fp = fopen(DB_VERSION_PATH, "r");
+ if (fp == NULL) {
+ _LOGE("Failed to open db version file");
+ return -1;
+ }
+
+ if (fgets(version, sizeof(version), fp) == NULL) {
+ _LOGE("Failed to get version information");
+ fclose(fp);
+ return -1;
+ }
+ fclose(fp);
+
+ query = sqlite3_mprintf(query_raw, version);
+ if (!query) {
+ _LOGE("Out of memory");
+ return -1;
+ }
+
+ ret = sqlite3_exec(db, query, NULL, NULL, NULL);
+ if (ret != SQLITE_OK) {
+ _LOGE("exec failed: %s", sqlite3_errmsg(db));
+ sqlite3_free(query);
+ return -1;
+ }
+ sqlite3_free(query);
+
+ return 0;
+}
+
+static int __create_tables(sqlite3 *db, const char **queries)
+{
+ int ret;
+ int i;
+ for (i = 0; queries[i] != NULL; i++) {
+ ret = sqlite3_exec(db, queries[i], NULL, NULL, NULL);
+ if (ret != SQLITE_OK) {
+ _LOGE("exec failed: %s", sqlite3_errmsg(db));
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static int __initialize_db(sqlite3 *db, const char *dbpath, uid_t uid)
+{
+ const char **queries;
+
+ if (__set_db_version(db))
+ return -1;
+
+ if (strstr(dbpath, ".pkgmgr_parser.db")) {
+ queries = PARSER_INIT_QUERIES;
+ } else if (strstr(dbpath, ".pkgmgr_cert.db")) {
+ queries = CERT_INIT_QUERIES;
+ } else {
+ _LOGE("unexpected dbpath: %s", dbpath);
+ return -1;
+ }
+
+ __BEGIN_TRANSACTION(db);
+ __DO_TRANSACTION(db, __create_tables(db, queries));
+ __END_TRANSACTION(db);
+
+ if (__set_db_permission(dbpath, uid))
+ _LOGE("failed to set db permission");
+
+ return 0;
+}
+
+API int pkgmgr_parser_internal_initialize_db(sqlite3 *db, uid_t uid)
+{
+ const char *dbpath;
+ const char **queries;
+
+ dbpath = sqlite3_db_filename(db, "main");
+ if (dbpath == NULL) {
+ _LOGE("Fail to get db filename");
+ return -1;
+ }
+
+ return __initialize_db(db, dbpath, uid);
+}
#include "pkgmgrinfo_debug.h"
#include "pkgmgr-info.h"
-#include "pkgmgrinfo_internal.h"
-
-#define __BEGIN_TRANSACTION(db) \
-do { \
- if (sqlite3_exec(db, "BEGIN DEFERRED", NULL, NULL, NULL) != \
- SQLITE_OK) { \
- _LOGE("begin transaction failed: %s", sqlite3_errmsg(db)); \
- return -1; \
- } \
-} while (0) \
-
-#define __DO_TRANSACTION(db, func) \
-do { \
- if (func) { \
- _LOGE("transaction failed: %s, rollback", sqlite3_errmsg(db)); \
- if (sqlite3_exec(db, "ROLLBACK", NULL, NULL, NULL) != \
- SQLITE_OK) \
- _LOGE("roll back transaction failed: %s", \
- sqlite3_errmsg(db)); \
- return -1; \
- } \
-} while (0) \
-
-#define __END_TRANSACTION(db) \
-do { \
- if (sqlite3_exec(db, "COMMIT", NULL, NULL, NULL) != \
- SQLITE_OK) { \
- _LOGE("commit failed: %s, rollback", sqlite3_errmsg(db)); \
- if (sqlite3_exec(db, "ROLLBACK", NULL, NULL, NULL) != \
- SQLITE_OK) \
- _LOGE("roll back transaction failed: %s", \
- sqlite3_errmsg(db)); \
- return -1; \
- } \
-} while (0) \
-
-#define __BIND_TEXT(db, stmt, i, text) \
-do { \
- if (sqlite3_bind_text(stmt, i, text, -1, SQLITE_STATIC) != SQLITE_OK) {\
- _LOGE("bind error(index %d): %s", i, sqlite3_errmsg(db)); \
- sqlite3_finalize(stmt); \
- return -1; \
- } \
-} while (0)
-
-#define __BIND_INT(db, stmt, i, int) \
-do { \
- if (sqlite3_bind_int(stmt, i, int) != SQLITE_OK) { \
- _LOGE("bind error(index %d): %s", i, sqlite3_errmsg(db)); \
- sqlite3_finalize(stmt); \
- return -1; \
- } \
-} while (0)
-
#define LDPI "ldpi"
#define MDPI "mdpi"
#define HDPI "hdpi"
GList *argument;
} query_args;
+#define __BEGIN_TRANSACTION(db) \
+do { \
+ if (sqlite3_exec(db, "BEGIN DEFERRED", NULL, NULL, NULL) != \
+ SQLITE_OK) { \
+ _LOGE("begin transaction failed: %s", sqlite3_errmsg(db)); \
+ return -1; \
+ } \
+} while (0) \
+
+#define __DO_TRANSACTION(db, func) \
+do { \
+ if (func) { \
+ _LOGE("transaction failed: %s, rollback", sqlite3_errmsg(db)); \
+ if (sqlite3_exec(db, "ROLLBACK", NULL, NULL, NULL) != \
+ SQLITE_OK) \
+ _LOGE("roll back transaction failed: %s", \
+ sqlite3_errmsg(db)); \
+ return -1; \
+ } \
+} while (0) \
+
+#define __END_TRANSACTION(db) \
+do { \
+ if (sqlite3_exec(db, "COMMIT", NULL, NULL, NULL) != \
+ SQLITE_OK) { \
+ _LOGE("commit failed: %s, rollback", sqlite3_errmsg(db)); \
+ if (sqlite3_exec(db, "ROLLBACK", NULL, NULL, NULL) != \
+ SQLITE_OK) \
+ _LOGE("roll back transaction failed: %s", \
+ sqlite3_errmsg(db)); \
+ return -1; \
+ } \
+} while (0) \
+
+#define __BIND_TEXT(db, stmt, i, text) \
+do { \
+ if (sqlite3_bind_text(stmt, i, text, -1, SQLITE_STATIC) != SQLITE_OK) {\
+ _LOGE("bind error(index %d): %s", i, sqlite3_errmsg(db)); \
+ sqlite3_finalize(stmt); \
+ return -1; \
+ } \
+} while (0)
+
+#define __BIND_INT(db, stmt, i, int) \
+do { \
+ if (sqlite3_bind_int(stmt, i, int) != SQLITE_OK) { \
+ _LOGE("bind error(index %d): %s", i, sqlite3_errmsg(db)); \
+ sqlite3_finalize(stmt); \
+ return -1; \
+ } \
+} while (0)
+
int pkginfo_internal_filter_get_list(sqlite3 *db, pkgmgrinfo_pkginfo_filter_h filter, uid_t uid, const char *locale, GHashTable *list);
int appinfo_internal_filter_get_list(sqlite3 *db, pkgmgrinfo_appinfo_filter_h filter, uid_t db_uid, uid_t uid, const char *locale, GHashTable *list);
int certinfo_internal_get(sqlite3 *db, const char *pkgid, uid_t uid, pkgmgrinfo_certinfo_h certinfo);
int pkgmgr_parser_update_pkg_info(sqlite3 *db, manifest_x *mfx, uid_t uid);
int pkgmgr_parser_delete_pkg_info(sqlite3 *db, const char *package, uid_t uid);
+int pkgmgr_parser_internal_initialize_db(sqlite3 *db, uid_t uid);
+
/** @} */
#ifdef __cplusplus
}
--- /dev/null
+// Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by an apache-2.0 license that can be
+// found in the LICENSE file.
+
+#include "create_db_request_handler.hh"
+
+#include <string>
+
+#include "parcelable_factory.hh"
+#include "create_db_parcelable.hh"
+#include "create_db_handler.hh"
+#include "db_type.hh"
+
+#include "pkgmgr_parser.h"
+
+#include "pkgmgrinfo_debug.h"
+
+namespace pcp = pkgmgr_common::parcel;
+namespace psd = pkgmgr_server::database;
+
+namespace pkgmgr_server {
+namespace request_handler {
+
+bool CreateDBRequestHandler::HandleRequest(unsigned char* data, int size,
+ std::string locale) {
+ auto abstract_parcel =
+ pcp::ParcelableFactory::GetInst().CreateParcel(data, size);
+
+ if (abstract_parcel == nullptr ||
+ abstract_parcel->GetType() != pcp::ParcelableType::CreateDB) {
+ _LOGE("Invalid parcel or type");
+ result_ = std::make_shared<pcp::ResultParcelable>(
+ PM_PARSER_R_ERROR, std::vector<std::vector<std::string>>{});
+ return false;
+ }
+
+ auto* parcel = dynamic_cast<pcp::CreateDBParcelable*>(abstract_parcel.get());
+ if (parcel == nullptr) {
+ _LOGE("Parcel is empty");
+ result_ = std::make_shared<pcp::ResultParcelable>(
+ PM_PARSER_R_ERROR, std::vector<std::vector<std::string>>{});
+ return false;
+ }
+
+ psd::CreateDBHandler db(parcel->GetUid(), GetPID());
+ db.SetOpType(pkgmgr_common::DBOperationType::OPERATION_TYPE_CREATE);
+
+ int ret = PM_PARSER_R_ERROR;
+
+ ret = db.Execute();
+
+ result_ = std::make_shared<pcp::ResultParcelable>(
+ ret, std::vector<std::vector<std::string>>{});
+
+ return true;
+}
+
+std::vector<uint8_t> CreateDBRequestHandler::ExtractResult() {
+ tizen_base::Parcel parcel;
+
+ parcel.WriteParcelable(*result_);
+ std::vector<uint8_t> raw = parcel.GetRaw();
+
+ result_.reset();
+
+ return raw;
+}
+
+} // namespace request_handler
+} // namespace pkgmgr_server
--- /dev/null
+// Copyright (c) 2021 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by an apache-2.0 license that can be
+// found in the LICENSE file.
+
+#ifndef SERVER_CREATE_DB_REQUEST_HANDLER_HH_
+#define SERVER_CREATE_DB_REQUEST_HANDLER_HH_
+
+#include "abstract_request_handler.hh"
+#include "result_parcelable.hh"
+
+#include <string>
+
+namespace pkgmgr_server {
+namespace request_handler {
+
+#ifndef EXPORT_API
+#define EXPORT_API __attribute__((visibility("default")))
+#endif
+
+class EXPORT_API CreateDBRequestHandler : public AbstractRequestHandler {
+ public:
+ bool HandleRequest(unsigned char* data, int size, std::string locale) override;
+
+ std::vector<uint8_t> ExtractResult() override;
+
+ private:
+ std::shared_ptr<pkgmgr_common::parcel::ResultParcelable> result_;
+};
+
+} // namespace request_handler
+} // namespace pkgmgr_server
+
+#endif // SERVER_CREATE_DB_REQUEST_HANDLER_HH_
#include "common/parcel/parcelable_factory.hh"
#include "command_request_handler.hh"
+#include "create_db_request_handler.hh"
#include "get_appinfo_request_handler.hh"
#include "get_cert_request_handler.hh"
#include "get_depinfo_request_handler.hh"
case pkgmgr_common::ReqType::COMMAND:
handler.reset(new pkgmgr_server::request_handler::CommandRequestHandler());
break;
+ case pkgmgr_common::ReqType::CREATE_DB:
+ handler.reset(new pkgmgr_server::request_handler::CreateDBRequestHandler());
+ break;
default:
handler.reset(nullptr);
break;
#include "get_cert_request_handler.hh"
#include "get_pkginfo_request_handler.hh"
#include "get_depinfo_request_handler.hh"
+#include "create_db_request_handler.hh"
#include "query_request_handler.hh"
#include "set_cert_request_handler.hh"
#include "set_pkginfo_request_handler.hh"
new request_handler::QueryRequestHandler());
handler[pkgmgr_common::ReqType::COMMAND].reset(
new request_handler::CommandRequestHandler());
+ handler[pkgmgr_common::ReqType::CREATE_DB].reset(
+ new request_handler::CreateDBRequestHandler());
LOGD("Initialize request handlers");
while (true) {
if (ret != 0)
LOGE("failed to remove database for uid[%d]", uid);
- ret = pkgmgr_parser_initialize_parser_db((uid_t)uid);
+ ret = pkgmgr_parser_create_and_initialize_db((uid_t)uid);
if (ret != 0) {
- LOGE("failed to create parser db for uid [%d], err[%d]", uid, ret);
+ LOGE("failed to create db for uid [%d], err[%d]", uid, ret);
return -1;
}
- if (uid == GLOBAL_USER || uid == OWNER_ROOT) {
- ret = pkgmgr_parser_initialize_cert_db();
- if (ret != 0) {
- LOGE("failed to create cert db for uid [%d], err[%d]", uid, ret);
- return -1;
- }
- }
-
return 0;
}