M module-apps/application-settings/windows/Info.cpp => module-apps/application-settings/windows/Info.cpp +9 -7
@@ 15,7 15,7 @@
#include <gui/widgets/Style.hpp>
#include <i18n/i18n.hpp>
-#include <vfs.hpp>
+#include <boot/bootconfig.hpp>
namespace gui
{
@@ 48,12 48,14 @@ namespace gui
addAlignedLabelWithValue(box, "GIT tag:", std::string(GIT_TAG));
addAlignedLabelWithValue(box, "GIT branch:", std::string(GIT_BRANCH));
addAlignedLabelWithValue(box, "Version:", std::string(VERSION));
- addAlignedLabelWithValue(box,
- "Bootloader:",
- (vfs.getBootConfig().bootloader_verion.empty()
- ? utils::localize.get("not available")
- : vfs.getBootConfig().bootloader_verion));
-
+ {
+ boot::BootConfig bootCfg;
+ bootCfg.load();
+ addAlignedLabelWithValue(box,
+ "Bootloader:",
+ (bootCfg.bootloader_version().empty() ? utils::localize.get("not available")
+ : bootCfg.bootloader_version()));
+ }
std::string firmwareVersion;
CellularServiceAPI::GetFirmwareVersion(getApplication(), firmwareVersion);
addAlignedLabelWithValue(
M module-services/service-desktop/endpoints/update/UpdateMuditaOS.cpp => module-services/service-desktop/endpoints/update/UpdateMuditaOS.cpp +5 -4
@@ 49,6 49,7 @@ json11::Json FileInfo::to_json() const
UpdateMuditaOS::UpdateMuditaOS(ServiceDesktop *ownerService) : owner(ownerService)
{
status = updateos::UpdateState::Initial;
+ bootConfig.load();
}
updateos::UpdateError UpdateMuditaOS::setUpdateFile(fs::path updateFileToUse)
@@ 80,7 81,7 @@ updateos::UpdateError UpdateMuditaOS::runUpdate()
informDebug("Prepraring temp dir");
updateRunStatus.startTime = utils::time::getCurrentTimestamp().getTime();
- updateRunStatus.fromVersion = vfs.getBootConfig().to_json();
+ updateRunStatus.fromVersion = bootConfig.to_json();
storeRunStatusInDB();
updateos::UpdateError err = prepareTempDirForUpdate();
@@ 256,9 257,9 @@ updateos::UpdateError UpdateMuditaOS::verifyVersion()
else {
/* version comparison goes here */
updateRunStatus.toVersion = targetVersionInfo;
- const bool ret = vfs.getBootConfig().version_compare(
- targetVersionInfo[purefs::json::version_string].string_value(), vfs.getBootConfig().os_version);
- LOG_DEBUG("verifyVersion comaprison result == %s", ret ? "true" : "false");
+ const bool ret = bootConfig.version_compare(targetVersionInfo[purefs::json::version_string].string_value(),
+ bootConfig.os_version());
+ LOG_DEBUG("verifyVersion comparison result == %s", ret ? "true" : "false");
}
return updateos::UpdateError::NoError;
}
M module-services/service-desktop/endpoints/update/UpdateMuditaOS.hpp => module-services/service-desktop/endpoints/update/UpdateMuditaOS.hpp +2 -0
@@ 5,6 5,7 @@
#include <json/json11.hpp>
#include <module-utils/microtar/src/microtar.hpp>
+#include <boot/bootconfig.hpp>
#include <cstdint>
#include <filesystem>
@@ 181,5 182,6 @@ class UpdateMuditaOS : public updateos::UpdateStats
updateos::UpdateRunStatus updateRunStatus;
json11::Json updateHistory;
json11::Json targetVersionInfo;
+ boot::BootConfig bootConfig;
[[nodiscard]] static std::string readContent(const char *filename) noexcept;
};
M module-utils/CMakeLists.txt => module-utils/CMakeLists.txt +2 -0
@@ 93,3 93,5 @@ endif()
if (${ENABLE_TESTS})
add_subdirectory( test )
endif()
+
+add_subdirectory(bootconfig)
A module-utils/bootconfig/CMakeLists.txt => module-utils/bootconfig/CMakeLists.txt +18 -0
@@ 0,0 1,18 @@
+cmake_minimum_required(VERSION 3.12)
+
+project( utils-bootconfig VERSION 1.0
+ DESCRIPTION "Library for processing boot config"
+)
+
+set ( SOURCES
+ src/bootconfig.cpp
+)
+
+set( INCLUDES
+ include
+)
+
+add_library( ${PROJECT_NAME} STATIC ${SOURCES} )
+
+target_include_directories( ${PROJECT_NAME} PUBLIC ${INCLUDES} )
+target_link_libraries( ${PROJECT_NAME} PRIVATE module-utils module-vfs)
A module-utils/bootconfig/include/boot/bootconfig.hpp => module-utils/bootconfig/include/boot/bootconfig.hpp +61 -0
@@ 0,0 1,61 @@
+// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+#include <module-utils/json/json11.hpp>
+#include <string>
+#include <filesystem>
+
+namespace boot
+{
+ class BootConfig
+ {
+ public:
+ BootConfig();
+ static int version_compare(const std::string &v1, const std::string &v2);
+ [[nodiscard]] json11::Json to_json() const;
+ int load();
+ int save();
+ auto os_image() -> const std::string &
+ {
+ return m_os_image;
+ }
+ auto os_type() -> const std::string &
+ {
+ return m_os_type;
+ }
+ auto os_version() -> const std::string &
+ {
+ return m_os_version;
+ }
+ auto bootloader_version() -> const std::string &
+ {
+ return m_bootloader_version;
+ }
+ auto timestamp() -> const std::string &
+ {
+ return m_timestamp;
+ }
+ auto os_root_path() -> const std::filesystem::path &
+ {
+ return m_os_root_path;
+ }
+ void updateTimestamp();
+
+ private:
+ bool loadBootConfig(const std::filesystem::path &bootJsonPath);
+ const std::filesystem::path getCurrentBootJSON();
+ bool verifyCRC(const std::filesystem::path filePath);
+ bool verifyCRC(const std::string filePath, const unsigned long crc32);
+
+ private:
+ std::string m_os_image{"boot.bin"};
+ std::string m_os_type{"current"};
+ std::string m_os_version;
+ std::string m_bootloader_version;
+ std::string m_timestamp;
+ json11::Json m_boot_json_parsed;
+ std::filesystem::path m_os_root_path;
+ std::filesystem::path m_boot_json;
+ };
+} // namespace boot
A module-utils/bootconfig/src/bootconfig.cpp => module-utils/bootconfig/src/bootconfig.cpp +271 -0
@@ 0,0 1,271 @@
+// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+#include <boot/bootconfig.hpp>
+
+#include <purefs/filesystem_paths.hpp>
+#include <source/version.hpp>
+#include <time/time_conversion.hpp>
+#include <ticks.hpp>
+#include <stdio.h>
+#include <log/log.hpp>
+#include <crc32/crc32.h>
+
+namespace boot
+{
+ namespace
+ {
+ bool replaceWithString(const fs::path &fileToModify, const std::string &stringToWrite)
+ {
+ auto lamb = [](::FILE *stream) { fclose(stream); };
+ std::unique_ptr<::FILE, decltype(lamb)> fp(fopen(fileToModify.c_str(), "w"), lamb);
+
+ if (fp.get() != nullptr) {
+ size_t dataWritten = fwrite(stringToWrite.c_str(), stringToWrite.length(), 1, fp.get());
+ return dataWritten == 1;
+ }
+ else {
+ return false;
+ }
+ }
+ void computeCRC32(::FILE *file, unsigned long *outCrc32)
+ {
+ if (outCrc32 == nullptr)
+ return;
+
+ std::unique_ptr<unsigned char[]> buf(new unsigned char[purefs::buffer::crc_buf]);
+ size_t bufLen;
+
+ *outCrc32 = 0;
+
+ while (!::feof(file)) {
+ bufLen = ::fread(buf.get(), 1, purefs::buffer::crc_buf, file);
+ if (bufLen <= 0)
+ break;
+
+ *outCrc32 = Crc32_ComputeBuf(*outCrc32, buf.get(), bufLen);
+ }
+ }
+
+ bool updateFileCRC32(const fs::path &file)
+ {
+ unsigned long fileCRC32 = 0;
+ auto lamb = [](::FILE *stream) { ::fclose(stream); };
+
+ std::unique_ptr<::FILE, decltype(lamb)> fp(fopen(file.c_str(), "r"), lamb);
+
+ if (fp.get() != nullptr) {
+ std::unique_ptr<char[]> crc32Buf(new char[purefs::buffer::crc_char_size]);
+ int written = 0;
+ computeCRC32(fp.get(), &fileCRC32);
+ LOG_INFO("updateFileCRC32 writing new crc32 %08" PRIX32 " for %s",
+ static_cast<std::uint32_t>(fileCRC32),
+ file.c_str());
+ if (fileCRC32 != 0) {
+ if ((written = sprintf(crc32Buf.get(), "%08" PRIX32, fileCRC32)) !=
+ (purefs::buffer::crc_char_size - 1)) {
+ LOG_INFO("updateFileCRC32 can't prepare string for crc32, sprintf returned %d instead of %d",
+ written,
+ purefs::buffer::crc_char_size - 1);
+ return false;
+ }
+ fs::path fileCRC32Path = file;
+ fileCRC32Path += purefs::extension::crc32;
+
+ std::unique_ptr<::FILE, decltype(lamb)> fpCRC32(fopen(fileCRC32Path.c_str(), "w"), lamb);
+
+ if (fpCRC32.get() != nullptr) {
+ if (fwrite(crc32Buf.get(), 1, purefs::buffer::crc_char_size, fpCRC32.get()) ==
+ purefs::buffer::crc_char_size) {
+ LOG_INFO("updateFileCRC32 wrote \"%s\" in %s", crc32Buf.get(), fileCRC32Path.c_str());
+ return true;
+ }
+ else {
+ LOG_WARN("updateFileCRC32 can't write new crc32");
+ return false;
+ }
+ }
+ else {
+ LOG_WARN("updateFileCRC32 can't open crc32 file for write");
+ return false;
+ }
+ }
+ }
+ else {
+ LOG_WARN("updateFileCRC32 can't open file %s for write", file.c_str());
+ return false;
+ }
+
+ return false;
+ }
+ std::string loadFileAsString(const fs::path &fileToLoad)
+ {
+ auto lamb = [](::FILE *stream) { ::fclose(stream); };
+ std::unique_ptr<char[]> readBuf(new char[purefs::buffer::tar_buf]);
+ std::unique_ptr<::FILE, decltype(lamb)> fp(fopen(fileToLoad.c_str(), "r"), lamb);
+ std::string contents;
+ size_t readSize;
+
+ if (fp.get() != nullptr) {
+ while (!feof(fp.get())) {
+ readSize = fread(readBuf.get(), 1, purefs::buffer::tar_buf, fp.get());
+ contents.append(static_cast<const char *>(readBuf.get()), readSize);
+ }
+ }
+
+ return contents;
+ }
+
+ } // namespace
+
+ BootConfig::BootConfig() : m_os_root_path(purefs::dir::getRootDiskPath())
+ {}
+ json11::Json BootConfig::to_json() const
+ {
+ return json11::Json::object{
+ {purefs::json::main,
+ json11::Json::object{{purefs::json::os_image, m_os_image},
+ {purefs::json::os_type, m_os_type},
+ {purefs::json::os_version, m_os_version},
+ {purefs::json::timestamp, m_timestamp}}},
+
+ {purefs::json::git_info,
+ json11::Json::object{{purefs::json::os_git_tag, std::string(GIT_TAG)},
+ {purefs::json::os_git_revision, std::string(GIT_REV)},
+ {purefs::json::os_git_branch, std::string(GIT_BRANCH)}}},
+ {purefs::json::bootloader, json11::Json::object{{purefs::json::os_version, m_bootloader_version}}}};
+ }
+ int BootConfig::load()
+ {
+ return !loadBootConfig(getCurrentBootJSON());
+ }
+
+ // Method to compare two version strings
+ // v1 < v2 -> -1
+ // v1 == v2 -> 0
+ int BootConfig::version_compare(const std::string &v1, const std::string &v2)
+ {
+ size_t i = 0, j = 0;
+ while (i < v1.length() || j < v2.length()) {
+ int acc1 = 0, acc2 = 0;
+
+ while (i < v1.length() && v1[i] != '.') {
+ acc1 = acc1 * 10 + (v1[i] - '0');
+ i++;
+ }
+ while (j < v2.length() && v2[j] != '.') {
+ acc2 = acc2 * 10 + (v2[j] - '0');
+ j++;
+ }
+
+ if (acc1 < acc2)
+ return -1;
+ if (acc1 > acc2)
+ return +1;
+
+ ++i;
+ ++j;
+ }
+ return 0;
+ }
+
+ void BootConfig::updateTimestamp()
+ {
+ m_timestamp = utils::time::Timestamp().str("%c");
+ LOG_INFO("vfs::updateTimestamp \"%s\"", to_json().dump().c_str());
+
+ if (replaceWithString(m_boot_json, to_json().dump())) {
+ updateFileCRC32(m_boot_json);
+ }
+ }
+ bool BootConfig::loadBootConfig(const std::filesystem::path &bootJsonPath)
+ {
+ std::string parseErrors = "";
+ std::string jsonContents = loadFileAsString(bootJsonPath);
+
+ LOG_INFO("vfs::getOSRootFromJSON parsing %s", bootJsonPath.c_str());
+ LOG_INFO("vfs::getOSRootFromJSON \"%s\"", jsonContents.c_str());
+
+ m_boot_json_parsed = json11::Json::parse(jsonContents, parseErrors);
+
+ if (parseErrors == "") {
+ m_os_type = m_boot_json_parsed[purefs::json::main][purefs::json::os_type].string_value();
+ m_os_image = m_boot_json_parsed[purefs::json::main][purefs::json::os_image].string_value();
+ m_os_root_path = purefs::createPath(purefs::dir::getRootDiskPath(), m_os_type);
+ m_boot_json = bootJsonPath;
+ m_bootloader_version =
+ m_boot_json_parsed[purefs::json::bootloader][purefs::json::os_version].string_value();
+ m_timestamp = utils::time::Timestamp().str("%c");
+ m_os_version = std::string(VERSION);
+
+ LOG_INFO("boot_config: %s", to_json().dump().c_str());
+ return true;
+ }
+ else {
+ m_os_type = PATH_CURRENT;
+ m_os_image = purefs::file::boot_bin;
+ m_os_root_path = purefs::createPath(purefs::dir::getRootDiskPath(), m_os_type);
+ m_boot_json = bootJsonPath;
+ m_timestamp = utils::time::Timestamp().str("%c");
+ m_os_version = std::string(VERSION);
+ LOG_WARN("vfs::getOSRootFromJSON failed to parse %s: \"%s\"", bootJsonPath.c_str(), parseErrors.c_str());
+ return false;
+ }
+ }
+ const std::filesystem::path BootConfig::getCurrentBootJSON()
+ {
+ if (verifyCRC(purefs::file::boot_json)) {
+ return purefs::createPath(purefs::dir::getRootDiskPath(), purefs::file::boot_json);
+ }
+ LOG_INFO("vfs::getCurrentBootJSON crc check failed on %s", purefs::file::boot_json);
+ // replace broken .boot.json with a default one
+ replaceWithString(purefs::dir::getRootDiskPath() / purefs::file::boot_json, to_json().dump());
+ return purefs::createPath(purefs::dir::getRootDiskPath(), purefs::file::boot_json);
+ }
+
+ bool BootConfig::verifyCRC(const std::string filePath, const unsigned long crc32)
+ {
+ unsigned long crc32Read;
+ auto lamb = [](::FILE *stream) { ::fclose(stream); };
+
+ std::unique_ptr<::FILE, decltype(lamb)> fp(::fopen(filePath.c_str(), "r"), lamb);
+
+ if (fp.get() != nullptr) {
+ computeCRC32(fp.get(), &crc32Read);
+ LOG_INFO("verifyCRC computed crc32 for %s is %08" PRIX32,
+ filePath.c_str(),
+ static_cast<std::uint32_t>(crc32Read));
+ return (crc32Read == crc32);
+ }
+ LOG_ERROR("verifyCRC can't open %s", filePath.c_str());
+ return (false);
+ }
+
+ bool BootConfig::verifyCRC(const std::filesystem::path filePath)
+ {
+ auto lamb = [](::FILE *stream) { ::fclose(stream); };
+ std::unique_ptr<char[]> crcBuf(new char[purefs::buffer::crc_char_size]);
+ size_t readSize;
+ fs::path crcFilePath(filePath);
+ crcFilePath += purefs::extension::crc32;
+
+ std::unique_ptr<::FILE, decltype(lamb)> fp(::fopen(crcFilePath.c_str(), "r"), lamb);
+
+ if (fp.get() != nullptr) {
+ if ((readSize = ::fread(crcBuf.get(), 1, purefs::buffer::crc_char_size, fp.get())) !=
+ (purefs::buffer::crc_char_size)) {
+ LOG_ERROR("verifyCRC fread on %s returned different size then %d [%zu]",
+ crcFilePath.c_str(),
+ purefs::buffer::crc_char_size,
+ readSize);
+ return false;
+ }
+
+ const unsigned long crc32Read = strtoull(crcBuf.get(), nullptr, purefs::buffer::crc_radix);
+
+ LOG_INFO("verifyCRC read %s string:\"%s\" hex:%08lX", crcFilePath.c_str(), crcBuf.get(), crc32Read);
+ return verifyCRC(filePath, crc32Read);
+ }
+ LOG_ERROR("verifyCRC can't open %s", crcFilePath.c_str());
+ return false;
+ }
+} // namespace boot
M module-vfs/CMakeLists.txt => module-vfs/CMakeLists.txt +4 -2
@@ 75,8 75,8 @@ set(SOURCES ""
src/purefs/vfs_subsystem.cpp
drivers/src/purefs/fs/filesystem_vfat.cpp
drivers/src/purefs/fs/filesystem_littlefs.cpp
- src/deprecated/vfs-utils.cpp
src/deprecated/vfs.cpp
+ src/deprecated/vfs-utils.cpp
src/deprecated/vfsNotifier.cpp
)
@@ 126,7 126,9 @@ target_include_directories(${PROJECT_NAME}
)
target_link_libraries(${PROJECT_NAME} PUBLIC ${TARGET_LIBRARIES} module-bsp module-utils)
-target_link_libraries(${PROJECT_NAME} PRIVATE littlefs)
+target_link_libraries(${PROJECT_NAME} PRIVATE littlefs )
+# TODO: Temporary only remove when removing old vfs
+target_link_libraries(${PROJECT_NAME} PUBLIC utils-bootconfig )
if (${ENABLE_TESTS})
add_subdirectory(tests)
M module-vfs/board/cross/free_rtos_custom/portable/vfs.cpp => module-vfs/board/cross/free_rtos_custom/portable/vfs.cpp +8 -10
@@ 23,22 23,20 @@ void vfs::Init()
/* Print out information on the disk. */
FF_eMMC_user_DiskShowPartition(emmcFFDisk);
- bootConfig.os_root_path = purefs::dir::getRootDiskPath();
-
- chnNotifier.onFileSystemInitialized();
initDone = true;
-
- if (loadBootConfig(getCurrentBootJSON())) {
- LOG_INFO("vfs::Init osType %s root:%s", bootConfig.os_type.c_str(), bootConfig.os_root_path.c_str());
- if (ff_chdir(bootConfig.os_root_path.c_str()) != 0) {
- LOG_ERROR("vfs::Init can't chdir to %s", bootConfig.os_root_path.c_str());
+ int err = bootConfig.load();
+ if (!err) {
+ LOG_INFO("vfs::Init osType %s root:%s", bootConfig.os_type().c_str(), bootConfig.os_root_path().c_str());
+ if (ff_chdir(bootConfig.os_root_path().c_str()) != 0) {
+ LOG_ERROR("vfs::Init can't chdir to %s", bootConfig.os_root_path().c_str());
}
}
else {
- LOG_ERROR("vfs::Init unable to determine OS type, fallback to %s", bootConfig.os_root_path.c_str());
+ LOG_ERROR("vfs::Init unable to determine OS type, fallback to %s", bootConfig.os_root_path().c_str());
}
- LOG_INFO("vfs::Init running on ARM osRootPath: %s", bootConfig.os_root_path.c_str());
+ chnNotifier.onFileSystemInitialized();
+ LOG_INFO("vfs::Init running on ARM osRootPath: %s", bootConfig.os_root_path().c_str());
// this should already exist and have user data in it
// if it does not create an exmpty directory so that sqlite3 does not fault
M module-vfs/board/linux/free_rtos_custom/portable/vfs.cpp => module-vfs/board/linux/free_rtos_custom/portable/vfs.cpp +11 -9
@@ 47,19 47,22 @@ void vfs::Init()
/* Print out information on the disk. */
freertos_fat::internals::diskShowPartition(emmcFFDisk);
- bootConfig.os_root_path = purefs::dir::getRootDiskPath();
-
- if (loadBootConfig(getCurrentBootJSON())) {
- LOG_INFO("vfs::Init osType %s root:%s", bootConfig.os_type.c_str(), bootConfig.os_root_path.c_str());
- if (ff_chdir(bootConfig.os_root_path.c_str()) != 0) {
- LOG_ERROR("vfs::Init can't chdir to %s", bootConfig.os_root_path.c_str());
+ initDone = true;
+ int err = bootConfig.load();
+ if (!err) {
+ if (ff_chdir(bootConfig.os_root_path().c_str()) != 0) {
+ LOG_ERROR("vfs::Init can't chdir to %s", bootConfig.os_root_path().c_str());
+ }
+ LOG_INFO("vfs::Init osType %s root:%s", bootConfig.os_type().c_str(), bootConfig.os_root_path().c_str());
+ if (ff_chdir(bootConfig.os_root_path().c_str()) != 0) {
+ LOG_ERROR("vfs::Init can't chdir to %s", bootConfig.os_root_path().c_str());
}
}
else {
- LOG_ERROR("vfs::Init unable to determine OS type, fallback to %s", bootConfig.os_root_path.c_str());
+ LOG_ERROR("vfs::Init unable to determine OS type, fallback to %s", bootConfig.os_root_path().c_str());
}
- LOG_INFO("vfs::Init running on ARM osRootPath: %s", bootConfig.os_root_path.c_str());
+ LOG_INFO("vfs::Init running on ARM osRootPath: %s", bootConfig.os_root_path().c_str());
// this should already exist and have user data in it
// if it does not create an exmpty directory so that sqlite3 does not fault
@@ 73,6 76,5 @@ void vfs::Init()
LOG_INFO("vfs::Init looks like %s exists", userDiskPath.c_str());
}
chnNotifier.onFileSystemInitialized();
- initDone = true;
}
#pragma GCC diagnostic pop
M module-vfs/include/user/deprecated/vfs.hpp => module-vfs/include/user/deprecated/vfs.hpp +2 -30
@@ 8,10 8,9 @@
#include <vector>
#include <sstream>
#include <filesystem>
-#include <crc32/crc32.h>
#include <log/log.hpp>
-#include <json/json11.hpp>
#include <atomic>
+#include <boot/bootconfig.hpp>
#include "vfsNotifier.hpp"
#include "vfs_globals.hpp"
@@ 59,21 58,6 @@ namespace purefs
inline constexpr auto bootloader = "bootloader";
} // namespace json
- struct BootConfig
- {
- std::string os_image = "boot.bin";
- std::string os_type = "current";
- std::string os_version;
- std::string bootloader_verion;
- std::string timestamp;
- json11::Json boot_json_parsed;
-
- fs::path os_root_path;
- fs::path boot_json;
-
- static int version_compare(const std::string &v1, const std::string &v2);
- [[nodiscard]] json11::Json to_json() const;
- };
}; // namespace purefs
/* NOTE: VFS global object class is now deprecated more information
@@ 141,10 125,6 @@ class vfs
[[deprecated]] std::string loadFileAsString(const fs::path &fileToLoad);
[[deprecated]] bool replaceWithString(const fs::path &fileToModify, const std::string &stringToWrite);
[[deprecated]] void updateTimestamp();
- [[deprecated]] struct purefs::BootConfig &getBootConfig()
- {
- return bootConfig;
- }
[[deprecated]] void registerNotificationHandler(vfsn::utility::vfsNotifier::NotifyHandler handler)
{
chnNotifier.registerNotificationHandler(handler);
@@ 157,23 137,15 @@ class vfs
FF_Disk_t *emmcFFDisk{};
- [[deprecated]] static void computeCRC32(FILE *file, unsigned long *outCrc32);
- [[deprecated]] static bool verifyCRC(const std::string filePath, const unsigned long crc32);
- [[deprecated]] static bool verifyCRC(const fs::path filePath);
- [[deprecated]] static std::string generateRandomId(size_t length);
auto isInitialized() const noexcept
{
return initDone.load();
}
private:
- bool updateFileCRC32(const fs::path &file);
- const fs::path getCurrentBootJSON();
- bool loadBootConfig(const fs::path &bootJsonPath);
- bool updateBootConfig(const fs::path &bootJsonPath);
- struct purefs::BootConfig bootConfig;
vfsn::utility::vfsNotifier chnNotifier;
static std::atomic<bool> initDone;
+ boot::BootConfig bootConfig;
};
extern vfs vfs;
M module-vfs/src/deprecated/vfs-utils.cpp => module-vfs/src/deprecated/vfs-utils.cpp +0 -236
@@ 9,88 9,6 @@
#include <purefs/filesystem_paths.hpp>
-std::string vfs::generateRandomId(size_t length = 0)
-{
- const std::string CHARACTERS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
-
- std::random_device random_device;
- std::mt19937 generator(random_device());
- generator.seed(utils::time::Timestamp().getTime());
- std::uniform_int_distribution<> distribution(0, CHARACTERS.size() - 1);
-
- std::string random_string;
-
- for (std::size_t i = 0; i < length; ++i) {
- random_string += CHARACTERS[distribution(generator)];
- }
-
- return random_string;
-}
-
-void vfs::computeCRC32(vfs::FILE *file, unsigned long *outCrc32)
-{
- if (outCrc32 == nullptr)
- return;
-
- std::unique_ptr<unsigned char[]> buf(new unsigned char[purefs::buffer::crc_buf]);
- size_t bufLen;
-
- *outCrc32 = 0;
-
- while (!::vfs.eof(file)) {
- bufLen = ::vfs.fread(buf.get(), 1, purefs::buffer::crc_buf, file);
- if (bufLen <= 0)
- break;
-
- *outCrc32 = Crc32_ComputeBuf(*outCrc32, buf.get(), bufLen);
- }
-}
-
-bool vfs::verifyCRC(const std::string filePath, const unsigned long crc32)
-{
- unsigned long crc32Read;
- auto lamb = [](vfs::FILE *stream) { ::vfs.fclose(stream); };
-
- std::unique_ptr<vfs::FILE, decltype(lamb)> fp(::vfs.fopen(filePath.c_str(), "r"), lamb);
-
- if (fp.get() != nullptr) {
- computeCRC32(fp.get(), &crc32Read);
- LOG_INFO(
- "verifyCRC computed crc32 for %s is %08" PRIX32, filePath.c_str(), static_cast<std::uint32_t>(crc32Read));
- return (crc32Read == crc32);
- }
- LOG_ERROR("verifyCRC can't open %s", filePath.c_str());
- return (false);
-}
-
-bool vfs::verifyCRC(const fs::path filePath)
-{
- auto lamb = [](vfs::FILE *stream) { ::vfs.fclose(stream); };
- std::unique_ptr<char[]> crcBuf(new char[purefs::buffer::crc_char_size]);
- size_t readSize;
- fs::path crcFilePath(filePath);
- crcFilePath += purefs::extension::crc32;
-
- std::unique_ptr<vfs::FILE, decltype(lamb)> fp(::vfs.fopen(crcFilePath.c_str(), "r"), lamb);
-
- if (fp.get() != nullptr) {
- if ((readSize = ::vfs.fread(crcBuf.get(), 1, purefs::buffer::crc_char_size, fp.get())) !=
- (purefs::buffer::crc_char_size)) {
- LOG_ERROR("verifyCRC fread on %s returned different size then %d [%zu]",
- crcFilePath.c_str(),
- purefs::buffer::crc_char_size,
- readSize);
- return false;
- }
-
- const unsigned long crc32Read = strtoull(crcBuf.get(), nullptr, purefs::buffer::crc_radix);
-
- LOG_INFO("verifyCRC read %s string:\"%s\" hex:%08lX", crcFilePath.c_str(), crcBuf.get(), crc32Read);
- return verifyCRC(filePath, crc32Read);
- }
- LOG_ERROR("verifyCRC can't open %s", crcFilePath.c_str());
- return false;
-}
std::string vfs::loadFileAsString(const fs::path &fileToLoad)
{
@@ 124,157 42,3 @@ bool vfs::replaceWithString(const fs::path &fileToModify, const std::string &str
}
}
-const fs::path vfs::getCurrentBootJSON()
-{
- if (verifyCRC(purefs::file::boot_json)) {
- return relativeToRoot(purefs::file::boot_json);
- }
-
- LOG_INFO("vfs::getCurrentBootJSON crc check failed on %s", purefs::file::boot_json);
- // replace broken .boot.json with a default one
- replaceWithString(purefs::dir::getRootDiskPath() / purefs::file::boot_json, bootConfig.to_json().dump());
-
- return relativeToRoot(purefs::file::boot_json);
-}
-
-bool vfs::loadBootConfig(const fs::path &bootJsonPath)
-{
- std::string parseErrors = "";
- std::string jsonContents = loadFileAsString(bootJsonPath);
-
- LOG_INFO("vfs::getOSRootFromJSON parsing %s", bootJsonPath.c_str());
- LOG_INFO("vfs::getOSRootFromJSON \"%s\"", jsonContents.c_str());
-
- bootConfig.boot_json_parsed = json11::Json::parse(jsonContents, parseErrors);
-
- if (parseErrors == "") {
- bootConfig.os_type = bootConfig.boot_json_parsed[purefs::json::main][purefs::json::os_type].string_value();
- bootConfig.os_image = bootConfig.boot_json_parsed[purefs::json::main][purefs::json::os_image].string_value();
- bootConfig.os_root_path = purefs::createPath(purefs::dir::getRootDiskPath(), bootConfig.os_type);
- bootConfig.boot_json = bootJsonPath;
- bootConfig.bootloader_verion =
- bootConfig.boot_json_parsed[purefs::json::bootloader][purefs::json::os_version].string_value();
- bootConfig.timestamp = utils::time::Timestamp().str("%c");
- bootConfig.os_version = std::string(VERSION);
-
- LOG_INFO("boot_config: %s", bootConfig.to_json().dump().c_str());
- return true;
- }
- else {
- bootConfig.os_type = PATH_CURRENT;
- bootConfig.os_image = purefs::file::boot_bin;
- bootConfig.os_root_path = purefs::createPath(purefs::dir::getRootDiskPath(), bootConfig.os_type);
- bootConfig.boot_json = bootJsonPath;
- bootConfig.timestamp = utils::time::Timestamp().str("%c");
- bootConfig.os_version = std::string(VERSION);
-
- LOG_WARN("vfs::getOSRootFromJSON failed to parse %s: \"%s\"", bootJsonPath.c_str(), parseErrors.c_str());
- return false;
- }
-}
-
-bool vfs::updateFileCRC32(const fs::path &file)
-{
- unsigned long fileCRC32 = 0;
- auto lamb = [](vfs::FILE *stream) { ::vfs.fclose(stream); };
-
- std::unique_ptr<vfs::FILE, decltype(lamb)> fp(fopen(file.c_str(), "r"), lamb);
-
- if (fp.get() != nullptr) {
- std::unique_ptr<char[]> crc32Buf(new char[purefs::buffer::crc_char_size]);
- int written = 0;
- computeCRC32(fp.get(), &fileCRC32);
- LOG_INFO("updateFileCRC32 writing new crc32 %08" PRIX32 " for %s",
- static_cast<std::uint32_t>(fileCRC32),
- file.c_str());
- if (fileCRC32 != 0) {
- if ((written = sprintf(crc32Buf.get(), "%08" PRIX32, fileCRC32)) != (purefs::buffer::crc_char_size - 1)) {
- LOG_INFO("updateFileCRC32 can't prepare string for crc32, sprintf returned %d instead of %d",
- written,
- purefs::buffer::crc_char_size - 1);
- return false;
- }
- fs::path fileCRC32Path = file;
- fileCRC32Path += purefs::extension::crc32;
-
- std::unique_ptr<vfs::FILE, decltype(lamb)> fpCRC32(fopen(fileCRC32Path.c_str(), "w"), lamb);
-
- if (fpCRC32.get() != nullptr) {
- if (fwrite(crc32Buf.get(), 1, purefs::buffer::crc_char_size, fpCRC32.get()) ==
- purefs::buffer::crc_char_size) {
- LOG_INFO("updateFileCRC32 wrote \"%s\" in %s", crc32Buf.get(), fileCRC32Path.c_str());
- return true;
- }
- else {
- LOG_WARN("updateFileCRC32 can't write new crc32");
- return false;
- }
- }
- else {
- LOG_WARN("updateFileCRC32 can't open crc32 file for write");
- return false;
- }
- }
- }
- else {
- LOG_WARN("updateFileCRC32 can't open file %s for write", file.c_str());
- return false;
- }
-
- return false;
-}
-
-void vfs::updateTimestamp()
-{
- bootConfig.timestamp = utils::time::Timestamp().str("%c");
- LOG_INFO("vfs::updateTimestamp \"%s\"", bootConfig.to_json().dump().c_str());
-
- if (replaceWithString(bootConfig.boot_json, bootConfig.to_json().dump())) {
- updateFileCRC32(bootConfig.boot_json);
- }
-}
-
-json11::Json purefs::BootConfig::to_json() const
-{
- return json11::Json::object{
- {purefs::json::main,
- json11::Json::object{{purefs::json::os_image, os_image},
- {purefs::json::os_type, os_type},
- {purefs::json::os_version, os_version},
- {purefs::json::timestamp, timestamp}}},
-
- {purefs::json::git_info,
- json11::Json::object{{purefs::json::os_git_tag, std::string(GIT_TAG)},
- {purefs::json::os_git_revision, std::string(GIT_REV)},
- {purefs::json::os_git_branch, std::string(GIT_BRANCH)}}},
- {purefs::json::bootloader, json11::Json::object{{purefs::json::os_version, bootloader_verion}}}};
-}
-
-// Method to compare two version strings
-// v1 < v2 -> -1
-// v1 == v2 -> 0
-int purefs::BootConfig::version_compare(const std::string &v1, const std::string &v2)
-{
- size_t i = 0, j = 0;
- while (i < v1.length() || j < v2.length()) {
- int acc1 = 0, acc2 = 0;
-
- while (i < v1.length() && v1[i] != '.') {
- acc1 = acc1 * 10 + (v1[i] - '0');
- i++;
- }
- while (j < v2.length() && v2[j] != '.') {
- acc2 = acc2 * 10 + (v2[j] - '0');
- j++;
- }
-
- if (acc1 < acc2)
- return -1;
- if (acc1 > acc2)
- return +1;
-
- ++i;
- ++j;
- }
- return 0;
-}
M module-vfs/src/deprecated/vfs.cpp => module-vfs/src/deprecated/vfs.cpp +3 -3
@@ 289,16 289,16 @@ std::string vfs::relativeToRoot(const std::string path)
fs::path fsPath(path);
if (fsPath.is_absolute()) {
- if (bootConfig.os_root_path.root_directory() == fsPath.root_directory())
+ if (bootConfig.os_root_path().root_directory() == fsPath.root_directory())
return fsPath;
else
return purefs::createPath(purefs::dir::getRootDiskPath(), fsPath.relative_path()).c_str();
}
if (path.empty())
- return bootConfig.os_root_path;
+ return bootConfig.os_root_path();
else
- return bootConfig.os_root_path / fsPath;
+ return bootConfig.os_root_path() / fsPath;
}
bool vfs::isDir(const char *path)
M module-vfs/tests/CMakeLists.txt => module-vfs/tests/CMakeLists.txt +1 -1
@@ 7,7 7,7 @@ add_catch2_executable(
SRCS
${CMAKE_CURRENT_LIST_DIR}/unittest_vfs.cpp
LIBS
- module-vfs
+ module-vfs module-utils
)
add_catch2_executable(
M module-vfs/tests/unittest_vfs.cpp => module-vfs/tests/unittest_vfs.cpp +0 -61
@@ 80,70 80,9 @@ TEST_CASE("Test vfs case 1")
}
}
-#define RANDDOM_TESTS 4
-TEST_CASE("Random strings")
-{
- const std::string allowedChars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
- std::string randomIds8, randomIds16, randomIds32;
- randomIds8 = vfs.generateRandomId(8);
- randomIds16 = vfs.generateRandomId(16);
- randomIds32 = vfs.generateRandomId(32);
-
- REQUIRE(randomIds8.size() == 8);
- for (unsigned int i = 0; i < randomIds8.size(); i++)
- REQUIRE(allowedChars.find_first_of(randomIds8[i]) != std::string::npos);
-
- REQUIRE(randomIds16.size() == 16);
- for (unsigned int i = 0; i < randomIds16.size(); i++)
- REQUIRE(allowedChars.find_first_of(randomIds16[i]) != std::string::npos);
-
- REQUIRE(randomIds32.size() == 32);
- for (unsigned int i = 0; i < randomIds32.size(); i++)
- REQUIRE(allowedChars.find_first_of(randomIds32[i]) != std::string::npos);
-}
-
-TEST_CASE("CRC32 tests")
-{
- unsigned long crc32 = 0;
- char crcBuf[purefs::buffer::crc_char_size];
- std::string randomData = vfs.generateRandomId(128);
- auto fd = vfs.fopen("testFile.txt", "w");
- REQUIRE(fd != nullptr);
-
- auto bytesWritten = vfs.fwrite(randomData.c_str(), 1, randomData.size(), fd);
- REQUIRE(bytesWritten == randomData.size());
- REQUIRE(vfs.fclose(fd) == 0);
- fd = vfs.fopen("testFile.txt", "r");
- vfs.computeCRC32(fd, &crc32);
- sprintf(crcBuf, "%lX", crc32);
- auto fdCRC = vfs.fopen("testFile.txt.crc32", "w");
- bytesWritten = vfs.fwrite(&crcBuf, 1, purefs::buffer::crc_char_size, fdCRC);
- REQUIRE(bytesWritten == purefs::buffer::crc_char_size);
- REQUIRE(vfs.fclose(fdCRC) == 0);
- REQUIRE(vfs.fclose(fd) == 0);
- REQUIRE(vfs.verifyCRC("testFile.txt") == true);
- REQUIRE(vfs.remove("testFile.txt") == 0);
- REQUIRE(vfs.remove("testFile.txt.crc32") == 0);
-}
-TEST_CASE("File loading and saving")
-{
- static constexpr auto test_str = "abcd";
- auto fd = vfs.fopen("test1.txt", "w");
- REQUIRE(fd != nullptr);
- const auto slen = std::strlen(test_str);
- REQUIRE(vfs.fwrite(test_str, 1, slen, fd) == slen);
- vfs.fclose(fd);
- std::string fileContents = vfs.loadFileAsString("test1.txt");
- REQUIRE(strcmp(fileContents.c_str(), test_str) == 0);
- vfs.mkdir("module-vfs/test_dirx");
- vfs.replaceWithString("module-vfs/test_dirx/testWrite.txt", "this is a test");
- fileContents = vfs.loadFileAsString("module-vfs/test_dirx/testWrite.txt");
- REQUIRE(strcmp(fileContents.c_str(), "this is a test") == 0);
- REQUIRE(vfs.remove("module-vfs/test_dirx/testWrite.txt") == 0);
-}
TEST_CASE("VFS lseek check")
{