Add plugin parser plugin to generate /etc/skel image sandbox/klewandowski/generate-skel2
authorKarol Lewandowski <k.lewandowsk@samsung.com>
Wed, 16 Apr 2025 13:53:09 +0000 (15:53 +0200)
committerKarol Lewandowski <k.lewandowsk@samsung.com>
Mon, 28 Apr 2025 13:50:20 +0000 (15:50 +0200)
To be used to make adding subsession faster.  They way it's inteded to be is

 1. Template image from /etc/skel is generated per each user (FIXME) after any package is installed
  - check case if no package is installed during image build (FIXME)
  - file has to be generated in some sensible directory, not /tmp (FIXME)

 2. sessiond add will copy the image file instead of creating their own (TODO)
  - sessiond has to resize the image to users specified size (TODO)

Change-Id: I2b859f71174c690fa2c1658f2986fad60dd803e9

17 files changed:
packaging/sessiond.spec
src/CMakeLists.txt
src/service/CMakeLists.txt
src/service/src/dir_backend.hpp
src/service/src/dir_backend_fixed_size.cpp
src/service/src/dir_backend_fixed_size.hpp
src/service/src/dir_backend_regular_dir.cpp
src/service/src/dir_backend_regular_dir.hpp
src/service/src/fs_helpers.cpp
src/service/src/fs_helpers.hpp
src/service/src/main.cpp
src/service/src/main_restore.cpp
src/service/src/main_skel.cpp [new file with mode: 0644]
src/service/src/main_skel.hpp [new file with mode: 0644]
src/tpkplugin/CMakeLists.txt [new file with mode: 0644]
src/tpkplugin/plugin.c [new file with mode: 0644]
src/tpkplugin/sessiond-update-skelimg.info [new file with mode: 0644]

index 300df5ce31861f9212aed1a98d12d52d538d5635..9a460b584bf9b09e25edae72bd173aee270119c5 100644 (file)
@@ -13,6 +13,10 @@ BuildRequires: gtest-devel
 BuildRequires: pkgconfig(libsmack)
 BuildRequires: pkgconfig(dlog)
 BuildRequires: pkgconfig(libsyscommon-plugin-api-sessiond)
+
+BuildRequires: pkgconfig(capi-system-info)
+BuildRequires: pkgconfig(libxml-2.0)
+BuildRequires: pkgconfig(pkgmgr-info)
 %description
 
 %package -n libsessiond
@@ -84,6 +88,8 @@ popd
 %{_unitdir}/sessiond.service
 %{_datadir}/dbus-1/system-services/org.tizen.system.sessiond.service
 /etc/dbus-1/system.d/org.tizen.sessiond.conf
+/etc/package-manager/parserlib/libsessiond-update-skelimg.so
+/usr/share/parser-plugins/sessiond-update-skelimg.info
 
 %files -n libsessiond
 %manifest sessiond.manifest
index fa8cc96a56c6dc818dd288e9c06f59daae6c0c7f..fda2a665101f858d221de9a4ae744fb2c8c39294 100644 (file)
@@ -1,3 +1,4 @@
 add_subdirectory(common)
 add_subdirectory(library)
 add_subdirectory(service)
