Remove sqlite dependency from pkgmgr_parser_db (#167)
author김일호/Tizen Platform Lab(SR)/Engineer/삼성전자 <ilho159.kim@samsung.com>
Mon, 26 Apr 2021 02:36:44 +0000 (11:36 +0900)
committerGitHub Enterprise <noreply-CODE@samsung.com>
Mon, 26 Apr 2021 02:36:44 +0000 (11:36 +0900)
Remove sqlite dependency from pkgmgr_parser_db

Change-Id: I705e888ab5e43a719bfdf4eb7c2d625c8baf7288
Signed-off-by: Ilho Kim <ilho159.kim@samsung.com>
26 files changed:
parser/CMakeLists.txt
parser/include/pkgmgr_parser_db.h
parser/src/pkgmgr_parser_db.c
src/client/pkginfo_client.cc
src/common/db_type.hh
src/common/parcel/abstract_parcelable.hh
src/common/parcel/create_db_parcelable.cc [new file with mode: 0644]
src/common/parcel/create_db_parcelable.hh [new file with mode: 0644]
src/common/parcel/parcelable_factory.cc
src/common/request_type.cc
src/common/request_type.hh
src/manager/pkginfo_manager.cc
src/manager/pkginfo_manager.h
src/server/CMakeLists.txt
src/server/database/abstract_db_handler.cc
src/server/database/abstract_db_handler.hh
src/server/database/create_db_handler.cc [new file with mode: 0644]
src/server/database/create_db_handler.hh [new file with mode: 0644]
src/server/initialize_db_internal.c [new file with mode: 0644]
src/server/pkginfo_internal.c
src/server/pkgmgrinfo_internal.h
src/server/request_handler/create_db_request_handler.cc [new file with mode: 0644]
src/server/request_handler/create_db_request_handler.hh [new file with mode: 0644]
src/server/request_handler/request_handler_direct_access.cc
src/server/worker_thread.cc
tool/pkg-db-creator.c

index dce7a93..776eb43 100644 (file)
@@ -33,7 +33,7 @@ endif()
 ### 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}")
index 80e3740..8021c0d 100644 (file)
@@ -581,8 +581,6 @@ int pkgmgr_parser_unregister_pkg_plugin_info_in_db(const char *pkgid);
 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);
index e63248c..5034849 100644 (file)
@@ -29,7 +29,6 @@
 
 #include <glib.h>
 #include <gio/gio.h>
-#include <sqlite3.h>
 
 #include <tzplatform_config.h>
 #include <system_info.h>
@@ -106,421 +105,6 @@ static inline uid_t __getuid(void)
                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;
@@ -542,13 +126,9 @@ API int pkgmgr_parser_create_and_initialize_db(uid_t uid)
                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;
 }
 
