Skip to content
This repository has been archived by the owner on May 21, 2024. It is now read-only.

Commit

Permalink
Android support
Browse files Browse the repository at this point in the history
* build script update required by atkualizr-android
* package manager for android
* log system integration

Signed-off-by: Maksim Beznos <maximbns@gmail.com>
  • Loading branch information
riqkum committed Jan 16, 2019
1 parent 067185a commit aa4f3b4
Show file tree
Hide file tree
Showing 12 changed files with 233 additions and 27 deletions.
19 changes: 17 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,15 @@ unset(AKTUALIZR_CHECKED_SRCS CACHE)
set(Boost_USE_STATIC_LIBS ON)
set(BOOST_COMPONENTS log_setup log filesystem program_options)

if(ANDROID)
set(BOOST_ROOT ${PREBUILD_BOOST_ROOT})
set(Boost_INCLUDE_DIR ${BOOST_ROOT}/include)
set(Boost_LIBRARY_DIR ${BOOST_ROOT}/libs/llvm/${ANDROID_ABI})
if(Boost_FOUND)
include_directories(${Boost_INCLUDE_DIRS})
endif()
endif(ANDROID)

if(BUILD_OPCUA)
list(APPEND BOOST_COMPONENTS serialization iostreams)
endif(BUILD_OPCUA)
Expand All @@ -71,6 +80,7 @@ find_package(sodium REQUIRED)
find_package(SQLite3 REQUIRED)
find_package(Git)
find_package(Asn1c REQUIRED)
find_package(ZLIB)

if(NOT AKTUALIZR_VERSION)
if(GIT_EXECUTABLE)
Expand Down Expand Up @@ -266,6 +276,7 @@ include_directories(${SQLITE3_INCLUDE_DIRS})
include_directories(${LIBP11_INCLUDE_DIR})
include_directories(${sodium_INCLUDE_DIR})
include_directories(${OPENSSL_INCLUDE_DIR})
include_directories(${CURL_INCLUDE_DIR})
include_directories(${LibArchive_INCLUDE_DIR})

set_source_files_properties(third_party/jsoncpp/jsoncpp.cpp PROPERTIES COMPILE_FLAGS -w)
Expand Down Expand Up @@ -336,7 +347,12 @@ set (AKTUALIZR_EXTERNAL_LIBS
${LIBP11_LIBRARIES}
${LIBDPKG_LIBRARIES}
${GLIB2_LIBRARIES}
${SYSTEMD_LIBRARY})
${SYSTEMD_LIBRARY}
${ZLIB_LIBRARY})

if(ANDROID)
list(APPEND AKTUALIZR_EXTERNAL_LIBS liblog.so)
endif()

get_directory_property(hasParent PARENT_DIRECTORY)
if(hasParent)
Expand All @@ -351,7 +367,6 @@ if(BUILD_WITH_CODE_COVERAGE)
list(APPEND TEST_LIBS gcov)
endif(BUILD_WITH_CODE_COVERAGE)