+add_subdirectory(tpkplugin)
index 13ee438037c0c9fb914f61fd4c7a08e025879e08..2575197cdc6593b8e4d0f415b4a94c60cb0f77b4 100644 (file)
@@ -10,6 +10,7 @@ set(
        sessiond_SRCS
        src/main.cpp
        src/main_restore.cpp
+       src/main_skel.cpp
        src/fs_helpers.cpp
        src/os_ops.cpp
        src/plugin.cpp
index d1c66c5cc41935fe4f1842639fda842a14e188a2..d3e8c62934fa3b50bea32bf9aa5e3fd294a82b3c 100644 (file)
@@ -11,7 +11,8 @@ struct DirBackend {
 };
 
 struct DirBackendAdd {
-       virtual fs::path AddSubsessionPrepare (const fs::path& subsession_path, int uid, int gid) const = 0;
+        virtual fs::path AddSubsessionPrepare (const fs::path& subsession_path, int uid, int gid) const = 0;
+        virtual fs::path AddSubsessionPrepareFromTemplate (const fs::path& subsession_path, const fs::path& main_path, int uid, int gid) const = 0;
        virtual void AddSubsessionFinalize (const fs::path& tmpdir_path, const fs::path& subsession_path, int uid, int gid) const = 0;
        virtual void AddSubsessionCleanupFailure (const fs::path& tmpdir_path, const fs::path& subsession_path) const = 0;
 };
index c79c7b70c89ef21f43d0e59c7e10a290e69eb135..3711a9e8ce37484eeb44820da3e3e42f5429f7c7 100644 (file)
@@ -25,6 +25,7 @@
 #include <dlog.h>
 
 #include "dir_backend_fixed_size.hpp"
+#include "fs_helpers.hpp"
 #include "os_ops.hpp"
 
 #include <sys/mount.h>
@@ -43,7 +44,28 @@ fs::path DirBackendFixedSize::GetImagePathFromSubsessionPath(fs::path subsession
        return subsession_path;
 }
 
-static void do_mkfs(const fs::path& image_path, int uid, int gid, uint64_t size_kB)
+void do_resize2fs(const fs::path& image_path, uint64_t size_kB)
+{
+       const auto child_pid = OS::throwing_fork();
+       if (child_pid == 0) {
+               const auto cmd = "/usr/sbin/resize2fs"sv;
+
+               std::string size_arg = std::to_string(size_kB);
+
+               execl
+                       ( cmd.data(), cmd.data() /* argv[0] convention */
+                       , image_path.c_str()
+                       , size_arg.c_str()
+                       , (char *) NULL
+               );
+
+               _exit(1);
+       } else {
+               OS::throw_if_child_failed(child_pid, "resize2fs failed!");
+       }
+}
+
+void do_mkfs(const fs::path& image_path, int uid, int gid, uint64_t size_kB)
 {
        const auto child_pid = OS::throwing_fork();
        if (child_pid == 0) {
@@ -73,7 +95,7 @@ static void do_mkfs(const fs::path& image_path, int uid, int gid, uint64_t size_
        }
 }
 
-static void do_mount(const fs::path& image_path, const fs::path& mount_path)
+void do_mount(const fs::path& image_path, const fs::path& mount_path)
 {
        /* Don't just call mount() since there's some extra steps involved
         * in making it work properly, such as setting up a loop device,
@@ -97,7 +119,7 @@ static void do_mount(const fs::path& image_path, const fs::path& mount_path)
        }
 }
 
-static void do_umount(const fs::path& path)
+void do_umount(const fs::path& path)
 {
        const auto child_pid = OS::throwing_fork();
        if (child_pid == 0) {
@@ -115,6 +137,41 @@ static void do_umount(const fs::path& path)
        }
 }
 
+void umount_and_remove (const fs::path& path) try {
+       do_umount(path);
+       fs::remove(path);
+} catch (const std::exception& ex) {
+       LOGE("umount & rmdir (%s) failed!", path.c_str());
+       throw;
+}
+
+fs::path DirBackendAddFixedSize::AddSubsessionPrepareFromTemplate (const fs::path& subsession_path, const fs::path& main_path, int uid, int gid) const
+{
+       fs::path template_path = main_path / ".template";
+
+       auto tmp_subsession_path = subsession_path;
+       tmp_subsession_path.replace_filename(TMP_NEW_PREFIX + subsession_path.filename().native());
+       auto image_template = DirBackendFixedSize::GetImagePathFromSubsessionPath(template_path);
+       auto image_new_tmp  = DirBackendFixedSize::GetImagePathFromSubsessionPath(tmp_subsession_path);
+       fs::copy_file (image_template, image_new_tmp);
+       do_resize2fs (image_new_tmp, size_kB);
+
+       try {
+               fs::create_directory(tmp_subsession_path);
+               OS::change_owner_and_group(tmp_subsession_path, uid, gid);
+       } catch (const std::exception& ex) {
+               fs::remove(image_new_tmp);
+               fs::remove(tmp_subsession_path);
+               throw;
+       }
+
+       // We do not really need to mount this image here, so we won't as it will make add_user() slower
+       // Fankly, AddSubsessionPrepare does mount() so it will make switch() faster later on
+       // Thus, this is subject to change
+
+       return tmp_subsession_path;
+}
+
 fs::path DirBackendAddFixedSize::AddSubsessionPrepare (const fs::path& subsession_path, int uid, int gid) const
 {
        /* Work off a temp image first so that the "real" image
@@ -129,6 +186,7 @@ fs::path DirBackendAddFixedSize::AddSubsessionPrepare (const fs::path& subsessio
 
        try {
                fs::create_directory(tmp_subsession_path);
+               OS::change_owner_and_group(tmp_subsession_path, uid, gid);
        } catch (const std::exception& ex) {
                fs::remove(image_path);
                throw;
@@ -145,14 +203,6 @@ fs::path DirBackendAddFixedSize::AddSubsessionPrepare (const fs::path& subsessio
        return tmp_subsession_path;
 }
 
-static void umount_and_remove (const fs::path& path) try {
-       do_umount(path);
-       fs::remove(path);
-} catch (const std::exception& ex) {
-       LOGE("umount & rmdir (%s) failed!", path.c_str());
-       throw;
-}
-
 void DirBackendAddFixedSize::AddSubsessionCleanupFailure (const fs::path& tmpdir_path, const fs::path& subsession_path) const
 {
        auto tmp_image_path = DirBackendFixedSize::GetImagePathFromSubsessionPath(subsession_path);
@@ -164,30 +214,40 @@ void DirBackendAddFixedSize::AddSubsessionCleanupFailure (const fs::path& tmpdir
 
 void DirBackendAddFixedSize::AddSubsessionFinalize (const fs::path& tmpdir_path, const fs::path& subsession_path, int uid, int gid) const
 {
-       umount_and_remove(tmpdir_path);
+       // XXX keep mounts! it should be possible to reuse this dir too!
+       // XXX this is pointless step, need to introduce mount --move
+        // umount_and_remove(tmpdir_path);
+       if (OS::is_mountpoint(tmpdir_path))
+               do_umount(tmpdir_path);
 
        const auto image_path = DirBackendFixedSize::GetImagePathFromSubsessionPath(subsession_path);
-       auto temp_image_path = image_path;
-       temp_image_path.replace_filename(TMP_NEW_PREFIX + image_path.filename().native());
-       fs::rename(temp_image_path, image_path);
+       auto tmp_image_path = image_path;
+       tmp_image_path.replace_filename(TMP_NEW_PREFIX + image_path.filename().native());
 
        /* The image file (as opposed to the FS inside it) doesn't
         * really need any rights, and maybe it would even be better
         * if it was harder to disrupt. This way all three concepts,
         * i.e. the image, the mount dir, and the FS root, are all
         * consistent with their rights though. */
-       OS::change_owner_and_group(image_path, uid, gid);
+       //LOGI("change_owner_and_group %s %s", tmp_image_path.c_str(), image_path.c_str());
+       OS::change_owner_and_group(tmp_image_path, uid, gid);
 
        /* Order matters - handle .img first and the directory last,
         * since all other logic assumes that the existence of the dir
         * signifies that a valid subsession exists. */
-       fs::create_directory(subsession_path);
+       //fs::create_directory(subsession_path);
+
+       //LOGI("rename %s %s", tmp_image_path.c_str(), image_path.c_str());
+       fs::rename(tmp_image_path, image_path);
+       //LOGI("rename %s %s", tmpdir_path.c_str(), subsession_path.c_str());
+       fs::rename(tmpdir_path, subsession_path);
 
        /* The mountpoint's properties don't actually matter, since
         * they are completely replaced with the image filesystem's
         * root dir's, but this way they are consistent regardless of
         * whether the image is mounted or not. */
-       OS::change_owner_and_group(subsession_path, uid, gid);
+       // XXX moved to AddSubsessionPrepare* for dir_backend_fixe - NEED to check dir_regular_dir
+       //OS::change_owner_and_group(subsession_path, uid, gid);
 }
 
 void DirBackendFixedSize::RemoveSubsession (const fs::path& subsession_path) const
index cd752921d35bd17d9583a1d6e082bab01be7b9df..d2ab98df4de7842d4d3380d00d6f4dba1e51b9d5 100644 (file)
@@ -17,6 +17,7 @@ struct DirBackendAddFixedSize : public DirBackendAdd {
        DirBackendAddFixedSize(uint32_t s) : size_kB(s) { }
 
        fs::path AddSubsessionPrepare (const fs::path& subsession_path, int uid, int gid) const override;
+       fs::path AddSubsessionPrepareFromTemplate (const fs::path& subsession_path, const fs::path& main_path, int uid, int gid) const override;
        void AddSubsessionFinalize (const fs::path& tmpdir_path, const fs::path& subsession_path, int uid, int gid) const override;
        void AddSubsessionCleanupFailure (const fs::path& tmpdir_path, const fs::path& subsession_path) const override;
 };
index 5f46a7f946fff456721f845f340ab77e014a2edc..4bb79552658f44ba53412be16ec1529057790e50 100644 (file)
 
 using namespace std::string_literals;
 
+fs::path DirBackendAddRegularDir::AddSubsessionPrepareFromTemplate (const fs::path& subsession_path, const fs::path &main_path, int uid, int gid) const
+{
+       throw std::runtime_error("not supported");
+}
+
 fs::path DirBackendAddRegularDir::AddSubsessionPrepare (const fs::path& subsession_path, int uid, int gid) const
 {
        auto tmp_subsession_path = subsession_path;
index ed4a9f612077af4db094b6254a8ac5e0da5fb63d..d749b4316e1c77bc1008e768d16a444b3de193a4 100644 (file)
@@ -10,6 +10,7 @@ struct DirBackendRegularDir : public DirBackend {
 
 struct DirBackendAddRegularDir : public DirBackendAdd {
        fs::path AddSubsessionPrepare (const fs::path& subsession_path, int uid, int gid) const override;
+        fs::path AddSubsessionPrepareFromTemplate (const fs::path& subsession_path, const fs::path &main_path, int uid, int gid) const override;
        void AddSubsessionFinalize (const fs::path& tmpdir_path, const fs::path& subsession_path, int uid, int gid) const override;
        void AddSubsessionCleanupFailure (const fs::path& tmpdir_path, const fs::path& subsession_path) const override;
 };
index 18a83bfca8366a3bdaf2839647fb5fcf81895344..f0efcc413155ef4c025356e26af950740f60c2d7 100644 (file)
@@ -38,6 +38,7 @@
 
 namespace fs = std::filesystem;
 using namespace std::string_literals;
+using namespace std::string_view_literals;
 
 fs::path get_main_dir_by_user_id(const int uid)
 {
@@ -143,6 +144,36 @@ void add_user_subsession(const int session_uid, const std::string_view subsessio
                        throw std::system_error(EEXIST, std::generic_category(),
                                "Subsession directory already exists");
 
+               const int system_share_gid = OS::get_gid_from_name(system_share_group);
+               const auto tmp_subsession_path = backend.AddSubsessionPrepareFromTemplate
+                       ( subsession_path, main_path, session_uid, system_share_gid );
+               backend.AddSubsessionFinalize(tmp_subsession_path, subsession_path, session_uid, system_share_gid);
+
+       }
+       catch (const std::exception &ex) {
+               LOGE("Logic exception while copying skel from template [session_uid=%d subsession_id=%s]: %s", session_uid, subsession_id.data(), ex.what());
+               return add_user_subsession_inner(session_uid, subsession_id, backend, false);
+       }
+}
+
+void add_user_subsession_inner(const int session_uid, const std::string_view subsession_id, const DirBackendAdd &backend, bool force)
+{
+       try {
+               fs::path main_path = get_main_dir_by_user_id(session_uid);
+
+               create_main_subdirectory(session_uid, main_path);
+
+               fs::path subsession_path = main_path / subsession_id;
+
+               if (fs::exists(subsession_path)) {
+                       if (force) {
+                               LOGI("Removing old subsession subsession_id=%s in force mode", subsession_id.data());
+                               fs::remove_all(subsession_path);
+                       } else
+                               throw std::system_error(EEXIST, std::generic_category(),
+                                       "Subsession directory already exists");
+               }
+
                const int system_share_gid = OS::get_gid_from_name(system_share_group);
 
                // Work off a temporary dir and then switch it at once so that it appears atomically
@@ -342,4 +373,3 @@ std::vector<std::string> get_user_list(const int session_uid) try
        LOGE("Exception while enumerating user subsessions [session_uid=%d]: %s", session_uid, ex.what());
        throw std::runtime_error("Couldn't enumerate user subsessions");
 }
-
index a237379d0fc6571e0ccfee563184d49f964e879a..a366f1a107c2e15107a162e0aa66f65287586f66 100644 (file)
@@ -12,6 +12,7 @@ std::filesystem::path get_main_dir_by_user_id(const int uid);
 std::filesystem::path get_last_subsession_path_by_user_id(const int uid);
 bool subsession_exists(const int session_uid, const std::string_view subsession_id);
 void add_user_subsession(const int session_uid, const std::string_view subsession_id, const DirBackendAdd& backend);
+void add_user_subsession_inner(const int session_uid, const std::string_view subsession_id, const DirBackendAdd& backend, bool force);
 void remove_user_subsession(const int session_uid, const std::string_view subsession_id);
 bool switch_user_subsession(const int session_uid, const std::string_view prev_subsession, const std::string_view next_subsession);
 std::vector<std::string> get_user_list(const int session_uid);
@@ -19,3 +20,4 @@ std::vector<std::string> get_user_list(const int session_uid);
 constexpr static std::string_view main_dir_name  = "subsession";
 constexpr static std::string_view system_share_group = "system_share";
 constexpr static std::string_view main_dir_smack = "User::Home";
+
index 07a3ff92c571780a8f634511bdb05ca444f1154e..4d3c84ed66d9721515c143b9ce0f6918043316be 100644 (file)
@@ -22,6 +22,7 @@
 
 #include "main_context.hpp"
 #include "main_restore.hpp"
+#include "main_skel.hpp"
 #include <stdexcept>
 
 std::unique_ptr <sessiond_context> g_sessiond_context;
@@ -34,9 +35,21 @@ bool isRestoreOnly(int argc, char **argv)
        return std::string_view(argv[1]) == "--restore-only";
 }
 
+
+bool isGenSkel(int argc, char **argv)
+{
+       if (argc < 2)
+               return false;
+
+       return std::string_view(argv[1]) == "--regenerate-skel";
+}
+
+
 int main(int argc, char **argv) try {
        if (isRestoreOnly(argc, argv)) {
                restore_all_user_sessions();
+       } else if (isGenSkel(argc, argv)) {
+               regenerate_skel();
        } else {
                g_sessiond_context = std::make_unique <sessiond_context> ();
                restore_all_user_sessions();
index 1761c294023b29e7e4e403143698fad31b28b426..70fdfcfc08b6b87f970e13e68cd53d08dbcfe86c 100644 (file)
@@ -38,7 +38,7 @@
 #include <utility>
 
 #undef LOG_TAG
-#define LOG_TAG "SESSIOND"
+#define LOG_TAG "SESSIOND_RESTORE_ONLY"
 #include <dlog.h>
 
 using namespace std::string_literals;
diff --git a/src/service/src/main_skel.cpp b/src/service/src/main_skel.cpp
new file mode 100644 (file)
index 0000000..be9c50c
--- /dev/null
@@ -0,0 +1,44 @@
+#include <filesystem>
+#include <iostream>
+
+#undef LOG_TAG
+#define LOG_TAG "SESSIOND_REGENERATE_SKEL"
+#include <dlog.h>
+
+#include "fs_helpers.hpp"
+#include "os_ops.hpp"
+#include "dir_backend_fixed_size.hpp"
+
+namespace fs = std::filesystem;
+
+using namespace std;
+
+const auto template_img_size_kb = 10240;
+
+int regenerate_skel() {
+
+       int r = 0;
+
+       try {
+               fs::current_path("/opt/usr/home");
+       } catch (std::exception& ex) {
+               std::cerr << "Unable to chdir to HOME. Can not continue" << std::endl;
+       }
+
+       for (auto const& entry : fs::directory_iterator(".")) {
+               if (!fs::is_directory(entry.status()))
+                       continue;
+
+               const auto &username = entry.path().filename();
+               const int username_uid = OS::get_uid_from_name(username.string());
+
+               try {
+                       add_user_subsession_inner(username_uid, ".template", DirBackendAddFixedSize {template_img_size_kb}, true);
+               } catch (std::exception& ex) {
+                       LOGW("Unable to generate skel template for username %s (uid %d): %s", username, username_uid, ex.what());
+                       continue;
+               }
+       }
+
+       return r;
+}
diff --git a/src/service/src/main_skel.hpp b/src/service/src/main_skel.hpp
new file mode 100644 (file)
index 0000000..750076e
--- /dev/null
@@ -0,0 +1,25 @@
+/* MIT License
+ *
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is furnished
+ * to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE. */
+
+#pragma once
+
+void regenerate_skel();
diff --git a/src/tpkplugin/CMakeLists.txt b/src/tpkplugin/CMakeLists.txt
new file mode 100644 (file)
index 0000000..eae3d9b
--- /dev/null
@@ -0,0 +1,16 @@
+FIND_PACKAGE(PkgConfig)
+INCLUDE(GNUInstallDirs)
+
+pkg_check_modules(deps REQUIRED
+                  dlog
+                  capi-system-info
+                  pkgmgr-info
+                  )
+
+ADD_LIBRARY(libsessiond-update-skelimg SHARED plugin.c)
+TARGET_COMPILE_OPTIONS(libsessiond-update-skelimg PUBLIC -fPIC ${deps_CFLAGS})
+TARGET_LINK_LIBRARIES(libsessiond-update-skelimg PRIVATE ${deps_LDFLAGS})
+
+INSTALL(TARGETS libsessiond-update-skelimg LIBRARY DESTINATION /etc/package-manager/parserlib/)
+INSTALL(FILES sessiond-update-skelimg.info DESTINATION /usr/share/parser-plugins/)
+
diff --git a/src/tpkplugin/plugin.c b/src/tpkplugin/plugin.c
new file mode 100644 (file)
index 0000000..ba7e9cc
--- /dev/null
@@ -0,0 +1,77 @@
+#include <stdio.h>
+#include <dlog.h>
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+#include <pkgmgr-info.h>
+#include <stdlib.h>
+
+#ifndef EXPORT_API
+#define EXPORT_API __attribute__((visibility("default")))
+#endif
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "SESSIOND_GEN_SKEL_IMG"
+
+int gen_skel(void) {
+       // The logic for skel generation is not in plugin to make it possible to call it also manually during image build
+       return system("/usr/sbin/sessiond --regenerate-skel");
+}
+
+EXPORT_API
+int PKGMGR_PARSER_PLUGIN_PRE_INSTALL(const char* packageId)
+{
+       return 0;
+}
+
+EXPORT_API
+int PKGMGR_PARSER_PLUGIN_INSTALL(xmlDocPtr docPtr, const char* packageId)
+{
+       return 0;
+}
+
+EXPORT_API
+int PKGMGR_PARSER_PLUGIN_POST_INSTALL(const char* packageId)
+{
+       SLOGD("Generate sessiond skel image for fast session add - triggered by %s package installation", packageId);
+       return gen_skel();
+}
+
+EXPORT_API
+int PKGMGR_PARSER_PLUGIN_UNINSTALL(xmlDocPtr docPtr, const char* packageId)
+{
+       return 0;
+}
+
+EXPORT_API
+int PKGMGR_PARSER_PLUGIN_PRE_UNINSTALL(const char* packageId)
+{
+       return 0;
+}
+
+EXPORT_API
+int PKGMGR_PARSER_PLUGIN_POST_UNINSTALL(const char* packageId)
+{
+       SLOGD("Generate sessiond skel image for fast session add - triggered by %s package deinstallation", packageId);
+       return gen_skel();
+}
+
+EXPORT_API
+int PKGMGR_PARSER_PLUGIN_PRE_UPGRADE(const char* packageId)
+{
+       return 0;
+}
+
+EXPORT_API
+int PKGMGR_PARSER_PLUGIN_UPGRADE(xmlDocPtr docPtr, const char* packageId)
+{
+       return 0;
+}
+
+EXPORT_API
+int PKGMGR_PARSER_PLUGIN_POST_UPGRADE(const char* packageId)
+{
+       SLOGD("Generate sessiond skel image for fast session add - triggered by %s package upgrade", packageId);
+       return gen_skel();
+}
diff --git a/src/tpkplugin/sessiond-update-skelimg.info b/src/tpkplugin/sessiond-update-skelimg.info
new file mode 100644 (file)
index 0000000..20026c4
--- /dev/null
@@ -0,0 +1 @@
+type="tag";name="sessiond";path="/etc/package-manager/parserlib/libsessiond-update-skelimg.so"