index 8c48db9..894416c 100644 (file)
@@ -44,6 +44,13 @@ bool PkgInfoClient::SendRequest() {
     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();
index 4c4c0d4..9a5ecfc 100644 (file)
@@ -29,7 +29,8 @@ enum class DBType {
 enum class DBOperationType {
   OPERATION_TYPE_NONE,
   OPERATION_TYPE_READ,
-  OPERATION_TYPE_WRITE
+  OPERATION_TYPE_WRITE,
+  OPERATION_TYPE_CREATE
 };
 
 }  // namespace pkgmgr_common
index 6ab6fc5..ff0864a 100644 (file)
@@ -24,7 +24,8 @@ enum ParcelableType {
   DepInfo,
   Query,
   Result,
-  Command
+  Command,
+  CreateDB
 };
 
 class EXPORT_API AbstractParcelable : public tizen_base::Parcelable {
diff --git a/src/common/parcel/create_db_parcelable.cc b/src/common/parcel/create_db_parcelable.cc
new file mode 100644 (file)
index 0000000..4beb285
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * 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
diff --git a/src/common/parcel/create_db_parcelable.hh b/src/common/parcel/create_db_parcelable.hh
new file mode 100644 (file)
index 0000000..d772b95
--- /dev/null
@@ -0,0 +1,28 @@
+#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_
index ce1e34f..2ced47a 100644 (file)
@@ -23,6 +23,7 @@
 #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"
@@ -82,6 +83,10 @@ std::unique_ptr<AbstractParcelable> ParcelableFactory::CreateParcel(
       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());
index d5401fb..9ae546b 100644 (file)
@@ -28,6 +28,7 @@ const char* ReqTypeToString(ReqType type) {
       "GET_PKG_DEP_INFO",
       "QUERY",
       "COMMAND",
+      "CREATE_DB",
       "ERROR_REQ_TYPE"
   };
   if (type <= ReqType::REQ_TYPE_NONE
index d528120..f3512db 100644 (file)
@@ -35,6 +35,7 @@ enum ReqType {
   GET_PKG_DEP_INFO,
   QUERY,
   COMMAND,
+  CREATE_DB,
   MAX
 };
 
index bc3fcbd..75ba781 100644 (file)
@@ -33,6 +33,7 @@
 #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"
@@ -1145,3 +1146,41 @@ extern "C" EXPORT_API int _parser_clear_cache_memory_db(uid_t uid) {
 
   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;
+}
index 41497ab..03c0ea0 100644 (file)
@@ -95,6 +95,8 @@ int _pkginfo_delete_certinfo(const char *pkgid);
 
 int _parser_clear_cache_memory_db(uid_t uid);
 
+int _parser_create_and_initialize_db(uid_t uid);
+
 #ifdef __cplusplus
 }
 #endif
index e2e24c7..2ce0d2b 100644 (file)
@@ -11,6 +11,8 @@ ADD_LIBRARY(pkgmgr-info-server SHARED
   ${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})
index 27e88de..d469a79 100644 (file)
@@ -211,6 +211,28 @@ int __open_write_db(uid_t uid, const char* path,
   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);
@@ -232,7 +254,7 @@ AbstractDBHandler::AbstractDBHandler(uid_t uid, int pid) {
 
 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() {
@@ -260,10 +282,20 @@ bool AbstractDBHandler::Connect() {
     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);
     }
 
@@ -276,6 +308,13 @@ bool AbstractDBHandler::Connect() {
   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_;
 }
@@ -288,6 +327,8 @@ std::string AbstractDBHandler::GetLocale() { return locale_; }
 
 int AbstractDBHandler::GetPID() { return pid_; }
 
+uid_t AbstractDBHandler::GetUID() { return uid_; }
+
 void AbstractDBHandler::SetLocale(const std::string& locale) {
   locale_ = locale;
 }
index a835454..5554c01 100644 (file)
@@ -47,7 +47,9 @@ class EXPORT_API AbstractDBHandler {
  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:
diff --git a/src/server/database/create_db_handler.cc b/src/server/database/create_db_handler.cc
new file mode 100644 (file)
index 0000000..a123fb3
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * 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
diff --git a/src/server/database/create_db_handler.hh b/src/server/database/create_db_handler.hh
new file mode 100644 (file)
index 0000000..ff40360
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * 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_
+
diff --git a/src/server/initialize_db_internal.c b/src/server/initialize_db_internal.c
new file mode 100644 (file)
index 0000000..6e4379e
--- /dev/null
@@ -0,0 +1,231 @@
+/*
+ * 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);
+}
index 7f35703..cd9ee32 100644 (file)
 #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"
index b97ae13..00556c8 100644 (file)
@@ -36,6 +36,58 @@ typedef struct {
     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);
@@ -52,6 +104,8 @@ int pkgmgr_parser_insert_pkg_info(sqlite3 *db, manifest_x *mfx, uid_t uid);
 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
 }
diff --git a/src/server/request_handler/create_db_request_handler.cc b/src/server/request_handler/create_db_request_handler.cc
new file mode 100644 (file)
index 0000000..91dbf15
--- /dev/null
@@ -0,0 +1,70 @@
+// 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
diff --git a/src/server/request_handler/create_db_request_handler.hh b/src/server/request_handler/create_db_request_handler.hh
new file mode 100644 (file)
index 0000000..2f71072
--- /dev/null
@@ -0,0 +1,33 @@
+// 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_
index a63e5a9..97cea92 100644 (file)
@@ -20,6 +20,7 @@
 
 #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"
@@ -68,6 +69,9 @@ extern "C" EXPORT_API void* _request_handler_direct_access(int req_type,
     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;
index eab2f66..d49cd40 100644 (file)
@@ -25,6 +25,7 @@
 #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"
@@ -86,6 +87,8 @@ void WorkerThread::Run() {
       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) {
index 59b6345..6a50e37 100644 (file)
@@ -124,20 +124,12 @@ int main(int argc, char *argv[])
        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;
 }