From 07ab6516a40c318e47e56d820563afcb5a4762af Mon Sep 17 00:00:00 2001 From: Youmin Ha Date: Fri, 30 Jan 2015 13:38:00 +0900 Subject: [PATCH] Add TPK backend Native tpk backend implementation: First version. Only simple tizen-manifest.xml format can be parsed for now. Signed-Off-By: Youmin Ha Change-Id: I95037fa6b08639c6dd008d0ffb796cfd375c8060 --- CMakeLists.txt | 1 + packaging/app-installers.spec | 12 ++ src/CMakeLists.txt | 1 + src/tpk/CMakeLists.txt | 31 +++++ src/tpk/exception.h | 52 +++++++++ src/tpk/main.cc | 20 ++++ src/tpk/manifest_parser.cc | 91 +++++++++++++++ src/tpk/manifest_parser.h | 35 ++++++ src/tpk/step/step_parse.cc | 151 +++++++++++++++++++++++++ src/tpk/step/step_parse.h | 31 +++++ src/tpk/step/step_symbolic_link.cc | 116 +++++++++++++++++++ src/tpk/step/step_symbolic_link.h | 21 ++++ src/tpk/task.cc | 106 ++++++++++++++++++ src/tpk/task.h | 30 +++++ src/tpk/xml_nodes.h | 224 +++++++++++++++++++++++++++++++++++++ 15 files changed, 922 insertions(+) create mode 100644 src/tpk/CMakeLists.txt create mode 100644 src/tpk/exception.h create mode 100644 src/tpk/main.cc create mode 100644 src/tpk/manifest_parser.cc create mode 100644 src/tpk/manifest_parser.h create mode 100644 src/tpk/step/step_parse.cc create mode 100644 src/tpk/step/step_parse.h create mode 100644 src/tpk/step/step_symbolic_link.cc create mode 100644 src/tpk/step/step_symbolic_link.h create mode 100644 src/tpk/task.cc create mode 100644 src/tpk/task.h create mode 100644 src/tpk/xml_nodes.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 7d037f4..c2050a2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,6 +28,7 @@ SET(TARGET_LIBNAME_WIDGET_MANIFEST_PARSER "common-installer-widget-manifest-pars SET(TARGET_WGT_BACKEND "wgt-backend") SET(TARGET_XPK_BACKEND "xpk-backend") SET(TARGET_NATIVE_BACKEND "native-backend") +SET(TARGET_TPK_BACKEND "tpk-backend") ADD_DEFINITIONS("-Wall") ADD_DEFINITIONS("-Wextra") diff --git a/packaging/app-installers.spec b/packaging/app-installers.spec index 25f1741..53fc9d1 100644 --- a/packaging/app-installers.spec +++ b/packaging/app-installers.spec @@ -43,6 +43,12 @@ Summary: Backend of XPK files %description -n xpk-backend Backend for standard widget files XPK +%package -n tpk-backend +Summary: Backend of TPK files + +%description -n tpk-backend +Backend for tizen package files + %prep %setup -q @@ -58,6 +64,7 @@ make %{?_smp_mflags} mkdir -p %{buildroot}/etc/package-manager/backend ln -s %{_bindir}/wgt-backend %{buildroot}%{_sysconfdir}/package-manager/backend/wgt ln -s %{_bindir}/xpk-backend %{buildroot}%{_sysconfdir}/package-manager/backend/xpk +ln -s %{_bindir}/tpk-backend %{buildroot}%{_sysconfdir}/package-manager/backend/tpk %post -p /sbin/ldconfig @@ -79,3 +86,8 @@ ln -s %{_bindir}/xpk-backend %{buildroot}%{_sysconfdir}/package-manager/backend/ %files -n xpk-backend %{_sysconfdir}/package-manager/backend/xpk + +%files -n tpk-backend +%{_sysconfdir}/package-manager/backend/tpk +%{_bindir}/tpk-backend + diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2ae5de0..e35d46a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -3,5 +3,6 @@ ADD_SUBDIRECTORY(signature) ADD_SUBDIRECTORY(utils) ADD_SUBDIRECTORY(wgt) ADD_SUBDIRECTORY(widget-manifest-parser) +ADD_SUBDIRECTORY(tpk) #ADD_SUBDIRECTORY(xpk) #ADD_SUBDIRECTORY(native) diff --git a/src/tpk/CMakeLists.txt b/src/tpk/CMakeLists.txt new file mode 100644 index 0000000..c2c4689 --- /dev/null +++ b/src/tpk/CMakeLists.txt @@ -0,0 +1,31 @@ +IF(NOT DEFINED TARGET_TPK_BACKEND) + SET(TARGET_TPK_BACKEND "tpk-backend") +ENDIF(NOT DEFINED TARGET_TPK_BACKEND) + +SET(TARGET_TPK ${TARGET_TPK_BACKEND}) +OPTION(HOSTTEST "Option for the test on the host PC" OFF) +SET(SRCS + main.cc + task.cc + step/step_parse.cc + step/step_symbolic_link.cc + manifest_parser.cc +) +ADD_EXECUTABLE(${TARGET_TPK} ${SRCS}) + +SET(TPK_LDFLAGS -rdynamic) +IF(${HOSTTEST}) + MESSAGE("Host Test mode.") +SET(TPK_CFLAGS ${TPK_CFLAGS} -DHOSTTEST) + SET(MOCK_MODULES test/mock_pkgmgr_installer.c) +SET(SRCS ${SRCS} ${MOCK_MODULES}) + +ELSE(${HOSTTEST}) + SET(TPK_CFLAGS ${TPK_CFLAGS} -I${CMAKE_CURRENT_SOURCE_DIR}/../) + ADD_DEFINITIONS(${TPK_CFLAGS}) +ENDIF(${HOSTTEST}) + +APPLY_PKG_CONFIG(${TARGET_TPK} PUBLIC PKGMGR_DEPS) +TARGET_LINK_LIBRARIES(${TARGET_TPK} PUBLIC ${TARGET_LIBNAME_COMMON}) + +INSTALL(TARGETS ${TARGET_TPK} DESTINATION ${BINDIR}) diff --git a/src/tpk/exception.h b/src/tpk/exception.h new file mode 100644 index 0000000..34c1d80 --- /dev/null +++ b/src/tpk/exception.h @@ -0,0 +1,52 @@ +/* Copyright 2015 Samsung Electronics, license APACHE-2.0, see LICENSE file */ +#ifndef TPK_EXCEPTION_H_ +#define TPK_EXCEPTION_H_ + +#include +#include +#include +#include +#include +#include "utils/logging.h" + +namespace tpk { + +class Exception: public std::exception { +SCOPE_LOG_TAG(UncaughtException) + + public: + Exception() { + this->message_ = nullptr; + StoreStackTrace(); + } + explicit Exception(const char *message) { + this->message_ = strdup(message); + StoreStackTrace(); + } + ~Exception() { + if (message_) free(message_); + } + virtual void StoreStackTrace() { + stack_size_ = backtrace(stack_, kMaxStackSize); + } + virtual void PrintStackTrace() { + if (message_) { + LOG(ERROR) << message_; + } + // Exclude top 1 stack entry (storeStackTrace) + backtrace_symbols_fd(stack_+1, stack_size_-1, STDERR_FILENO); + } + + + protected: + char* message_; + + + private: + static const size_t kMaxStackSize = 100; + size_t stack_size_; + void *stack_[kMaxStackSize]; +}; + +} // namespace tpk +#endif // TPK_EXCEPTION_H_ diff --git a/src/tpk/main.cc b/src/tpk/main.cc new file mode 100644 index 0000000..30e935f --- /dev/null +++ b/src/tpk/main.cc @@ -0,0 +1,20 @@ +/* Copyright 2015 Samsung Electronics, license APACHE-2.0, see LICENSE file */ +#include +#include +#include "tpk/task.h" +#include "tpk/exception.h" + + +int main(const int argc, char* argv[]) { + try { + // Create a task to do + tpk::Task t(argc, argv); + + // Do the task + t.Run(); + } catch(tpk::Exception &e) { + e.PrintStackTrace(); + return -1; + } + return 0; +} diff --git a/src/tpk/manifest_parser.cc b/src/tpk/manifest_parser.cc new file mode 100644 index 0000000..74d8ae3 --- /dev/null +++ b/src/tpk/manifest_parser.cc @@ -0,0 +1,91 @@ +/* Copyright 2015 Samsung Electronics, license APACHE-2.0, see LICENSE file */ + +#include "tpk/manifest_parser.h" +#include +#include +#include +#include "tpk/xml_nodes.h" + +namespace tpk { + + +template +void ManifestParser::CheckAndSetNode(xmlTextReaderPtr reader, + const char* name, + const T& xmlNode) { + T& node = const_cast(xmlNode); + if (xmlStrEqual(reinterpret_cast(name), + xmlTextReaderConstName(reader)) && + xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT) { + node.Init(reader); + } +} + + +template +void ManifestParser::CheckAndAppendNode(xmlTextReaderPtr reader, + const char* name, + const std::vector &v) { + if (xmlStrEqual(reinterpret_cast(name), + xmlTextReaderConstName(reader)) && + xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT) { + T *p = new T(); + p->Init(reader); + std::vector& _v = const_cast&>(v); + _v.push_back(p); + } +} + + +void ManifestParser::ProcessNode(xmlTextReaderPtr reader) { + // For each node, find required node names and get data + CheckAndSetNode(reader, "manifest", manifest); + CheckAndSetNode(reader, "ui-application", manifest.ui_application); + CheckAndSetNode(reader, "icon", manifest.ui_application.icon); + CheckAndSetNode(reader, "label", manifest.ui_application.label); + CheckAndSetNode(reader, "privileges", manifest.privileges); + CheckAndAppendNode(reader, "privilege", manifest.privileges.v_privilege); +} + + +void ManifestParser::StreamFile(const char* filePath) { + xmlTextReaderPtr reader; + int ret; + + // TODO(youmin.ha@samsung.com): add DTD validation + reader = xmlReaderForFile(filePath, NULL, 0); + if (reader == nullptr) { + throw FileOpenFailureException(); + } else { + ret = xmlTextReaderRead(reader); + while (ret == 1) { + ProcessNode(reader); + ret = xmlTextReaderRead(reader); + } + xmlFreeTextReader(reader); + if (ret != 0) { + throw ParseFailureException(); + } + } +} + + +/* constructor + */ +ManifestParser::ManifestParser(const char* filePath) { + LIBXML_TEST_VERSION + + StreamFile(filePath); + + xmlCleanupParser(); + xmlMemoryDump(); +} + + +/* destructor + */ +ManifestParser::~ManifestParser() { +} + + +} // namespace tpk diff --git a/src/tpk/manifest_parser.h b/src/tpk/manifest_parser.h new file mode 100644 index 0000000..c982340 --- /dev/null +++ b/src/tpk/manifest_parser.h @@ -0,0 +1,35 @@ +/* Copyright 2015 Samsung Electronics, license APACHE-2.0, see LICENSE file */ +#ifndef TPK_MANIFEST_PARSER_H_ +#define TPK_MANIFEST_PARSER_H_ + +#include +#include +#include "tpk/xml_nodes.h" +#include "tpk/exception.h" + + +namespace tpk { + +/* Internal exceptions */ +class FileOpenFailureException : public Exception {}; +class ParseFailureException : public Exception {}; + + +class ManifestParser { + public: + explicit ManifestParser(const char *manifestFilePath); + ~ManifestParser(); + XmlNodeManifest manifest; + + + private: + template void CheckAndSetNode( + xmlTextReaderPtr reader, const char* name, const T &xmlNode); + template void CheckAndAppendNode( + xmlTextReaderPtr reader, const char* name, const std::vector &v); + void ProcessNode(xmlTextReaderPtr reader); + void StreamFile(const char* filePath); +}; + +} // namespace tpk +#endif // TPK_MANIFEST_PARSER_H_ diff --git a/src/tpk/step/step_parse.cc b/src/tpk/step/step_parse.cc new file mode 100644 index 0000000..b47cef1 --- /dev/null +++ b/src/tpk/step/step_parse.cc @@ -0,0 +1,151 @@ +/* Copyright 2015 Samsung Electronics, license APACHE-2.0, see LICENSE file */ +#include "tpk/step/step_parse.h" +#include +#include +#include +#include "common/context_installer.h" +#include "common/step/step.h" +#include "tpk/manifest_parser.h" +#include "tpk/xml_nodes.h" +#include "utils/logging.h" + +using std::vector; + +namespace tpk { +namespace step { + +namespace { + const char kManifestFileName[] = "tizen-manifest.xml"; +} // namespace + +SCOPE_LOG_TAG(StepParse) + +/* short namespace/class name */ +typedef common_installer::Step::Status Status; +using boost::filesystem::path; + + +/* Internal exceptions */ +class FileNotFoundException : public std::exception {}; + + +/* process() + * Parse tizen-manifest.xml and get the data from it + * Store the data into the context_ + */ +Status StepParse::process() { + try { + boost::filesystem::path mPath = GetManifestFilePath( + context_->unpacked_dir_path()); + ManifestParser m(mPath.c_str()); + SetContextByManifestParser(m); + } catch (FileNotFoundException &e) { + return Status::ERROR; + } catch (FileOpenFailureException &e) { + return Status::ERROR; + } + return Status::OK; +} + + +/* in parse() : Get manifest file path from the package unzipped directory + */ +boost::filesystem::path StepParse::GetManifestFilePath( + const boost::filesystem::path& dir) { + path mPath(dir); + mPath /= kManifestFileName; + + LOG(INFO) << "manifest file path: " << mPath; + if (!boost::filesystem::exists(mPath)) { + LOG(ERROR) << kManifestFileName << " not found from the package"; + throw FileNotFoundException(); + } + return mPath; // object copy +} + + +/* Read manifest xml, and set up context_ object + */ +void StepParse::SetContextByManifestParser(const ManifestParser &m) { + const XmlNodeManifest& manifest = m.manifest; + LOG(DEBUG) << "Parse manifest xml values:"; + LOG(DEBUG) << "xmlns(" << manifest.xmlns << ") api_version(" << + manifest.api_version << ") package(" << manifest.package << + ") version(" << manifest.version << ")"; + + // set context_ + context_->config_data()->set_application_name( + std::string(reinterpret_cast(manifest.ui_application.label.data))); + context_->config_data()->set_required_version( + std::string(reinterpret_cast(manifest.api_version))); + + context_->set_pkgid(std::string(reinterpret_cast(manifest.package))); + + // set context_->manifest_data() + SetPkgInfoManifest(context_->manifest_data(), manifest); +} + +void StepParse::SetPkgInfoManifest(manifest_x* m, + const XmlNodeManifest &manifest) { + // Common values + m->label = static_cast + (calloc(1, sizeof(label_x))); + m->description = static_cast + (calloc(1, sizeof(description_x))); + m->privileges = static_cast + (calloc(1, sizeof(privileges_x))); + m->privileges->next = nullptr; + m->privileges->privilege = nullptr; + + // Basic values + m->package = strdup(reinterpret_cast(manifest.package)); + m->type = strdup("tpk"); + m->version = strdup(reinterpret_cast(manifest.version)); + m->label->name = strdup( + reinterpret_cast(manifest.ui_application.label.name)); + // TODO(youmin.ha@samsung.com): get name from XML if exists + m->description->name = nullptr; + m->mainapp_id = strdup( + reinterpret_cast(manifest.ui_application.appid)); + + // Privileges + vector vp = + const_cast(manifest).privileges.getPrivilegeVector(); + vector::iterator it; + for (it = vp.begin(); it != vp.end(); it++) { + privilege_x *p = + static_cast(calloc(1, sizeof(privilege_x))); + // privilege data text + p->text = strdup(reinterpret_cast((*it)->data)); + LISTADD(m->privileges->privilege, p); + LOG(INFO) << "add privilege: " << p->text; + } + + // Other app data (null initialization) + m->serviceapplication = nullptr; // ignore service application + m->uiapplication = static_cast + (calloc (1, sizeof(uiapplication_x))); + m->uiapplication->icon = static_cast + (calloc(1, sizeof(icon_x))); + m->uiapplication->label = static_cast + (calloc(1, sizeof(label_x))); + m->description = static_cast + (calloc(1, sizeof(description_x))); + m->uiapplication->appcontrol = nullptr; + + m->uiapplication->appid = strdup( + reinterpret_cast(manifest.ui_application.appid)); + m->uiapplication->exec = strdup( + reinterpret_cast(manifest.ui_application.exec)); + m->uiapplication->type = strdup( + reinterpret_cast(manifest.ui_application.type)); + + m->uiapplication->label->name = strdup( + reinterpret_cast(manifest.ui_application.label.data)); + m->uiapplication->icon->name = strdup( + reinterpret_cast(manifest.ui_application.icon.data)); + m->uiapplication->next = nullptr; +} + +} // namespace step +} // namespace tpk diff --git a/src/tpk/step/step_parse.h b/src/tpk/step/step_parse.h new file mode 100644 index 0000000..0bb9d56 --- /dev/null +++ b/src/tpk/step/step_parse.h @@ -0,0 +1,31 @@ +/* Copyright 2015 Samsung Electronics, license APACHE-2.0, see LICENSE file */ +#ifndef TPK_STEP_STEP_PARSE_H_ +#define TPK_STEP_STEP_PARSE_H_ + +#include +#include "common/step/step.h" +#include "tpk/manifest_parser.h" + +namespace tpk { +namespace step { + +class StepParse : public common_installer::Step { + public: + using Step::Step; + + Status process() override; + Status clean() override { return Status::OK; }; + Status undo() override { return Status::OK; }; + + + private: + boost::filesystem::path + GetManifestFilePath(const boost::filesystem::path& dir); + void SetContextByManifestParser(const ManifestParser &m); + void SetPkgInfoManifest(manifest_x* m, const XmlNodeManifest &manifest); +}; + +} // namespace step +} // namespace tpk + +#endif // TPK_STEP_STEP_PARSE_H_ diff --git a/src/tpk/step/step_symbolic_link.cc b/src/tpk/step/step_symbolic_link.cc new file mode 100644 index 0000000..8e10f01 --- /dev/null +++ b/src/tpk/step/step_symbolic_link.cc @@ -0,0 +1,116 @@ +/* Copyright 2015 Samsung Electronics, license APACHE-2.0, see LICENSE file */ +#include "tpk/step/step_symbolic_link.h" +#include +#include +#include "common/step/step.h" +#include "common/app_installer.h" +#include "common/context_installer.h" +#include "common/utils.h" +#include "utils/logging.h" + + +namespace tpk { +namespace step { + +namespace fs = boost::filesystem; +using common_installer::ContextInstaller; +typedef common_installer::Step::Status Status; + +SCOPE_LOG_TAG(SymbolicLink) + +namespace { + +template +bool CreateSymLink(T *app, ContextInstaller* context) { + boost::system::error_code error; + + for (; app != nullptr; app=app->next) { + fs::path bindir = fs::path(context->pkg_path()) / fs::path(app->appid) / + fs::path("bin"); + LOG(INFO) << "Creating dir: " << bindir; + if (!utils::CreateDir(bindir)) { + LOG(ERROR) << "Directory creation failure"; + return false; + } + + // Make a symlink with the name of appid, pointing exec file + fs::path symlink_path = bindir / fs::path(app->appid); + LOG(INFO) << "Creating symlink pointing " << symlink_path << " to " << + app->exec; + fs::create_symlink(fs::path(app->exec), symlink_path, error); + if (error) { + LOG(ERROR) << "Symlink creation failure"; + return false; + } + + // Give a execution permission to the original executable + fs::path exec_path = bindir / fs::path(app->exec); + LOG(INFO) << "Giving exec permission to " << exec_path; + fs::permissions(exec_path, fs::owner_all | + fs::group_read | fs::group_exe | + fs::others_read | fs::others_exe, error); + if (error) { + LOG(ERROR) << "Permission change failure"; + return false; + } + } + return true; +} + + +template +bool RemoveSymLink(T *app, ContextInstaller* context) { + /* NOTE: Unlike WRT app, tpk apps have bin/ directory by default. + * So we don't remove the bin/ directory itself. + */ + for (; app != nullptr; app=app->next) { + fs::path exec_path = fs::path(context->pkg_path()) / + fs::path(app->appid) / fs::path("bin"); + fs::remove_all(exec_path / fs::path(app->appid)); + } + return true; +} + +} // namespace + + + +Status StepSymbolicLink::process() { + // Get manifest_x + manifest_x *m = context_->manifest_data(); + if (!m) { + LOG(ERROR) << "manifest_x is null"; + return Status::ERROR; + } + + // get ui-app and service-app + uiapplication_x *uiapp = m->uiapplication; + serviceapplication_x *svcapp = m->serviceapplication; + if (!(uiapp || svcapp)) { + LOG(ERROR) << "Neither ui-application nor service-application exists"; + return Status::ERROR; + } + if (!CreateSymLink(uiapp, context_)) return Status::ERROR; + if (!CreateSymLink(svcapp, context_)) return Status::ERROR; + + return Status::OK; +} + + +Status StepSymbolicLink::clean() { + return Status::OK; +} + + +Status StepSymbolicLink::undo() { + manifest_x* m = context_->manifest_data(); + uiapplication_x *uiapp = m->uiapplication; + serviceapplication_x *svcapp = m->serviceapplication; + if (!RemoveSymLink(uiapp, context_)) return Status::ERROR; + if (!RemoveSymLink(svcapp, context_)) return Status::ERROR; + + return Status::OK; +} + +} // namespace step +} // namespace tpk diff --git a/src/tpk/step/step_symbolic_link.h b/src/tpk/step/step_symbolic_link.h new file mode 100644 index 0000000..cb16c55 --- /dev/null +++ b/src/tpk/step/step_symbolic_link.h @@ -0,0 +1,21 @@ +/* Copyright 2015 Samsung Electronics, license APACHE-2.0, see LICENSE file */ +#ifndef TPK_STEP_STEP_SYMBOLIC_LINK_H_ +#define TPK_STEP_STEP_SYMBOLIC_LINK_H_ + +#include "common/app_installer.h" + +namespace tpk { +namespace step { + +class StepSymbolicLink : public common_installer::Step { + public: + using Step::Step; + Status process() override; + Status clean() override; + Status undo() override; +}; + +} // namespace step +} // namespace tpk + +#endif // TPK_STEP_STEP_SYMBOLIC_LINK_H_ diff --git a/src/tpk/task.cc b/src/tpk/task.cc new file mode 100644 index 0000000..bedd1de --- /dev/null +++ b/src/tpk/task.cc @@ -0,0 +1,106 @@ +/* Copyright 2015 Samsung Electronics, license APACHE-2.0, see LICENSE file */ +#include "tpk/task.h" +#ifdef HOSTTEST +#include "test/mock_pkgmgr_installer.h" +#else +#include +#include "common/app_installer.h" +#include "common/step/step_copy.h" +#include "common/step/step_generate_xml.h" +#include "common/step/step_parse.h" +#include "common/step/step_record.h" +#include "common/step/step_remove.h" +#include "common/step/step_revoke_security.h" +#include "common/step/step_security.h" +#include "common/step/step_signal.h" +#include "common/step/step_signature.h" +#include "common/step/step_unregister.h" +#include "common/step/step_unzip.h" +#include "tpk/step/step_parse.h" +#include "tpk/step/step_symbolic_link.h" +#include "tpk/exception.h" +#endif + + +namespace ci = common_installer; + +namespace { + const char kPkgType[] = "tpk"; +} // namespace + + +namespace tpk { + +/* Constructor + */ +Task::Task(const int argc, char** argv) { + pi_ = pkgmgr_installer_new(); + if (!pi_) { + throw Exception("Not enough memory"); + } + if (!!pkgmgr_installer_receive_request(pi_, argc, argv)) { + throw Exception("Invalid Argument"); + } + request_ = pkgmgr_installer_get_request_type(pi_); +} + + +/* Destructor + */ +::tpk::Task::~Task() { + if (pi_) { + pkgmgr_installer_free(pi_); + pi_ = NULL; + } +} + + +void Task::Run(void) { + switch (request_) { + case PKGMGR_REQ_INSTALL: + Install(); + break; + case PKGMGR_REQ_UNINSTALL: + Uninstall(); + break; + case PKGMGR_REQ_REINSTALL: + Reinstall(); + break; + default: + throw Exception("Unsupported request"); + } +} + +void Task::Install(void) { + ci::AppInstaller ai(pi_, kPkgType); + + ai.AddStep(); + ai.AddStep(); + ai.AddStep(); + ai.AddStep(); + ai.AddStep(); + ai.AddStep(); + ai.AddStep(); + ai.AddStep(); + ai.AddStep(); + + ai.Run(); +} + +void Task::Uninstall(void) { + ci::AppInstaller ai(pi_, kPkgType); + + ai.AddStep(); + ai.AddStep(); + ai.AddStep(); + ai.AddStep(); + ai.AddStep(); + + ai.Run(); +} + +void Task::Reinstall(void) { +} + +} // namespace tpk + diff --git a/src/tpk/task.h b/src/tpk/task.h new file mode 100644 index 0000000..2730716 --- /dev/null +++ b/src/tpk/task.h @@ -0,0 +1,30 @@ +/* Copyright 2015 Samsung Electronics, license APACHE-2.0, see LICENSE file */ +#ifndef TPK_TASK_H_ +#define TPK_TASK_H_ + +#ifdef HOSTTEST +#include "test/mock_pkgmgr_installer.h" +#else +#include +#endif + +namespace tpk { + +class Task { + public: + Task(int argc, char** argv); + ~Task(); + void Run(); + + + private: + void Install(); + void Uninstall(); + void Reinstall(); + + pkgmgr_installer* pi_; + int request_; +}; // class Task + +} // namespace tpk +#endif // TPK_TASK_H_ diff --git a/src/tpk/xml_nodes.h b/src/tpk/xml_nodes.h new file mode 100644 index 0000000..3a041aa --- /dev/null +++ b/src/tpk/xml_nodes.h @@ -0,0 +1,224 @@ +/* Copyright 2015 Samsung Electronics, license APACHE-2.0, see LICENSE file */ +#ifndef TPK_XML_NODES_H_ +#define TPK_XML_NODES_H_ + +#include +#include +#include +#include +#include "tpk/exception.h" +#include "utils/logging.h" + +using std::vector; + +namespace tpk { + +class InvalidNodeTypeException: public tpk::Exception {}; +class InvalidNodeNameException: public tpk::Exception {}; + + +class XmlNode { + SCOPE_LOG_TAG(XmlNode) + + public: + int depth; + int node_type; + xmlChar* name; // The name of node + xmlChar* data; // Internal text of the node + + XmlNode() : name(NULL), data(NULL), depth(-1), + node_type(XML_READER_TYPE_NONE) { + } + + virtual ~XmlNode() { + Free(); + } + + virtual void ReadBasicValues(xmlTextReaderPtr reader) { + depth = xmlTextReaderDepth(reader); + node_type = xmlTextReaderNodeType(reader); + data = xmlTextReaderReadString(reader); + } + + virtual void Init(xmlTextReaderPtr reader) { + name = xmlTextReaderName(reader); + if (!xmlStrEqual(name, node_name_)) { + LOG(ERROR) << "Invalid node! actual name=" << name + << ", expected name=" << node_name_ << std::endl; + xmlFree(name); + throw InvalidNodeNameException(); + } + ReadBasicValues(reader); + } + + virtual void Free() { + xmlFree(name); + xmlFree(data); + } + + virtual void SetExpectedNodeName(const char* nodeName) { + node_name_ = const_cast( + reinterpret_cast(nodeName)); + } + + + private: + xmlChar* node_name_; +}; + + +class XmlNodeIcon : public XmlNode { + public: + XmlNodeIcon() { + XmlNode::SetExpectedNodeName("icon"); + } + + virtual void Init(xmlTextReaderPtr reader) { + XmlNode::Init(reader); + } +}; + + +class XmlNodeLabel : public XmlNode { + public: + XmlNodeLabel() { + XmlNode::SetExpectedNodeName("label"); + } + virtual void Init(xmlTextReaderPtr reader) { + XmlNode::Init(reader); + } +}; + +class XmlNodeProfile : public XmlNode { + public: + XmlNodeProfile() { + XmlNode::SetExpectedNodeName("profile"); + } + + virtual void Init(xmlTextReaderPtr reader) { + XmlNode::Init(reader); + } +}; + +class XmlNodeUiApplication : public XmlNode { + public: + xmlChar *appid; + xmlChar *exec; + xmlChar *type; + xmlChar *multiple; + xmlChar *taskmanage; + xmlChar *nodisplay; + + XmlNodeIcon icon; + XmlNodeLabel label; + + XmlNodeUiApplication() : appid(NULL), exec(NULL), type(NULL), + multiple(NULL), taskmanage(NULL), nodisplay(NULL) { + XmlNode::SetExpectedNodeName("ui-application"); + } + + void Init(xmlTextReaderPtr reader) { + XmlNode::Init(reader); + + appid = xmlTextReaderGetAttribute(reader, + const_cast(reinterpret_cast("appid"))); + exec = xmlTextReaderGetAttribute(reader, + const_cast(reinterpret_cast("exec"))); + type = xmlTextReaderGetAttribute(reader, + const_cast(reinterpret_cast("type"))); + multiple = xmlTextReaderGetAttribute(reader, + const_cast(reinterpret_cast("multiple"))); + taskmanage = xmlTextReaderGetAttribute(reader, + const_cast(reinterpret_cast("taskmanage"))); + nodisplay = xmlTextReaderGetAttribute(reader, + const_cast(reinterpret_cast("nodisplay"))); + } + virtual ~XmlNodeUiApplication() { + xmlFree(appid); + xmlFree(exec); + xmlFree(type); + xmlFree(multiple); + xmlFree(taskmanage); + xmlFree(nodisplay); + } +}; + + +class XmlNodePrivilege : public XmlNode { + public: + XmlNodePrivilege() { + XmlNode::SetExpectedNodeName("privilege"); + } + virtual void Init(xmlTextReaderPtr reader) { + XmlNode::Init(reader); + } +}; + +class XmlNodePrivileges: public XmlNode { + public: + vector v_privilege; + + XmlNodePrivileges() { + XmlNode::SetExpectedNodeName("privileges"); + } + ~XmlNodePrivileges() { + // clear v_privilege + vector::iterator it; + for (auto& ptr : v_privilege) { + delete ptr; + } + } + virtual void Init(xmlTextReaderPtr reader) { + XmlNode::Init(reader); + } + virtual void addPrivilege(xmlTextReaderPtr reader) { + if (xmlStrEqual(xmlTextReaderConstName(reader), + reinterpret_cast("privilege"))) { + XmlNodePrivilege *p = new XmlNodePrivilege(); + p->Init(reader); + v_privilege.push_back(p); + } + } + vector getPrivilegeVector(void) { + return v_privilege; + } +}; + +class XmlNodeManifest : public XmlNode { + public: + xmlChar *xmlns; + xmlChar *api_version; + xmlChar *package; + xmlChar *version; + XmlNodeProfile profile; + XmlNodeUiApplication ui_application; + XmlNodePrivileges privileges; + + XmlNodeManifest() : xmlns(NULL), api_version(NULL), package(NULL), + version(NULL) { + XmlNode::SetExpectedNodeName("manifest"); + } + + void Init(xmlTextReaderPtr reader) { + XmlNode::Init(reader); + + xmlns = xmlTextReaderGetAttribute(reader, + reinterpret_cast("xmlns")); + api_version = xmlTextReaderGetAttribute(reader, + reinterpret_cast("api-version")); + package = xmlTextReaderGetAttribute(reader, + reinterpret_cast("package")); + version = xmlTextReaderGetAttribute(reader, + reinterpret_cast("version")); + } + + ~XmlNodeManifest() { + xmlFree(xmlns); + xmlFree(api_version); + xmlFree(package); + xmlFree(version); + } +}; + +} // namespace tpk +#endif // TPK_XML_NODES_H_ -- 2.7.4