include(CTest)
ENABLE_TESTING()
# It would be great to use GTEST_OUTPUT directly, but I couldn't get it to work.
Expand Down
6 changes: 2 additions & 4 deletions src/libaktualizr/config/config.cc
Original file line number Diff line number Diff line change
Expand Up @@ -139,9 +139,7 @@ KeyManagerConfig Config::keymanagerConfig() const {
void Config::postUpdateValues() {
logger_set_threshold(logger);

if (provision.provision_path.empty()) {
provision.mode = ProvisionMode::kImplicit;
}
provision.mode = provision.provision_path.empty() ? ProvisionMode::kImplicit : ProvisionMode::kAutomatic;

if (tls.server.empty()) {
if (!tls.server_url_path.empty()) {
Expand Down Expand Up @@ -253,7 +251,7 @@ void Config::readSecondaryConfigs(const boost::filesystem::path& sconfigs_dir) {
LOG_ERROR << "Could not read secondary configs from " << sconfigs_dir << ": not a directory";
return;
}
for (const auto& config_file : Utils::glob((sconfigs_dir / "*.json").string())) {
for (const auto& config_file : Utils::getDirEntriesByExt(sconfigs_dir, ".json")) {
LOG_INFO << "Parsing secondary config: " << config_file;
uptane.secondary_configs.emplace_back(config_file);
}
Expand Down
6 changes: 6 additions & 0 deletions src/libaktualizr/package_manager/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,9 @@ aktualizr_source_file_checks(packagemanagerfactory_test.cc ostreemanager_test.cc

aktualizr_source_file_checks(ostreemanager.cc ostreereposync.cc
ostreemanager.h ostreereposync.h)

if(ANDROID)
target_sources(package_manager PRIVATE androidmanager.cc)
endif(ANDROID)

aktualizr_source_file_checks(androidmanager.cc androidmanager.h)
105 changes: 105 additions & 0 deletions src/libaktualizr/package_manager/androidmanager.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
#include <regex>

#include "androidmanager.h"

#include "utilities/utils.h"

Json::Value AndroidManager::getInstalledPackages() const {
Json::Value packages(Json::arrayValue);
Json::Value package;
package["name"] = "aktualizr";
package["version"] = "n/a";
packages.append(package);
return packages;
}

Uptane::Target AndroidManager::getCurrent() const {
std::vector<Uptane::Target> installed_versions;
std::string current_hash;
size_t current_k = SIZE_MAX;
storage_->loadPrimaryInstalledVersions(&installed_versions, &current_k, nullptr);
if (current_k != SIZE_MAX) {
current_hash = installed_versions[current_k].sha256Hash();
}
AndroidInstallationState installation_state;
if (AndroidInstallationDispatcher::GetState().state_ == AndroidInstallationState::STATE_INSTALLED) {
installation_state = AndroidInstallationDispatcher::Dispatch();
if (installation_state.state_ == AndroidInstallationState::STATE_UPDATE) {
current_hash = installation_state.payload_;
}
}
std::vector<Uptane::Target>::iterator it;
for (it = installed_versions.begin(); it != installed_versions.end(); it++) {
if (it->sha256Hash() == current_hash) {
if (installation_state.state_ == AndroidInstallationState::STATE_UPDATE) {
storage_->savePrimaryInstalledVersion(*it, InstalledVersionUpdateMode::kCurrent);
auto outcome = data::InstallOutcome(data::UpdateResultCode::kOk, "package successfully intalled");
storage_->storeInstallationResult(data::OperationResult(it->filename(), outcome));
}
return *it;
}
}
return getUnknown();
}

data::InstallOutcome AndroidManager::install(const Uptane::Target& target) const {
if (AndroidInstallationDispatcher::GetState().state_ == AndroidInstallationState::STATE_NOP) {
LOG_INFO << "Begin Android package installation";
storage_->savePrimaryInstalledVersion(target, InstalledVersionUpdateMode::kPending);
auto package_filename = (Utils::getStorageRootPath() / target.filename()).string() + "." + target.sha256Hash();
std::ofstream package_file(package_filename.c_str());
if (!package_file.good()) {
throw std::runtime_error(std::string("Error opening file ") + package_filename);
}
package_file << *storage_->openTargetFile(target);
}
return data::InstallOutcome(data::UpdateResultCode::kInProgress, "Installation is in progress");
}

data::InstallOutcome AndroidManager::finalizeInstall(const Uptane::Target& target) const {
(void)target;
return data::InstallOutcome(data::UpdateResultCode::kOk, "package installation successfully finalized");
}

AndroidInstallationState AndroidInstallationDispatcher::GetState() {
boost::filesystem::directory_iterator entryItEnd, entryIt(Utils::getStorageRootPath());
for (; entryIt != entryItEnd; ++entryIt) {
auto& entry_path = entryIt->path();
if (boost::filesystem::is_directory(*entryIt)) {
continue;
}
auto package_file_path = entry_path.string();
auto ext = entry_path.extension().string();
if (ext == ".installed") {
return {AndroidInstallationState::STATE_INSTALLED, package_file_path};
} else if (ext == ".inprogress") {
return {AndroidInstallationState::STATE_IN_PROGRESS, package_file_path};
} else if (std::regex_match(ext, std::regex("\\.[[:xdigit:]]+"))) {
return {AndroidInstallationState::STATE_READY, package_file_path};
}
}
return {AndroidInstallationState::STATE_NOP, ""};
}

AndroidInstallationState AndroidInstallationDispatcher::Dispatch() {
auto current = GetState();
if (current.state_ == AndroidInstallationState::STATE_INSTALLED) {
auto hash = boost::filesystem::path(current.payload_).stem().extension().string();
if (!hash.empty()) {
hash = hash.substr(1);
}
boost::filesystem::remove(current.payload_);
return {AndroidInstallationState::STATE_UPDATE, hash};
} else if (current.state_ == AndroidInstallationState::STATE_IN_PROGRESS) {
boost::filesystem::path installed_package_file_path(current.payload_);
installed_package_file_path.replace_extension(".installed");
boost::filesystem::rename(boost::filesystem::path(current.payload_), installed_package_file_path);
return {AndroidInstallationState::STATE_UPDATE, installed_package_file_path.string()};
} else if (std::regex_match(boost::filesystem::path(current.payload_).extension().string(),
std::regex("\\.[[:xdigit:]]+"))) {
boost::filesystem::path inprogress_package_file_path = boost::filesystem::path(current.payload_ + ".inprogress");
boost::filesystem::rename(boost::filesystem::path(current.payload_), inprogress_package_file_path);
return {AndroidInstallationState::STATE_IN_PROGRESS, inprogress_package_file_path.string()};
}
return {AndroidInstallationState::STATE_NOP, ""};
}
39 changes: 39 additions & 0 deletions src/libaktualizr/package_manager/androidmanager.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#ifndef ANDROIDMANAGER_H
#define ANDROIDMANAGER_H

#include "package_manager/packagemanagerinterface.h"
#include "storage/invstorage.h"

class AndroidInstallationDispatcher;

class AndroidManager : public PackageManagerInterface {
public:
explicit AndroidManager(std::shared_ptr<INvStorage> storage) : storage_(std::move(storage)) {}
~AndroidManager() override = default;
std::string name() const override { return "android"; }
Json::Value getInstalledPackages() const override;

Uptane::Target getCurrent() const override;
bool imageUpdated() override { return true; };

data::InstallOutcome install(const Uptane::Target &target) const override;
data::InstallOutcome finalizeInstall(const Uptane::Target &target) const override;

private:
std::shared_ptr<INvStorage> storage_;
};

struct AndroidInstallationState {
enum State { STATE_NOP, STATE_READY, STATE_IN_PROGRESS, STATE_INSTALLED, STATE_UPDATE };

State state_;
std::string payload_;
};

class AndroidInstallationDispatcher {
public:
static AndroidInstallationState GetState();
static AndroidInstallationState Dispatch();
};

#endif // ANDROIDMANAGER_H
4 changes: 3 additions & 1 deletion src/libaktualizr/package_manager/packagemanagerconfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

#include "utilities/config_utils.h"

enum class PackageManager { kNone = 0, kOstree, kDebian };
enum class PackageManager { kNone = 0, kOstree, kDebian, kAndroid };

struct PackageConfig {
PackageManager type{PackageManager::kOstree};
Expand All @@ -33,6 +33,8 @@ inline void CopyFromConfig(PackageManager& dest, const std::string& option_name,
dest = PackageManager::kOstree;
} else if (pm_type == "debian") {
dest = PackageManager::kDebian;
} else if (pm_type == "android") {
dest = PackageManager::kAndroid;
} else {
dest = PackageManager::kNone;
}
Expand Down
10 changes: 10 additions & 0 deletions src/libaktualizr/package_manager/packagemanagerfactory.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
#include "package_manager/debianmanager.h"
#endif

#if defined(ANDROID)
#include "package_manager/androidmanager.h"
#endif

#include "logging/logging.h"

std::shared_ptr<PackageManagerInterface> PackageManagerFactory::makePackageManager(
Expand All @@ -27,6 +31,12 @@ std::shared_ptr<PackageManagerInterface> PackageManagerFactory::makePackageManag
return std::make_shared<DebianManager>(pconfig, storage);
#else
throw std::runtime_error("aktualizr was compiled without debian packages support!");
#endif
case PackageManager::kAndroid:
#if defined(ANDROID)
return std::make_shared<AndroidManager>(storage);
#else
throw std::runtime_error("aktualizr was compiled without android support!");
#endif
case PackageManager::kNone:
return std::make_shared<PackageManagerFake>(pconfig, storage, bootloader);
Expand Down
4 changes: 1 addition & 3 deletions src/libaktualizr/telemetry/telemetryconfig.cc
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
#include "telemetry/telemetryconfig.h"

#include <boost/log/trivial.hpp>

#include "utilities/config_utils.h"

void TelemetryConfig::updateFromPropertyTree(const boost::property_tree::ptree& pt) {
Expand All @@ -10,4 +8,4 @@ void TelemetryConfig::updateFromPropertyTree(const boost::property_tree::ptree&

void TelemetryConfig::writeToStream(std::ostream& out_stream) const {
writeOption(out_stream, report_network, "report_network");
}
}
2 changes: 2 additions & 0 deletions src/libaktualizr/uptane/managedsecondary.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
#include "crypto/crypto.h"
#include "logging/logging.h"

#include <sys/stat.h>

namespace Uptane {
ManagedSecondary::ManagedSecondary(const SecondaryConfig &sconfig_in) : SecondaryInterface(sconfig_in) {
// TODO: FIX
Expand Down
3 changes: 1 addition & 2 deletions src/libaktualizr/utilities/config_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,9 +144,8 @@ class BaseConfig {
continue;
}
if (boost::filesystem::is_directory(config)) {
for (const auto& config_file : Utils::glob((config / "*.toml").string())) {
for (const auto& config_file : Utils::getDirEntriesByExt(config, ".toml"))
configs_map[config_file.filename().string()] = config_file;
}
} else {
configs_map[config.filename().string()] = config;
}
Expand Down
50 changes: 37 additions & 13 deletions src/libaktualizr/utilities/utils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <archive_entry.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <glob.h>
#include <ifaddrs.h>
#include <netinet/in.h>
#include <sys/stat.h>
Expand Down Expand Up @@ -646,17 +647,18 @@ boost::filesystem::path Utils::absolutePath(const boost::filesystem::path &root,
return (root / file);
}

std::vector<boost::filesystem::path> Utils::glob(const std::string &pat) {
glob_t glob_result;
::glob(pat.c_str(), GLOB_TILDE, nullptr, &glob_result);
std::vector<boost::filesystem::path> ret;
for (unsigned int i = 0; i < glob_result.gl_pathc; ++i) {
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
ret.emplace_back(glob_result.gl_pathv[i]);
// passing ext argument keep the leading point e.g. '.ext'
std::vector<boost::filesystem::path> Utils::getDirEntriesByExt(const boost::filesystem::path &dir_path,
const std::string &ext) {
std::vector<boost::filesystem::path> entries;
boost::filesystem::directory_iterator entryItEnd, entryIt(dir_path);
for (; entryIt != entryItEnd; ++entryIt) {
auto &entry_path = entryIt->path();
if (!boost::filesystem::is_directory(*entryIt) && entry_path.extension().string() == ext) {
entries.push_back(entry_path);
}
}
globfree(&glob_result);
std::sort(ret.begin(), ret.end());
return ret;
return entries;
}

void Utils::createDirectories(const boost::filesystem::path &path, mode_t mode) {
Expand Down Expand Up @@ -715,9 +717,16 @@ class SafeTempRoot {

private:
SafeTempRoot() {
boost::filesystem::path p =
boost::filesystem::temp_directory_path() / boost::filesystem::unique_path("aktualizr-%%%%-%%%%-%%%%-%%%%");

boost::filesystem::path prefix;
#if !defined(ANDROID)
prefix = boost::filesystem::temp_directory_path();
#else
prefix = Utils::getStorageRootPath();
if (prefix.empty()) {
throw std::runtime_error("Empty temp root dir prefix");
}
#endif // defined(ANDROID)
boost::filesystem::path p = prefix / boost::filesystem::unique_path("aktualizr-%%%%-%%%%-%%%%-%%%%");
if (mkdir(p.c_str(), S_IRWXU) == -1) {
throw std::runtime_error("could not create temporary directory root: " + p.native());
}
Expand All @@ -735,6 +744,21 @@ class SafeTempRoot {
boost::filesystem::path path;
};

#if defined(ANDROID)
std::mutex Utils::storage_root_path_mutex_;
std::string Utils::storage_root_path_;

void Utils::setStorageRootPath(const std::string &storage_root_path) {
std::lock_guard<std::mutex> guard(storage_root_path_mutex_);
storage_root_path_ = storage_root_path;
}

boost::filesystem::path Utils::getStorageRootPath() {
std::lock_guard<std::mutex> guard(storage_root_path_mutex_);
return storage_root_path_;
}
#endif // defined(ANDROID)

TemporaryFile::TemporaryFile(const std::string &hint)
: tmp_name_(SafeTempRoot::Get() / boost::filesystem::unique_path("%%%%-%%%%-" + hint)) {}

Expand Down
Loading

0 comments on commit aa4f3b4

Please sign in to comment.