SET(CMAKE_C_FLAGS_RELEASE "-O2 -fPIE")
ADD_SUBDIRECTORY(src)
+ADD_SUBDIRECTORY(tests)
+
+IF(NOT DEFINED MINIMUM_BUILD)
+ENABLE_TESTING()
+SET(PKGMGR_TOOL_UNIT_TESTS pkgmgr-tool_unittests)
+ADD_TEST(NAME ${PKGMGR_TOOL_UNIT_TESTS} COMMAND ${PKGMGR_TOOL_UNIT_TESTS})
+ENDIF(NOT DEFINED MINIMUM_BUILD)
INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/data/mime.wac.xml DESTINATION /usr/share/mime/packages/)
INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/data/mime.tpk.xml DESTINATION /usr/share/mime/packages/)
BuildRequires: pkgconfig(aul)
BuildRequires: pkgconfig(storage)
BuildRequires: pkgconfig(sqlite3)
+BuildRequires: pkgconfig(gmock)
BuildRequires: pkgmgr-info-parser-devel
BuildRequires: pkgmgr-info-parser
BuildRequires: fdupes
+%if 0%{?gcov:1}
+BuildRequires: lcov
+BuildRequires: zip
+%endif
Requires(posttrans): /usr/bin/pkg_initdb
%description
Packager Manager Tool for packaging
+%package -n pkgmgr-tool_unittests
+Summary: GTest for pkgmgr-tool
+Group: Development/Libraries
+Requires: %{name}
+
+%description -n pkgmgr-tool_unittests
+GTest for pkgmgr-tool
+
+%if 0%{?gcov:1}
+%package gcov
+Summary: pkgmgr-tool API(gcov)
+Group: System/API
+
+%description gcov
+gcov objects of an pkgmgr-tool
+%endif
+
%prep
%setup -q
cp %{SOURCE1001} .
%build
-%cmake .
+%if 0%{?gcov:1}
+export CFLAGS+=" -fprofile-arcs -ftest-coverage"
+export CXXFLAGS+=" -fprofile-arcs -ftest-coverage"
+export FFLAGS+=" -fprofile-arcs -ftest-coverage"
+export LDFLAGS+=" -lgcov"
+%endif
+%cmake .
%__make %{?_smp_mflags}
+%if 0%{?gcov:1}
+mkdir -p gcov-obj
+find . -name '*.gcno' -exec cp '{}' gcov-obj ';'
+%endif
+
+%check
+ctest -V
+%if 0%{?gcov:1}
+lcov -c --ignore-errors graph --no-external -q -d . -o pkgmgr-tool.info
+genhtml pkgmgr-tool.info -o pkgmgr-tool.out
+zip -r pkgmgr-tool.zip pkgmgr-tool.out
+install -m 0644 pkgmgr-tool.zip %{buildroot}%{_datadir}/gcov/pkgmgr-tool.zip
+%endif
%install
%make_install
mkdir -p %{buildroot}%{_sysconfdir}/opt/upgrade
+%if 0%{?gcov:1}
+mkdir -p %{buildroot}%{_datadir}/gcov/obj
+install -m 0644 gcov-obj/* %{buildroot}%{_datadir}/gcov/obj
+%endif
%fdupes %{buildroot}
%attr(0700,root,root) %{_sysconfdir}/opt/upgrade/pkgmgr.patch.sh
%attr(0700,root,root) /usr/share/fixed_multiuser/scripts/pkgmgr-clear-skel.sh
%attr(0700,root,root) %{_sysconfdir}/package-manager/pkgmgr-label-initial-image.sh
+
+%files -n pkgmgr-tool_unittests
+%{_bindir}/pkgmgr-tool_unittests
+%{_datadir}/pkgmgr-tool_unittests/*
+%if 0%{?gcov:1}
+%files gcov
+%{_datadir}/gcov/*
+%endif
info = (struct pkginfo *)pkg_list->data;
_D("Add [%s][%s][%s] to preload-rw list", info->pkgid,
info->version, info->type);
- snprintf(pkg_info, BUFSZE, "package=\"%s\"\tversion=\"%s\"\t"
- "type=\"%s\":\n",
+ snprintf(pkg_info, BUFSZE, "\"package=%s\":\"version=%s\":"
+ "\"type=%s\":\"removable=true\"\n",
info->pkgid, info->version, info->type);
fwrite(pkg_info, 1, strlen(pkg_info), file);
}
# Target - sources
-SET(SRCS
- pkg_upgrade.c
-)
+AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/src SRCS)
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/include)
# Target - definition
ADD_EXECUTABLE(${TARGET_PKG_UPGRADE} ${SRCS})
# Dependency
APPLY_PKG_CONFIG(${TARGET_PKG_UPGRADE} PUBLIC
- INIPARSER_DEPS
- SQLITE_DEPS
PKGMGR_INFO_DEPS
- PKGMGR_DEPS
PKGMGR_PARSER_DEPS
- STORAGE_DEPS
TZPLATFORM_DEPS
SMACK_DEPS
+ DLOG_DEPS
)
# Install
-INSTALL(TARGETS ${TARGET_PKG_UPGRADE} DESTINATION bin)
\ No newline at end of file
+INSTALL(TARGETS ${TARGET_PKG_UPGRADE} DESTINATION bin)
+
--- /dev/null
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * 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 BACKEND_INVOKER_H_
+#define BACKEND_INVOKER_H_
+
+#include <list>
+#include <string>
+
+#include "common_type.hh"
+
+namespace common_fota {
+
+class BackendInvoker {
+ public:
+ BackendInvoker(std::string pkgid, PkgType type, PkgLocation loc,
+ PkgOperation op, bool removable);
+ BackendInvoker() {}
+
+ int Run() const;
+
+ static int XSystem(const char *argv[]);
+
+ private:
+ std::list<std::string> parameters_;
+};
+
+} // common_fota
+
+#endif // BACKEND_INVOKER_H_
--- /dev/null
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * 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 COMMON_TYPE_H_
+#define COMMON_TYPE_H_
+
+#include <memory>
+#include <string>
+
+namespace common_fota {
+
+enum class PkgType {
+ TPK,
+ WGT,
+ UNKNOWN
+};
+
+enum class PkgLocation {
+ RO,
+ RW,
+ UNKNOWN
+};
+
+enum class PkgOperation {
+ INSTALL,
+ UPDATE,
+ UNINSTALL,
+ UNINSTALL_KEEP_RW_DATA,
+ COMPLEX
+};
+
+class PkgContext {
+ public:
+ PkgContext(std::string id, std::string version, std::string type,
+ bool read_only, bool removable = false)
+ : id_(std::move(id)), version_(std::move(version)),
+ type_(std::move(type)), read_only_(read_only), removable_(removable) {
+ if (read_only)
+ removable_ = false;
+ }
+
+ const std::string& GetId() const { return id_; }
+ const std::string& GetVersion() const { return version_; }
+ PkgType GetType() const {
+ if (type_ == "wgt" )
+ return PkgType::WGT;
+ return PkgType::TPK;
+ }
+ PkgLocation GetLocation() const {
+ if (read_only_)
+ return PkgLocation::RO;
+ return PkgLocation::RW;
+ }
+ bool IsReadOnly() const { return read_only_; }
+ bool IsRemovable() const { return removable_; }
+
+ private:
+ std::string id_;
+ std::string version_;
+ std::string type_;
+ bool read_only_;
+ bool removable_;
+};
+
+} // common_fota
+
+#endif // COMMON_TYPE_H_
--- /dev/null
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * 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 FILE_LOGBACKEND_H_
+#define FILE_LOGBACKEND_H_
+
+#include <memory>
+#include <sstream>
+#include <string>
+
+#include "logging.hh"
+
+namespace utils {
+
+class FileLogBackend : public ILogBackend {
+ public:
+ FileLogBackend(std::string file_name, int rotation_size, int max_rotation);
+ void WriteLog(LogLevel level, const std::string& tag,
+ const std::string& logstr) override;
+ void WriteLogToFile();
+
+ private:
+ bool Rotate();
+ int GetFileSize(const std::string& file_name);
+ std::string GetTimeStamp();
+ std::string GetPid();
+
+ std::string file_name_;
+ int rotation_size_;
+ int max_rotation_;
+ std::unique_ptr<std::ostringstream> log_stream_;
+};
+
+} // namespace utils
+
+#endif // FILE_LOGBACKEND_H_
--- /dev/null
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * 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 LOGGING_H_
+#define LOGGING_H_
+
+#include <dlog.h>
+
+#ifndef PROJECT_TAG
+#define PROJECT_TAG ""
+#endif
+
+#ifdef LOG
+#undef LOG
+#endif
+
+#include <cassert>
+#include <climits>
+#include <cstdio>
+#include <cstring>
+#include <iomanip>
+#include <iostream>
+#include <memory>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#ifndef __FILENAME__
+#define __FILENAME__ \
+ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
+#endif
+
+namespace utils {
+
+enum class LogLevel {
+ LOG_ERROR,
+ LOG_WARNING,
+ LOG_INFO,
+ LOG_DEBUG,
+};
+
+log_priority LogLevelToPriority(LogLevel level);
+
+template<LogLevel> struct LogTag;
+template<> struct LogTag<LogLevel::LOG_ERROR> {
+ static constexpr const char* value = "\033[1;31m| ERROR |\033[0m";
+};
+template<> struct LogTag<LogLevel::LOG_WARNING> {
+ static constexpr const char* value = "\033[1;33m| WARNING |\033[0m";
+};
+template<> struct LogTag<LogLevel::LOG_INFO> {
+ static constexpr const char* value = "\033[1;32m| INFO |\033[0m";
+};
+template<> struct LogTag<LogLevel::LOG_DEBUG> {
+ static constexpr const char* value = "\033[0m| DEBUG |\033[0m";
+};
+
+template <class charT, class traits = std::char_traits<charT>>
+class StringStream : private std::basic_ostringstream<charT, traits> {
+ public:
+ using std::basic_ostringstream<charT, traits>::str;
+
+ template <class T>
+ StringStream& operator<<(const T& value) {
+ static_cast<std::basic_ostringstream<charT, traits> &>(*this) << value;
+ return *this;
+ }
+};
+
+// Interface class for logging backends. The custom LogBackend which wants
+// log using LOG() macro should be implement following interface.
+class ILogBackend {
+ public:
+ virtual void WriteLog(LogLevel level, const std::string& tag,
+ const std::string& logstr) = 0;
+};
+
+class DLogBackend : public ILogBackend {
+ public:
+ void WriteLog(LogLevel level, const std::string& tag,
+ const std::string& logstr) override {
+ dlog_print(LogLevelToPriority(level), tag.c_str(), "%s",
+ Escape(logstr).c_str());
+ }
+
+ private:
+ // Since LogCatcher passes input to dlog_print(), the input which contains
+ // format string(such as %d, %n) can cause unexpected result.
+ // This is simple function to escape '%'.
+ // NOTE: Is there any gorgeous way instead of this?
+ std::string Escape(const std::string& str) const {
+ std::string escaped = std::string(str);
+ size_t start_pos = 0;
+ std::string from = "%";
+ std::string to = "%%";
+ while ((start_pos = escaped.find(from, start_pos)) != std::string::npos) {
+ escaped.replace(start_pos, from.length(), to);
+ start_pos += to.length();
+ }
+ return escaped;
+ }
+};
+
+class LogCore {
+ public:
+ // Do not call this function at destructor of global object
+ static LogCore& GetCore() {
+ static LogCore core;
+ return core;
+ }
+
+ void AddLogBackend(std::shared_ptr<ILogBackend> backend) {
+ backend_list_.emplace_back(backend);
+ }
+
+ void Log(LogLevel level, const std::string& tag, const std::string& log) {
+ for (auto backend : backend_list_)
+ backend->WriteLog(level, tag, log);
+ }
+
+ private:
+ LogCore() {
+ // add default dlog backend
+ AddLogBackend(std::shared_ptr<ILogBackend>(new DLogBackend()));
+ }
+ ~LogCore() = default;
+ LogCore(const LogCore&) = delete;
+ LogCore& operator=(const LogCore&) = delete;
+
+ std::vector<std::shared_ptr<ILogBackend>> backend_list_;
+};
+
+class LogCatcher {
+ public:
+ LogCatcher(LogLevel level, const char* tag)
+ : level_(level), tag_(tag) { }
+
+ void operator&(const StringStream<char>& str) const {
+ LogCore::GetCore().Log(level_, tag_, str.str());
+ }
+
+ private:
+ LogLevel level_;
+ std::string tag_;
+};
+
+} // namespace utils
+
+
+inline static const constexpr char* __tag_for_logging() {
+ return "";
+}
+
+inline static const constexpr char* __tag_for_project() {
+ return PROJECT_TAG;
+}
+
+// To be defined in class namespace if user want different log tag for given
+// scope
+#define SCOPE_LOG_TAG(TAG) \
+ inline static const constexpr char* __tag_for_logging() { \
+ return #TAG; \
+ } \
+
+// Simple logging macro of following usage:
+// LOG(LEVEL) << object_1 << object_2 << object_n;
+// where:
+// LEVEL = ERROR | WARNING | INFO | DEBUG
+#define LOG(LEVEL) \
+ ::utils::LogCatcher( \
+ ::utils::LogLevel::LOG_ ## LEVEL, __tag_for_project()) \
+ & ::utils::StringStream<char>() \
+ << std::string(::utils::LogTag<::utils::LogLevel::LOG_ ## LEVEL>::value) \
+ << " " << std::setw(25) << std::left << __tag_for_logging() \
+ << " : " << std::setw(36) \
+ << (std::string(__FILENAME__) + ":" + std::to_string(__LINE__)).c_str() \
+ << std::setw(0) << " : " \
+
+#endif // LOGGING_H_
--- /dev/null
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * 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 PKG_FINDER_H_
+#define PKG_FINDER_H_
+
+#include <memory>
+#include <list>
+#include <string>
+
+#include <pkgmgr-info.h>
+#include <libxml/xmlreader.h>
+
+#include "common_type.hh"
+
+namespace common_fota {
+
+class PkgFinder {
+ public:
+ PkgFinder();
+ ~PkgFinder();
+ int Find();
+ const std::list<PkgContext>& GetOldPkgs() { return old_pkgs_; }
+ const std::list<PkgContext>& GetNewPkgs() { return new_pkgs_; }
+ void SetManifestDir(std::string dir);
+ void SetPreloadRwListPath(std::string path);
+
+ private:
+ static int PkgidListCb(const pkgmgrinfo_pkginfo_h handle, void* user_data);
+ int FindPreloadPkgidFromDb(bool read_only = true);
+ int FindPreloadPkgidFromXml(const std::string& xml_directory);
+ int FindPreloadPkgidFromFile();
+ std::string GetValidManifest(std::string manifest);
+ std::string FindInfoFromXml(const std::string& manifest,
+ const std::string& find_info);
+ int MoveToChildElement(xmlTextReaderPtr reader, int depth);
+ void AddRwPkgInfoFromFile(const char* info_str);
+ std::string GetToken(const char* pBuf, const char* pKey);
+ void StrTrim(char *input);
+ int UnzipFileOnlyToPath(const char* dest_path, const char* unzip_to);
+
+ private:
+ std::list<PkgContext> old_pkgs_;
+ std::list<PkgContext> new_pkgs_;
+ bool read_only_ = true;
+ std::string manifest_dir_;
+ std::string preload_rw_list_path_;
+};
+
+} // common_fota
+
+#endif // PKG_FINDER_H_
+++ /dev/null
-/*
- * Copyright (c) 2000 - 2015 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 PKG_FOTA_H_
-#define PKG_FOTA_H_
-
-
-#define TOKEN_TYPE_STR "type="
-#define TOKEN_PKGID_STR "package="
-#define TOKEN_VERSION_STR "version="
-#define TOKEN_OPERATION_STR "op="
-#define TOKEN_REMOVE_STR "removable="
-#define TOKEN_UPDATE_STR "update="
-
-#define SEPERATOR_END '"'
-#define SEPERATOR_MID ':'
-
-
-#define ASCII(s) (const char *)s
-#define XMLCHAR(s) (const xmlChar *)s
-
-#define BUF_SIZE 1024
-#define DIRECTORY_PERMISSION_755 0755
-#define FOTA_RESULT_FILE tzplatform_mkpath(TZ_SYS_GLOBALUSER_DATA, \
- "pkgmgr/fota/result.txt")
-
-#ifndef FREE_AND_NULL
-#define FREE_AND_NULL(ptr) do { \
- if (ptr) { \
- free((void *)ptr); \
- ptr = NULL; \
- } \
-} while (0)
-#endif
-
-#ifndef FREE_AND_STRDUP
-#define FREE_AND_STRDUP(from, to) do { \
- if (to) free((void *)to); \
- if (from) to = strdup(from); \
-} while (0)
-#endif
-
-#define _LOGE(fmt, arg...) do { \
- int fd = 0;\
- FILE* file = NULL;\
- file = fopen(FOTA_RESULT_FILE, "a");\
- if (file == NULL) break;\
- fprintf(file, "[PKG_FOTA][%5d][err] "fmt"", getpid(), ##arg); \
- fflush(file);\
- fd = fileno(file);\
- fsync(fd);\
- fclose(file);\
- fprintf(stderr, "[PKG_FOTA][%5d][err] "fmt"", getpid(), ##arg); \
-} while (0)
-
-#define retvm_if(expr, val, fmt, arg...) do { \
- if (expr) { \
- _LOGE("(%s)"fmt, #expr, ##arg); \
- return (val); \
- } \
-} while (0)
-
-#define err_if(expr, fmt, arg...) do { \
- if (expr) { \
- _LOGE("(%s)"fmt, #expr, ##arg); \
- } \
-} while (0)
-
-#define tryvm_if(expr, val, fmt, arg...) do { \
- if (expr) { \
- _LOGE("(%s)"fmt, #expr, ##arg); \
- val; \
- goto catch; \
- } \
-} while (0)
-
-typedef enum {
- PKG_IS_NOT_EXIST = 0,
- PKG_IS_SAME,
- PKG_IS_UPDATED,
- PKG_IS_INSERTED,
- PKG_IS_OLD
-} COMPARE_RESULT;
-
-typedef enum {
- PKG_NEED_NOTHING = 0,
- PKG_NEED_INSTALL,
- PKG_NEED_UNINSTALL,
- PKG_NEED_ROUPDATE,
- PKG_NEED_UPDATE_TO_RW,
- PKG_NEED_RWUNINSTALL,
- PKG_NEED_UPDATE_TO_RO,
- PKG_NEED_RO_DBREMOVE,
- PKG_NEED_RO_UNINSTALL_KEEPRWDATA,
- PKG_NEED_PRELOADRW_INSTALL
-} UPGRADE_OPRATION;
-
-enum rpm_request_type {
- INSTALL_REQ,
- UNINSTALL_REQ,
- UPGRADE_REQ
-};
-
-#endif /* PKG_FOTA_H_ */
--- /dev/null
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * 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 PKG_UPGRADER_H_
+#define PKG_UPGRADER_H_
+
+#include <string>
+
+#include "backend_invoker.hh"
+#include "common_type.hh"
+
+namespace common_fota {
+
+class PkgUpgrader {
+ public:
+ PkgUpgrader(const PkgContext& context, PkgOperation pkg_op);
+ PkgUpgrader(std::string id);
+ virtual ~PkgUpgrader() = default;
+
+ PkgType GetType() const;
+ PkgLocation GetLocation() const;
+ PkgOperation GetOperation() const;
+ std::string GetId() const;
+ std::string GetVersion() const;
+ const BackendInvoker& GetBackendInvoker() const;
+ int CompareVersion(const PkgUpgrader& pkg) const;
+
+ virtual bool Upgrade() = 0;
+
+ private:
+ PkgType type_;
+ PkgLocation loc_;
+ PkgOperation op_;
+ std::string id_;
+ std::string version_;
+ BackendInvoker backend_;
+};
+
+} // namespace common_fota
+
+#endif // PKG_UPGRADER_H_
--- /dev/null
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * 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 PKG_UPGRADER_FACTORY_H_
+#define PKG_UPGRADER_FACTORY_H_
+
+#include <list>
+#include <memory>
+#include <string>
+
+#include "pkg_finder.hh"
+#include "pkg_upgrader.hh"
+#include "common_type.hh"
+
+namespace common_fota {
+
+class PkgUpgraderFactory {
+ public:
+ std::list<std::unique_ptr<PkgUpgrader>> MakeList(PkgFinder* finder);
+
+ private:
+ std::list<std::unique_ptr<PkgUpgrader>> Merge(
+ const std::list<PkgContext>& old_pkgs,
+ const std::list<PkgContext>& new_pkgs);
+ const PkgContext* FindPkgById(const std::list<PkgContext>& pkgs,
+ std::string id);
+};
+
+} // common_fota
+
+#endif // PKG_UPGRADER_FACTORY_H_
--- /dev/null
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * 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 RO2RW_UPGRADER_H_
+#define RO2RW_UPGRADER_H_
+
+#include "pkg_upgrader.hh"
+
+namespace common_fota {
+
+class Ro2RwUpgrader : public PkgUpgrader {
+ public:
+ Ro2RwUpgrader(std::unique_ptr<PkgUpgrader> old_pkg,
+ std::unique_ptr<PkgUpgrader> new_pkg);
+ virtual ~Ro2RwUpgrader() = default;
+ bool Upgrade() override;
+
+ private:
+ int UnzipFiles(const char* dest_path);
+ int UnzipXml(const std::string& pkgid);
+ int UnzipData(const std::string& pkgid, const std::string& dest);
+ int UnzipPkgFromZip(const std::string& pkgid);
+
+ private:
+ std::unique_ptr<PkgUpgrader> old_pkg_;
+ std::unique_ptr<PkgUpgrader> new_pkg_;
+};
+
+} // common_fota
+
+#endif // RO2RW_UPGRADER_H_
--- /dev/null
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * 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 RW2RO_UPGRADER_H_
+#define RW2RO_UPGRADER_H_
+
+#include "pkg_upgrader.hh"
+
+namespace common_fota {
+
+class Rw2RoUpgrader : public PkgUpgrader {
+ public:
+ Rw2RoUpgrader(std::unique_ptr<PkgUpgrader> old_pkg,
+ std::unique_ptr<PkgUpgrader> new_pkg);
+ virtual ~Rw2RoUpgrader() = default;
+ bool Upgrade() override;
+
+ private:
+ std::unique_ptr<PkgUpgrader> old_pkg_;
+ std::unique_ptr<PkgUpgrader> new_pkg_;
+};
+
+} // common_fota
+
+#endif // RW2RO_UPGRADER_H_
--- /dev/null
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * 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 RW_UPGRADER_H_
+#define RW_UPGRADER_H_
+
+#include "ro2rw_upgrader.hh"
+
+namespace common_fota {
+
+class RwUpgrader : public Ro2RwUpgrader {
+ public:
+ RwUpgrader(std::unique_ptr<PkgUpgrader> new_pkg)
+ : Ro2RwUpgrader(nullptr, std::move(new_pkg)) {}
+ virtual ~RwUpgrader() = default;
+};
+
+} // common_fota
+
+#endif // RW_UPGRADER_H_
--- /dev/null
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * 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 SIMPLE_UPGRADER_H_
+#define SIMPLE_UPGRADER_H_
+
+#include "pkg_upgrader.hh"
+#include "pkg_finder.hh"
+
+namespace common_fota {
+
+class SimpleUpgrader : public PkgUpgrader {
+ public:
+ SimpleUpgrader(const PkgContext& context, PkgOperation pkg_op);
+ bool Upgrade() override;
+};
+
+} // common_fota
+
+#endif // SIMPLE_UPGRADER_H_
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * 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 UPGRADER_H_
+#define UPGRADER_H_
+
+#include <list>
+#include <memory>
+
+#include "file_logbackend.hh"
+#include "pkg_finder.hh"
+#include "pkg_upgrader.hh"
+
+namespace common_fota {
+
+class Upgrader {
+ public:
+ Upgrader();
+ bool Process(PkgFinder* finder);
+ const std::list<std::unique_ptr<PkgUpgrader>>& GetSuccessList() const;
+ const std::list<std::unique_ptr<PkgUpgrader>>& GetFailureList() const;
+ void SetDbPath(const std::string& path);
+
+ private:
+ int CheckAndRestoreBackupDbs();
+ int CheckAndRestoreBackup(const std::string& origin_path);
+ int BackupDb(const std::string& src_path, const std::string& dest_path);
+ int MakeBackupDbs();
+ void RemoveBackupPath(const std::string& origin_path);
+ void RemoveBackupDbs();
+ int SetDbPermission(const std::string& path);
+ int BackupFile(const std::string& src_path, const std::string& dest_path);
+ int CreateBackupFlag(const std::string& path);
+ int CheckBackupFlag(const std::string& path);
+ int RemoveBackupFlag(const std::string& path);
+
+ private:
+ std::shared_ptr<utils::FileLogBackend> logger_;
+ std::list<std::unique_ptr<PkgUpgrader>> success_list_;
+ std::list<std::unique_ptr<PkgUpgrader>> failure_list_;
+ std::string parser_db_;
+ std::string parser_db_journal_;
+ std::string cert_db_;
+ std::string cert_db_journal_;
+};
+
+} // common_fota
+
+#endif // UPGRADER_H_
+++ /dev/null
-/*
- * pkg-fota
- *
- * Copyright (c) 2000 - 2011 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 <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <dirent.h>
-#include <unistd.h>
-#include <sys/smack.h>
-#include <sys/stat.h>
-#include <errno.h>
-#include <iniparser.h>
-#include <ctype.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <sys/time.h>
-#include <libxml/xmlreader.h>
-#include <sqlite3.h>
-#include <pwd.h>
-
-#include <package-manager-types.h>
-#include <package-manager.h>
-#include <pkgmgr_parser.h>
-#include <pkgmgr-info.h>
-#include "include/pkg_upgrade.h"
-
-#include <tzplatform_config.h>
-
-#define USR_MANIFEST_DIRECTORY tzplatform_getenv(TZ_SYS_RO_PACKAGES)
-#define OPT_USR_MANIFEST_DIRECTORY tzplatform_getenv(TZ_SYS_RW_PACKAGES)
-#define RW_PKG_DIRECTORY tzplatform_getenv(TZ_SYS_RW_APP)
-#define SKEL_DIRECTORY tzplatform_mkpath(TZ_SYS_ETC, "skel/apps_rw")
-
-#define PKGMGR_FOTA_PATH tzplatform_mkpath(TZ_SYS_GLOBALUSER_DATA, \
- "pkgmgr/fota")
-#define PKGID_LIST_FROM_DB_FILE tzplatform_mkpath(TZ_SYS_GLOBALUSER_DATA, \
- "pkgmgr/fota/pkgid_list_from_db.txt")
-#define PKGID_LIST_FROM_XML_FILE \
- tzplatform_mkpath(TZ_SYS_GLOBALUSER_DATA, \
- "pkgmgr/fota/pkgid_list_from_xml.txt")
-#define PRELOAD_RW_PKG_LIST \
- tzplatform_mkpath(TZ_SYS_GLOBALUSER_DATA, \
- "pkgmgr/fota/.all_preload_rw_list")
-#define DBPATH tzplatform_mkpath(TZ_SYS_DB, "/.pkgmgr_parser.db")
-#define JOURNAL_DBPATH tzplatform_mkpath(TZ_SYS_DB, \
- "/.pkgmgr_parser.db-journal")
-#define CERT_DBPATH tzplatform_mkpath(TZ_SYS_DB, "/.pkgmgr_cert.db")
-#define JOURNAL_CERT_DBPATH tzplatform_mkpath(TZ_SYS_DB, \
- "/.pkgmgr_cert.db-journal")
-#define OPT_ZIP_FILE "/usr/system/RestoreDir/opt.zip"
-#define ALL_PRELOAD_RW_PKG_LIST "/opt/usr/share/.all_preload_rw_list"
-#define GLOBAL_USER tzplatform_getuid(TZ_SYS_GLOBALAPP_USER)
-#define APPFW_USER "app_fw"
-
-struct pkginfo {
- char *pkgid;
- char *version;
- char *type;
-};
-
-static char *unzip_path[BUF_SIZE] = {
- "opt/usr/globalapps",
- "opt/etc/skel/apps_rw",
- NULL
-};
-
-static void __free_pkginfo(gpointer data)
-{
- struct pkginfo *info = (struct pkginfo *)data;
- free(info->pkgid);
- free(info->version);
- free(info->type);
- free(info);
-}
-
-float __get_elapsed_time()
-{
- static long start_time = 0;
- long endtime = 0;
- struct timeval tv;
-
- if (start_time == 0) {
- gettimeofday(&tv, NULL);
- start_time = tv.tv_sec * 1000l + tv.tv_usec / 1000l;
- }
-
- gettimeofday(&tv, NULL);
- endtime = tv.tv_sec * 1000l + tv.tv_usec / 1000l;
-
- return (endtime - start_time)/1000.0;
-}
-
-#define _LOG(fmt, arg...) do { \
- int fd = 0; \
- FILE *file = NULL; \
- file = fopen(FOTA_RESULT_FILE, "a"); \
- if (file == NULL) break; \
- fprintf(file, "[PKG_FOTA][%5d][%10.3fs] "fmt"", getpid(), \
- __get_elapsed_time(), ##arg); \
- fflush(file); \
- fd = fileno(file); \
- fsync(fd); \
- fclose(file); \
- fprintf(stderr, "[PKG_FOTA][%5d][%10.3fs] "fmt"", getpid(), \
- __get_elapsed_time(), ##arg); \
-} while (0)
-
-int remove_directory(const char *path)
-{
- DIR *dir;
- struct dirent *entry;
- size_t path_len = strlen(path);
- int ret = 0;
- int iterate_ret;
- char buf[BUF_SIZE] = {0};
- size_t len;
- struct stat statbuf;
-
- dir = opendir(path);
- if (!dir)
- return -1;
-
- while (!ret && (entry = readdir(dir))) {
- iterate_ret = -1;
-
- if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, ".."))
- continue;
-
- len = path_len + strlen(entry->d_name) + 2;
- snprintf(buf, len, "%s/%s", path, entry->d_name);
-
- if (!stat(buf, &statbuf)) {
- if (S_ISDIR(statbuf.st_mode))
- iterate_ret = remove_directory(buf);
- else
- iterate_ret = unlink(buf);
- }
- ret = iterate_ret;
- }
-
- closedir(dir);
- if (!ret)
- ret = rmdir(path);
-
- return ret;
-}
-
-static void __iter_cb(gpointer key, gpointer value, gpointer user_data)
-{
-
- FILE *file;
- char *pkgid;
- char *version;
- char *type;
- char pkg_info[BUF_SIZE];
- pkgmgrinfo_pkginfo_h info;
-
- if (user_data == NULL || key == NULL)
- return;
-
- file = user_data;
- pkgid = key;
-
- if (pkgmgrinfo_pkginfo_get_pkginfo(pkgid, &info)) {
- _LOGE("failed to get pkginfo of %s\n", pkgid);
- return;
- }
-
- if (pkgmgrinfo_pkginfo_get_version(info, &version)) {
- pkgmgrinfo_pkginfo_destroy_pkginfo(info);
- return;
- }
-
- if (pkgmgrinfo_pkginfo_get_type(info, &type)) {
- pkgmgrinfo_pkginfo_destroy_pkginfo(info);
- return;
- }
-
- snprintf(pkg_info, BUF_SIZE,
- "package=\"%s\"\tversion=\"%s\"\ttype=\"%s\":\n",
- pkgid, version, type);
- fwrite(pkg_info, 1, strlen(pkg_info), file);
- pkgmgrinfo_pkginfo_destroy_pkginfo(info);
-}
-
-static void __make_preload_rw_list(GHashTable *preload_rw_table)
-{
- if (preload_rw_table == NULL) {
- _LOG("preload_rw_table is null\n");
- return;
- }
- FILE *file = NULL;
-
- char buf[BUF_SIZE];
- char tmp_path[BUF_SIZE];
- snprintf(tmp_path, BUF_SIZE, "%s.tmp", ALL_PRELOAD_RW_PKG_LIST);
-
- if (rename(ALL_PRELOAD_RW_PKG_LIST, tmp_path)) {
- if (errno != ENOENT)
- _LOG("can not backup preload rw pkg list: %d", errno);
- }
-
- file = fopen(ALL_PRELOAD_RW_PKG_LIST, "w");
- if (file == NULL) {
- _LOG("can not open [%s]: %s\n", ALL_PRELOAD_RW_PKG_LIST,
- strerror_r(errno, buf, sizeof(buf)));
- return;
- }
- g_hash_table_foreach(preload_rw_table, __iter_cb, file);
- fsync(fileno(file));
- fclose(file);
- if (remove(tmp_path))
- _LOG("cannot remove backup file(%s): %d", tmp_path, errno);
-}
-
-static int __is_dir(const char *dirname)
-{
- struct stat stFileInfo;
-
- retvm_if(dirname == NULL, -1, "dirname == NULL\n");
- retvm_if(stat(dirname, &stFileInfo) < 0, -1,
- "stFileInfo is not enough\n");
-
- if (S_ISDIR(stFileInfo.st_mode))
- return 0;
- return -1;
-}
-
-static int __xsystem(const char *argv[])
-{
- int status = 0;
- pid_t pid;
- pid = fork();
- switch (pid) {
- case -1:
- perror("fork failed");
- return -1;
- case 0:
- /* child */
- execvp(argv[0], (char *const *)argv);
- _exit(-1);
- default:
- /* parent */
- break;
- }
- if (waitpid(pid, &status, 0) == -1) {
- perror("waitpid failed");
- return -1;
- }
- if (WIFSIGNALED(status)) {
- perror("signal");
- return -1;
- }
- if (!WIFEXITED(status)) {
- /* shouldn't happen */
- perror("should not happen");
- return -1;
- }
- return WEXITSTATUS(status);
-}
-
-static int __check_pkgmgr_fota_dir()
-{
- int ret = 0;
-
- if (__is_dir(PKGMGR_FOTA_PATH) < 0) {
- const char *mkdir_argv[] = { "/bin/mkdir",
- "-p", PKGMGR_FOTA_PATH, NULL };
- ret = __xsystem(mkdir_argv);
- retvm_if(ret != 0, -1, "mkdir_argv error [%d]\n", ret);
- }
-
- return 0;
-}
-
-static int __remove_pkgid_list()
-{
- int ret = 0;
-
- if (access(FOTA_RESULT_FILE, R_OK) == 0) {
- ret = remove(FOTA_RESULT_FILE);
- err_if(ret < 0, "remove[%s] failed", FOTA_RESULT_FILE);
- }
-
- if (access(PKGID_LIST_FROM_DB_FILE, R_OK) == 0) {
- ret = remove(PKGID_LIST_FROM_DB_FILE);
- err_if(ret < 0, "remove[%s] failed", PKGID_LIST_FROM_DB_FILE);
- }
-
- if (access(PKGID_LIST_FROM_XML_FILE, R_OK) == 0) {
- ret = remove(PKGID_LIST_FROM_XML_FILE);
- err_if(ret < 0, "remove[%s] failed", PKGID_LIST_FROM_XML_FILE);
- }
-
- return 0;
-}
-
-static int __make_pkgid_list(const char *file_path, char *pkgid,
- char *version, char *type, bool is_update)
-{
- FILE *fp;
-
- if (NULL == pkgid)
- return 0;
-
- fp = fopen(file_path, "a+");
- if (NULL == fp)
- return -1;
-
- fprintf(fp, "%s\"%s\" %s\"%s\" %s\"%s\" %s\"%s\":\n",
- TOKEN_PKGID_STR, pkgid,
- TOKEN_VERSION_STR, version,
- TOKEN_TYPE_STR, type,
- TOKEN_UPDATE_STR, (is_update) ? "true" : "false");
-
- fclose(fp);
-
- return 0;
-}
-
-static int __insert_preload_rw_table(GHashTable *preload_rw_table,
- const char *pkgid, const char *version, const char *type)
-{
- struct pkginfo *info;
- char *package;
-
- info = calloc(1, sizeof(struct pkginfo));
- if (info == NULL) {
- _LOGE("out of memory");
- return -1;
- }
-
- info->pkgid = strdup(pkgid);
- if (info->pkgid == NULL) {
- _LOGE("out of memory");
- __free_pkginfo((struct pkginfo *)info);
- return -1;
- }
-
- info->version = strdup(version);
- if (info->version == NULL) {
- _LOGE("out of memory");
- __free_pkginfo((struct pkginfo *)info);
- return -1;
- }
-
- info->type = strdup(type);
- if (info->type == NULL) {
- _LOGE("out of memory");
- __free_pkginfo((struct pkginfo *)info);
- return -1;
- }
-
- package = strdup(pkgid);
- if (package == NULL) {
- _LOGE("out of memory");
- __free_pkginfo((struct pkginfo *)info);
- return -1;
- }
-
- g_hash_table_insert(preload_rw_table, package, info);
- return 0;
-}
-
-static int __delete_preload_rw_table(GHashTable *preload_rw_table,
- const char *pkgid)
-{
- gboolean removed;
- removed = g_hash_table_remove(preload_rw_table, pkgid);
- return removed ? 0 : -1;
-}
-
-static int __pkgid_list_cb(const pkgmgrinfo_pkginfo_h handle, void *user_data)
-{
- int ret = -1;
- char *pkgid = NULL;
- char *version = NULL;
- char *type = NULL;
- bool is_update = false;
-
- ret = pkgmgrinfo_pkginfo_get_pkgid(handle, &pkgid);
- err_if(ret < 0, "pkgmgrinfo_pkginfo_get_pkgid failed");
-
- ret = pkgmgrinfo_pkginfo_get_version(handle, &version);
- err_if(ret < 0, "pkgmgrinfo_pkginfo_get_version failed");
-
- ret = pkgmgrinfo_pkginfo_get_type(handle, &type);
- err_if(ret < 0, "pkgmgrinfo_pkginfo_get_type failed");
-
- ret = pkgmgrinfo_pkginfo_is_update(handle, &is_update);
- err_if(ret < 0, "pkgmgrinfo_pkginfo_is_update failed");
-
- ret = __make_pkgid_list((char *)user_data, pkgid,
- version, type, is_update);
- return ret;
-}
-
-static int __preload_rw_pkgid_list_cb(const pkgmgrinfo_pkginfo_h handle,
- void *user_data)
-{
- int ret;
- char *pkgid;
- char *version;
- char *type;
- GHashTable *preload_rw_table = (GHashTable *)user_data;
-
- ret = pkgmgrinfo_pkginfo_get_pkgid(handle, &pkgid);
- if (ret < 0) {
- _LOGE("pkgmgrinfo_pkginfo_get_pkgid failed\n");
- return -1;
- }
-
- ret = pkgmgrinfo_pkginfo_get_version(handle, &version);
- if (ret < 0) {
- _LOGE("pkgmgrinfo_pkginfo_get_version failed\n");
- return -1;
- }
-
- ret = pkgmgrinfo_pkginfo_get_type(handle, &type);
- if (ret < 0) {
- _LOGE("pkgmgrinfo_pkginfo_get_type failed\n");
- return -1;
- }
-
- ret = __insert_preload_rw_table(preload_rw_table, pkgid, version, type);
- if (ret < 0) {
- _LOGE("__insert_preload_rw_table failed\n");
- return -1;
- }
-
- return 0;
-}
-
-static void __str_trim(char *input)
-{
- char *trim_str = input;
-
- if (input == NULL)
- return;
-
- while (*input != 0) {
- if (!isspace(*input)) {
- *trim_str = *input;
- trim_str++;
- }
- input++;
- }
-
- *trim_str = 0;
- return;
-}
-
-static char *__getvalue(const char *pBuf, const char *pKey, int depth)
-{
- const char *p = NULL;
- const char *pStart = NULL;
- const char *pEnd = NULL;
-
- p = strstr(pBuf, pKey);
- if (p == NULL)
- return NULL;
-
- pStart = p + strlen(pKey) + depth;
- pEnd = strchr(pStart, SEPERATOR_END);
- if (pEnd == NULL) {
- pEnd = strchr(pStart, SEPERATOR_MID);
- if (pEnd == NULL)
- return NULL;
- }
-
- size_t len = pEnd - pStart;
- if (len <= 0)
- return NULL;
-
- char *pRes = (char *)malloc(len + 1);
- if (pRes == NULL) {
- _LOG("malloc failed.\n");
- return NULL;
- }
- strncpy(pRes, pStart, len);
- pRes[len] = 0;
-
- return pRes;
-}
-
-static int __compare_pkgid(char *file_path, char *fota_pkgid,
- char *fota_version, bool *is_updated)
-{
- retvm_if(file_path == NULL, -1, "file_path is null.\n");
- retvm_if(fota_pkgid == NULL, -1, "fota_pkgid is null.\n");
- retvm_if(fota_version == NULL, -1, "fota_version is null.\n");
-
- int ret = PKG_IS_NOT_EXIST;
- FILE *fp = NULL;
- char buf[BUF_SIZE] = {0};
- char *pkgid = NULL;
- char *version = NULL;
- char *update = NULL;
- int compare = PMINFO_VERSION_SAME;
-
- fp = fopen(file_path, "r");
- retvm_if(fp == NULL, -1, "Fail get : %s\n", file_path);
-
- while (fgets(buf, BUF_SIZE, fp) != NULL) {
- __str_trim(buf);
-
- pkgid = __getvalue(buf, TOKEN_PKGID_STR, 1);
- if (pkgid == NULL) {
- _LOG("pkgid is null\n");
- continue;
- }
-
- version = __getvalue(buf, TOKEN_VERSION_STR, 1);
- if (version == NULL) {
- FREE_AND_NULL(pkgid);
- _LOG("compare_data is null\n");
- continue;
- }
-
- update = __getvalue(buf, TOKEN_UPDATE_STR, 1);
- if (update == NULL) {
- FREE_AND_NULL(pkgid);
- FREE_AND_NULL(version);
- _LOG("compare_data is null\n");
- continue;
- }
- if (!strncmp(update, "true", strlen("true")))
- *is_updated = true;
- else
- *is_updated = false;
-
- if (strcmp(pkgid, fota_pkgid) == 0) {
- ret = pkgmgrinfo_compare_package_version(version,
- fota_version, &compare);
- if (compare == PMINFO_VERSION_NEW) {
- _LOG("pkgid = %s, db version = %s, new package"
- " version = %s\n", pkgid, version,
- fota_version);
- _LOG("pkg is updated, need to upgrade\n");
-
- ret = PKG_IS_UPDATED;
- FREE_AND_NULL(pkgid);
- FREE_AND_NULL(version);
- FREE_AND_NULL(update);
- break;
- } else if (compare == PMINFO_VERSION_OLD) {
- ret = PKG_IS_OLD;
- FREE_AND_NULL(pkgid);
- FREE_AND_NULL(version);
- FREE_AND_NULL(update);
- break;
- }
-
- FREE_AND_NULL(pkgid);
- FREE_AND_NULL(version);
- FREE_AND_NULL(update);
- ret = PKG_IS_SAME;
- break;
- }
-
- FREE_AND_NULL(pkgid);
- FREE_AND_NULL(version);
- FREE_AND_NULL(update);
- memset(buf, 0x00, BUF_SIZE);
- }
-
- if (fp != NULL)
- fclose(fp);
-
- return ret;
-}
-
-static bool __check_deleted_pkg(GHashTable *preload_rw_table,
- const char *fota_pkgid)
-{
- if (g_hash_table_contains(preload_rw_table, fota_pkgid))
- return true;
- return false;
-}
-
-char *__manifest_to_package(const char *manifest)
-{
- char *package;
-
- if (manifest == NULL)
- return NULL;
-
- package = strdup(manifest);
- if (package == NULL)
- return NULL;
-
- if (!strstr(package, ".xml")) {
- _LOG("%s is not a manifest file \n", manifest);
- free(package);
- return NULL;
- }
-
- return package;
-}
-
-static void __send_args_to_backend(const char *pkgid, const char *pkgtype,
- int operation)
-{
- int ret = 0;
-
- long starttime;
- long endtime;
- struct timeval tv;
- gettimeofday(&tv, NULL);
- starttime = tv.tv_sec * 1000l + tv.tv_usec / 1000l;
- char *query;
- char backend_cmd[BUF_SIZE];
- const char *new_pkgtype;
- const char tpk_pkgtype[] = "tpk";
-
- const char *preload_rw[] = { backend_cmd, "-y", pkgid,
- "--preload-rw", NULL };
- const char *install_ro[] = { backend_cmd, "-y", pkgid,
- "--preload", "--partial-rw", NULL };
- const char *uninstall_ro[] = { backend_cmd, "-d", pkgid,
- "--preload", "--force-remove",
- "--partial-rw", NULL };
- const char *uninstall_ro_keeprwdata[] = { backend_cmd, "-d", pkgid,
- "--preload", "--force-remove",
- "--keep-rwdata", NULL };
- const char *uninstall_ro_update[] = { backend_cmd, "-d",
- pkgid, "--keep-rwdata", NULL };
- const char *db_cmd[] = {"/usr/bin/sqlite3",
- NULL, NULL, NULL};
-
- if (operation == PKG_NEED_NOTHING)
- return;
-
- if (!strcmp(pkgtype, "rpm"))
- new_pkgtype = tpk_pkgtype;
- else
- new_pkgtype = pkgtype;
-
- snprintf(backend_cmd, sizeof(backend_cmd), "/usr/bin/%s-backend",
- new_pkgtype);
-
- switch (operation) {
- case PKG_NEED_INSTALL:
- case PKG_NEED_ROUPDATE:
- ret = __xsystem(install_ro);
- break;
- case PKG_NEED_UNINSTALL:
- ret = __xsystem(uninstall_ro);
- break;
- case PKG_NEED_UPDATE_TO_RW:
- query = sqlite3_mprintf(
- "UPDATE package_info SET " \
- "package_preload='false', " \
- "package_system='false' "\
- "WHERE package=%Q", pkgid);
- db_cmd[1] = strdup(DBPATH);
- db_cmd[2] = query;
- ret = __xsystem(db_cmd);
- FREE_AND_NULL(db_cmd[1]);
- sqlite3_free(query);
- break;
- case PKG_NEED_RWUNINSTALL:
- case PKG_NEED_UPDATE_TO_RO:
- ret = __xsystem(uninstall_ro_update);
- break;
- case PKG_NEED_RO_DBREMOVE:
- query = sqlite3_mprintf(
- "PRAGMA foreign_keys=on; " \
- "DELETE FROM package_info " \
- "WHERE package=%Q", pkgid);
- db_cmd[1] = strdup(DBPATH);
- db_cmd[2] = query;
- ret = __xsystem(db_cmd);
- FREE_AND_NULL(db_cmd[1]);
- sqlite3_free(query);
- break;
- case PKG_NEED_PRELOADRW_INSTALL:
- ret = __xsystem(preload_rw);
- break;
- case PKG_NEED_RO_UNINSTALL_KEEPRWDATA:
- ret = __xsystem(uninstall_ro_keeprwdata);
- break;
- }
-
- gettimeofday(&tv, NULL);
- endtime = tv.tv_sec * 1000l + tv.tv_usec / 1000l;
-
- _LOG("result[%ld ms, %d] \t Pkgid[%s] \n",
- (endtime - starttime), ret, pkgid);
-}
-
-int __child_element(xmlTextReaderPtr reader, int depth)
-{
- int ret = xmlTextReaderRead(reader);
- int cur = xmlTextReaderDepth(reader);
- while (ret == 1) {
- switch (xmlTextReaderNodeType(reader)) {
- case XML_READER_TYPE_ELEMENT:
- if (cur == depth + 1)
- return 1;
- break;
- case XML_READER_TYPE_TEXT:
- /*text is handled by each function separately*/
- if (cur == depth + 1)
- return 0;
- break;
- case XML_READER_TYPE_END_ELEMENT:
- if (cur == depth)
- return 0;
- break;
- default:
- if (cur <= depth)
- return 0;
- break;
- }
-
- ret = xmlTextReaderRead(reader);
- cur = xmlTextReaderDepth(reader);
- }
- return ret;
-}
-
-char *__find_info_from_xml(const char *manifest, const char *find_info)
-{
- retvm_if(manifest == NULL, NULL, "manifest is null.\n");
- retvm_if(find_info == NULL, NULL, "find_info is null.\n");
-
- const xmlChar *node;
- xmlTextReaderPtr reader;
- char *info_val = NULL;
- xmlChar *tmp = NULL;
-
- reader = xmlReaderForFile(manifest, NULL, 0);
-
- if (reader) {
- if (__child_element(reader, -1)) {
- node = xmlTextReaderConstName(reader);
- if (!node) {
- printf("xmlTextReaderConstName value is NULL\n");
- goto end;
- }
-
- if (!strcmp(ASCII(node), "manifest")) {
- tmp = xmlTextReaderGetAttribute(reader,
- XMLCHAR(find_info));
- if (tmp) {
- FREE_AND_STRDUP(ASCII(tmp), info_val);
- if (info_val == NULL)
- printf("Malloc Failed\n");
- FREE_AND_NULL(tmp);
- }
- } else {
- printf("Manifest Node is not found\n");
- }
- }
- } else {
- printf("xmlReaderForFile value is NULL\n");
- }
-
-end:
- if (reader)
- xmlFreeTextReader(reader);
-
- return info_val;
-}
-
-static int __find_preload_pkgid_from_xml(const char *file_path,
- const char *xml_directory)
-{
- retvm_if(file_path == NULL, -1, "file_path is NULL.\n");
- retvm_if(xml_directory == NULL, -1, "xml_directory is NULL.\n");
-
- int ret = 0;
- char buf[BUF_SIZE] = {0};
- DIR *dir;
- struct dirent *entry = NULL;
-
- dir = opendir(xml_directory);
- if (!dir) {
- if (strerror_r(errno, buf, sizeof(buf)) == 0)
- _LOG("Failed to access the [%s] because %s\n",
- xml_directory, buf);
- return -1;
- }
-
- while ((entry = readdir(dir)) != NULL) {
- char *manifest = NULL;
- char *pkgid = NULL;
- char *version = NULL;
- char *type = NULL;
-
- if (entry->d_name[0] == '.') continue;
-
- manifest = __manifest_to_package(entry->d_name);
- if (!manifest) {
- _LOG("Failed to convert file to xml[%s]\n",
- entry->d_name);
- continue;
- }
-
- snprintf(buf, sizeof(buf), "%s/%s", xml_directory, manifest);
-
- /*Get the package name from manifest file*/
- pkgid = __find_info_from_xml(buf, "package");
- if (pkgid == NULL) {
- FREE_AND_NULL(manifest);
- continue;
- }
-
- version = __find_info_from_xml(buf, "version");
- if (version == NULL)
- version = strdup("0.0.1");
-
- type = __find_info_from_xml(buf, "type");
- if (type == NULL)
- type = strdup("tpk");
-
- ret = __make_pkgid_list((char *)file_path, pkgid,
- version, type, false);
- if (ret < 0)
- _LOG("Make file Fail : %s => %s, %s\n",
- buf, pkgid, version);
-
- FREE_AND_NULL(pkgid);
- FREE_AND_NULL(version);
- FREE_AND_NULL(manifest);
- FREE_AND_NULL(type);
- }
-
- closedir(dir);
-
- return 0;
-}
-
-static int __find_preload_pkgid_from_db(const char *file_path)
-{
- retvm_if(file_path == NULL, -1, "file_path is NULL.\n");
-
- int ret = 0;
- pkgmgrinfo_pkginfo_filter_h handle = NULL;
-
- ret = pkgmgrinfo_pkginfo_filter_create(&handle);
- retvm_if(ret != PMINFO_R_OK, -1,
- "pkginfo filter handle create failed\n");
-
- ret = pkgmgrinfo_pkginfo_filter_add_bool(handle,
- PMINFO_PKGINFO_PROP_PACKAGE_PRELOAD, 1);
- tryvm_if(ret < 0, ret = -1, "pkgmgrinfo_pkginfo_filter_add_bool"
- "(PMINFO_PKGINFO_PROP_PACKAGE_PRELOAD) failed\n");
-
- ret = pkgmgrinfo_pkginfo_filter_add_bool(handle,
- PMINFO_PKGINFO_PROP_PACKAGE_SYSTEM, 1);
- tryvm_if(ret < 0, ret = -1, "pkgmgrinfo_pkginfo_filter_add_bool"
- "(PMINFO_PKGINFO_PROP_PACKAGE_SYSTEM) failed\n");
-
- ret = pkgmgrinfo_pkginfo_filter_foreach_pkginfo(handle,
- __pkgid_list_cb, (void *)file_path);
- err_if(ret < 0,
- "pkgmgrinfo_pkginfo_filter_foreach_pkginfo() failed\n");
-
-catch:
- pkgmgrinfo_pkginfo_filter_destroy(handle);
- return ret;
-}
-
-static int __find_preload_rw_pkgid_from_db(GHashTable *preload_rw_table)
-{
- int ret;
- pkgmgrinfo_pkginfo_filter_h handle;
-
- ret = pkgmgrinfo_pkginfo_filter_create(&handle);
- retvm_if(ret != PMINFO_R_OK, -1,
- "pkginfo filter handle create failed\n");
-
- ret = pkgmgrinfo_pkginfo_filter_add_bool(handle,
- PMINFO_PKGINFO_PROP_PACKAGE_PRELOAD, 1);
- tryvm_if(ret != PMINFO_R_OK, ret = -1, "pkgmgrinfo_pkginfo_filter_add_bool"
- "(PMINFO_PKGINFO_PROP_PACKAGE_PRELOAD) failed\n");
-
- ret = pkgmgrinfo_pkginfo_filter_add_bool(handle,
- PMINFO_PKGINFO_PROP_PACKAGE_REMOVABLE, 1);
- tryvm_if(ret != PMINFO_R_OK, ret = -1, "pkgmgrinfo_pkginfo_filter_add_bool"
- "(PMINFO_PKGINFO_PROP_PACKAGE_REMOVABLE) failed\n");
-
- ret = pkgmgrinfo_pkginfo_filter_add_bool(handle,
- PMINFO_PKGINFO_PROP_PACKAGE_READONLY, 0);
- tryvm_if(ret != PMINFO_R_OK, ret = -1, "pkgmgrinfo_pkginfo_filter_add_bool"
- "(PMINFO_PKGINFO_PROP_PACKAGE_READONLY) failed\n");
-
- ret = pkgmgrinfo_pkginfo_filter_add_bool(handle,
- PMINFO_PKGINFO_PROP_PACKAGE_SYSTEM, 0);
- tryvm_if(ret != PMINFO_R_OK, ret = -1, "pkgmgrinfo_pkginfo_filter_add_bool"
- "(PMINFO_PKGINFO_PROP_PACKAGE_SYSTEM) failed\n");
-
- ret = pkgmgrinfo_pkginfo_filter_foreach_pkginfo(handle,
- __preload_rw_pkgid_list_cb, (void *)preload_rw_table);
- err_if(ret != PMINFO_R_OK,
- "pkgmgrinfo_pkginfo_filter_foreach_pkginfo() failed\n");
-
- ret = 0;
-catch:
- pkgmgrinfo_pkginfo_filter_destroy(handle);
- return ret;
-}
-
-static int __find_matched_pkgid_from_list(const char *source_file,
- const char *target_file)
-{
- retvm_if(source_file == NULL, -1, "source_file is NULL.\n");
- retvm_if(target_file == NULL, -1, "target_file is NULL.\n");
-
- FILE *fp = NULL;
- char buf[BUF_SIZE] = {0};
- char *pkgid = NULL;
- char *version = NULL;
- char *pkgtype = NULL;
-
- int same_pkg_cnt = 0;
- int update_pkg_cnt = 0;
- int insert_pkg_cnt = 0;
- int total_pkg_cnt = 0;
-
- int compare_result = 0;
- int operation;
-
- bool db_update;
-
- fp = fopen(source_file, "r");
- retvm_if(fp == NULL, -1, "Fail get : %s\n", source_file);
-
- _LOG("Searching...... inserted or Updated package \n");
-
- while (fgets(buf, BUF_SIZE, fp) != NULL) {
- __str_trim(buf);
-
- pkgid = __getvalue(buf, TOKEN_PKGID_STR, 1);
- if (pkgid == NULL)
- continue;
-
- version = __getvalue(buf, TOKEN_VERSION_STR, 1);
- if (version == NULL) {
- free(pkgid);
- continue;
- }
- pkgtype = __getvalue(buf, TOKEN_TYPE_STR, 1);
- if (pkgtype == NULL) {
- free(version);
- free(pkgid);
- continue;
- }
-
- operation = PKG_NEED_NOTHING;
- compare_result = __compare_pkgid((char *)target_file, pkgid,
- version, &db_update);
- if (compare_result == PKG_IS_NOT_EXIST) {
- _LOG("pkgid[%s] is installed, Start install\n", pkgid);
- operation = PKG_NEED_INSTALL;
- insert_pkg_cnt++;
- } else if (compare_result == PKG_IS_SAME) {
- if (db_update) {
- operation = PKG_NEED_RWUNINSTALL;
- update_pkg_cnt++;
- } else {
- operation = PKG_NEED_NOTHING;
- same_pkg_cnt++;
- }
- } else if (compare_result == PKG_IS_UPDATED) {
- if (db_update) {
- operation = PKG_NEED_UPDATE_TO_RO;
- } else {
- operation = PKG_NEED_ROUPDATE;
- }
- update_pkg_cnt++;
- }
-
- total_pkg_cnt++;
- __send_args_to_backend(pkgid, pkgtype, operation);
-
- memset(buf, 0x00, BUF_SIZE);
- FREE_AND_NULL(pkgid);
- FREE_AND_NULL(version);
- FREE_AND_NULL(pkgtype);
- }
-
- _LOG("-------------------------------------------------------\n");
- _LOG("[Total pkg=%d, same pkg=%d, updated pkg=%d, "
- "inserted package=%d]\n",
- total_pkg_cnt, same_pkg_cnt, update_pkg_cnt, insert_pkg_cnt);
- _LOG("-------------------------------------------------------\n");
-
- if (fp != NULL)
- fclose(fp);
-
- return 0;
-}
-
-static bool __find_pkgid_from_rw_list(const char *pkgid)
-{
- if (pkgid == NULL)
- return false;
-
- bool ret = false;
- FILE *fp = NULL;
- char buf[BUF_SIZE] = {0};
- char *preload_rw_pkgid = NULL;
-
- fp = fopen(PRELOAD_RW_PKG_LIST, "r");
- retvm_if(fp == NULL, -1, "Failed to open : %s\n", PRELOAD_RW_PKG_LIST);
-
- while (fgets(buf, BUF_SIZE, fp) != NULL) {
- __str_trim(buf);
-
- preload_rw_pkgid = __getvalue(buf, TOKEN_PKGID_STR, 1);
- if (preload_rw_pkgid == NULL) {
- _LOG("Failed to get pkgidstring[%s]\n", buf);
- continue;
- }
-
- if (strcmp(pkgid, preload_rw_pkgid) == 0) {
- _LOG("pkgid[%s] is converted to preload rw pkg\n", pkgid);
- FREE_AND_NULL(preload_rw_pkgid);
- ret = true;
- break;
- }
- FREE_AND_NULL(preload_rw_pkgid);
- }
-
- fclose(fp);
- return ret;
-}
-
-static int __unzip_file_only_to_path(char *dest_path, char *unzip_to)
-{
- const char *unzip_argv[] = { "/usr/bin/unzip", "-joXqq",
- OPT_ZIP_FILE, dest_path, "-d", unzip_to, NULL };
- int ret = __xsystem(unzip_argv);
-
- return ret;
-}
-
-static int __unzip_files(char *dest_path)
-{
- const char *unzip_argv[] = { "/usr/bin/unzip", "-oXqq",
- OPT_ZIP_FILE, dest_path, "-d", "/", NULL };
- int ret = __xsystem(unzip_argv);
-
- return ret;
-}
-
-static int __install_preload_rw(const char *pkgid, const char *version,
- const char *pkgtype, GHashTable *preload_rw_table)
-{
- if (pkgid == NULL || version == NULL || pkgtype == NULL)
- return -1;
-
- int index;
- int ret;
- char buf[BUF_SIZE] = {0};
-
- /* copy modified manifest */
- snprintf(buf, BUF_SIZE, "%s/%s.xml",
- (tzplatform_getenv(TZ_SYS_RW_PACKAGES) + 1), pkgid);
- ret = __unzip_files(buf);
- if (ret != 0) {
- _LOG("Failed to unzip file from backup[%s]\n", buf);
- return ret;
- }
-
- /* copy stored signature */
- snprintf(buf, BUF_SIZE, "%s/signatures/%s.txt",
- (tzplatform_getenv(TZ_SYS_SHARE) + 1), pkgid);
- ret = __unzip_files(buf);
- if (ret != 0) {
- _LOG("Failed to unzip file from backup[%s]\n", buf);
- return ret;
- }
-
- /* copy RO and RW components */
- for (index = 0; index < BUF_SIZE; index++) {
- if (unzip_path[index] == NULL)
- break;
-
- snprintf(buf, BUF_SIZE, "%s/%s/*", unzip_path[index], pkgid);
- ret = __unzip_files(buf);
- if (ret != 0) {
- _LOG("Failed to unzip file from backup[%s]\n", buf);
- return ret;
- }
- }
-
- ret = __insert_preload_rw_table(preload_rw_table, pkgid, version,
- pkgtype);
- retvm_if(ret < 0, -1, "__insert_preload_rw_table fail\n");
-
- __send_args_to_backend(pkgid, pkgtype, PKG_NEED_PRELOADRW_INSTALL);
- return ret;
-}
-
-static void __convert_preload_to_rw(const char *pkgid, const char *version,
- const char *pkgtype, GHashTable *preload_rw_table)
-{
- if (pkgid == NULL || version == NULL || pkgtype == NULL)
- return;
- char buf[BUF_SIZE] = {0};
- int ret;
-
- snprintf(buf, BUF_SIZE, "%s/skel/apps_rw/%s",
- tzplatform_getenv(TZ_SYS_ETC), pkgid);
-
- __send_args_to_backend(pkgid, pkgtype, PKG_NEED_RO_UNINSTALL_KEEPRWDATA);
- ret = remove_directory(buf);
- if (ret != 0)
- _LOG("Failed to remove directory[%s]\n", buf);
-
- ret = __install_preload_rw(pkgid, version, pkgtype, preload_rw_table);
- if (ret != 0) {
- _LOG("Failed install preload rw pkg[%s]\n", pkgid);
- return;
- }
-}
-
-static int __find_deleted_pkgid_from_list(const char *source_file,
- const char *target_file, GHashTable *preload_rw_table)
-{
- retvm_if(source_file == NULL, -1, "source_file is NULL.\n");
- retvm_if(target_file == NULL, -1, "target_file is NULL.\n");
-
- FILE *fp = NULL;
- char buf[BUF_SIZE] = {0};
- char *pkgid;
- char *version;
- char *pkgtype = NULL;
- char *update = NULL;
- bool is_preload_rw_pkg;
- bool xml_update;
- int deleted_pkg_cnt = 0;
- int modified_pkg_cnt = 0;
- int total_pkg_cnt = 0;
- int compare_result = 0;
-
- fp = fopen(source_file, "r");
- retvm_if(fp == NULL, -1, "Fail get : %s\n", source_file);
-
- _LOG("Searching...... deleted package \n");
-
- while (fgets(buf, BUF_SIZE, fp) != NULL) {
- __str_trim(buf);
-
- pkgid = __getvalue(buf, TOKEN_PKGID_STR, 1);
- version = __getvalue(buf, TOKEN_VERSION_STR, 1);
- pkgtype = __getvalue(buf, TOKEN_TYPE_STR, 1);
- if (pkgid == NULL || version == NULL || pkgtype == NULL) {
- _LOG("Failed to get pkg info from string[%s]\n", buf);
- FREE_AND_NULL(pkgid);
- FREE_AND_NULL(version);
- FREE_AND_NULL(pkgtype);
- continue;
- }
-
- compare_result = __compare_pkgid((char *)target_file, pkgid,
- version, &xml_update);
- if (compare_result == PKG_IS_NOT_EXIST) {
- update = __getvalue(buf, TOKEN_UPDATE_STR, 1);
- if (update == NULL) {
- FREE_AND_NULL(pkgid);
- FREE_AND_NULL(version);
- FREE_AND_NULL(pkgtype);
- continue;
- }
-
- is_preload_rw_pkg = __find_pkgid_from_rw_list(pkgid);
-
- if (!strncmp(update, "false", strlen("false"))) {
- if (is_preload_rw_pkg) {
- __convert_preload_to_rw(pkgid, version,
- pkgtype,
- preload_rw_table);
- modified_pkg_cnt++;
- } else {
- __send_args_to_backend(pkgid, pkgtype,
- PKG_NEED_UNINSTALL);
- deleted_pkg_cnt++;
- }
- } else {
- __send_args_to_backend(pkgid, pkgtype,
- PKG_NEED_UPDATE_TO_RW);
- modified_pkg_cnt++;
- if (is_preload_rw_pkg) {
- __send_args_to_backend(pkgid, pkgtype,
- PKG_NEED_RWUNINSTALL);
- __install_preload_rw(pkgid, version,
- pkgtype,
- preload_rw_table);
- }
- }
- }
- total_pkg_cnt++;
-
- memset(buf, 0x00, BUF_SIZE);
- FREE_AND_NULL(pkgid);
- FREE_AND_NULL(version);
- FREE_AND_NULL(pkgtype);
- FREE_AND_NULL(update);
- }
-
- _LOG("-------------------------------------------------------\n");
- _LOG("[Total pkg=%d, deleted package=%d, modified package=%d]\n",
- total_pkg_cnt, deleted_pkg_cnt, modified_pkg_cnt);
- _LOG("-------------------------------------------------------\n");
-
- if (fp != NULL)
- fclose(fp);
-
- return 0;
-
-}
-
-static int __get_pkgid_list_from_db_and_xml()
-{
- _LOG("=======================================================\n");
- _LOG("RO preload package fota\n");
- _LOG("=======================================================\n");
-
- int ret = 0;
- char updated_preload_rw_list[BUF_SIZE];
-
- /*get pkg info on pkgmgr db, it means old version */
- ret = __find_preload_pkgid_from_db(PKGID_LIST_FROM_DB_FILE);
- retvm_if(ret < 0, -1, "__find_preload_pkgid_from_db fail.\n");
-
- _LOG("Make pkgid list from db success!! \n");
-
- /*get pkg info on xml, it means new version */
- ret = __find_preload_pkgid_from_xml(PKGID_LIST_FROM_XML_FILE,
- USR_MANIFEST_DIRECTORY);
- retvm_if(ret < 0, -1, "__find_preload_pkgid_from_xml fail.\n");
-
- _LOG("Make pkgid list from xml success!! \n");
-
-
- /*get preload rw pkg info on xml from opt.zip, it means new version */
- snprintf(updated_preload_rw_list, sizeof(updated_preload_rw_list), "%s",
- ALL_PRELOAD_RW_PKG_LIST);
- ret = __unzip_file_only_to_path(updated_preload_rw_list + 1,
- (char *)PKGMGR_FOTA_PATH);
- if (ret != 0) {
- _LOG("Failed to unzip file from backup[%s]\n",
- updated_preload_rw_list);
- return ret;
- }
-
- _LOG("Make rw pkgid list from xml success!! \n");
-
- return 0;
-}
-
-static int __process_ro_fota(GHashTable *preload_rw_table)
-{
- int ret;
- long starttime;
- long endtime;
- struct timeval tv;
-
- xmlInitParser();
-
- gettimeofday(&tv, NULL);
- starttime = tv.tv_sec * 1000l + tv.tv_usec / 1000l;
-
- /* find deleted pkgid */
- ret = __find_deleted_pkgid_from_list(PKGID_LIST_FROM_DB_FILE,
- PKGID_LIST_FROM_XML_FILE, preload_rw_table);
- err_if(ret < 0, "__find_deleted_pkgid_from_list fail.\n");
-
- /* find updated, inserted pkgid */
- ret = __find_matched_pkgid_from_list(PKGID_LIST_FROM_XML_FILE,
- PKGID_LIST_FROM_DB_FILE);
- err_if(ret < 0, "__find_matched_pkgid_from_list fail.\n");
-
- gettimeofday(&tv, NULL);
- endtime = tv.tv_sec * 1000l + tv.tv_usec / 1000l;
-
- _LOG("=======================================================\n");
- _LOG("End RO process[time : %ld ms]\n", endtime - starttime);
- _LOG("=======================================================\n");
-
- xmlCleanupParser();
-
- return 0;
-}
-
-static void __remove_pkg_directories(const char *pkgid)
-{
- int i;
- int ret;
- char buf[BUF_SIZE];
- const char *base_dirs[] = {
- OPT_USR_MANIFEST_DIRECTORY,
- RW_PKG_DIRECTORY,
- SKEL_DIRECTORY,
- NULL
- };
-
- for (i = 0; base_dirs[i] != NULL; i++) {
- ret = snprintf(buf, sizeof(buf), "%s/%s", base_dirs[i], pkgid);
- if (ret < 0 || ret > sizeof(buf)) {
- printf("snprintf fail\n");
- continue;
- }
- if (!access(buf, F_OK)) {
- if (remove_directory(buf))
- _LOGE("failed to remove directory: %s", buf);
- }
- }
-}
-
-static int __process_rw_fota(GHashTable *preload_rw_table)
-{
- FILE *fp = NULL;
- char buf[BUF_SIZE] = {0};
- int ret = -1;
- char *pkgid = NULL;
- char *list_version = NULL;
- char *db_stored_version = NULL;
- char *pkgtype = NULL;
- char *version = NULL;
- pkgmgrinfo_pkginfo_h handle = NULL;
- int compare = PMINFO_VERSION_SAME;
- long total_time = 0;
-
- long starttime;
- long endtime;
- struct timeval tv;
- bool is_deleted_pkg;
-
- _LOG("=======================================================\n");
- _LOG("RW preload package fota\n");
- _LOG("=======================================================\n");
-
- fp = fopen(PRELOAD_RW_PKG_LIST, "r");
- retvm_if(fp == NULL, -1, "Fail get : %s\n", PRELOAD_RW_PKG_LIST);
-
- while (fgets(buf, BUF_SIZE, fp) != NULL) {
- __str_trim(buf);
-
- gettimeofday(&tv, NULL);
- starttime = tv.tv_sec * 1000l + tv.tv_usec / 1000l;
-
- pkgid = __getvalue(buf, TOKEN_PKGID_STR, 1);
- if (pkgid == NULL)
- continue;
-
- ret = pkgmgrinfo_pkginfo_get_pkginfo(pkgid, &handle);
- if (ret == PMINFO_R_OK) {
- list_version = __getvalue(buf, TOKEN_VERSION_STR, 1);
- if (list_version == NULL) {
- FREE_AND_NULL(pkgid);
- continue;
- }
- ret = pkgmgrinfo_pkginfo_get_version(handle, &db_stored_version);
- ret = pkgmgrinfo_compare_package_version(db_stored_version,
- list_version, &compare);
- if (ret != PMINFO_R_OK) {
- _LOG("can not compare pkg version[%s]\n", pkgid);
- pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
- handle = NULL;
- FREE_AND_NULL(pkgid);
- FREE_AND_NULL(list_version);
- continue;
- }
-
- if (compare != PMINFO_VERSION_NEW) {
- /* package version is not update on FOTA. */
- _LOG("pkgid[%s] is not updated\n", pkgid);
- pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
- handle = NULL;
- FREE_AND_NULL(pkgid);
- FREE_AND_NULL(list_version);
- continue;
- }
-
- _LOG("pkgid[%s] is updated, need to upgrade "
- "from version [%s] to [%s]\n",
- pkgid, db_stored_version, list_version);
- } else {
- is_deleted_pkg = __check_deleted_pkg(preload_rw_table, pkgid);
- if (is_deleted_pkg) {
- _LOG("pkgid[%s] is deleted pkg\n", pkgid);
- __delete_preload_rw_table(preload_rw_table,
- pkgid);
- /* maybe there are pkg directories which are
- * extracted from opt.zip by FOTA
- */
- __remove_pkg_directories(pkgid);
- FREE_AND_NULL(pkgid);
- continue;
- }
- _LOG("pkgid[%s] is new\n", pkgid);
- }
-
- version = __getvalue(buf, TOKEN_VERSION_STR, 1);
- pkgtype = __getvalue(buf, TOKEN_TYPE_STR, 1);
- __install_preload_rw(pkgid, version, pkgtype, preload_rw_table);
-
- FREE_AND_NULL(pkgid);
- FREE_AND_NULL(pkgtype);
- FREE_AND_NULL(version);
-
- if (handle)
- pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
-
- gettimeofday(&tv, NULL);
- endtime = tv.tv_sec * 1000l + tv.tv_usec / 1000l;
- total_time += (int)(endtime - starttime);
- _LOG("finish request [time : %d ms]\n",
- (int)(endtime - starttime));
- }
- fclose(fp);
-
- return 0;
-}
-
-static int __check_tmp_all_preload_rw_pkg_list()
-{
- char buf[BUF_SIZE];
- char tmp_path[BUF_SIZE];
- snprintf(tmp_path, BUF_SIZE, "%s.tmp", ALL_PRELOAD_RW_PKG_LIST);
- if (access(tmp_path, F_OK) == 0) {
- if (rename(tmp_path, ALL_PRELOAD_RW_PKG_LIST)) {
- _LOG("rename tmp all preload rw pkg list fail : %s\n",
- strerror_r(errno, buf, sizeof(buf)));
- return -1;
- }
- }
- return 0;
-}
-
-static int __fill_preload_rw_table(GHashTable *preload_rw_table)
-{
- FILE *fp;
- char buf[BUF_SIZE];
- char *pkgid;
- char *version;
- char *type;
-
- fp = fopen(ALL_PRELOAD_RW_PKG_LIST, "r");
- retvm_if(fp == NULL, -1, "Fail get : %s\n", ALL_PRELOAD_RW_PKG_LIST);
-
- while (fgets(buf, BUF_SIZE, fp) != NULL) {
- __str_trim(buf);
-
- pkgid = __getvalue(buf, TOKEN_PKGID_STR, 1);
- if (pkgid == NULL) {
- _LOG("pkgid is null\n");
- continue;
- }
-
- version = __getvalue(buf, TOKEN_VERSION_STR, 1);
- if (version == NULL) {
- _LOG("version is null\n");
- version = strdup("");
- if (version == NULL) {
- _LOGE("out of memory\n");
- FREE_AND_NULL(pkgid);
- continue;
- }
- }
-
- type = __getvalue(buf, TOKEN_TYPE_STR, 1);
- if (type == NULL) {
- _LOG("type is null\n");
- type = strdup("");
- if (type == NULL) {
- _LOGE("out of memory\n");
- FREE_AND_NULL(version);
- FREE_AND_NULL(pkgid);
- continue;
- }
- }
-
- __insert_preload_rw_table(preload_rw_table, pkgid, version,
- type);
- FREE_AND_NULL(pkgid);
- FREE_AND_NULL(version);
- FREE_AND_NULL(type);
- }
- fclose(fp);
-
- return 0;
-}
-
-#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 \
- _LOG("chsmack -a %s %s", DB_LABEL, x); \
-} while (0)
-
-static int __set_db_permission(const char *path)
-{
- int fd;
- struct stat sb;
- mode_t mode;
- uid_t uid;
- struct passwd pwd;
- struct passwd *result;
- char buf[BUF_SIZE];
- int ret;
-
- ret = getpwnam_r(APPFW_USER, &pwd, buf, sizeof(buf), &result);
- if (result == NULL) {
- if (ret == 0)
- _LOGE("no such user: %s", APPFW_USER);
- else
- _LOGE("getpwnam_r failed: %d", errno);
- return -1;
- }
- uid = pwd.pw_uid;
-
- 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;
- }
- fd = open(path, O_RDONLY);
- if (fd == -1) {
- _LOGE("open %s failed: %d", path, errno);
- return -1;
- }
- ret = fstat(fd, &sb);
- if (ret == -1) {
- _LOGE("stat %s failed: %d", path, errno);
- close(fd);
- return -1;
- }
- if (S_ISLNK(sb.st_mode)) {
- _LOGE("%s is symlink!", path);
- close(fd);
- return -1;
- }
- ret = fchown(fd, uid, pwd.pw_gid);
- if (ret == -1) {
- _LOGE("fchown %s failed: %d", path, errno);
- close(fd);
- return -1;
- }
-
- mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH;
- if (strstr(path, CERT_DBPATH))
- mode |= S_IWOTH;
- ret = fchmod(fd, mode);
- if (ret == -1) {
- _LOGE("fchmod %s failed: %d", path, errno);
- close(fd);
- return -1;
- }
- fsync(fd);
- close(fd);
- SET_SMACK_LABEL(path);
-
- return 0;
-}
-
-static int __create_backup_flag(const char *path)
-{
- int fd;
- char temp_buf[8192] = {'\0', };
-
- snprintf(temp_buf, sizeof(temp_buf), "%s.bck.flag", path);
-
- fd = open(temp_buf, O_CREAT | O_WRONLY, 0644);
- if (fd == -1) {
- _LOG("failed to create flag file %s, %d", temp_buf, errno);
- return -1;
- }
- close(fd);
-
- return 0;
-}
-
-static int __check_backup_flag(const char *path)
-{
- char temp_buf[8192] = {'\0', };
-
- snprintf(temp_buf, sizeof(temp_buf), "%s.bck.flag", path);
- if (access(temp_buf, F_OK) != 0)
- return -1;
-
- return 0;
-}
-
-static int __remove_backup_flag(const char *path)
-{
- char temp_buf[8192] = {'\0', };
-
- snprintf(temp_buf, sizeof(temp_buf), "%s.bck.flag", path);
- if (remove(temp_buf)) {
- _LOG("cannot remove flag file(%s): %d", temp_buf, errno);
- return -1;
- }
-
- return 0;
-}
-
-static int __check_and_restore_backup(const char *origin_path) {
- char backup_path[BUF_SIZE];
- char buf[BUF_SIZE];
- snprintf(backup_path, BUF_SIZE, "%s.bck", origin_path);
-
- // if backup flag exists, it means the previous backup process aborted.
- if (access(backup_path, F_OK) && __check_backup_flag(origin_path))
- return 0;
-
- if (access(origin_path, F_OK) == 0) {
- if (remove(origin_path)) {
- _LOG("cannot remove path(%s) : %s\n", origin_path,
- strerror_r(errno, buf, sizeof(buf)));
- return -1;
- }
- }
-
- if (rename(backup_path, origin_path)) {
- _LOG("fail to rename %s to %s : %s\n", backup_path, origin_path,
- strerror_r(errno, buf, sizeof(buf)));
- return -1;
- }
-
- return 0;
-}
-
-static int __check_and_restore_backup_dbs() {
- if (__check_and_restore_backup(DBPATH))
- return -1;
-
- if (__check_and_restore_backup(JOURNAL_DBPATH))
- return -1;
-
- if (__check_and_restore_backup(CERT_DBPATH))
- return -1;
-
- if (__check_and_restore_backup(JOURNAL_CERT_DBPATH))
- return -1;
-
- return 0;
-}
-
-static int __backup_file(const char *src_path, const char *dest_path)
-{
- int ret = 0;
- int rc;
- FILE *src = NULL;
- FILE *dest = NULL;
- char temp_buf[8192] = {'\0', };
- size_t size_of_char = sizeof(char);
- size_t size_of_temp_buf = sizeof(temp_buf);
-
- retvm_if(src_path == NULL || dest_path == NULL,
- -1, "Invalid parameters");
-
- retvm_if(access(src_path, F_OK) != 0, -1,
- "File(%s) is not exist", src_path);
-
- // if backup flag exists, it means the previous backup process aborted.
- if (__check_backup_flag(src_path)) {
- if (access(dest_path, F_OK) == 0) {
- if (remove(dest_path))
- _LOG("Failed to remove uncompleted backup file "
- "%s: %d", dest_path, errno);
- return -1;
- }
- } else {
- if (__create_backup_flag(src_path)) {
- _LOG("failed to create backup flag");
- return -1;
- }
- }
-
- src = fopen(src_path, "r");
- tryvm_if(src == NULL, ret = -1, "Failed to open : %s\n", src_path);
-
- dest = fopen(dest_path, "w");
- tryvm_if(dest == NULL, ret = -1, "Failed to open : %s\n", dest_path);
-
- while (!feof(src)) {
- rc = fread(temp_buf, size_of_char, size_of_temp_buf, src);
- fwrite(temp_buf, size_of_char, rc, dest);
- }
-
- fsync(fileno(dest));
-
-catch:
- if (src)
- fclose(src);
-
- if (dest)
- fclose(dest);
-
- __remove_backup_flag(src_path);
-
- return ret;
-}
-
-static int __backup_db(const char *src_path, const char *dest_path) {
- if (__backup_file(src_path, dest_path) != 0)
- return -1;
-
- if (__set_db_permission(dest_path) != 0)
- return -1;
-
- return 0;
-}
-
-static int __make_backup_dbs() {
- int ret = 0;
- char parser_db_bck[BUF_SIZE];
- char parser_db_journal_bck[BUF_SIZE];
- char cert_db_bck[BUF_SIZE];
- char cert_db_journal_bck[BUF_SIZE];
-
- snprintf(parser_db_bck, BUF_SIZE, "%s.bck", DBPATH);
- snprintf(parser_db_journal_bck, BUF_SIZE, "%s.bck", JOURNAL_DBPATH);
- snprintf(cert_db_bck, BUF_SIZE, "%s.bck", CERT_DBPATH);
- snprintf(cert_db_journal_bck, BUF_SIZE, "%s.bck", JOURNAL_CERT_DBPATH);
-
- tryvm_if(__backup_db(DBPATH, parser_db_bck) == -1,
- ret = -1, "Fail to backup [%s] to [%s]\n",
- DBPATH, parser_db_bck);
-
- tryvm_if(__backup_db(JOURNAL_DBPATH, parser_db_journal_bck) == -1,
- ret = -1, "Fail to backup [%s] to [%s]\n",
- JOURNAL_DBPATH, parser_db_journal_bck);
-
- tryvm_if(__backup_db(CERT_DBPATH, cert_db_bck) == -1,
- ret = -1, "Fail to backup [%s] to [%s]\n",
- CERT_DBPATH, cert_db_bck);
-
- tryvm_if(__backup_db(JOURNAL_CERT_DBPATH, cert_db_journal_bck) == -1,
- ret = -1, "Fail to backup [%s] to [%s]\n",
- JOURNAL_CERT_DBPATH, cert_db_journal_bck);
-
- return 0;
-
-catch:
- remove(parser_db_bck);
- remove(parser_db_journal_bck);
- remove(cert_db_bck);
- remove(cert_db_journal_bck);
-
- return ret;
-}
-
-static void __remove_backup_path(const char *origin_path) {
- char backup_path[BUF_SIZE];
-
- snprintf(backup_path, BUF_SIZE, "%s.bck", origin_path);
-
- if (remove(backup_path))
- _LOG("cannot remove backup file(%s): %d", backup_path, errno);
-}
-
-static void __remove_backup_dbs() {
- __remove_backup_path(DBPATH);
- __remove_backup_path(JOURNAL_DBPATH);
- __remove_backup_path(CERT_DBPATH);
- __remove_backup_path(JOURNAL_CERT_DBPATH);
-}
-
-int main(int argc, char *argv[])
-{
- GHashTable *preload_rw_table;
- int ret = 0;
-
- ret = __check_and_restore_backup_dbs();
- retvm_if(ret < 0, -1, "__check_and_restore_backup_dbs is failed.\n");
-
- ret = __make_backup_dbs();
- retvm_if(ret < 0, -1, "__make_backup_dbs is failed.\n");
-
- /* check pkgmgr-fota dir, if it is not, then exit */
- ret = __check_pkgmgr_fota_dir();
- retvm_if(ret < 0, -1, "__check_pkgmgr_fota_dir is failed.\n");
-
- /* clean pkgid list file */
- ret = __remove_pkgid_list();
- err_if(ret < 0, "remove[%s] failed\n", FOTA_RESULT_FILE);
-
- /* get pkgid from orginal pkgmgr db */
- ret = __get_pkgid_list_from_db_and_xml();
- retvm_if(ret < 0, -1, "__get_pkgid_list_from_db_and_xml is failed.\n");
-
- //__get_pkginfo_from_opt();
-
- ret = __check_tmp_all_preload_rw_pkg_list();
- retvm_if(ret < 0, -1,
- "__check_tmp_all_preload_rw_pkg_list is failed.\n");
-
- preload_rw_table = g_hash_table_new_full(
- g_str_hash, g_str_equal, free, __free_pkginfo);
- if (__fill_preload_rw_table(preload_rw_table) < 0) {
- ret = __find_preload_rw_pkgid_from_db(preload_rw_table);
- retvm_if(ret < 0, -1, "__find_preload_rw_pkgid_from_db is failed\n");
- }
-
- if (argc == 1) {
- ret = __process_ro_fota(preload_rw_table);
- if (ret < 0) {
- g_hash_table_destroy(preload_rw_table);
- _LOGE("__process_ro_fota is failed.\n");
- return EXIT_FAILURE;
- }
- ret = __process_rw_fota(preload_rw_table);
- if (ret < 0) {
- g_hash_table_destroy(preload_rw_table);
- _LOGE("__process_rw_fota is failed.\n");
- return EXIT_FAILURE;
- }
- } else {
- if (strcmp(argv[1], "-rof") == 0) {
- ret = __process_ro_fota(preload_rw_table);
- if (ret < 0) {
- g_hash_table_destroy(preload_rw_table);
- _LOGE("__process_ro_fota is failed.\n");
- return EXIT_FAILURE;
- }
- } else if (strcmp(argv[1], "-rwf") == 0) {
- ret = __process_rw_fota(preload_rw_table);
- if (ret < 0) {
- g_hash_table_destroy(preload_rw_table);
- _LOGE("__process_rw_fota is failed.\n");
- return EXIT_FAILURE;
- }
- } else {
- fprintf(stderr, "not supported operand\n");
- }
- }
- __make_preload_rw_list(preload_rw_table);
- g_hash_table_destroy(preload_rw_table);
- __remove_backup_dbs();
-
- return EXIT_SUCCESS;
-}
--- /dev/null
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * 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 <unistd.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include "backend_invoker.hh"
+#include "logging.hh"
+
+namespace common_fota {
+
+BackendInvoker::BackendInvoker(std::string pkgid, PkgType type, PkgLocation loc,
+ PkgOperation op, bool removable) {
+ if (type == PkgType::WGT) {
+ parameters_.push_back("/usr/bin/wgt-backend");
+ } else {
+ parameters_.push_back("/usr/bin/tpk-backend");
+ }
+
+ if (op == PkgOperation::INSTALL || op == PkgOperation::UPDATE) {
+ parameters_.push_back("-y");
+ parameters_.push_back(std::move(pkgid));
+ if (loc == PkgLocation::RO) {
+ parameters_.push_back("--preload");
+ parameters_.push_back("--partial-rw");
+ } else {
+ if (!removable)
+ parameters_.push_back("--no-remove");
+ parameters_.push_back("--preload-rw");
+ }
+ parameters_.push_back("--skip-check-reference");
+ } else if (op == PkgOperation::UNINSTALL) {
+ parameters_.push_back("-d");
+ parameters_.push_back(std::move(pkgid));
+ if (loc == PkgLocation::RO)
+ parameters_.push_back("--preload");
+ parameters_.push_back("--force-remove");
+ parameters_.push_back("--partial-rw");
+ } else if (op == PkgOperation::UNINSTALL_KEEP_RW_DATA) {
+ parameters_.push_back("-d");
+ parameters_.push_back(std::move(pkgid));
+ if (loc == PkgLocation::RO)
+ parameters_.push_back("--preload");
+ parameters_.push_back("--force-remove");
+ parameters_.push_back("--keep-rwdata");
+ }
+}
+
+int BackendInvoker::Run() const {
+ const char* param[parameters_.size() + 1] = { nullptr, };
+
+ int i = 0;
+ for (auto& str : parameters_) {
+ param[i++] = str.c_str();
+ }
+
+ return XSystem(param);
+}
+
+int BackendInvoker::XSystem(const char *argv[]) {
+ int status = 0;
+ pid_t pid;
+
+ std::string cmd;
+ for (int i = 0; argv[i] != nullptr; i++) {
+ cmd += argv[i];
+ cmd += " ";
+ }
+ LOG(DEBUG) << "Cmd: " << cmd;
+
+ pid = fork();
+ switch (pid) {
+ case -1:
+ LOG(ERROR) << "fork failed ";
+ return -1;
+ case 0:
+ /* child */
+ execvp(argv[0], (char *const *)argv);
+ _exit(-1);
+ default:
+ /* parent */
+ break;
+ }
+ if (waitpid(pid, &status, 0) == -1) {
+ LOG(ERROR) << "waitpid failed";
+ return -1;
+ }
+ if (WIFSIGNALED(status)) {
+ LOG(ERROR) << "signal";
+ return -1;
+ }
+ if (!WIFEXITED(status)) {
+ LOG(ERROR) << "should not happen";
+ return -1;
+ }
+
+ return WEXITSTATUS(status);
+}
+
+} // namespace common_fota
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * 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 <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <fstream>
+#include <memory>
+#include <sstream>
+#include <string>
+#include <utility>
+
+#include "logging.hh"
+#include "file_logbackend.hh"
+
+
+namespace utils {
+
+FileLogBackend::FileLogBackend(std::string file_name, int rotation_size,
+ int max_rotation)
+ : file_name_(std::move(file_name)), rotation_size_(rotation_size),
+ max_rotation_(max_rotation), log_stream_(
+ std::unique_ptr<std::ostringstream>(new std::ostringstream())) {
+}
+
+
+void FileLogBackend::WriteLog(LogLevel level, const std::string& /* tag */,
+ const std::string& logstr) {
+ if (level != LogLevel::LOG_DEBUG)
+ *log_stream_ << GetTimeStamp() << GetPid() << logstr << std::endl;
+}
+
+void FileLogBackend::WriteLogToFile() {
+ if (file_name_.empty())
+ return;
+
+ int size = GetFileSize(file_name_);
+ if (size > rotation_size_)
+ if (!Rotate())
+ return;
+
+ std::ofstream ofs(file_name_.c_str(), std::ios::app);
+ ofs << log_stream_->str();
+ ofs.close();
+
+ // clean the log stream
+ log_stream_->str("");
+ log_stream_->clear();
+}
+
+bool FileLogBackend::Rotate() {
+ for (int i = max_rotation_; i > 0; i--) {
+ std::string old_log = file_name_ + "." + std::to_string(i);
+ // the oldest log will be removed
+ if (i == max_rotation_) {
+ if (std::remove(old_log.c_str()) != 0)
+ return false;
+ } else {
+ std::string new_log = file_name_ + "." + std::to_string(i + 1);
+ if (std::rename(old_log.c_str(), new_log.c_str()) != 0)
+ return false;
+ }
+ }
+ std::string new_log = file_name_ + ".1";
+ if (std::rename(file_name_.c_str(), new_log.c_str()) != 0)
+ return false;
+
+ return true;
+}
+
+int FileLogBackend::GetFileSize(const std::string& file_name) {
+ struct stat sb;
+ int ret = stat(file_name.c_str(), &sb);
+ return ret == 0 ? sb.st_size : -1;
+}
+
+std::string FileLogBackend::GetTimeStamp() {
+ struct timespec ts;
+ clock_gettime(CLOCK_REALTIME, &ts);
+
+ time_t seconds = ts.tv_sec;
+ struct tm gmt;
+ if (!gmtime_r(&seconds, &gmt))
+ return "|";
+ int32_t miliseconds = ts.tv_nsec / 1000000;
+
+ char buf[32];
+ strftime(buf, sizeof(buf), "%Y%m%d.%H%M%S", &gmt);
+ char timestamp[64];
+ snprintf(timestamp, sizeof(timestamp), "%s.%03dUTC|", buf, miliseconds);
+
+ return timestamp;
+}
+
+std::string FileLogBackend::GetPid() {
+ return std::to_string(getpid()) + "|";
+}
+
+} // namespace utils
--- /dev/null
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * 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 "logging.hh"
+
+namespace utils {
+
+log_priority LogLevelToPriority(LogLevel level) {
+ switch (level) {
+ case LogLevel::LOG_ERROR:
+ return log_priority::DLOG_ERROR;
+ case LogLevel::LOG_WARNING:
+ return log_priority::DLOG_WARN;
+ case LogLevel::LOG_INFO:
+ return log_priority::DLOG_INFO;
+ case LogLevel::LOG_DEBUG:
+ return log_priority::DLOG_DEBUG;
+ default:
+ return log_priority::DLOG_UNKNOWN;
+ }
+}
+
+} // namespace utils
--- /dev/null
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * 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 "pkg_finder.hh"
+#include "upgrader.hh"
+
+int main(int argc, char *argv[]) {
+ common_fota::PkgFinder finder;
+ common_fota::Upgrader upgrader;
+
+ if (!upgrader.Process(&finder))
+ return -1;
+
+ return 0;
+}
--- /dev/null
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * 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 <stdlib.h>
+#include <stdio.h>
+#include <dirent.h>
+#include <cstring>
+
+#include <algorithm>
+#include <cctype>
+
+#include <tzplatform_config.h>
+
+#include "logging.hh"
+#include "pkg_finder.hh"
+#include "backend_invoker.hh"
+
+#define ASCII(s) reinterpret_cast<const char*>(s)
+#define XMLCHAR(s) reinterpret_cast<const xmlChar*>(s)
+#define USR_MANIFEST_DIRECTORY tzplatform_getenv(TZ_SYS_RO_PACKAGES)
+#define PRELOAD_RW_LIST_FILE \
+ tzplatform_mkpath(TZ_SYS_GLOBALUSER_DATA, \
+ "pkgmgr/fota/.all_preload_rw_list")
+#define ALL_PRELOAD_RW_PKG_LIST "opt/usr/share/.all_preload_rw_list"
+#define PKGMGR_FOTA_PATH tzplatform_mkpath(TZ_SYS_GLOBALUSER_DATA, \
+ "pkgmgr/fota")
+
+
+using namespace std;
+
+namespace {
+constexpr char kOptZipFile[] = "/usr/system/RestoreDir/opt.zip";
+constexpr int kBufSize = 1024;
+constexpr char kSeperatorEnd = '"';
+constexpr char kSeperatorMid = ':';
+constexpr char kTokenTypeStr[] = "type=";
+constexpr char kTokenPkgidStr[] = "package=";
+constexpr char kTokenVersionStr[] = "version=";
+constexpr char kTokenRemoveStr[] = "removable=";
+} // namespace
+
+namespace common_fota {
+
+PkgFinder::PkgFinder() {
+ xmlInitParser();
+ manifest_dir_ = USR_MANIFEST_DIRECTORY;
+ preload_rw_list_path_ = PRELOAD_RW_LIST_FILE;
+ if (access(kOptZipFile, F_OK) != 0)
+ return;
+
+ int ret = UnzipFileOnlyToPath(ALL_PRELOAD_RW_PKG_LIST, PKGMGR_FOTA_PATH);
+ if (ret != 0) {
+ LOG(ERROR) << "Failed to unzip file from backup";
+ return;
+ }
+}
+
+PkgFinder::~PkgFinder() {
+ xmlCleanupParser();
+}
+
+int PkgFinder::UnzipFileOnlyToPath(const char* dest_path, const char* unzip_to) {
+ const char* unzip_argv[] = { "/usr/bin/unzip", "-joXqq",
+ kOptZipFile, dest_path, "-d", unzip_to, nullptr };
+ return BackendInvoker::XSystem(unzip_argv);
+}
+
+int PkgFinder::Find() {
+ if (FindPreloadPkgidFromDb(true) != 0) {
+ LOG(ERROR) << "FindPreloadPkgidFromDb(true) failed";
+ return -1;
+ }
+
+ if (FindPreloadPkgidFromDb(false) != 0) {
+ LOG(ERROR) << "FindPreloadPkgidFromDb(false) failed";
+ return -1;
+ }
+
+ if (FindPreloadPkgidFromXml(manifest_dir_) != 0) {
+ LOG(ERROR) << "FindPreloadPkgidFromXml(" << manifest_dir_ << ") failed";
+ return -1;
+ }
+
+ if (FindPreloadPkgidFromFile() != 0) {
+ LOG(ERROR) << "FindPreloadPkgidFromFile failed";
+ return -1;
+ }
+
+ return 0;
+}
+
+void PkgFinder::SetManifestDir(std::string dir) {
+ manifest_dir_ = std::move(dir);
+}
+
+void PkgFinder::SetPreloadRwListPath(std::string path) {
+ preload_rw_list_path_ = std::move(path);
+}
+
+int PkgFinder::PkgidListCb(const pkgmgrinfo_pkginfo_h handle, void* user_data) {
+ char* pkgid = nullptr;
+ int ret = -1;
+ ret = pkgmgrinfo_pkginfo_get_pkgid(handle, &pkgid);
+ if (ret < 0)
+ return 0;
+
+ char* version = nullptr;
+ ret = pkgmgrinfo_pkginfo_get_version(handle, &version);
+ if (ret < 0)
+ return 0;
+
+ char* type = nullptr;
+ ret = pkgmgrinfo_pkginfo_get_type(handle, &type);
+ if (ret < 0)
+ return 0;
+
+ PkgFinder* finder = static_cast<PkgFinder*>(user_data);
+ finder->old_pkgs_.emplace_back(pkgid, version, type, finder->read_only_);
+ return 0;
+}
+
+int PkgFinder::FindPreloadPkgidFromDb(bool read_only) {
+ int ret = 0;
+ pkgmgrinfo_pkginfo_filter_h handle = nullptr;
+
+ ret = pkgmgrinfo_pkginfo_filter_create(&handle);
+ if (ret != PMINFO_R_OK) {
+ LOG(ERROR) << "pkgmgrinfo_pkginfo_filter_create failed " << ret;
+ return -1;
+ }
+
+ ret = pkgmgrinfo_pkginfo_filter_add_bool(handle,
+ PMINFO_PKGINFO_PROP_PACKAGE_PRELOAD, 1);
+ if (ret != PMINFO_R_OK) {
+ LOG(ERROR) << "pkgmgrinfo_pkginfo_filter_add_bool failed " << ret;
+ return -1;
+ }
+
+ ret = pkgmgrinfo_pkginfo_filter_add_bool(handle,
+ PMINFO_PKGINFO_PROP_PACKAGE_READONLY, read_only ? 1 : 0);
+ if (ret != PMINFO_R_OK) {
+ LOG(ERROR) << "pkgmgrinfo_pkginfo_filter_add_bool failed " << ret;
+ return -1;
+ }
+
+ read_only_ = read_only;
+ ret = pkgmgrinfo_pkginfo_filter_foreach_pkginfo(handle,
+ PkgidListCb, this);
+ if (ret != PMINFO_R_OK) {
+ LOG(ERROR) << "pkgmgrinfo_pkginfo_filter_foreach_pkginfo failed " << ret;
+ return -1;
+ }
+
+ ret = pkgmgrinfo_pkginfo_filter_destroy(handle);
+ if (ret != PMINFO_R_OK) {
+ LOG(ERROR) << "pkgmgrinfo_pkginfo_filter_destroy failed " << ret;
+ return -1;
+ }
+
+ return 0;
+}
+
+int PkgFinder::FindPreloadPkgidFromXml(
+ const string& xml_directory) {
+ DIR* dir;
+ struct dirent* entry = nullptr;
+
+ dir = opendir(xml_directory.c_str());
+ if (!dir) {
+ LOG(ERROR) << "opendir(" << xml_directory << ") failed ";
+ return -1;
+ }
+
+ while ((entry = readdir(dir)) != nullptr) {
+ if (entry->d_name[0] == '.') continue;
+
+ string manifest = GetValidManifest(entry->d_name);
+ if (manifest.empty()) {
+ continue;
+ }
+
+ string buf = xml_directory + "/" + manifest;
+ string pkgid = FindInfoFromXml(buf, "package");
+ string version = FindInfoFromXml(buf, "version");
+
+ if (version.empty())
+ version = "0.0.1";
+
+ string type = FindInfoFromXml(buf, "type");
+ if (type.empty())
+ type = "tpk";
+
+ new_pkgs_.emplace_back(pkgid, version, type, true);
+ }
+
+ closedir(dir);
+
+ return 0;
+}
+
+string PkgFinder::GetValidManifest(string manifest) {
+ size_t found = manifest.rfind(".xml");
+ if (found == string::npos)
+ return "";
+
+ return manifest;
+}
+
+string PkgFinder::FindInfoFromXml(const string& manifest,
+ const string& find_info) {
+ const xmlChar* node;
+ xmlTextReaderPtr reader;
+ string info_val;
+ xmlChar* tmp = nullptr;
+
+ reader = xmlReaderForFile(manifest.c_str(), nullptr, 0);
+
+ if (reader) {
+ if (MoveToChildElement(reader, -1)) {
+ node = xmlTextReaderConstName(reader);
+ if (!node) {
+ LOG(ERROR) << "xmlTextReaderConstName value is NULL";
+ goto end;
+ }
+
+ if (!strcmp(ASCII(node), "manifest")) {
+ tmp = xmlTextReaderGetAttribute(reader,
+ XMLCHAR(find_info.c_str()));
+ if (tmp) {
+ info_val = ASCII(tmp);
+ free(tmp);
+ tmp = nullptr;
+ }
+ } else {
+ LOG(ERROR) << "Manifest Node is not found";
+ }
+ }
+ } else {
+ LOG(ERROR) << "xmlReaderForFile value is NULL";
+ }
+
+end:
+ if (reader)
+ xmlFreeTextReader(reader);
+
+ return info_val;
+}
+
+int PkgFinder::MoveToChildElement(xmlTextReaderPtr reader,
+ int depth) {
+ int ret = xmlTextReaderRead(reader);
+ int cur = xmlTextReaderDepth(reader);
+ while (ret == 1) {
+ switch (xmlTextReaderNodeType(reader)) {
+ case XML_READER_TYPE_ELEMENT:
+ if (cur == depth + 1)
+ return 1;
+ break;
+ case XML_READER_TYPE_TEXT:
+ if (cur == depth + 1)
+ return 0;
+ break;
+ case XML_READER_TYPE_END_ELEMENT:
+ if (cur == depth)
+ return 0;
+ break;
+ default:
+ if (cur <= depth)
+ return 0;
+ break;
+ }
+
+ ret = xmlTextReaderRead(reader);
+ cur = xmlTextReaderDepth(reader);
+ }
+ return ret;
+}
+
+int PkgFinder::FindPreloadPkgidFromFile() {
+ char buf[kBufSize] = {0};
+ FILE *fp = nullptr;
+
+ fp = fopen(preload_rw_list_path_.c_str(), "r");
+ if (fp == nullptr) {
+ LOG(INFO) << "no preload rw list file";
+ return 0;
+ }
+
+ while (fgets(buf, kBufSize, fp) != NULL) {
+ StrTrim(buf);
+ AddRwPkgInfoFromFile(buf);
+ }
+
+ fclose(fp);
+ return 0;
+}
+
+void PkgFinder::AddRwPkgInfoFromFile(const char* info_str) {
+ if (info_str == nullptr)
+ return;
+
+ string pkgid = GetToken(info_str, kTokenPkgidStr);
+ string version = GetToken(info_str, kTokenVersionStr);
+ string type = GetToken(info_str, kTokenTypeStr);
+ string removable = GetToken(info_str, kTokenRemoveStr);
+
+ transform(type.begin(), type.end(), type.begin(),
+ [](unsigned char c) {
+ return tolower(c);
+ });
+
+ transform(removable.begin(), removable.end(), removable.begin(),
+ [](unsigned char c) {
+ return tolower(c);
+ });
+
+ if (removable == "false")
+ new_pkgs_.emplace_back(pkgid, version, type, false, false);
+ else
+ new_pkgs_.emplace_back(pkgid, version, type, false, true);
+}
+
+string PkgFinder::GetToken(const char* pBuf, const char* pKey) {
+ const char *p = nullptr;
+ const char *pStart = nullptr;
+ const char *pEnd = nullptr;
+
+ p = strstr(pBuf, pKey);
+ if (p == nullptr)
+ return "";
+
+ pStart = p + strlen(pKey);
+ pEnd = strchr(pStart, kSeperatorEnd);
+ if (pEnd == nullptr) {
+ pEnd = strchr(pStart, kSeperatorMid);
+ if (pEnd == nullptr)
+ return "";
+ }
+
+ size_t len = pEnd - pStart;
+ if (len <= 0)
+ return "";
+
+ string res(pStart, len);
+
+ return res;
+}
+
+void PkgFinder::StrTrim(char *input) {
+ char *trim_str = input;
+
+ if (input == nullptr)
+ return;
+
+ while (*input != 0) {
+ if (!isspace(*input)) {
+ *trim_str = *input;
+ trim_str++;
+ }
+ input++;
+ }
+
+ *trim_str = 0;
+ return;
+}
+
+} // common_fota
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * 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 <pkgmgr-info.h>
+
+#include "pkg_upgrader.hh"
+
+namespace common_fota {
+
+PkgUpgrader::PkgUpgrader(const PkgContext& context, PkgOperation pkg_op)
+ : type_(context.GetType()), loc_(context.GetLocation()), op_(pkg_op),
+ id_(context.GetId()), version_(context.GetVersion()),
+ backend_(context.GetId(), context.GetType(), context.GetLocation(),
+ pkg_op, context.IsRemovable()) {
+}
+
+PkgUpgrader::PkgUpgrader(std::string id)
+ : type_(PkgType::UNKNOWN), loc_(PkgLocation::UNKNOWN),
+ op_(PkgOperation::COMPLEX), id_(std::move(id)) {
+}
+
+PkgType PkgUpgrader::GetType() const {
+ return type_;
+}
+
+PkgLocation PkgUpgrader::GetLocation() const {
+ return loc_;
+}
+
+PkgOperation PkgUpgrader::GetOperation() const {
+ return op_;
+}
+
+std::string PkgUpgrader::GetId() const {
+ return id_;
+}
+
+std::string PkgUpgrader::GetVersion() const {
+ return version_;
+}
+
+const BackendInvoker& PkgUpgrader::GetBackendInvoker() const {
+ return backend_;
+}
+
+int PkgUpgrader::CompareVersion(const PkgUpgrader& pkg) const {
+ pkgmgrinfo_version_compare_type compare = PMINFO_VERSION_OLD;
+ int ret = pkgmgrinfo_compare_package_version(version_.c_str(),
+ pkg.GetVersion().c_str(), &compare);
+ if (ret != 0)
+ return -1;
+
+ if (compare == PMINFO_VERSION_NEW)
+ return -1;
+ else if (compare == PMINFO_VERSION_OLD)
+ return 1;
+
+ return 0;
+}
+
+
+} // common_fota
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * 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 "logging.hh"
+#include "pkg_upgrader_factory.hh"
+#include "ro2rw_upgrader.hh"
+#include "rw2ro_upgrader.hh"
+#include "rw_upgrader.hh"
+#include "simple_upgrader.hh"
+
+using namespace std;
+
+namespace common_fota {
+
+list<unique_ptr<PkgUpgrader>> PkgUpgraderFactory::MakeList(PkgFinder* finder) {
+ if (finder->Find() != 0) {
+ LOG(ERROR) << "PkgFinder::Find() failed";
+ return {};
+ }
+ return Merge(finder->GetOldPkgs(), finder->GetNewPkgs());
+}
+
+list<unique_ptr<PkgUpgrader>> PkgUpgraderFactory::Merge(
+ const list<PkgContext>& old_pkgs, const list<PkgContext>& new_pkgs) {
+ list<unique_ptr<PkgUpgrader>> pkgs;
+
+ for (auto& new_pkg : new_pkgs) {
+ const auto* old_pkg = FindPkgById(old_pkgs, new_pkg.GetId());
+ if (old_pkg != nullptr) {
+ // UPDATE
+ if (old_pkg->IsReadOnly() && new_pkg.IsReadOnly()) {
+ // RO to RO
+ pkgs.emplace_back(new SimpleUpgrader(new_pkg, PkgOperation::UPDATE));
+ } else if (!old_pkg->IsReadOnly() && !new_pkg.IsReadOnly()) {
+ // RW to RW
+ pkgs.emplace_back(new RwUpgrader(
+ unique_ptr<PkgUpgrader>(new SimpleUpgrader(new_pkg,
+ PkgOperation::UPDATE))));
+ } else if (!old_pkg->IsReadOnly() && new_pkg.IsReadOnly()) {
+ // RW to RO
+ pkgs.emplace_back(new Rw2RoUpgrader(
+ unique_ptr<PkgUpgrader>(new SimpleUpgrader(*old_pkg,
+ PkgOperation::UNINSTALL_KEEP_RW_DATA)),
+ unique_ptr<PkgUpgrader>(new SimpleUpgrader(new_pkg,
+ PkgOperation::INSTALL))
+ ));
+ } else if (old_pkg->IsReadOnly() && !new_pkg.IsReadOnly()) {
+ // RO to RW
+ pkgs.emplace_back(new Ro2RwUpgrader(
+ unique_ptr<PkgUpgrader>(new SimpleUpgrader(*old_pkg,
+ PkgOperation::UNINSTALL_KEEP_RW_DATA)),
+ unique_ptr<PkgUpgrader>(new SimpleUpgrader(new_pkg,
+ PkgOperation::INSTALL))
+ ));
+ }
+ } else {
+ // INSTALL
+ if (new_pkg.IsReadOnly()) {
+ // RO
+ pkgs.emplace_back(new SimpleUpgrader(new_pkg, PkgOperation::INSTALL));
+ } else {
+ // RW
+ pkgs.emplace_back(new RwUpgrader(
+ unique_ptr<PkgUpgrader>(new SimpleUpgrader(new_pkg,
+ PkgOperation::INSTALL))));
+ }
+ }
+ }
+
+ for (auto& old_pkg : old_pkgs) {
+ const auto* new_pkg = FindPkgById(new_pkgs, old_pkg.GetId());
+ if (new_pkg == nullptr) {
+ // UNINSTALL
+ if (old_pkg.IsReadOnly()) {
+ pkgs.emplace_back(new SimpleUpgrader(old_pkg,
+ PkgOperation::UNINSTALL));
+ }
+ }
+ }
+
+ return pkgs;
+}
+
+const PkgContext* PkgUpgraderFactory::FindPkgById(
+ const list<PkgContext>& pkgs, string id) {
+ for (auto& pkg : pkgs) {
+ if (pkg.GetId() == id)
+ return &pkg;
+ }
+
+ return nullptr;
+}
+
+} // common_fota
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * 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 "logging.hh"
+#include "ro2rw_upgrader.hh"
+
+namespace {
+constexpr char kOptZipFile[] = "/usr/system/RestoreDir/opt.zip";
+} // namespace
+
+namespace common_fota {
+
+Ro2RwUpgrader::Ro2RwUpgrader(std::unique_ptr<PkgUpgrader> old_pkg,
+ std::unique_ptr<PkgUpgrader> new_pkg)
+ : PkgUpgrader(new_pkg->GetId()), old_pkg_(std::move(old_pkg)),
+ new_pkg_(std::move(new_pkg)) {
+}
+
+bool Ro2RwUpgrader::Upgrade() {
+ if (old_pkg_.get() != nullptr) {
+ if (!old_pkg_->Upgrade()) {
+ LOG(ERROR) << "old_pkg_->Upgrade() failed";
+ return false;
+ }
+ }
+
+ if (UnzipPkgFromZip(new_pkg_->GetId().c_str()) != 0) {
+ LOG(ERROR) << "UnzipPkgFromZip(" << new_pkg_->GetId() << ") failed";
+ return false;
+ }
+
+ if (new_pkg_.get() != nullptr) {
+ if (!new_pkg_->Upgrade()) {
+ LOG(ERROR) << "new_pkg_->Upgrade() failed";
+ return false;
+ }
+ }
+
+ return true;
+}
+
+int Ro2RwUpgrader::UnzipFiles(const char* dest_path) {
+ const char* unzip_argv[] = { "/usr/bin/unzip", "-oXqq", kOptZipFile,
+ dest_path, "-d", "/", nullptr };
+ int ret = BackendInvoker::XSystem(unzip_argv);
+
+ return ret;
+}
+
+int Ro2RwUpgrader::UnzipXml(const std::string& pkgid) {
+ std::string path = "opt/share/packages/" + pkgid + ".xml";
+ int ret = UnzipFiles(path.c_str());
+
+ return ret;
+}
+
+int Ro2RwUpgrader::UnzipData(const std::string& pkgid, const std::string& dest) {
+ std::string path = dest + pkgid + "/*";
+ int ret = UnzipFiles(path.c_str());
+ if (ret != 0)
+ return -1;
+
+ return 0;
+}
+
+int Ro2RwUpgrader::UnzipPkgFromZip(const std::string& pkgid) {
+ int ret = -1;
+
+ ret = UnzipXml(pkgid);
+ if (ret != 0) {
+ LOG(ERROR) << "UnzipXml(" << pkgid << ") failed";
+ return ret;
+ }
+
+ ret = UnzipData(pkgid, "opt/usr/globalapps/");
+ if (ret != 0) {
+ LOG(ERROR) << "UnzipData(" << pkgid << ") failed";
+ return ret;
+ }
+
+ ret = UnzipData(pkgid, "opt/etc/skel/apps_rw/");
+ if (ret != 0) {
+ LOG(ERROR) << "UnzipData(" << pkgid << ") failed";
+ return ret;
+ }
+
+ return 0;
+}
+
+} // common_fota
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * 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 "logging.hh"
+#include "rw2ro_upgrader.hh"
+
+namespace common_fota {
+
+Rw2RoUpgrader::Rw2RoUpgrader(std::unique_ptr<PkgUpgrader> old_pkg,
+ std::unique_ptr<PkgUpgrader> new_pkg)
+ : PkgUpgrader(new_pkg->GetId()), old_pkg_(std::move(old_pkg)),
+ new_pkg_(std::move(new_pkg)) {
+}
+
+bool Rw2RoUpgrader::Upgrade() {
+ if (new_pkg_->CompareVersion(*old_pkg_) >= 0) {
+ if (!old_pkg_->Upgrade()) {
+ LOG(ERROR) << "old_pkg_->Upgrade() failed";
+ return false;
+ }
+
+ if (!new_pkg_->Upgrade()) {
+ LOG(ERROR) << "new_pkg_->Upgrade() failed";
+ return false;
+ }
+ } else {
+ LOG(DEBUG) << "new_pkg version < old_pkg version";
+ }
+
+ return true;
+}
+
+} // common_fota
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * 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 "simple_upgrader.hh"
+
+namespace common_fota {
+
+SimpleUpgrader::SimpleUpgrader(const PkgContext& context,
+ PkgOperation pkg_op)
+ : PkgUpgrader(context, pkg_op) {
+}
+
+bool SimpleUpgrader::Upgrade() {
+ if (GetBackendInvoker().Run() == 0)
+ return true;
+ return false;
+}
+
+} // common_fota
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * 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 <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <sys/smack.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/time.h>
+#include <pwd.h>
+#include <tzplatform_config.h>
+
+#include "logging.hh"
+#include "pkg_upgrader_factory.hh"
+#include "upgrader.hh"
+
+using namespace std;
+
+namespace {
+constexpr char kLogFileName[] = "/var/log/appfw/app-installers/fota.log";
+constexpr int kLogRotationSize = 1024 * 1024; // 1MB
+constexpr int kLogMaximumRotation = 3;
+constexpr int kBufSize = 1024;
+constexpr char kDbLabel[] = "User::Home";
+constexpr char kAppfwUser[] = "app_fw";
+
+class File {
+ public:
+ File(const string& path) {
+ fd_ = open(path.c_str(), O_RDONLY);
+ }
+
+ File(const string& path, int flags, mode_t mode) {
+ fd_ = open(path.c_str(), flags, mode);
+ }
+
+ ~File() {
+ if (fd_ != -1)
+ close(fd_);
+ }
+
+ int GetFd() const {
+ return fd_;
+ }
+
+ int FStat(struct stat* statbuf) {
+ return fstat(fd_, statbuf);
+ }
+
+ int FChOwn(uid_t owner, gid_t group) {
+ return fchown(fd_, owner, group);
+ }
+
+ int FChMod(mode_t mode) {
+ return fchmod(fd_, mode);
+ }
+
+ int FSync() {
+ return fsync(fd_);
+ }
+
+ private:
+ int fd_ = -1;
+};
+
+}
+
+namespace common_fota {
+
+Upgrader::Upgrader() {
+ logger_ = shared_ptr<utils::FileLogBackend>(new utils::FileLogBackend(
+ ::kLogFileName, ::kLogRotationSize, ::kLogMaximumRotation));
+ ::utils::LogCore::GetCore().AddLogBackend(logger_);
+ string path = tzplatform_getenv(TZ_SYS_DB);
+ SetDbPath(path);
+}
+
+void Upgrader::SetDbPath(const string& path) {
+ parser_db_ = path + "/.pkgmgr_parser.db";
+ parser_db_journal_ = path + "/.pkgmgr_parser.db-journal";
+ cert_db_ = path + "/.pkgmgr_cert.db";
+ cert_db_journal_ = path + "/.pkgmgr_cert.db-journal";
+}
+
+bool Upgrader::Process(PkgFinder* finder) {
+ if (CheckAndRestoreBackupDbs() != 0) {
+ LOG(ERROR) << "CheckAndRestoreBackupDbs failed";
+ return false;
+ }
+
+ if (MakeBackupDbs() != 0) {
+ LOG(ERROR) << "MakeBackupDbs failed";
+ return false;
+ }
+
+ PkgUpgraderFactory factory;
+ auto list = factory.MakeList(finder);
+
+ for(auto& pkg : list) {
+ if(pkg->Upgrade()) {
+ LOG(DEBUG) << "upgrade success (" << pkg->GetId() << ")";
+ success_list_.push_back(move(pkg));
+ } else {
+ LOG(ERROR) << "upgrade failed (" << pkg->GetId() << ")";
+ failure_list_.push_back(move(pkg));
+ }
+ }
+
+ RemoveBackupDbs();
+
+ logger_->WriteLog(::utils::LogLevel::LOG_INFO, "", "Upgrade Done");
+ logger_->WriteLogToFile();
+ return true;
+}
+
+const list<unique_ptr<PkgUpgrader>>& Upgrader::GetSuccessList() const {
+ return success_list_;
+}
+
+const list<unique_ptr<PkgUpgrader>>& Upgrader::GetFailureList() const {
+ return failure_list_;
+}
+
+int Upgrader::CheckAndRestoreBackupDbs() {
+ if (CheckAndRestoreBackup(parser_db_))
+ return -1;
+
+ if (CheckAndRestoreBackup(parser_db_journal_))
+ return -1;
+
+ if (CheckAndRestoreBackup(cert_db_))
+ return -1;
+
+ if (CheckAndRestoreBackup(cert_db_journal_))
+ return -1;
+
+ return 0;
+}
+
+int Upgrader::CheckAndRestoreBackup(const string& origin_path) {
+ string backup_path = origin_path + ".bck";
+
+ // if backup flag exists, it means the previous backup process aborted.
+ if (access(backup_path.c_str(), F_OK) && CheckBackupFlag(origin_path))
+ return 0;
+
+ if (access(origin_path.c_str(), F_OK) == 0) {
+ if (remove(origin_path.c_str())) {
+ LOG(ERROR) << "cannot remove path(" << origin_path << " : " << errno;
+ return -1;
+ }
+ }
+
+ if (rename(backup_path.c_str(), origin_path.c_str())) {
+ LOG(ERROR) << "fail to rename " << backup_path << " to " <<
+ origin_path << errno;
+ return -1;
+ }
+
+ return 0;
+}
+
+int Upgrader::SetDbPermission(const string& path) {
+ struct stat sb;
+ struct passwd pwd;
+ struct passwd *result;
+ char buf[kBufSize];
+
+ int ret = getpwnam_r(kAppfwUser, &pwd, buf, sizeof(buf), &result);
+ if (result == NULL) {
+ LOG(ERROR) << "getpwnam_r failed: " << errno;
+ return -1;
+ }
+ uid_t uid = pwd.pw_uid;
+
+ ret = getpwuid_r(uid, &pwd, buf, sizeof(buf), &result);
+ if (result == NULL) {
+ LOG(ERROR) << "getpwuid_r failed: " << errno;
+ return -1;
+ }
+
+ ::File file(path);
+
+ if (file.GetFd() == -1) {
+ LOG(ERROR) << "open(" << path << "failed: " << errno;
+ return -1;
+ }
+
+ ret = file.FStat(&sb);
+ if (ret == -1) {
+ LOG(ERROR) << "stat " << path << "failed: " << errno;
+ return -1;
+ }
+ if (S_ISLNK(sb.st_mode)) {
+ LOG(ERROR) << path << " is symlink!";
+ return -1;
+ }
+ ret = file.FChOwn(uid, pwd.pw_gid);
+ if (ret == -1) {
+ LOG(ERROR) << "fchown " << path << " failed: " << errno;
+ return -1;
+ }
+
+ mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH;
+ if (path.find(cert_db_) != string::npos)
+ mode |= S_IWOTH;
+ ret = file.FChMod(mode);
+ if (ret == -1) {
+ LOG(ERROR) << "fchmod " << path << " failed: " << errno;
+ return -1;
+ }
+ file.FSync();
+ if (smack_setlabel(path.c_str(), kDbLabel, SMACK_LABEL_ACCESS))
+ LOG(ERROR) << "failed chsmack -a " << kDbLabel << " " << path;
+
+ return 0;
+}
+
+int Upgrader::CreateBackupFlag(const string& path) {
+ string flag = path + ".bck.flag";
+
+ ::File file(flag, O_CREAT | O_WRONLY, 0644);
+ if (file.GetFd() == -1) {
+ LOG(ERROR) << "failed to create flag file " << flag << ", " << errno;
+ return -1;
+ }
+
+ return 0;
+}
+
+int Upgrader::CheckBackupFlag(const string& path) {
+ string flag = path + ".bck.flag";
+
+ if (access(flag.c_str(), F_OK) != 0)
+ return -1;
+
+ return 0;
+}
+
+int Upgrader::RemoveBackupFlag(const string& path) {
+ string flag = path + ".bck.flag";
+
+ if (remove(flag.c_str())) {
+ LOG(ERROR) << "cannot remove flag file(" << flag << ") " << errno;
+ return -1;
+ }
+
+ return 0;
+}
+
+int Upgrader::BackupFile(const string& src_path, const string& dest_path) {
+ char temp_buf[8192] = {'\0', };
+ size_t size_of_char = sizeof(char);
+ size_t size_of_temp_buf = sizeof(temp_buf);
+
+ if (access(src_path.c_str(), F_OK) != 0) {
+ LOG(ERROR) << "File(" << src_path << ") is not exist";
+ return -1;
+ }
+
+ // if backup flag exists, it means the previous backup process aborted.
+ if (CheckBackupFlag(src_path)) {
+ if (access(dest_path.c_str(), F_OK) == 0) {
+ if (remove(dest_path.c_str())) {
+ LOG(ERROR) << "Failed to remove uncompleted backup file " <<
+ dest_path << " : " << errno;
+ return -1;
+ }
+ }
+ } else {
+ if (CreateBackupFlag(src_path)) {
+ LOG(ERROR) << "failed to create backup flag";
+ return -1;
+ }
+ }
+
+ FILE* src = fopen(src_path.c_str(), "r");
+ unique_ptr<FILE, decltype(fclose)*> src_auto(src, fclose);
+ if (src == nullptr) {
+ LOG(ERROR) << "Failed to open : " << src_path;
+ return -1;
+ }
+
+ FILE* dest = fopen(dest_path.c_str(), "w");
+ unique_ptr<FILE, decltype(fclose)*> dest_auto(dest, fclose);
+ if (dest == nullptr) {
+ LOG(ERROR) << "Failed to open : " << dest_path;
+ return -1;
+ }
+
+ while (!feof(src)) {
+ int rc = fread(temp_buf, size_of_char, size_of_temp_buf, src);
+ fwrite(temp_buf, size_of_char, rc, dest);
+ }
+
+ fsync(fileno(dest));
+ RemoveBackupFlag(src_path);
+
+ return 0;
+}
+
+int Upgrader::BackupDb(const string& src_path, const string& dest_path) {
+ if (BackupFile(src_path, dest_path) != 0)
+ return -1;
+
+ if (SetDbPermission(dest_path) != 0)
+ return -1;
+
+ return 0;
+}
+
+int Upgrader::MakeBackupDbs() {
+ string parser_db_bck = parser_db_ + ".bck";
+ string parser_db_journal_bck = parser_db_journal_ + ".bck";
+ string cert_db_bck = cert_db_ + ".bck";
+ string cert_db_journal_bck = cert_db_journal_ + ".bck";
+
+ if (BackupDb(parser_db_, parser_db_bck) == -1 ) {
+ LOG(ERROR) << "Fail to backup [" << parser_db_ << "] to [" << parser_db_bck <<
+ "]";
+ goto CATCH;
+ }
+
+ if (BackupDb(parser_db_journal_, parser_db_journal_bck) == -1) {
+ LOG(ERROR) << "Fail to backup [" << parser_db_journal_ << "] to [" <<
+ parser_db_journal_bck << "]";
+ goto CATCH;
+ }
+
+ if (BackupDb(cert_db_, cert_db_bck) == -1) {
+ LOG(ERROR) << "Fail to backup [" << cert_db_ << "] to [" <<
+ cert_db_bck << "]";
+ goto CATCH;
+ }
+
+ if (BackupDb(cert_db_journal_, cert_db_journal_bck) == -1) {
+ LOG(ERROR) << "Fail to backup [" << cert_db_journal_ << "] to [" <<
+ cert_db_journal_bck << "]";
+ goto CATCH;
+ }
+
+ return 0;
+
+CATCH:
+ remove(parser_db_bck.c_str());
+ remove(parser_db_journal_bck.c_str());
+ remove(cert_db_bck.c_str());
+ remove(cert_db_journal_bck.c_str());
+
+ return -1;
+}
+
+void Upgrader::RemoveBackupPath(const string& origin_path) {
+ string backup_path = origin_path + ".bck";
+
+ if (remove(origin_path.c_str()))
+ LOG(ERROR) << "cannot remove backup file(" << backup_path << ") " << errno;
+}
+
+void Upgrader::RemoveBackupDbs() {
+ RemoveBackupPath(parser_db_);
+ RemoveBackupPath(parser_db_journal_);
+ RemoveBackupPath(cert_db_);
+ RemoveBackupPath(cert_db_journal_);
+}
+
+} // common_fota
--- /dev/null
+ADD_SUBDIRECTORY(unit_tests)
--- /dev/null
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * 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 MOCK_MOCK_HOOK_H_
+#define MOCK_MOCK_HOOK_H_
+
+#define MOCK_HOOK_P0(MOCK_CLASS, f) \
+ TestFixture::GetMock<MOCK_CLASS>().f()
+#define MOCK_HOOK_P1(MOCK_CLASS, f, p1) \
+ TestFixture::GetMock<MOCK_CLASS>().f(p1)
+#define MOCK_HOOK_P2(MOCK_CLASS, f, p1, p2) \
+ TestFixture::GetMock<MOCK_CLASS>().f(p1, p2)
+#define MOCK_HOOK_P3(MOCK_CLASS, f, p1, p2, p3) \
+ TestFixture::GetMock<MOCK_CLASS>().f(p1, p2, p3)
+#define MOCK_HOOK_P4(MOCK_CLASS, f, p1, p2, p3, p4) \
+ TestFixture::GetMock<MOCK_CLASS>().f(p1, p2, p3, p4)
+#define MOCK_HOOK_P5(MOCK_CLASS, f, p1, p2, p3, p4, p5) \
+ TestFixture::GetMock<MOCK_CLASS>().f(p1, p2, p3, p4, p5)
+#define MOCK_HOOK_P6(MOCK_CLASS, f, p1, p2, p3, p4, p5, p6) \
+ TestFixture::GetMock<MOCK_CLASS>().f(p1, p2, p3, p4, p5, p6)
+#define MOCK_HOOK_P7(MOCK_CLASS, f, p1, p2, p3, p4, p5, p6, p7) \
+ TestFixture::GetMock<MOCK_CLASS>().f(p1, p2, p3, p4, p5, p6, p7)
+#define MOCK_HOOK_P8(MOCK_CLASS, f, p1, p2, p3, p4, p5, p6, p7, p8) \
+ TestFixture::GetMock<MOCK_CLASS>().f(p1, p2, p3, p4, p5, p6, p7, p8)
+#define MOCK_HOOK_P10(MOCK_CLASS, f, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10) \
+ TestFixture::GetMock<MOCK_CLASS>().f( \
+ p1, p2, p3, p4, p5, p6, p7, p8, p9, p10)
+
+#endif // MOCK_MOCK_HOOK_H_
--- /dev/null
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * 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 MOCK_MODULE_MOCK_H_
+#define MOCK_MODULE_MOCK_H_
+
+class ModuleMock {
+ public:
+ virtual ~ModuleMock() {}
+};
+
+#endif // MOCK_MODULE_MOCK_H_
--- /dev/null
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * 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 "os_mock.h"
+#include "mock_hook.h"
+#include "test_fixture.h"
+
+extern "C" pid_t fork(void) {
+ return MOCK_HOOK_P0(OsMock, fork);
+}
+
+extern "C" pid_t waitpid(pid_t pid, int *status, int options) {
+ return MOCK_HOOK_P3(OsMock, waitpid, pid, status, options);
+}
+
+extern "C" int fchown(int fd, uid_t owner, gid_t group) {
+ return MOCK_HOOK_P3(OsMock, fchown, fd, owner, group);
+}
+
+extern "C" int fchmod(int fd, mode_t mode) {
+ return MOCK_HOOK_P2(OsMock, fchmod, fd, mode);
+}
+
+extern "C" int smack_setlabel(const char *path, const char* label,
+ enum smack_label_type type) {
+ return MOCK_HOOK_P3(OsMock, smack_setlabel, path, label, type);
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * 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 MOCK_OS_MOCK_H_
+#define MOCK_OS_MOCK_H_
+
+#include <gmock/gmock.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/smack.h>
+
+#include "module_mock.h"
+
+class OsMock : public virtual ModuleMock {
+ public:
+ virtual ~OsMock() {}
+
+ MOCK_METHOD0(fork, pid_t());
+ MOCK_METHOD3(waitpid, pid_t(pid_t, int*, int));
+ MOCK_METHOD3(fchown, int(int, uid_t, gid_t));
+ MOCK_METHOD2(fchmod, int(int, mode_t));
+ MOCK_METHOD3(smack_setlabel, int(const char*, const char*, smack_label_type));
+};
+
+#endif // MOCK_OS_MOCK_H_
--- /dev/null
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * 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 "pkgmgr_info_mock.h"
+#include "mock_hook.h"
+#include "test_fixture.h"
+
+extern "C" int pkgmgrinfo_pkginfo_filter_create(
+ pkgmgrinfo_pkginfo_filter_h *handle) {
+ return MOCK_HOOK_P1(PkgMgrInfoMock, pkgmgrinfo_pkginfo_filter_create, handle);
+}
+
+extern "C" int pkgmgrinfo_pkginfo_filter_destroy(
+ pkgmgrinfo_pkginfo_filter_h handle) {
+ return MOCK_HOOK_P1(PkgMgrInfoMock, pkgmgrinfo_pkginfo_filter_destroy,
+ handle);
+}
+
+extern "C" int pkgmgrinfo_pkginfo_filter_add_bool(
+ pkgmgrinfo_pkginfo_filter_h handle,
+ const char *property, const bool value) {
+ return MOCK_HOOK_P3(PkgMgrInfoMock, pkgmgrinfo_pkginfo_filter_add_bool,
+ handle, property, value);
+}
+
+extern "C" int pkgmgrinfo_pkginfo_filter_foreach_pkginfo(
+ pkgmgrinfo_pkginfo_filter_h handle,
+ pkgmgrinfo_pkg_list_cb pkg_cb, void *user_data) {
+ return MOCK_HOOK_P3(PkgMgrInfoMock, pkgmgrinfo_pkginfo_filter_foreach_pkginfo,
+ handle, pkg_cb, user_data);
+}
+
+extern "C" int pkgmgrinfo_pkginfo_get_pkgid(pkgmgrinfo_pkginfo_h handle,
+ char **pkgid) {
+ return MOCK_HOOK_P2(PkgMgrInfoMock, pkgmgrinfo_pkginfo_get_pkgid,
+ handle, pkgid);
+}
+
+extern "C" int pkgmgrinfo_pkginfo_get_type(pkgmgrinfo_pkginfo_h handle,
+ char **type) {
+ return MOCK_HOOK_P2(PkgMgrInfoMock, pkgmgrinfo_pkginfo_get_type,
+ handle, type);
+}
+
+extern "C" int pkgmgrinfo_pkginfo_get_version(pkgmgrinfo_pkginfo_h handle,
+ char **version) {
+ return MOCK_HOOK_P2(PkgMgrInfoMock, pkgmgrinfo_pkginfo_get_version,
+ handle, version);
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * 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 MOCK_PKGMGR_INFO_MOCK_H_
+#define MOCK_PKGMGR_INFO_MOCK_H_
+
+#include <tizen.h>
+#include <gmock/gmock.h>
+#include <pkgmgr-info.h>
+
+#include "module_mock.h"
+
+class PkgMgrInfoMock : public virtual ModuleMock {
+ public:
+ virtual ~PkgMgrInfoMock() {}
+
+ MOCK_METHOD1(pkgmgrinfo_pkginfo_filter_create,
+ int(pkgmgrinfo_pkginfo_filter_h*));
+ MOCK_METHOD1(pkgmgrinfo_pkginfo_filter_destroy,
+ int(pkgmgrinfo_pkginfo_filter_h));
+ MOCK_METHOD3(pkgmgrinfo_pkginfo_filter_add_bool,
+ int(pkgmgrinfo_pkginfo_filter_h, const char*, const bool));
+ MOCK_METHOD3(pkgmgrinfo_pkginfo_filter_foreach_pkginfo,
+ int(pkgmgrinfo_pkginfo_filter_h, pkgmgrinfo_pkg_list_cb, void*));
+ MOCK_METHOD2(pkgmgrinfo_pkginfo_get_pkgid, int(pkgmgrinfo_pkginfo_h, char**));
+ MOCK_METHOD2(pkgmgrinfo_pkginfo_get_type, int(pkgmgrinfo_pkginfo_h, char**));
+ MOCK_METHOD2(pkgmgrinfo_pkginfo_get_version, int(pkgmgrinfo_pkginfo_h, char**));
+};
+
+#endif // MOCK_PKGMGR_INFO_MOCK_H_
--- /dev/null
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * 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 "test_fixture.h"
+
+#include <memory>
+
+std::unique_ptr<ModuleMock> TestFixture::mock_;
--- /dev/null
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * 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 MOCK_TEST_FIXTURE_H_
+#define MOCK_TEST_FIXTURE_H_
+
+#include <gtest/gtest.h>
+
+#include <memory>
+#include <stdexcept>
+#include <string>
+#include <utility>
+
+#include "module_mock.h"
+
+class TestFixture : public ::testing::Test {
+ public:
+ explicit TestFixture(std::unique_ptr<ModuleMock>&& mock) {
+ mock_ = std::move(mock);
+ }
+ virtual ~TestFixture() {
+ mock_.reset();
+ }
+
+ virtual void SetUp() {}
+ virtual void TearDown() {}
+
+ template <typename T>
+ static T& GetMock() {
+ auto ptr = dynamic_cast<T*>(mock_.get());
+ if (!ptr)
+ throw std::invalid_argument("The test does not provide mock of \"" +
+ std::string(typeid(T).name()) + "\"");
+ return *ptr;
+ }
+
+ static std::unique_ptr<ModuleMock> mock_;
+};
+
+#endif // MOCK_TEST_FIXTURE_H_
--- /dev/null
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)\r
+PROJECT(pkgmgr-tool_unittests C CXX)\r
+\r
+INCLUDE(FindPkgConfig)\r
+PKG_CHECK_MODULES(pkgmgr-tool_unittests REQUIRED\r
+ dlog\r
+ gmock\r
+ pkgmgr-parser\r
+ pkgmgr-info\r
+ libtzplatform-config\r
+ libsmack\r
+)\r
+\r
+FOREACH(flag ${pkgmgr-tool_unittests_CFLAGS})\r
+ SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")\r
+ENDFOREACH(flag)\r
+SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fvisibility=hidden -Wall -Werror -fPIE")\r
+\r
+SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CFLAGS} -std=c++14")\r
+SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g")\r
+SET(CMAKE_CXX_FLAGS_RELEASE "-O2")\r
+\r
+ADD_DEFINITIONS("-DDB_PATH=\"${DB_PATH}\"")\r
+\r
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../src/pkg_upgrade/include)\r
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../mock)\r
+\r
+AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/src SOURCES)\r
+AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/../../src/pkg_upgrade/src LIB_SOURCES)\r
+LIST(REMOVE_ITEM LIB_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/../../src/pkg_upgrade/src/main.cc)\r
+AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/../mock MOCK_SOURCES)\r
+\r
+ADD_EXECUTABLE(${PROJECT_NAME}\r
+ ${SOURCES}\r
+ ${MOCK_SOURCES}\r
+ ${LIB_SOURCES}\r
+)\r
+\r
+SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES COMPILE_FLAGS "${EXTRA_CFLAGS}")\r
+TARGET_LINK_LIBRARIES(${PROJECT_NAME}\r
+ ${pkgmgr-tool_unittests_LDFLAGS}\r
+)\r
+\r
+INSTALL(TARGETS ${PROJECT_NAME} DESTINATION /usr/bin/)\r
+INSTALL(DIRECTORY data/ DESTINATION ${CMAKE_INSTALL_PREFIX}/share/${PROJECT_NAME}/data)
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<manifest xmlns="http://tizen.org/ns/packages" api-version="4.0" package="org.tizen.alarm" version="2.0.0" type="tpk" readonly="true" preload="true" removable="false">
+ <profile name="wearable"/>
+ <ui-application appid="org.tizen.alarm" exec="/usr/apps/org.tizen.alarm/bin/alarm-app" hw-acceleration="on" multiple="false" nodisplay="false" taskmanage="true" type="capp">
+ <label>Alarm</label>
+ <label xml:lang="ar-ae">تنبيه</label>
+ <label xml:lang="az-az">Siqnal</label>
+ <label xml:lang="bg-bg">Аларма</label>
+ <label xml:lang="ca-es">Alarma</label>
+ <label xml:lang="cs-cz">Upozornění</label>
+ <label xml:lang="da-dk">Alarm</label>
+ <label xml:lang="de-de">Alarm</label>
+ <label xml:lang="el-gr">Ξυπνητήρι</label>
+ <label xml:lang="en-gb">Alarm</label>
+ <label xml:lang="en-ph">Alarm</label>
+ <label xml:lang="en-us">Alarm</label>
+ <label xml:lang="es-es">Alarma</label>
+ <label xml:lang="es-mx">Alarma</label>
+ <label xml:lang="et-ee">Märguanne</label>
+ <label xml:lang="eu-es">Alarma</label>
+ <label xml:lang="fi-fi">Hälytys</label>
+ <label xml:lang="fr-ca">Alarme</label>
+ <label xml:lang="fr-fr">Alarme</label>
+ <label xml:lang="ga-ie">Aláram</label>
+ <label xml:lang="gl-es">Alarma</label>
+ <label xml:lang="hr-hr">Alarm</label>
+ <label xml:lang="hu-hu">Jelzés</label>
+ <label xml:lang="hy-am">Տագնապ</label>
+ <label xml:lang="is-is">Vekjari</label>
+ <label xml:lang="it-it">Sveglia</label>
+ <label xml:lang="ja-jp">アラーム</label>
+ <label xml:lang="ka-ge">სიგნალი</label>
+ <label xml:lang="kk-kz">Оятар</label>
+ <label xml:lang="ko-kr">알람</label>
+ <label xml:lang="lt-lt">Signalas</label>
+ <label xml:lang="lv-lv">Signāls</label>
+ <label xml:lang="mk-mk">Аларм</label>
+ <label xml:lang="nb-no">Alarm</label>
+ <label xml:lang="nl-nl">Alarm</label>
+ <label xml:lang="pl-pl">Alarm</label>
+ <label xml:lang="pt-br">Alarme</label>
+ <label xml:lang="pt-pt">Alarme</label>
+ <label xml:lang="ro-ro">Alarmă</label>
+ <label xml:lang="ru-ru">Будильник</label>
+ <label xml:lang="sk-sk">Budík</label>
+ <label xml:lang="sl-si">Alarm</label>
+ <label xml:lang="sr-rs">Beleška</label>
+ <label xml:lang="sv-se">Alarm</label>
+ <label xml:lang="tr-tr">Alarm</label>
+ <label xml:lang="uk-ua">Будильник</label>
+ <label xml:lang="uz-uz">Uyg‘otgich</label>
+ <label xml:lang="zh-cn">闹钟</label>
+ <label xml:lang="zh-hk">鬧鐘</label>
+ <label xml:lang="zh-tw">鬧鐘</label>
+ <icon>org.tizen.alarm.png</icon>
+ </ui-application>
+ <ui-application appid="org.tizen.alarm.app-control" exec="/usr/apps/org.tizen.alarm/bin/alarm-app" hw-acceleration="on" multiple="true" nodisplay="true" taskmanage="false" type="capp">
+ <label>Alarm</label>
+ <label xml:lang="ar-ae">تنبيه</label>
+ <label xml:lang="az-az">Siqnal</label>
+ <label xml:lang="bg-bg">Аларма</label>
+ <label xml:lang="ca-es">Alarma</label>
+ <label xml:lang="cs-cz">Upozornění</label>
+ <label xml:lang="da-dk">Alarm</label>
+ <label xml:lang="de-de">Alarm</label>
+ <label xml:lang="el-gr">Ξυπνητήρι</label>
+ <label xml:lang="en-gb">Alarm</label>
+ <label xml:lang="en-ph">Alarm</label>
+ <label xml:lang="en-us">Alarm</label>
+ <label xml:lang="es-es">Alarma</label>
+ <label xml:lang="es-mx">Alarma</label>
+ <label xml:lang="et-ee">Märguanne</label>
+ <label xml:lang="eu-es">Alarma</label>
+ <label xml:lang="fi-fi">Hälytys</label>
+ <label xml:lang="fr-ca">Alarme</label>
+ <label xml:lang="fr-fr">Alarme</label>
+ <label xml:lang="ga-ie">Aláram</label>
+ <label xml:lang="gl-es">Alarma</label>
+ <label xml:lang="hr-hr">Alarm</label>
+ <label xml:lang="hu-hu">Jelzés</label>
+ <label xml:lang="hy-am">Տագնապ</label>
+ <label xml:lang="is-is">Vekjari</label>
+ <label xml:lang="it-it">Sveglia</label>
+ <label xml:lang="ja-jp">アラーム</label>
+ <label xml:lang="ka-ge">სიგნალი</label>
+ <label xml:lang="kk-kz">Оятар</label>
+ <label xml:lang="ko-kr">알람</label>
+ <label xml:lang="lt-lt">Signalas</label>
+ <label xml:lang="lv-lv">Signāls</label>
+ <label xml:lang="mk-mk">Аларм</label>
+ <label xml:lang="nb-no">Alarm</label>
+ <label xml:lang="nl-nl">Alarm</label>
+ <label xml:lang="pl-pl">Alarm</label>
+ <label xml:lang="pt-br">Alarme</label>
+ <label xml:lang="pt-pt">Alarme</label>
+ <label xml:lang="ro-ro">Alarmă</label>
+ <label xml:lang="ru-ru">Будильник</label>
+ <label xml:lang="sk-sk">Budík</label>
+ <label xml:lang="sl-si">Alarm</label>
+ <label xml:lang="sr-rs">Beleška</label>
+ <label xml:lang="sv-se">Alarm</label>
+ <label xml:lang="tr-tr">Alarm</label>
+ <label xml:lang="uk-ua">Будильник</label>
+ <label xml:lang="uz-uz">Uyg‘otgich</label>
+ <label xml:lang="zh-cn">闹钟</label>
+ <label xml:lang="zh-hk">鬧鐘</label>
+ <label xml:lang="zh-tw">鬧鐘</label>
+ <icon>org.tizen.alarm.png</icon>
+ <app-control>
+ <operation name="http://tizen.org/appcontrol/operation/add"/>
+ <mime name="application/vnd.tizen.alarm"/>
+ </app-control>
+ <app-control>
+ <operation name="http://tizen.org/appcontrol/operation/pick"/>
+ <mime name="application/vnd.tizen.alarm"/>
+ </app-control>
+ <app-control>
+ <operation name="http://tizen.org/appcontrol/operation/edit"/>
+ <mime name="application/vnd.tizen.alarm"/>
+ </app-control>
+ </ui-application>
+ <ui-application appid="org.tizen.alarm.alert" exec="/usr/apps/org.tizen.alarm/bin/alarm-app" hw-acceleration="on" multiple="false" nodisplay="true" taskmanage="false" type="capp">
+ <label>Alarm</label>
+ <label xml:lang="ar-ae">تنبيه</label>
+ <label xml:lang="az-az">Siqnal</label>
+ <label xml:lang="bg-bg">Аларма</label>
+ <label xml:lang="ca-es">Alarma</label>
+ <label xml:lang="cs-cz">Upozornění</label>
+ <label xml:lang="da-dk">Alarm</label>
+ <label xml:lang="de-de">Alarm</label>
+ <label xml:lang="el-gr">Ξυπνητήρι</label>
+ <label xml:lang="en-gb">Alarm</label>
+ <label xml:lang="en-ph">Alarm</label>
+ <label xml:lang="en-us">Alarm</label>
+ <label xml:lang="es-es">Alarma</label>
+ <label xml:lang="es-mx">Alarma</label>
+ <label xml:lang="et-ee">Märguanne</label>
+ <label xml:lang="eu-es">Alarma</label>
+ <label xml:lang="fi-fi">Hälytys</label>
+ <label xml:lang="fr-ca">Alarme</label>
+ <label xml:lang="fr-fr">Alarme</label>
+ <label xml:lang="ga-ie">Aláram</label>
+ <label xml:lang="gl-es">Alarma</label>
+ <label xml:lang="hr-hr">Alarm</label>
+ <label xml:lang="hu-hu">Jelzés</label>
+ <label xml:lang="hy-am">Տագնապ</label>
+ <label xml:lang="is-is">Vekjari</label>
+ <label xml:lang="it-it">Sveglia</label>
+ <label xml:lang="ja-jp">アラーム</label>
+ <label xml:lang="ka-ge">სიგნალი</label>
+ <label xml:lang="kk-kz">Оятар</label>
+ <label xml:lang="ko-kr">알람</label>
+ <label xml:lang="lt-lt">Signalas</label>
+ <label xml:lang="lv-lv">Signāls</label>
+ <label xml:lang="mk-mk">Аларм</label>
+ <label xml:lang="nb-no">Alarm</label>
+ <label xml:lang="nl-nl">Alarm</label>
+ <label xml:lang="pl-pl">Alarm</label>
+ <label xml:lang="pt-br">Alarme</label>
+ <label xml:lang="pt-pt">Alarme</label>
+ <label xml:lang="ro-ro">Alarmă</label>
+ <label xml:lang="ru-ru">Будильник</label>
+ <label xml:lang="sk-sk">Budík</label>
+ <label xml:lang="sl-si">Alarm</label>
+ <label xml:lang="sr-rs">Beleška</label>
+ <label xml:lang="sv-se">Alarm</label>
+ <label xml:lang="tr-tr">Alarm</label>
+ <label xml:lang="uk-ua">Будильник</label>
+ <label xml:lang="uz-uz">Uyg‘otgich</label>
+ <label xml:lang="zh-cn">闹钟</label>
+ <label xml:lang="zh-hk">鬧鐘</label>
+ <label xml:lang="zh-tw">鬧鐘</label>
+ <icon>org.tizen.alarm.png</icon>
+ </ui-application>
+ <privileges>
+ <privilege>http://tizen.org/privilege/haptic</privilege>
+ <privilege>http://tizen.org/privilege/datasharing</privilege>
+ <privilege>http://tizen.org/privilege/display</privilege>
+ <privilege>http://tizen.org/privilege/appmanager.launch</privilege>
+ <privilege>http://tizen.org/privilege/alarm.get</privilege>
+ <privilege>http://tizen.org/privilege/alarm.set</privilege>
+ </privileges>
+ <service-application appid="org.tizen.alarm.svc" exec="/usr/apps/org.tizen.alarm/bin/alarm-svc" multiple="false" nodisplay="true" taskmanage="false" type="capp">
+ <label>Alarm Service</label>
+ <icon>org.tizen.alarm.png</icon>
+ <datacontrol access="ReadWrite" providerid="http://alarm.tizen.org/datacontrol/provider/alarm" type="Sql"/>
+ </service-application>
+ <widget-application appid="org.tizen.alarm.widget" exec="/usr/apps/org.tizen.alarm/bin/alarm-widget" main="true" update-period="0">
+ <label>Alarm</label>
+ <icon>org.tizen.alarm.png</icon>
+ <support-size preview="alarm_widget_preview.png">2x2</support-size>
+ </widget-application>
+</manifest>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns="http://tizen.org/ns/packages" package="org.tizen.app-selector" version="0.1.9" api-version="3.0" install-location="internal-only" type="tpk" readonly="true" preload="true" removable="false">
+ <label>Application Selection Popup</label>
+ <description>Application Selection Popup</description>
+ <ui-application appid="org.tizen.app-selector" exec="/usr/apps/org.tizen.app-selector/bin/app-selector" nodisplay="true" multiple="false" type="capp" taskmanage="false" hw-acceleration="on" launch_mode="group">
+ <label>Application Selection Popup</label>
+ </ui-application>
+ <privileges>
+ <privilege>http://tizen.org/privilege/appmanager.launch</privilege>
+ <privilege>http://tizen.org/privilege/mediastorage</privilege>
+ <privilege>http://tizen.org/privilege/externalstorage</privilege>
+ </privileges>
+</manifest>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns="http://tizen.org/ns/packages" package="org.tizen.bluetooth" api-version="3.0" version="2.0.25" install-location="internal-only" type="rpm" preload="true" readonly="true" removable="false">
+ <label>iW bluetooth</label>
+ <author email="insung.cho@samsung.com" href="www.samsung.com">Insung Cho</author>
+ <description>W bluetooth</description>
+ <ui-application appid="org.tizen.bluetooth" exec="/usr/apps/org.tizen.bluetooth/bin/bluetooth" nodisplay="true" multiple="false" type="capp" taskmanage="false" launch_mode="group">
+ <icon/>
+ <label>Bluetooth application</label>
+ <label xml:lang="en-us">Bluetooth application</label>
+ <app-control>
+ <operation name="http://tizen.org/appcontrol/operation/edit"/>
+ <mime name="application/x-bluetooth-on-off"/>
+ <mime name="application/x-bluetooth-visibility"/>
+ </app-control>
+ </ui-application>
+ <privileges>
+ <privilege>http://tizen.org/privilege/bluetooth</privilege>
+ <privilege>http://tizen.org/privilege/bluetooth.admin</privilege>
+ </privileges>
+</manifest>
--- /dev/null
+"package=org.tizen.new_rw":"version=1.2.0":"type=tpk":"removable=false"
+"package=org.test.pkg2":"version=1.2.0":"type=wgt":"removable=true"
--- /dev/null
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * 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 <gtest/gtest.h>
+#include <gmock/gmock.h>
+
+int main(int argc, char** argv) {
+ int ret = -1;
+
+ try {
+ testing::InitGoogleTest(&argc, argv);
+ } catch(...) {
+ std::cout << "Exception occurred" << std::endl;
+ }
+
+ try {
+ ret = RUN_ALL_TESTS();
+ } catch (const ::testing::internal::GoogleTestFailureException& e) {
+ ret = -1;
+ std::cout << "GoogleTestFailureException was thrown:" << e.what() << std::endl;
+ }
+
+ return ret;
+}
--- /dev/null
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * 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 <stdlib.h>
+#include <gtest/gtest.h>
+#include <stdio.h>
+
+#include <memory>
+
+#include "pkgmgr_info_mock.h"
+#include "os_mock.h"
+#include "test_fixture.h"
+#include "pkg_finder.hh"
+#include "pkg_upgrader_factory.hh"
+#include "upgrader.hh"
+
+using ::testing::_;
+using ::testing::DoAll;
+using ::testing::Invoke;
+using ::testing::Return;
+using ::testing::SetArgPointee;
+using ::testing::InvokeArgument;
+using ::testing::SaveArg;
+
+using namespace common_fota;
+
+class Mocks : public ::testing::NiceMock<PkgMgrInfoMock>,
+ public ::testing::NiceMock<OsMock> {};
+
+class PkgFinderTest : public TestFixture {
+ public:
+ PkgFinderTest() : TestFixture(std::make_unique<Mocks>()) {}
+ virtual ~PkgFinderTest() {}
+
+ virtual void SetUp() {
+ static int k;
+ pkgmgrinfo_pkginfo_filter_h dummy_filter = (pkgmgrinfo_pkginfo_filter_h)&k;
+
+ EXPECT_CALL(GetMock<PkgMgrInfoMock>(), pkgmgrinfo_pkginfo_filter_create(_))
+ .WillRepeatedly(DoAll(SetArgPointee<0>(dummy_filter), Return(0)));
+ EXPECT_CALL(GetMock<PkgMgrInfoMock>(),
+ pkgmgrinfo_pkginfo_filter_add_bool(_, _, _))
+ .WillRepeatedly(Return(0));
+
+ EXPECT_CALL(GetMock<PkgMgrInfoMock>(),
+ pkgmgrinfo_pkginfo_filter_foreach_pkginfo(_, _, _))
+ .WillOnce(
+ Invoke([](pkgmgrinfo_pkginfo_filter_h handle,
+ pkgmgrinfo_pkg_list_cb pkg_cb, void *user_data) -> int {
+ pkg_cb(nullptr, user_data);
+ pkg_cb(nullptr, user_data);
+ pkg_cb(nullptr, user_data);
+ return 0;
+ })
+ )
+ .WillOnce(Invoke([](pkgmgrinfo_pkginfo_filter_h handle,
+ pkgmgrinfo_pkg_list_cb pkg_cb, void *user_data) -> int {
+ pkg_cb(nullptr, user_data);
+ return 0;
+ }));
+
+ const char* old_ro_pkgid[] = {
+ "org.test.pkg1",
+ "org.test.pkg2",
+ "org.tizen.app-selector"
+ };
+
+ const char* old_ro_pkg_type[] = {
+ "tpk",
+ "wgt",
+ "tpk"
+ };
+
+ const char* old_ro_pkg_version[] = {
+ "1.0.0",
+ "1.2.0",
+ "0.1.0"
+ };
+
+ const char* old_rw_pkgid[] = {
+ "org.tizen.alarm"
+ };
+
+ const char* old_rw_pkg_type[] = {
+ "tpk"
+ };
+
+ const char* old_rw_pkg_version[] = {
+ "1.5.0",
+ };
+
+ EXPECT_CALL(GetMock<PkgMgrInfoMock>(),
+ pkgmgrinfo_pkginfo_get_pkgid(_,_))
+ .WillOnce(DoAll(SetArgPointee<1>(const_cast<char*>(old_ro_pkgid[0])), Return(0)))
+ .WillOnce(DoAll(SetArgPointee<1>(const_cast<char*>(old_ro_pkgid[1])), Return(0)))
+ .WillOnce(DoAll(SetArgPointee<1>(const_cast<char*>(old_ro_pkgid[2])), Return(0)))
+ .WillOnce(DoAll(SetArgPointee<1>(const_cast<char*>(old_rw_pkgid[0])), Return(0)));
+ EXPECT_CALL(GetMock<PkgMgrInfoMock>(),
+ pkgmgrinfo_pkginfo_get_type(_,_))
+ .WillOnce(DoAll(SetArgPointee<1>(const_cast<char*>(old_ro_pkg_type[0])), Return(0)))
+ .WillOnce(DoAll(SetArgPointee<1>(const_cast<char*>(old_ro_pkg_type[1])), Return(0)))
+ .WillOnce(DoAll(SetArgPointee<1>(const_cast<char*>(old_ro_pkg_type[2])), Return(0)))
+ .WillOnce(DoAll(SetArgPointee<1>(const_cast<char*>(old_rw_pkg_type[0])), Return(0)));
+ EXPECT_CALL(GetMock<PkgMgrInfoMock>(),
+ pkgmgrinfo_pkginfo_get_version(_,_))
+ .WillOnce(DoAll(SetArgPointee<1>(const_cast<char*>(old_ro_pkg_version[0])), Return(0)))
+ .WillOnce(DoAll(SetArgPointee<1>(const_cast<char*>(old_ro_pkg_version[1])), Return(0)))
+ .WillOnce(DoAll(SetArgPointee<1>(const_cast<char*>(old_ro_pkg_version[2])), Return(0)))
+ .WillOnce(DoAll(SetArgPointee<1>(const_cast<char*>(old_rw_pkg_version[0])), Return(0)));
+
+ EXPECT_CALL(GetMock<PkgMgrInfoMock>(), pkgmgrinfo_pkginfo_filter_destroy(_))
+ .WillRepeatedly(Return(0));
+
+ finder_.SetManifestDir("./tests/unit_tests/data/packages/");
+ finder_.SetPreloadRwListPath("./tests/unit_tests/data/rw/list.txt");
+ }
+
+ virtual void TearDown() {
+ }
+
+ PkgFinder finder_;
+};
+
+TEST_F(PkgFinderTest, PkgFinder) {
+ finder_.Find();
+
+ EXPECT_EQ(finder_.GetOldPkgs().size(), 4);
+ EXPECT_EQ(finder_.GetNewPkgs().size(), 5);
+}
+
+TEST_F(PkgFinderTest, PkgUpgraderFactory) {
+ PkgUpgraderFactory factory;
+ auto list = factory.MakeList(&finder_);
+
+ EXPECT_EQ(list.size(), 6);
+}
+
+class PkgUpgraderTest : public PkgFinderTest {
+ public:
+ PkgUpgraderTest() {}
+ virtual ~PkgUpgraderTest() {}
+
+ void SetUp() override {
+ PkgFinderTest::SetUp();
+ EXPECT_CALL(GetMock<OsMock>(), fork())
+ .WillRepeatedly(Return(1));
+ EXPECT_CALL(GetMock<OsMock>(), waitpid(_, _, _))
+ .WillRepeatedly(DoAll(SetArgPointee<1>(0), Return(1)));
+ EXPECT_CALL(GetMock<OsMock>(), fchown(_, _, _))
+ .WillRepeatedly(Return(0));
+ EXPECT_CALL(GetMock<OsMock>(), fchmod(_, _))
+ .WillRepeatedly(Return(0));
+ EXPECT_CALL(GetMock<OsMock>(), smack_setlabel(_, _, _))
+ .WillRepeatedly(Return(0));
+ }
+
+ void TearDown() override {
+ PkgFinderTest::TearDown();
+ }
+};
+
+TEST_F(PkgUpgraderTest, Upgrader) {
+ Upgrader upgrader;
+
+ upgrader.SetDbPath("./tests/unit_tests/data/db");
+ ASSERT_TRUE(upgrader.Process(&finder_));
+
+ const auto& success = upgrader.GetSuccessList();
+ const auto& failure = upgrader.GetFailureList();
+
+ EXPECT_EQ(success.size(), 6);
+ EXPECT_EQ(failure.size(), 0);
+}
+
+TEST_F(PkgUpgraderTest, Upgrader_db_bck) {
+ Upgrader upgrader;
+
+ upgrader.SetDbPath("./tests/unit_tests/data/db_bck");
+ EXPECT_TRUE(upgrader.Process(&finder_));
+}
+
+class PkgUpgraderTestForInvalidDbPath : public TestFixture {
+ public:
+ PkgUpgraderTestForInvalidDbPath() : TestFixture(std::make_unique<Mocks>()) {}
+ virtual ~PkgUpgraderTestForInvalidDbPath() {}
+
+ virtual void SetUp() {
+ finder_.SetManifestDir("./tests/unit_tests/data/packages/");
+ finder_.SetPreloadRwListPath("./tests/unit_tests/data/rw/list.txt");
+ }
+
+ virtual void TearDown() {
+ }
+
+ PkgFinder finder_;
+};
+
+TEST_F(PkgUpgraderTestForInvalidDbPath, Upgrader_invalid_db) {
+ Upgrader upgrader;
+
+ upgrader.SetDbPath("./tests/unit_tests/data/invalid_path");
+ EXPECT_FALSE(upgrader.Process(&finder_));
+}