From 0f0192a8b4a92f5a8bd768da14a142b9d45b7935 Mon Sep 17 00:00:00 2001 From: Borys Jelenski Date: Mon, 25 Jan 2021 12:06:58 +0100 Subject: [PATCH] [EGD-5072] Refactor legacy VFS functions Functions were refactored and renamed for better readability. Some of them were moved to different files. In stat_vfs function the order of member initializations was corrected. --- .../endpoints/update/UpdateMuditaOS.cpp | 3 +- module-utils/Utils.cpp | 24 +- module-utils/Utils.hpp | 2 +- .../bootconfig/include/boot/bootconfig.hpp | 4 +- module-utils/bootconfig/src/bootconfig.cpp | 224 ++++++++---------- .../src/purefs/fs/filesystem_littlefs.cpp | 3 +- 6 files changed, 116 insertions(+), 144 deletions(-) diff --git a/module-services/service-desktop/endpoints/update/UpdateMuditaOS.cpp b/module-services/service-desktop/endpoints/update/UpdateMuditaOS.cpp index fb507137b472f3516c17037cf62466a0aa3e5d20..ee1216bbcef5a2a7213f059668e9588953e90571 100644 --- a/module-services/service-desktop/endpoints/update/UpdateMuditaOS.cpp +++ b/module-services/service-desktop/endpoints/update/UpdateMuditaOS.cpp @@ -377,14 +377,13 @@ updateos::UpdateError UpdateMuditaOS::prepareRoot() updateos::UpdateError UpdateMuditaOS::updateBootJSON() { - unsigned long bootJSONAbsoulteCRC = 0; fs::path bootJSONAbsoulte = purefs::createPath(purefs::dir::getRootDiskPath(), purefs::file::boot_json); informDebug("updateBootJSON %s", bootJSONAbsoulte.c_str()); auto *fp = std::fopen(bootJSONAbsoulte.c_str(), "r"); if (fp != nullptr) { - utils::filesystem::computeCRC32(fp, &bootJSONAbsoulteCRC); + unsigned long bootJSONAbsoulteCRC = utils::filesystem::computeFileCRC32(fp); bootJSONAbsoulte += boot::consts::ext_crc32; auto *fpCRC = std::fopen(bootJSONAbsoulte.c_str(), "w"); diff --git a/module-utils/Utils.cpp b/module-utils/Utils.cpp index 34b589297a64c7d0727f781c41b42d3cab930b12..1b481374ca03d7f64e75aef57904f189e945efc2 100644 --- a/module-utils/Utils.cpp +++ b/module-utils/Utils.cpp @@ -9,7 +9,7 @@ namespace utils::filesystem { namespace { - inline constexpr auto crc_buf = 1024; + inline constexpr auto crc_buf_len = 1024; } // namespace long int filelength(std::FILE *file) noexcept @@ -24,23 +24,21 @@ namespace utils::filesystem return endPosition; } - void computeCRC32(std::FILE *file, unsigned long *outCrc32) noexcept + unsigned long computeFileCRC32(::FILE *file) noexcept { - if (outCrc32 == nullptr) - return; - - auto buf = std::make_unique(crc_buf); - size_t bufLen; - - *outCrc32 = 0; + auto buf = std::make_unique(crc_buf_len); + unsigned long crc32 = 0; while (!std::feof(file)) { - bufLen = std::fread(buf.get(), 1, crc_buf, file); - if (bufLen <= 0) - break; + size_t dataLen = std::fread(buf.get(), 1, crc_buf_len, file); + if (dataLen == 0) { + return crc32; + } - *outCrc32 = Crc32_ComputeBuf(*outCrc32, buf.get(), bufLen); + crc32 = Crc32_ComputeBuf(crc32, buf.get(), dataLen); } + + return crc32; } std::string generateRandomId(std::size_t length) noexcept diff --git a/module-utils/Utils.hpp b/module-utils/Utils.hpp index 26da74259daf9a2ebbe788a5320e13fa48914dc7..7e2cd2e3d3b6be41ba8ae4022950d65f7eda4821 100644 --- a/module-utils/Utils.hpp +++ b/module-utils/Utils.hpp @@ -253,7 +253,7 @@ namespace utils namespace filesystem { [[nodiscard]] long int filelength(std::FILE *file) noexcept; - void computeCRC32(std::FILE *file, unsigned long *outCrc32) noexcept; + [[nodiscard]] unsigned long computeFileCRC32(std::FILE *file) noexcept; [[nodiscard]] std::string generateRandomId(std::size_t length = 0) noexcept; [[nodiscard]] std::string getline(std::FILE *stream, uint32_t length = 1024) noexcept; } // namespace filesystem diff --git a/module-utils/bootconfig/include/boot/bootconfig.hpp b/module-utils/bootconfig/include/boot/bootconfig.hpp index 0aa147573806ec71315bef8c0adaaa976f0e3847..7e0287dfaefb808a29ec468958fe43c84140cecd 100644 --- a/module-utils/bootconfig/include/boot/bootconfig.hpp +++ b/module-utils/bootconfig/include/boot/bootconfig.hpp @@ -64,9 +64,7 @@ namespace boot 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); + std::filesystem::path getCurrentBootJSON(); private: std::string m_os_image{"boot.bin"}; diff --git a/module-utils/bootconfig/src/bootconfig.cpp b/module-utils/bootconfig/src/bootconfig.cpp index 70e9b3aa911b98ed8d73c93a6ffd3124ab7576f2..2384eb3a7626f1447d4af1d81fd0a53765d61834 100644 --- a/module-utils/bootconfig/src/bootconfig.cpp +++ b/module-utils/bootconfig/src/bootconfig.cpp @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -12,94 +13,74 @@ #include #include #include +#include +#include namespace boot { namespace { - - bool replaceWithString(const std::filesystem::path &fileToModify, const std::string &stringToWrite) + bool writeToFile(const std::filesystem::path &file, 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 { + auto fp = fopen(file.c_str(), "w"); + if (!fp) { return false; } - } - void computeCRC32(std::FILE *file, unsigned long *outCrc32) - { - if (outCrc32 == nullptr) - return; - std::unique_ptr buf(new unsigned char[boot::consts::crc_buf]); - size_t bufLen; - *outCrc32 = 0; + size_t dataWritten = fwrite(stringToWrite.c_str(), stringToWrite.length(), 1, fp); - while (!std::feof(file)) { - bufLen = std::fread(buf.get(), 1, boot::consts::crc_buf, file); - if (bufLen <= 0) - break; + fclose(fp); - *outCrc32 = Crc32_ComputeBuf(*outCrc32, buf.get(), bufLen); - } + return dataWritten == 1; } bool updateFileCRC32(const std::filesystem::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 crc32Buf(new char[boot::consts::crc_char_size]); - int written = 0; - computeCRC32(fp.get(), &fileCRC32); - LOG_INFO("updateFileCRC32 writing new crc32 %08" PRIX32 " for %s", - static_cast(fileCRC32), - file.c_str()); - if (fileCRC32 != 0) { - if ((written = sprintf(crc32Buf.get(), "%08" PRIX32, fileCRC32)) != - (boot::consts::crc_char_size - 1)) { - LOG_INFO("updateFileCRC32 can't prepare string for crc32, sprintf returned %d instead of %d", - written, - boot::consts::crc_char_size - 1); - return false; - } - std::filesystem::path fileCRC32Path = file; - fileCRC32Path += boot::consts::ext_crc32; - - std::unique_ptr<::FILE, decltype(lamb)> fpCRC32(fopen(fileCRC32Path.c_str(), "w"), lamb); - - if (fpCRC32.get() != nullptr) { - if (fwrite(crc32Buf.get(), 1, boot::consts::crc_char_size, fpCRC32.get()) == - boot::consts::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 { + auto fp = fopen(file.c_str(), "r"); + if (!fp) { LOG_WARN("updateFileCRC32 can't open file %s for write", file.c_str()); return false; } + auto fpCloseAct = gsl::finally([fp] { fclose(fp); }); - return false; + unsigned long fileCRC32 = utils::filesystem::computeFileCRC32(fp); + LOG_INFO("updateFileCRC32 writing new crc32 %08" PRIX32 " for %s", + static_cast(fileCRC32), + file.c_str()); + + if (fileCRC32 == 0) { + return false; + } + + std::array crc32Buf; + + if (int written = sprintf(crc32Buf.data(), "%08" PRIX32, fileCRC32); + written != boot::consts::crc_char_size - 1) { + LOG_INFO("updateFileCRC32 can't prepare string for crc32, sprintf returned %d instead of %d", + written, + boot::consts::crc_char_size - 1); + return false; + } + + std::filesystem::path fileCRC32Path = file; + fileCRC32Path += boot::consts::ext_crc32; + + auto fpCRC32 = fopen(fileCRC32Path.c_str(), "w"); + if (!fpCRC32) { + LOG_WARN("updateFileCRC32 can't open crc32 file for write"); + return false; + } + auto fpCRC32CloseAct = gsl::finally([fpCRC32] { fclose(fpCRC32); }); + + if (fwrite(crc32Buf.data(), 1, boot::consts::crc_char_size, fpCRC32) != boot::consts::crc_char_size) { + LOG_WARN("updateFileCRC32 can't write new crc32"); + return false; + } + + LOG_INFO("updateFileCRC32 wrote \"%s\" in %s", crc32Buf.data(), fileCRC32Path.c_str()); + return true; } + std::string loadFileAsString(const std::filesystem::path &fileToLoad) { std::string content; @@ -108,6 +89,50 @@ namespace boot return content; } + bool verifyCRC(const std::filesystem::path &file, const unsigned long crc32) + { + auto fp = fopen(file.c_str(), "r"); + if (!fp) { + LOG_ERROR("verifyCRC can't open %s", file.c_str()); + return false; + } + auto fpCloseAct = gsl::finally([fp] { fclose(fp); }); + + unsigned long crc32Read = utils::filesystem::computeFileCRC32(fp); + LOG_INFO( + "verifyCRC computed crc32 for %s is %08" PRIX32, file.c_str(), static_cast(crc32Read)); + + return crc32Read == crc32; + } + + bool readAndVerifyCRC(const std::filesystem::path &file) + { + std::filesystem::path crcFilePath(file); + crcFilePath += boot::consts::ext_crc32; + + auto fp = fopen(crcFilePath.c_str(), "r"); + if (!fp) { + LOG_ERROR("verifyCRC can't open %s", crcFilePath.c_str()); + return false; + } + auto fpCloseAct = gsl::finally([fp] { fclose(fp); }); + + std::array crcBuf; + + if (size_t readSize = std::fread(crcBuf.data(), 1, boot::consts::crc_char_size, fp); + readSize != boot::consts::crc_char_size) { + LOG_ERROR("verifyCRC fread on %s returned different size then %d [%zu]", + crcFilePath.c_str(), + boot::consts::crc_char_size, + readSize); + return false; + } + + const unsigned long crc32Read = strtoull(crcBuf.data(), nullptr, boot::consts::crc_radix); + + LOG_INFO("verifyCRC read %s string:\"%s\" hex:%08lX", crcFilePath.c_str(), crcBuf.data(), crc32Read); + return verifyCRC(file, crc32Read); + } } // namespace BootConfig::BootConfig() : m_os_root_path(purefs::dir::getRootDiskPath()) @@ -166,7 +191,7 @@ namespace boot 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())) { + if (writeToFile(m_boot_json, to_json().dump())) { updateFileCRC32(m_boot_json); } } @@ -183,11 +208,11 @@ namespace boot if (parseErrors == "") { m_os_type = m_boot_json_parsed[boot::json::main][boot::json::os_type].string_value(); m_os_image = m_boot_json_parsed[boot::json::main][boot::json::os_image].string_value(); - m_os_root_path = purefs::createPath(purefs::dir::getRootDiskPath(), m_os_type); - m_boot_json = bootJsonPath; + m_os_root_path = purefs::createPath(purefs::dir::getRootDiskPath(), m_os_type); + m_boot_json = bootJsonPath; m_bootloader_version = m_boot_json_parsed[boot::json::bootloader][boot::json::os_version].string_value(); - m_timestamp = utils::time::Timestamp().str("%c"); - m_os_version = std::string(VERSION); + 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; @@ -203,61 +228,14 @@ namespace boot return false; } } - const std::filesystem::path BootConfig::getCurrentBootJSON() + std::filesystem::path BootConfig::getCurrentBootJSON() { - if (verifyCRC(purefs::file::boot_json)) { + if (readAndVerifyCRC(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()); + writeToFile(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(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 crcBuf(new char[boot::consts::crc_char_size]); - size_t readSize; - std::filesystem::path crcFilePath(filePath); - crcFilePath += boot::consts::ext_crc32; - - std::unique_ptr<::FILE, decltype(lamb)> fp(::fopen(crcFilePath.c_str(), "r"), lamb); - - if (fp.get() != nullptr) { - if ((readSize = ::fread(crcBuf.get(), 1, boot::consts::crc_char_size, fp.get())) != - (boot::consts::crc_char_size)) { - LOG_ERROR("verifyCRC fread on %s returned different size then %d [%zu]", - crcFilePath.c_str(), - boot::consts::crc_char_size, - readSize); - return false; - } - - const unsigned long crc32Read = strtoull(crcBuf.get(), nullptr, boot::consts::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 diff --git a/module-vfs/drivers/src/purefs/fs/filesystem_littlefs.cpp b/module-vfs/drivers/src/purefs/fs/filesystem_littlefs.cpp index 007cdb8036dd3a7645839efe0d35b1c3543e2c74..818b8409e8ee0674feedf11f23b72e77f26a3658 100644 --- a/module-vfs/drivers/src/purefs/fs/filesystem_littlefs.cpp +++ b/module-vfs/drivers/src/purefs/fs/filesystem_littlefs.cpp @@ -297,12 +297,11 @@ namespace purefs::fs::drivers stat.f_blocks = cfg->block_count; stat.f_bfree = stat.f_blocks - lerr; stat.f_bavail = stat.f_bfree; - lerr = 0; stat.f_bsize = cfg->prog_size; stat.f_frsize = cfg->block_size; - stat.f_blocks = cfg->block_count; stat.f_namemax = PATH_MAX; stat.f_flag = vmnt->flags(); + lerr = 0; } return lfs_to_errno(lerr); }