Name: app-installers
Summary: Application installers
Version: 1.0
-Release: 1
+Release: 2
Group: Application Framework/Package Management
License: Apache-2.0
Source0: %{name}-%{version}.tar.gz
pkgmgr_parser_parse_manifest_for_installation(
xml_path.c_str(), const_cast<char* const*>(kAppinstTags));
if (ret) {
- LOG(ERROR) << "Failed to unregister package: " << xml_path;
+ LOG(ERROR) << "Failed to register package: " << xml_path << ", "
+ "error code=" << ret;
return false;
}
if (!!cert_info.author_certificate.get()) {
if (!RegisterAuthorCertificate(cert_info, pkgid, uid)) {
+ LOG(ERROR) << "Failed to register author certificate";
return false;
}
}
"%s", BAD_CAST icon.c_str());
}
} else {
- //Default icon setting is role of the platform
+ // Default icon setting is role of the platform
LOG(DEBUG) << "Icon was not found in package";
}
task.cc
step/step_parse.cc
step/step_create_symbolic_link.cc
+ step/step_copy_manifest_xml.cc
../xml_parser/xml_parser.cc
)
ADD_EXECUTABLE(${TARGET_TPK} ${SRCS})
ADD_DEFINITIONS(${TPK_CFLAGS})
ENDIF(${HOSTTEST})
-APPLY_PKG_CONFIG(${TARGET_TPK} PUBLIC PKGMGR_DEPS)
-TARGET_LINK_LIBRARIES(${TARGET_TPK} PUBLIC ${TARGET_LIBNAME_COMMON})
+APPLY_PKG_CONFIG(${TARGET_TPK} PUBLIC PKGMGR_DEPS Boost)
+TARGET_LINK_LIBRARIES(${TARGET_TPK} PUBLIC ${TARGET_LIBNAME_COMMON} -lboost_regex)
INSTALL(TARGETS ${TARGET_TPK} DESTINATION ${BINDIR})
--- /dev/null
+/* Copyright 2015 Samsung Electronics, license APACHE-2.0, see LICENSE file */
+
+#include "tpk/step/step_copy_manifest_xml.h"
+
+#include <sys/types.h>
+#include <pkgmgr-info.h>
+#include <boost/filesystem.hpp>
+#include <boost/system/error_code.hpp>
+#include <boost/tr1/regex.hpp>
+
+#include <fstream>
+#include <iostream>
+#include <memory>
+#include <regex>
+#include <string>
+
+#include "common/utils/file_util.h"
+#include "common/utils/logging.h"
+
+namespace bf = boost::filesystem;
+using common_installer::Step;
+
+namespace {
+ const char* source_xml_filename = "tizen-manifest.xml";
+
+ bf::path _getOldDestXmlPath(const bf::path& dest_xml_path) {
+ bf::path old_dest_xml_path = dest_xml_path;
+ old_dest_xml_path += ".old";
+ return old_dest_xml_path;
+ }
+
+ bool _setValidSourceXmlPath(bf::path* source_xml_path_,
+ const common_installer::ContextInstaller* context_) {
+ bf::path& source_xml_path = *source_xml_path_;
+ source_xml_path = context_->pkg_path.get() / source_xml_filename;
+ if (!bf::exists(source_xml_path)) {
+ // Check single app path
+ source_xml_path = context_->pkg_path.get() /
+ context_->manifest_data.get()->mainapp_id / source_xml_filename;
+ if (!bf::exists(source_xml_path)) {
+ LOG(ERROR) << "Source xml file not found: " << source_xml_path;
+ return false;
+ }
+ }
+ return true;
+ }
+
+ void _setDestXmlPath(std::shared_ptr<bf::path>* dest_xml_path_, uid_t uid,
+ const std::string& pkgid) {
+ *dest_xml_path_ = std::make_shared<bf::path>(getUserManifestPath(uid));
+ **dest_xml_path_ /= bf::path(pkgid);
+ **dest_xml_path_ += ".xml";
+ }
+
+
+ bool _trimCopiedXmlContent(const bf::path& xml_path,
+ const common_installer::ContextInstaller* context_) {
+ bf::path pkg_path = context_->pkg_path.get();
+
+ std::ifstream infile(xml_path.string());
+ std::ofstream outfile(xml_path.string() + ".out");
+ std::string line;
+ std::string result;
+
+ boost::regex appid_pattern(".*<(ui|service)-application\\s+(\\S+\\s+)*"
+ "appid=\"(.+?)\".*>", boost::regex_constants::ECMAScript);
+ boost::regex appid_exec_replace_pattern("exec=\"(.+?)\"",
+ boost::regex_constants::ECMAScript);
+ boost::regex manifest_pattern(".*<manifest\\s+.*(type=\"\"){0,1}.*>",
+ boost::regex_constants::ECMAScript);
+ boost::regex manifest_type_replace_pattern("<manifest ",
+ boost::regex_constants::ECMAScript);
+
+ boost::smatch m;
+
+ while (!infile.eof()) {
+ getline(infile, line);
+ result = line; // Copy line by default
+
+ try {
+ // Find (ui|service)-application element, and get appid
+ if (boost::regex_search(line, m, appid_pattern)) {
+ std::string appid = m[3].str();
+ pkg_path /= bf::path(appid);
+ pkg_path /= bf::path("bin");
+
+ result = boost::regex_replace(line, appid_exec_replace_pattern,
+ std::string("exec=\"") + pkg_path.string() +
+ std::string("/$1\""));
+
+ } else if (boost::regex_search(line, m, manifest_pattern)) {
+ // Check if the 'type=' attribute is not given
+ LOG(DEBUG) << "found manifest";
+ if (m[1].str().size() == 0) {
+ // Add an attribute
+ result = boost::regex_replace(line,
+ manifest_type_replace_pattern,
+ std::string("<manifest type=\"tpk\" "));
+ LOG(DEBUG) << "Found no type attribute. changed:" << result;
+ }
+ }
+ } catch (boost::regex_error& e) {
+ LOG(ERROR) << "Regex error:" << e.what() << ":" << e.code();
+ return false;
+ }
+
+ // Write file
+ outfile << result << std::endl;
+ }
+
+ // Change old file to new file
+ bf::remove(xml_path);
+ bf::rename(xml_path.string() + ".out", xml_path);
+
+ return true;
+ }
+} // namespace
+
+
+namespace tpk {
+namespace step {
+
+SCOPE_LOG_TAG(TPKCopyManifestXml)
+
+typedef common_installer::Step::Status Status;
+
+Status StepCopyManifestXml::process() {
+ // Set source xml path
+ bf::path source_xml_path;
+ if (!_setValidSourceXmlPath(&source_xml_path, context_))
+ return Status::ERROR;
+
+ // Create destination xml path
+ _setDestXmlPath(&(this->dest_xml_path_), context_->uid.get(),
+ context_->pkgid.get());
+ bf::path& dest_xml_path = *dest_xml_path_;
+ if (!common_installer::CreateDir(dest_xml_path.parent_path())) {
+ LOG(ERROR) << "Destionation directory creation failure" << dest_xml_path;
+ return Status::ERROR;
+ }
+
+ // Backup old xml file if exists
+ if (bf::exists(dest_xml_path)) {
+ common_installer::MoveFile(dest_xml_path,
+ _getOldDestXmlPath(dest_xml_path));
+ }
+
+ // Copy xml file
+ boost::system::error_code boost_err;
+ bf::copy_file(source_xml_path, dest_xml_path, boost_err);
+ if (boost_err) {
+ LOG(ERROR) << "Manifest xml copy failure, from " << source_xml_path <<
+ " to " << dest_xml_path << ", error_code=" << boost_err;
+ return Status::ERROR;
+ }
+
+ // Trim xml file content
+ if (!_trimCopiedXmlContent(dest_xml_path, context_)) return Status::ERROR;
+
+ // Set dest_xml_path (to be used by StepRegisterApplication)
+ context_->xml_path.set(dest_xml_path.string());
+
+ return Status::OK;
+}
+
+
+Status StepCopyManifestXml::clean() {
+ // Delete old xml file if exists
+ bf::path old_dest_xml_path = _getOldDestXmlPath(*dest_xml_path_);
+ if (bf::exists(old_dest_xml_path)) bf::remove(old_dest_xml_path);
+
+ return Status::OK;
+}
+
+
+Status StepCopyManifestXml::undo() {
+ // Remove xml file
+ if (bf::exists(*dest_xml_path_)) bf::remove(*dest_xml_path_);
+
+ // Revert old xml file if exists
+ bf::path old_dest_xml_path = _getOldDestXmlPath(*dest_xml_path_);
+ if (bf::exists(old_dest_xml_path)) {
+ common_installer::MoveFile(old_dest_xml_path, *dest_xml_path_);
+ }
+
+ return Status::OK;
+}
+
+} // namespace step
+} // namespace tpk
--- /dev/null
+#ifndef TPK_STEP_STEP_COPY_MANIFEST_XML_H_
+#define TPK_STEP_STEP_COPY_MANIFEST_XML_H_
+
+/* Copyright 2015 Samsung Electronics, license APACHE-2.0, see LICENSE file */
+// Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a apache 2.0 license that can be
+// found in the LICENSE file.
+#include "common/step/step.h"
+#include <boost/filesystem.hpp>
+
+#include <memory>
+
+namespace tpk {
+namespace step {
+
+/** Copy tizen-manifest.xml into the application directory
+ *
+ */
+class StepCopyManifestXml : public common_installer::Step {
+ public:
+ using Step::Step;
+ Status precheck() override { return Status::OK; }
+ Status process() override;
+ Status clean() override;
+ Status undo() override;
+
+ private:
+ std::shared_ptr<boost::filesystem::path> dest_xml_path_;
+};
+
+} // namespace step
+} // namespace tpk
+
+#endif // TPK_STEP_STEP_COPY_MANIFEST_XML_H_
/* Copyright 2015 Samsung Electronics, license APACHE-2.0, see LICENSE file */
#include "tpk/step/step_create_symbolic_link.h"
#include <boost/filesystem.hpp>
+#include <boost/system/error_code.hpp>
+#include <pkgmgr-info.h>
+
#include <iostream>
+
#include "common/step/step.h"
#include "common/app_installer.h"
#include "common/context_installer.h"
template <typename T>
bool CreateSymLink(T *app, ContextInstaller* context) {
- boost::system::error_code error;
+ boost::system::error_code boost_error;
for (; app != nullptr; app=app->next) {
fs::path bindir = context->pkg_path.get() / fs::path(app->appid) /
fs::path("bin");
LOG(INFO) << "Creating dir: " << bindir;
if (!common_installer::CreateDir(bindir)) {
- LOG(ERROR) << "Directory creation failure";
+ LOG(ERROR) << "Directory creation failure: " << bindir;
return false;
}
+ // Exec path
// Make a symlink with the name of appid, pointing exec file
fs::path symlink_path = bindir / fs::path(app->appid);
LOG(INFO) << "Creating symlink " << symlink_path << " pointing " <<
app->exec;
- fs::create_symlink(fs::path(app->exec), symlink_path, error);
- if (error) {
- LOG(ERROR) << "Symlink creation failure";
+ fs::create_symlink(fs::path(app->exec), symlink_path, boost_error);
+ if (boost_error) {
+ LOG(ERROR) << "Symlink creation failure: " << symlink_path;
return false;
}
- // Give a execution permission to the original executable
+ // Give an 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) {
+ fs::others_read | fs::others_exe, boost_error);
+ if (boost_error) {
LOG(ERROR) << "Permission change failure";
return false;
}
+
+ // Icon path
+ // Make an Icon symlink, if the icon exists
+ if (app->icon && app->icon->name) {
+ // Check if the icon file actually exists
+ fs::path src_icon_path = fs::path(context->pkg_path.get())
+ / fs::path(app->appid)
+ / fs::path(app->icon->name);
+ if (fs::exists(src_icon_path)) {
+ // copy icon to the destination dir
+ fs::path dest_icon_dir = fs::path(getIconPath(context->uid.get()));
+ fs::path dest_icon_filename = fs::path(app->appid) +=
+ fs::path(app->icon->name).extension();
+ if (!common_installer::CreateDir(dest_icon_dir)) {
+ LOG(ERROR) << "Directory creation failure: " << dest_icon_dir;
+ return false;
+ }
+ fs::path dest_icon_path = dest_icon_dir;
+ dest_icon_path /= dest_icon_filename;
+ LOG(INFO) << "Creating symlink " << dest_icon_path << " pointing " <<
+ src_icon_path;
+ fs::create_symlink(src_icon_path, dest_icon_path, boost_error);
+ if (boost_error) {
+ LOG(ERROR) << "Symlink creation failure: " << dest_icon_path;
+ return false;
+ }
+ } else {
+ LOG(WARNING) << "No icon file found in the package: " << src_icon_path;
+ }
+ }
}
return true;
}
template <typename T>
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.
+ * So we don't remove the bin/ directory.
*/
for (; app != nullptr; app=app->next) {
fs::path exec_path = fs::path(context->pkg_path.get()) /
} // namespace
-
Status StepCreateSymbolicLink::process() {
// Get manifest_x
manifest_x *m = context_->manifest_data.get();
#include "common/step/step_unzip.h"
#include "common/step/step_update_app.h"
#include "common/step/step_update_security.h"
-#include "tpk/step/step_parse.h"
+#include "tpk/step/step_copy_manifest_xml.h"
#include "tpk/step/step_create_symbolic_link.h"
+#include "tpk/step/step_parse.h"
#include "common/utils/logging.h"
#endif
ai.AddStep<ci::create_storage::StepCreateStorageDirectories>();
ai.AddStep<tpk::step::StepCreateSymbolicLink>();
ai.AddStep<ci::security::StepRegisterSecurity>();
- ai.AddStep<ci::generate_xml::StepGenerateXml>();
+ ai.AddStep<tpk::step::StepCopyManifestXml>();
ai.AddStep<ci::register_app::StepRegisterApplication>();
return ai.Run();
ai.AddStep<ci::copy_storage::StepCopyStorageDirectories>();
ai.AddStep<tpk::step::StepCreateSymbolicLink>();
ai.AddStep<ci::update_security::StepUpdateSecurity>();
- ai.AddStep<ci::generate_xml::StepGenerateXml>();
+ ai.AddStep<tpk::step::StepCopyManifestXml>();
ai.AddStep<ci::update_app::StepUpdateApplication>();
return ai.Run();